Major overhault to add libuv event loop. Enhancements to config file to support profiles.

This commit is contained in:
Paul Dino Jones 2024-08-30 13:46:56 -04:00
parent 607a7ad7c3
commit 40726c06c8
14 changed files with 744 additions and 250 deletions

View File

@ -37,10 +37,10 @@ add_executable(monocoque src/monocoque/monocoque.c)
if(USE_PULSEAUDIO)
message("Using pulseaudio backend...")
add_compile_definitions(USE_PULSEAUDIO=true)
target_link_libraries(monocoque m hidapi-hidraw pulse serialport xml2 argtable2 config gameloop helper devices slog simulatorapi)
target_link_libraries(monocoque m hidapi-hidraw pulse serialport xml2 argtable2 config gameloop helper devices slog simulatorapi uv xdg-basedir)
else()
message("Using portaudio backend...")
target_link_libraries(monocoque m hidapi-hidraw portaudio serialport xml2 argtable2 config gameloop helper devices slog simulatorapi)
target_link_libraries(monocoque m hidapi-hidraw portaudio serialport xml2 argtable2 config gameloop helper devices slog simulatorapi uv xdg-basedir)
endif()
target_include_directories(monocoque PUBLIC config ${LIBXML_INCLUDE_DIR})

View File

@ -78,15 +78,12 @@ void stream_state_cb(pa_stream *s, void *mainloop) {
int usb_generic_shaker_free(SoundDevice* sounddevice)
{
int err = 0;
//err = Pa_CloseStream( sounddevice->stream );
//if( err != paNoError )
//{
// err = Pa_Terminate();
//}
if (sounddevice->stream)
{
pa_stream_disconnect(sounddevice->stream);
pa_stream_unref(sounddevice->stream);
pa_xfree(sounddevice->stream);
// why is this wrong
//pa_xfree(sounddevice->stream);
}
return err;
}

View File

@ -104,8 +104,7 @@ int sounddev_free(SimDevice* this)
{
SoundDevice* sounddevice = (void *) this->derived;
//figure out why this is causing problems
//usb_generic_shaker_free(sounddevice);
usb_generic_shaker_free(sounddevice);
free(sounddevice);

View File

@ -3,6 +3,7 @@ set(gameloop_source_files
gameloop.h
tachconfig.c
tachconfig.h
loopdata.h
)
set(LIBXML_INCLUDE_DIR /usr/include/libxml2)

View File

@ -7,8 +7,11 @@
#include <poll.h>
#include <termios.h>
#include <signal.h>
#include <uv.h>
#include "gameloop.h"
#include "loopdata.h"
#include "../helper/parameters.h"
#include "../helper/confighelper.h"
#include "../devices/simdevice.h"
@ -22,15 +25,17 @@ bool go = false;
bool go2 = false;
struct sigaction act;
void sighandler(int signum, siginfo_t* info, void* ptr)
{
sloge("caught signal");
go = false;
go2 = false;
//gfx_clear(pixels, pixels_len);
//gfx_swapbuffers();
//gfx_close();
}
uv_idle_t idler;
uv_timer_t datachecktimer;
uv_timer_t datamaptimer;
bool doui = false;
int appstate = 0;
void shmdatamapcallback(uv_timer_t* handle);
void datacheckcallback(uv_timer_t* handle);
void startdatalogger(MonocoqueSettings* ms, loop_data* l);
int showstats(SimData* simdata)
{
@ -181,26 +186,61 @@ int showstats(SimData* simdata)
fflush(stdout);
}
int clilooper(SimDevice* devices, int numdevices, Parameters* p, SimData* simdata, SimMap* simmap)
void shmdatamapcallback(uv_timer_t* handle)
{
struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI };
double update_rate = DEFAULT_UPDATE_RATE;
char ch;
int t=0;
int s=0;
go2 = true;
slogd("game data found, starting game loop");
while (go2 == true && simdata->simstatus > 1)
void* b = uv_handle_get_data((uv_handle_t*) handle);
loop_data* f = (loop_data*) b;
SimData* simdata = f->simdata;
SimMap* simmap = f->simmap;
MonocoqueSettings* ms = f->ms;
//appstate = 2;
if (appstate == 2)
{
simdatamap(simdata, simmap, p->sim);
showstats(simdata);
t++;
s++;
if(simdata->rpms<100)
simdatamap(simdata, simmap, f->sim);
if (doui == true)
{
simdata->rpms=100;
slogi("looking for ui config %s", ms->config_str);
int confignum = getconfigtouse(ms->config_str, simdata->car, f->sim);
int configureddevices;
configcheck(ms->config_str, confignum, &configureddevices);
DeviceSettings* ds = malloc(configureddevices * sizeof(DeviceSettings));
slogd("loading confignum %i, with %i devices.", confignum, configureddevices);
f->numdevices = uiloadconfig(ms->config_str, confignum, configureddevices, ms, ds);
f->simdevices = malloc(f->numdevices * sizeof(SimDevice));
int initdevices = devinit(f->simdevices, configureddevices, ds, ms);
int i = 0;
for( i = 0; i < configureddevices; i++)
{
settingsfree(ds[i]);
}
free(ds);
doui = false;
}
else
{
showstats(simdata);
SimDevice* devices = f->simdevices;
int numdevices = f->numdevices;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
}
}
if (f->simstate == false || simdata->simstatus <= 1 || appstate <= 1)
{
f->uion = false;
SimDevice* devices = f->simdevices;
int numdevices = f->numdevices;
for (int x = 0; x < numdevices; x++)
{
@ -209,51 +249,82 @@ int clilooper(SimDevice* devices, int numdevices, Parameters* p, SimData* simdat
devices[x].update(&devices[x], simdata);
}
}
if( poll(&mypoll, 1, 1000.0/update_rate) )
{
scanf("%c", &ch);
if(ch == 'q')
{
slogd("User gameloop exit requested.");
go2 = false;
}
}
}
simdata->velocity = 0;
simdata->rpms = 100;
simdata->gear = MONOCOQUE_GEAR_NEUTRAL;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
for (int x = 0; x < numdevices; x++)
{
devices[x].update(&devices[x], simdata);
if (devices[x].initialized == true)
{
devices[x].free(&devices[x]);
}
}
free(devices);
int r = simfree(simdata, simmap, f->sim);
slogd("simfree returned %i", r);
f->numdevices = 0;
slogi("stopped mapping data, press q again to quit");
//stopui(ms->ui_type, f);
// free loop data
uv_timer_stop(handle);
uv_timer_start(&datachecktimer, datacheckcallback, 3000, 1000);
}
}
void datacheckcallback(uv_timer_t* handle)
{
void* b = uv_handle_get_data((uv_handle_t*) handle);
loop_data* f = (loop_data*) b;
SimData* simdata = f->simdata;
SimMap* simmap = f->simmap;
if ( appstate == 1 )
{
getSim(simdata, simmap, &f->simstate, &f->sim);
}
if (f->simstate == true)
{
if ( appstate == 1 )
{
appstate++;
doui = true;
uv_timer_start(&datamaptimer, shmdatamapcallback, 2000, 16);
uv_timer_stop(handle);
}
}
fprintf(stdout, "\n");
int r = simfree(simdata, simmap, p->sim);
slogd("simfree returned %i", r);
return 0;
if (appstate == 0)
{
slogi("stopping checking for data");
uv_timer_stop(handle);
}
}
int looper(SimDevice* devices, int numdevices, Parameters* p)
void cb(uv_poll_t* handle, int status, int events)
{
char ch;
scanf("%c", &ch);
if (ch == 'q')
{
appstate--;
slogi("User requested stop appstate is now %i", appstate);
fprintf(stdout, "User requested stop appstate is now %i\n", appstate);
fflush(stdout);
}
if (appstate == 0)
{
slogi("Monocoque is exiting...");
uv_timer_stop(&datachecktimer);
uv_poll_stop(handle);
}
}
int monocoque_mainloop(MonocoqueSettings* ms)
{
memset(&act, 0, sizeof(act));
act.sa_sigaction = sighandler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &act, NULL);
sigaction(SIGINT, &act, NULL);
sigaction(SIGTSTP, &act, NULL);
SimData* simdata = malloc(sizeof(SimData));
SimMap* simmap = malloc(sizeof(SimMap));
simdata->tyrediameter[0] = -1;
simdata->tyrediameter[1] = -1;
simdata->tyrediameter[2] = -1;
simdata->tyrediameter[3] = -1;
struct termios newsettings, canonicalmode;
tcgetattr(0, &canonicalmode);
@ -265,64 +336,190 @@ int looper(SimDevice* devices, int numdevices, Parameters* p)
char ch;
struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI };
uv_poll_t* poll = (uv_poll_t*) malloc(uv_handle_size(UV_POLL));
loop_data* baton = (loop_data*) malloc(sizeof(loop_data));
baton->simmap = simmap;
baton->simdata = simdata;
baton->ms = ms;
baton->simstate = false;
baton->uion = false;
baton->sim = 0;
baton->req.data = (void*) baton;
uv_handle_set_data((uv_handle_t*) &datachecktimer, (void*) baton);
uv_handle_set_data((uv_handle_t*) &datamaptimer, (void*) baton);
uv_handle_set_data((uv_handle_t*) poll, (void*) baton);
appstate = 1;
slogd("setting initial app state");
uv_timer_init(uv_default_loop(), &datachecktimer);
fprintf(stdout, "Searching for sim data... Press q to quit...\n");
p->simon = false;
double update_rate = SIM_CHECK_RATE;
go = true;
while (go == true)
uv_timer_start(&datachecktimer, datacheckcallback, 1000, 1000);
if (0 != uv_poll_init(uv_default_loop(), poll, 0))
{
p->simon = false;
getSim(simdata, simmap, &p->simon, &p->sim);
if (p->simon == true && simdata->simstatus > 1)
{
slogi("preparing game loop with %i devices...", numdevices);
return 1;
};
if (0 != uv_poll_start(poll, UV_READABLE, cb))
{
return 2;
};
slogi("sending initial data to devices");
simdata->velocity = 16;
simdata->rpms = 100;
for (int x = 0; x < numdevices; x++)
{
devices[x].update(&devices[x], simdata);
}
sleep(3);
clilooper(devices, numdevices, p, simdata, simmap);
}
if (p->simon == true)
{
p->simon = false;
fprintf(stdout, "Searching for sim data... Press q again to quit...\n");
sleep(2);
}
if (poll(&mypoll, 1, 1000.0/update_rate) )
{
if (go != false )
{
scanf("%c", &ch);
if(ch == 'q')
{
slogd("User application exit requested.");
go = false;
}
}
}
}
uv_timer_init(uv_default_loop(), &datamaptimer);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
fprintf(stdout, "\n");
fflush(stdout);
tcsetattr(0, TCSANOW, &canonicalmode);
int r = simfree(simdata, simmap, p->sim);
slogd("simfree returned %i", r);
free(simdata);
free(simmap);
return 0;
}
//int clilooper(SimDevice* devices, int numdevices, Parameters* p, SimData* simdata, SimMap* simmap)
//{
// struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI };
// double update_rate = DEFAULT_UPDATE_RATE;
// char ch;
// int t=0;
// int s=0;
// go2 = true;
// slogd("game data found, starting game loop");
// while (go2 == true && simdata->simstatus > 1)
// {
// simdatamap(simdata, simmap, p->sim);
// showstats(simdata);
// t++;
// s++;
// if(simdata->rpms<100)
// {
// simdata->rpms=100;
// }
//
// for (int x = 0; x < numdevices; x++)
// {
// if (devices[x].initialized == true)
// {
// devices[x].update(&devices[x], simdata);
// }
// }
//
// if( poll(&mypoll, 1, 1000.0/update_rate) )
// {
// scanf("%c", &ch);
// if(ch == 'q')
// {
// slogd("User gameloop exit requested.");
// go2 = false;
// }
// }
// }
//
// simdata->velocity = 0;
// simdata->rpms = 100;
// simdata->gear = MONOCOQUE_GEAR_NEUTRAL;
// for (int x = 0; x < numdevices; x++)
// {
// if (devices[x].initialized == true)
// {
// devices[x].update(&devices[x], simdata);
// }
// }
//
// fprintf(stdout, "\n");
// int r = simfree(simdata, simmap, p->sim);
// slogd("simfree returned %i", r);
//
// return 0;
//}
//int looper(SimDevice* devices, int numdevices, Parameters* p)
//{
// memset(&act, 0, sizeof(act));
// act.sa_sigaction = sighandler;
// act.sa_flags = SA_SIGINFO;
// sigaction(SIGTERM, &act, NULL);
// sigaction(SIGINT, &act, NULL);
// sigaction(SIGTSTP, &act, NULL);
//
// SimData* simdata = malloc(sizeof(SimData));
// SimMap* simmap = malloc(sizeof(SimMap));
// simdata->tyrediameter[0] = -1;
// simdata->tyrediameter[1] = -1;
// simdata->tyrediameter[2] = -1;
// simdata->tyrediameter[3] = -1;
//
// struct termios newsettings, canonicalmode;
// tcgetattr(0, &canonicalmode);
// newsettings = canonicalmode;
// newsettings.c_lflag &= (~ICANON & ~ECHO);
// newsettings.c_cc[VMIN] = 1;
// newsettings.c_cc[VTIME] = 0;
// tcsetattr(0, TCSANOW, &newsettings);
// char ch;
// struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI };
//
// fprintf(stdout, "Searching for sim data... Press q to quit...\n");
// p->simon = false;
// double update_rate = SIM_CHECK_RATE;
// go = true;
// while (go == true)
// {
// p->simon = false;
// getSim(simdata, simmap, &p->simon, &p->sim);
//
// if (p->simon == true && simdata->simstatus > 1)
// {
// slogi("preparing game loop with %i devices...", numdevices);
//
//
// slogi("sending initial data to devices");
// simdata->velocity = 16;
// simdata->rpms = 100;
// for (int x = 0; x < numdevices; x++)
// {
// devices[x].update(&devices[x], simdata);
// }
// sleep(3);
//
// clilooper(devices, numdevices, p, simdata, simmap);
// }
// if (p->simon == true)
// {
// p->simon = false;
// fprintf(stdout, "Searching for sim data... Press q again to quit...\n");
// sleep(2);
// }
//
// if (poll(&mypoll, 1, 1000.0/update_rate) )
// {
// if (go != false )
// {
// scanf("%c", &ch);
// if(ch == 'q')
// {
// slogd("User application exit requested.");
// go = false;
// }
// }
// }
// }
//
// fprintf(stdout, "\n");
// fflush(stdout);
// tcsetattr(0, TCSANOW, &canonicalmode);
//
// int r = simfree(simdata, simmap, p->sim);
// slogd("simfree returned %i", r);
// free(simdata);
// free(simmap);
//
// return 0;
//}
int tester(SimDevice* devices, int numdevices)
{

View File

@ -3,3 +3,5 @@
int tester(SimDevice* devices, int numdevices);
int looper(SimDevice* devices, int numdevices, Parameters* p);
int monocoque_mainloop(MonocoqueSettings* ms);

View File

@ -0,0 +1,25 @@
#ifndef _LOOPDATA_H
#define _LOOPDATA_H
#include <uv.h>
#include "../helper/parameters.h"
#include "../helper/confighelper.h"
#include "../devices/simdevice.h"
#include "../simulatorapi/simapi/simapi/simdata.h"
#include "../simulatorapi/simapi/simapi/simmapper.h"
typedef struct loop_data
{
uv_work_t req;
Simulator sim;
bool simstate;
bool uion;
int numdevices;
MonocoqueSettings* ms;
SimData* simdata;
SimMap* simmap;
SimDevice* simdevices;
} loop_data;
#endif

View File

@ -176,6 +176,55 @@ int strtodev(const char* device_type, const char* device_subtype, DeviceSettings
return MONOCOQUE_ERROR_NONE;
}
int getconfigtouse(const char* config_file_str, char* car, int sim)
{
config_t cfg;
config_init(&cfg);
if (!config_read_file(&cfg, config_file_str))
{
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
return -1;
}
config_setting_t* config = NULL;
config_setting_t* config_widgets = NULL;
config = config_lookup(&cfg, "configs");
int configs = config_setting_length(config);
const char* temp;
config_setting_t* config_config = NULL;
int j = 0;
if ( configs == 1 )
{
return 0;
}
int confignum = 0;
for (j = 0; j < configs; j++)
{
config_config = config_setting_get_elem(config, j);
int found = 0;
int csim = 0;
config_setting_lookup_int(config_config, "sim", &csim);
if (csim != sim && csim != 0)
{
continue;
}
found = config_setting_lookup_string(config_config, "car", &temp);
if(strcicmp("default", car) == 0)
{
confignum = j;
}
if(strcicmp(temp, car) != 0)
{
continue;
}
confignum = j;
break;
}
return confignum;
}
int loadtachconfig(const char* config_file, DeviceSettings* ds)
{
@ -312,6 +361,28 @@ int loadconfig(const char* config_file, DeviceSettings* ds)
return 0;
}
int configcheck(const char* config_file_str, int confignum, int* devices)
{
slogt("ui config check");
config_t cfg;
config_init(&cfg);
if (!config_read_file(&cfg, config_file_str))
{
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
}
config_setting_t* config = NULL;
config = config_lookup(&cfg, "configs");
config_setting_t* selectedconfig = config_setting_get_elem(config, confignum);
slogt("selected num %i", confignum);
config_setting_t* config_devices = NULL;
config_devices = config_setting_lookup(selectedconfig, "devices");
*devices = config_setting_length(config_devices);
config_destroy(&cfg);
return 0;
//return cfg;
}
int devsetup(const char* device_type, const char* device_subtype, const char* config_file, MonocoqueSettings* ms, DeviceSettings* ds, config_setting_t* device_settings)
{
int error = MONOCOQUE_ERROR_NONE;
@ -442,6 +513,69 @@ int devsetup(const char* device_type, const char* device_subtype, const char* co
return error;
}
int uiloadconfig(const char* config_file_str, int confignum, int configureddevices, MonocoqueSettings* ms, DeviceSettings* ds)
{
int numdevices = 0;
config_t cfg;
config_init(&cfg);
if (!config_read_file(&cfg, config_file_str))
{
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
}
else
{
slogi("Parsing config file");
config_setting_t* config = NULL;
config = config_lookup(&cfg, "configs");
config_setting_t* selectedconfig = config_setting_get_elem(config, confignum);
config_setting_t* config_devices = NULL;
config_devices = config_setting_lookup(selectedconfig, "devices");
int i = 0;
int error = MONOCOQUE_ERROR_NONE;
while (i<configureddevices)
{
error = MONOCOQUE_ERROR_NONE;
DeviceSettings settings;
config_setting_t* config_device = config_setting_get_elem(config_devices, i);
const char* device_type;
const char* device_subtype;
const char* device_config_file;
config_setting_lookup_string(config_device, "device", &device_type);
config_setting_lookup_string(config_device, "type", &device_subtype);
config_setting_lookup_string(config_device, "config", &device_config_file);
//slogt("device type: %s", device_type);
//slogt("device sub type: %s", device_subtype);
//slogt("device config file: %s", device_config_file);
if (error == MONOCOQUE_ERROR_NONE)
{
error = devsetup(device_type, device_subtype, device_config_file, ms, &settings, config_device);
}
if (error == MONOCOQUE_ERROR_NONE)
{
numdevices++;
}
ds[i] = settings;
i++;
}
}
config_destroy(&cfg);
return numdevices;
}
int settingsfree(DeviceSettings ds)
{

View File

@ -117,6 +117,9 @@ typedef struct
int configcheck;
int useconfig;
char* tyre_diameter_config;
char* config_str;
char* log_filename_str;
char* log_dirname_str;
}
MonocoqueSettings;
@ -186,4 +189,10 @@ int settingsfree(DeviceSettings ds);
int strcicmp(char const *a, char const *b);
int getconfigtouse(const char* config_file_str, char* car, int sim);
int configcheck(const char* config_file_str, int confignum, int* devices);
int uiloadconfig(const char* config_file_str, int confignum, int configureddevices, MonocoqueSettings* ms, DeviceSettings* ds);
#endif

View File

@ -13,6 +13,36 @@
#include <string.h>
void create_dir(char* dir)
{
struct stat st = {0};
if (stat(dir, &st) == -1)
{
mkdir(dir, 0700);
}
}
void create_xdg_dir(const char* dir)
{
struct stat st = {0};
if (stat(dir, &st) == -1)
{
mkdir(dir, 0700);
}
}
char* create_user_dir(char* home_dir_str, const char* dirtype, const char* programname)
{
// +3 for slashes
size_t ss = (4 + strlen(home_dir_str) + strlen(dirtype) + strlen(programname));
char* config_dir_str = malloc(ss);
snprintf (config_dir_str, ss, "%s/%s/%s/", home_dir_str, dirtype, programname);
create_dir(config_dir_str);
return config_dir_str;
}
char* gethome()
{
char* homedir = getenv("HOME");
@ -175,28 +205,67 @@ void restrict_folders_to_cache(char* path, int cachesize)
}
bool does_directory_exist(char* path, char* dirname)
bool does_directory_exist(char* path)
{
struct dirent* de;
DIR* dr = opendir(path);
if (dr == NULL)
DIR* dir = opendir(path);
if (dir)
{
printf("Could not open current directory");
// Directory exists
closedir(dir);
return true;
}
else
{
// Directory does not exist or cannot be opened
return false;
}
// Refer http://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html
bool answer = false;
while ((de = readdir(dr)) != NULL)
{
if (strcmp(dirname,de->d_name) == 0)
{
answer = true;
}
}
closedir(dr);
return answer;
}
bool does_file_exist(const char* file)
{
if (file == NULL)
{
return false;
}
#if defined(OS_WIN)
#if defined(WIN_API)
// if you want the WinAPI, versus CRT
if (strnlen(file, MAX_PATH+1) > MAX_PATH)
{
// ... throw error here or ...
return false;
}
DWORD res = GetFileAttributesA(file);
return (res != INVALID_FILE_ATTRIBUTES &&
!(res& FILE_ATTRIBUTE_DIRECTORY));
#else
// Use Win CRT
struct stat fi;
if (_stat(file, &fi) == 0)
{
#if defined(S_ISSOCK)
// sockets come back as a 'file' on some systems
// so make sure it's not a socket or directory
// (in other words, make sure it's an actual file)
return !(S_ISDIR(fi.st_mode)) &&
!(S_ISSOCK(fi.st_mode));
#else
return !(S_ISDIR(fi.st_mode));
#endif
}
return false;
#endif
#else
struct stat fi;
if (stat(file, &fi) == 0)
{
#if defined(S_ISSOCK)
return !(S_ISDIR(fi.st_mode)) &&
!(S_ISSOCK(fi.st_mode));
#else
return !(S_ISDIR(fi.st_mode));
#endif
}
return false;
#endif
}

View File

@ -3,10 +3,14 @@
#include <stdbool.h>
void create_dir(char* dir);
void create_xdg_dir(const char* dir);
char* create_user_dir(char* home_dir_str, const char* dirtype, const char* programpath);
char* gethome();
char* str2md5(const char* str, int length);
bool does_directory_exist(char* path, char* dirname);
bool does_directory_exist(char* path);
void restrict_folders_to_cache(char* path, int cachesize);
void delete_dir(char* path);
bool does_file_exist(const char* file);
#endif

View File

@ -2,12 +2,39 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <libconfig.h>
#include <argtable2.h>
#include <regex.h>
int freeparams(Parameters* p)
{
if(p->config_dirpath != NULL)
{
free(p->config_dirpath);
}
if(p->config_filepath != NULL)
{
free(p->config_filepath);
}
if(p->log_filename_str != NULL)
{
free(p->log_filename_str);
}
if(p->log_fullfilename_str != NULL)
{
free(p->log_fullfilename_str);
}
if(p->log_dirname_str != NULL)
{
free(p->log_dirname_str);
}
return 0;
}
ConfigError getParameters(int argc, char** argv, Parameters* p)
{
@ -18,6 +45,10 @@ ConfigError getParameters(int argc, char** argv, Parameters* p)
p->max_revs = 0;
p->verbosity_count = 0;
p->user_specified_config_file = false;
p->user_specified_log_file = false;
p->user_specified_config_dir = false;
// setup argument handling structures
const char* progname = "monocoque";
@ -26,11 +57,13 @@ ConfigError getParameters(int argc, char** argv, Parameters* p)
struct arg_lit* arg_verbosity3 = arg_litn("v","verbose", 0, 2, "increase logging verbosity");
struct arg_rex* cmd1 = arg_rex1(NULL, NULL, "play", NULL, REG_ICASE, NULL);
struct arg_str* arg_sim = arg_strn("s", "sim", "<gamename>", 0, 1, NULL);
struct arg_file* arg_conf = arg_filen(NULL, "uiconf", "<config_file>", 0, 1, NULL);
struct arg_file* arg_log = arg_filen("l", "log", "<log_file>", 0, 1, NULL);
struct arg_str* arg_confdir = arg_strn(NULL, "configdir", "config_dir>", 0, 1, NULL);
struct arg_lit* help = arg_litn(NULL,"help", 0, 1, "print this help and exit");
struct arg_lit* vers = arg_litn(NULL,"version", 0, 1, "print version information and exit");
struct arg_end* end1 = arg_end(20);
void* argtable1[] = {cmd1,arg_sim,arg_verbosity1,help,vers,end1};
void* argtable1[] = {cmd1,arg_log,arg_conf,arg_verbosity1,help,vers,end1};
int nerrors1;
struct arg_rex* cmd2a = arg_rex1(NULL, NULL, "config", NULL, REG_ICASE, NULL);
@ -83,8 +116,24 @@ ConfigError getParameters(int argc, char** argv, Parameters* p)
if (nerrors1==0)
{
p->program_action = A_PLAY;
p->sim_string = arg_sim->sval[0];
p->verbosity_count = arg_verbosity1->count;
if(arg_conf->count > 0)
{
p->config_filepath = strdup(arg_conf->filename[0]);
p->user_specified_config_file = true;
}
if(arg_log->count > 0)
{
char* filename = strdup(arg_log->filename[0]);
p->log_fullfilename_str = strdup(arg_log->filename[0]);
p->log_filename_str = strdup(arg_log->basename[0]);
char* dname;
dname = dirname(filename);
p->log_dirname_str = strdup(dname);
p->user_specified_log_file = true;
free(filename);
}
exitcode = E_SUCCESS_AND_DO;
}
else

View File

@ -15,6 +15,16 @@ typedef struct
Simulator sim;
bool simon;
char* config_filepath;
char* config_dirpath;
bool user_specified_config_file;
bool user_specified_config_dir;
bool user_specified_log_file;
char* log_filename_str;
char* log_fullfilename_str;
char* log_dirname_str;
}
Parameters;
@ -35,6 +45,7 @@ typedef enum
}
ConfigError;
int freeparams(Parameters* p);
ConfigError getParameters(int argc, char** argv, Parameters* p);
struct _errordesc

View File

@ -2,8 +2,9 @@
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <basedir_fs.h>
#include <libconfig.h>
#include "gameloop/gameloop.h"
#include "gameloop/tachconfig.h"
#include "devices/simdevice.h"
@ -14,27 +15,7 @@
#include "simulatorapi/simapi/simapi/simdata.h"
#include "slog/slog.h"
int create_dir(char* dir)
{
struct stat st = {0};
if (stat(dir, &st) == -1)
{
mkdir(dir, 0700);
}
}
char* create_user_dir(char* dirtype)
{
char* home_dir_str = gethome();
char* config_dir_str = ( char* ) malloc(1 + strlen(home_dir_str) + strlen(dirtype) + strlen("monocoque/"));
strcpy(config_dir_str, home_dir_str);
strcat(config_dir_str, dirtype);
strcat(config_dir_str, "monocoque");
create_dir(config_dir_str);
free(config_dir_str);
}
#define PROGRAM_NAME "monocoque"
void display_banner()
{
@ -45,10 +26,57 @@ void display_banner()
printf("/_/ /_/ \\____/ /_/ |_/ \\____/ \\____/ \\____/ \\___\\_\\\\____/ /_____/ \n");
}
void SetSettingsFromParameters(Parameters* p, MonocoqueSettings* ms, char* configdir_str, char* cachedir_str)
{
if(p->user_specified_config_file == true && does_file_exist(p->config_filepath))
{
ms->config_str = strdup(p->config_filepath);
}
else
{
if(p->user_specified_config_dir == true && does_directory_exist(p->config_dirpath))
{
asprintf(&ms->config_str, "%s/%s", p->config_dirpath, "monocoque.config");
}
else
{
asprintf(&ms->config_str, "%s%s", configdir_str, "monocoque.config");
}
}
if(p->user_specified_log_file == true && does_file_exist(p->log_fullfilename_str))
{
ms->log_dirname_str = strdup(p->log_dirname_str);
ms->log_filename_str = strdup(p->log_filename_str);
}
else
{
ms->log_dirname_str = strdup(cachedir_str);
ms->log_filename_str = strdup("monocoque.log");
}
ms->program_action = A_TEST;
if (p->program_action == A_PLAY)
{
ms->program_action = A_PLAY;
}
if (p->program_action == A_CONFIG_TACH)
{
ms->program_action = A_CONFIG_TACH;
}
}
int main(int argc, char** argv)
{
display_banner();
char* home_dir_str = gethome();
if(home_dir_str == NULL)
{
fprintf(stderr, "You need a home directory");
return 0;
}
Parameters* p = malloc(sizeof(Parameters));
MonocoqueSettings* ms = malloc(sizeof(MonocoqueSettings));;
@ -57,33 +85,47 @@ int main(int argc, char** argv)
{
goto cleanup_final;
}
ms->program_action = p->program_action;
char* home_dir_str = gethome();
create_user_dir("/.config/");
create_user_dir("/.cache/");
char* config_file_str = ( char* ) malloc(1 + strlen(home_dir_str) + strlen("/.config/") + strlen("monocoque/monocoque.config"));
xdgHandle xdg;
if(!xdgInitHandle(&xdg))
{
fprintf(stderr, "Function xdgInitHandle() failed, is $HOME unset?");
}
const char* config_home_str = xdgConfigHome(&xdg);
const char* cache_home_str = xdgCacheHome(&xdg);
char* cachedir_str = NULL;
char* configdir_str = NULL;
if(p->user_specified_config_file == false && p->user_specified_config_dir == false)
{
create_xdg_dir(config_home_str);
configdir_str = create_user_dir(home_dir_str, ".config", PROGRAM_NAME);
}
if(p->user_specified_log_file == false)
{
create_xdg_dir(cache_home_str);
cachedir_str = create_user_dir(home_dir_str, ".cache", PROGRAM_NAME);
}
SetSettingsFromParameters(p, ms, configdir_str, cachedir_str);
freeparams(p);
free(p);
//char* config_file_str = ( char* ) malloc(1 + strlen(home_dir_str) + strlen("/.config/") + strlen("monocoque/monocoque.config"));
size_t diameters_file_sz = snprintf(NULL, 0, "%s/.config/monocoque/diameters.config", home_dir_str);
diameters_file_sz += 1;
char* diameters_file_str = ( char* ) malloc(diameters_file_sz);
snprintf(diameters_file_str, diameters_file_sz, "%s/.config/monocoque/diameters.config", home_dir_str);
char* cache_dir_str = ( char* ) malloc(1 + strlen(home_dir_str) + strlen("/.cache/monocoque/"));
strcpy(config_file_str, home_dir_str);
strcat(config_file_str, "/.config/");
strcpy(cache_dir_str, home_dir_str);
strcat(cache_dir_str, "/.cache/monocoque/");
strcat(config_file_str, "monocoque/monocoque.config");
slog_config_t slgCfg;
slog_config_get(&slgCfg);
slgCfg.eColorFormat = SLOG_COLORING_TAG;
slgCfg.eDateControl = SLOG_TIME_ONLY;
strcpy(slgCfg.sFileName, "monocoque.log");
strcpy(slgCfg.sFilePath, cache_dir_str);
strcpy(slgCfg.sFileName, ms->log_filename_str);
strcpy(slgCfg.sFilePath, ms->log_dirname_str);
slgCfg.nTraceTid = 0;
slgCfg.nToScreen = 1;
slgCfg.nUseHeap = 0;
@ -105,24 +147,22 @@ int main(int argc, char** argv)
ms->configcheck = 0;
free(diameters_file_str);
slogi("Loading configuration file: %s", config_file_str);
slogi("Loading configuration file: %s", ms->config_str);
slogd("using diameters file %s %i", ms->tyre_diameter_config, ms->configcheck);
config_t cfg;
config_init(&cfg);
config_setting_t* config_devices = NULL;
if (!config_read_file(&cfg, config_file_str))
if (!config_read_file(&cfg, ms->config_str))
{
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
goto cleanup_final;
}
else
{
slogi("Openend monocoque configuration file");
config_devices = config_lookup(&cfg, "devices");
}
free(config_file_str);
free(cache_dir_str);
if (p->program_action == A_CONFIG_TACH)
if (ms->program_action == A_CONFIG_TACH)
{
int error = 0;
SimDevice* tachdev = malloc(sizeof(SimDevice));
@ -169,70 +209,25 @@ int main(int argc, char** argv)
{
int error = 0;
int configureddevices = config_setting_length(config_devices);
int numdevices = 0;
DeviceSettings ds[configureddevices];
slogi("found %i devices in configuration", configureddevices);
int i = 0;
error = MONOCOQUE_ERROR_NONE;
while (i<configureddevices)
{
DeviceSettings settings;
config_setting_t* config_device = config_setting_get_elem(config_devices, i);
const char* device_type;
const char* device_subtype;
const char* device_config_file;
config_setting_lookup_string(config_device, "device", &device_type);
config_setting_lookup_string(config_device, "type", &device_subtype);
config_setting_lookup_string(config_device, "config", &device_config_file);
//slogt("device type: %s", device_type);
//slogt("device sub type: %s", device_subtype);
//slogt("device config file: %s", device_config_file);
if (error == MONOCOQUE_ERROR_NONE)
{
error = devsetup(device_type, device_subtype, device_config_file, ms, &settings, config_device);
}
if (error == MONOCOQUE_ERROR_NONE)
{
numdevices++;
}
ds[i] = settings;
i++;
}
i = 0;
int j = 0;
error = MONOCOQUE_ERROR_NONE;
setupsound();
if (p->program_action == A_PLAY)
if (ms->program_action == A_PLAY)
{
ms->useconfig = 1;
}
SimDevice* devices = malloc(numdevices * sizeof(SimDevice));
int initdevices = devinit(devices, configureddevices, ds, ms);
bool pulseaudio = false;
if (p->program_action == A_PLAY)
bool pulseaudio = false;
if (ms->program_action == A_PLAY)
{
slogi("running monocoque in gameloop mode..");
//error = strtogame(p->sim_string, ms);
//if (error != MONOCOQUE_ERROR_NONE)
//{
// goto cleanup_final;
//}
#ifdef USE_PULSEAUDIO
pa_threaded_mainloop_unlock(mainloop);
pulseaudio = true;
#endif
error = looper(devices, numdevices, p);
//error = looper(devices, numdevices, p);
error = monocoque_mainloop(ms);
if (error == MONOCOQUE_ERROR_NONE)
{
slogi("Game loop exited succesfully with error code: %i", error);
@ -252,7 +247,23 @@ int main(int argc, char** argv)
#endif
ms->useconfig = 0;
error = tester(devices, numdevices);
int confignum = getconfigtouse(ms->config_str, "default", 0);
int configureddevices;
configcheck(ms->config_str, confignum, &configureddevices);
DeviceSettings* ds = malloc(configureddevices * sizeof(DeviceSettings));
slogd("loading confignum %i, with %i devices.", confignum, configureddevices);
int numdevices = uiloadconfig(ms->config_str, confignum, configureddevices, ms, ds);
SimDevice* simdevices = malloc(numdevices * sizeof(SimDevice));
int initdevices = devinit(simdevices, configureddevices, ds, ms);
for( int i = 0; i < configureddevices; i++)
{
settingsfree(ds[i]);
}
free(ds);
error = tester(simdevices, numdevices);
if (error == MONOCOQUE_ERROR_NONE)
{
slogi("Test exited succesfully with error code: %i", error);
@ -261,35 +272,22 @@ int main(int argc, char** argv)
{
sloge("Test exited with error code: %i", error);
}
}
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
for (int x = 0; x < numdevices; x++)
{
devices[x].free(&devices[x]);
if (simdevices[x].initialized == true)
{
simdevices[x].free(&simdevices[x]);
}
}
}
if(pulseaudio == true)
{
freesound();
}
i = 0;
// improve the api around the config helper
// i don't like that i stack allocated but hid a malloc inside
for( i = 0; i < configureddevices; i++)
{
settingsfree(ds[i]);
}
}
configcleanup:
config_destroy(&cfg);
cleanup_final:
if(ms->tyre_diameter_config != NULL)
@ -297,7 +295,6 @@ cleanup_final:
free(ms->tyre_diameter_config);
}
free(ms);
free(p);
exit(0);
}