mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-07 20:23:24 +00:00
Add settings section to XML file format and store dive computer IDs
We only store the model/deviceid/nickname for those dive computers that are mentioned in the XML file. This should make the XML files nicely selfcontained. This also changes the code to consistently use model & deviceid to identify a dive computer. The deviceid is NOT guaranteed to be collision free between different libdivecomputer backends... Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
1bd6f72d31
commit
e726c9d65c
5 changed files with 139 additions and 39 deletions
5
dive.h
5
dive.h
|
@ -528,8 +528,9 @@ extern void dive_list_update_dives(void);
|
||||||
extern void flush_divelist(struct dive *dive);
|
extern void flush_divelist(struct dive *dive);
|
||||||
|
|
||||||
extern void set_dc_nickname(struct dive *dive);
|
extern void set_dc_nickname(struct dive *dive);
|
||||||
extern const char *get_dc_nickname(uint32_t deviceid);
|
extern const char *get_dc_nickname(const char *model, uint32_t deviceid);
|
||||||
extern void remember_dc(uint32_t deviceid, const char *model, const char *nickname, gboolean change_conf);
|
extern void remember_dc(const char *model, uint32_t deviceid, const char *nickname, gboolean change_conf);
|
||||||
|
extern void add_dc_to_string(char **dc_xml, struct divecomputer *dc);
|
||||||
|
|
||||||
#define DIVE_ERROR_PARSE 1
|
#define DIVE_ERROR_PARSE 1
|
||||||
|
|
||||||
|
|
103
gtk-gui.c
103
gtk-gui.c
|
@ -1245,7 +1245,7 @@ void init_ui(int *argcp, char ***argvp)
|
||||||
*nameend = '\0';
|
*nameend = '\0';
|
||||||
nickname = strdup(namestart);
|
nickname = strdup(namestart);
|
||||||
}
|
}
|
||||||
remember_dc(deviceid, model, nickname, FALSE);
|
remember_dc(model, deviceid, nickname, FALSE);
|
||||||
next_token = nameend + 1;
|
next_token = nameend + 1;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2047,27 +2047,40 @@ void set_filename(const char *filename, gboolean force)
|
||||||
existing_filename = NULL;
|
existing_filename = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *get_dc_nickname(uint32_t deviceid)
|
/* just find the entry for this divecomputer */
|
||||||
|
static struct dcnicknamelist *get_dc_nicknameentry(const char *model, int deviceid)
|
||||||
{
|
{
|
||||||
struct dcnicknamelist *known = nicknamelist;
|
struct dcnicknamelist *known = nicknamelist;
|
||||||
|
if (!model)
|
||||||
|
model = "";
|
||||||
while (known) {
|
while (known) {
|
||||||
if (known->deviceid == deviceid) {
|
if (!strcmp(known->model, model) && known->deviceid == deviceid)
|
||||||
if (known->nickname && *known->nickname)
|
return known;
|
||||||
return known->nickname;
|
|
||||||
else
|
|
||||||
return known->model;
|
|
||||||
}
|
|
||||||
known = known->next;
|
known = known->next;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *get_dc_nickname(const char *model, uint32_t deviceid)
|
||||||
|
{
|
||||||
|
struct dcnicknamelist *known = get_dc_nicknameentry(model, deviceid);
|
||||||
|
if (known) {
|
||||||
|
if (known->nickname && *known->nickname)
|
||||||
|
return known->nickname;
|
||||||
|
else
|
||||||
|
return known->model;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* do we have a DIFFERENT divecomputer of the same model? */
|
/* do we have a DIFFERENT divecomputer of the same model? */
|
||||||
static struct dcnicknamelist *get_different_dc_nicknameentry(const char *model, int deviceid)
|
static struct dcnicknamelist *get_different_dc_nicknameentry(const char *model, int deviceid)
|
||||||
{
|
{
|
||||||
struct dcnicknamelist *known = nicknamelist;
|
struct dcnicknamelist *known = nicknamelist;
|
||||||
|
if (!model)
|
||||||
|
model = "";
|
||||||
while (known) {
|
while (known) {
|
||||||
if (known->model && model && !strcmp(known->model, model) &&
|
if (known->model && !strcmp(known->model, model) &&
|
||||||
known->deviceid != deviceid)
|
known->deviceid != deviceid)
|
||||||
return known;
|
return known;
|
||||||
known = known->next;
|
known = known->next;
|
||||||
|
@ -2075,18 +2088,6 @@ static struct dcnicknamelist *get_different_dc_nicknameentry(const char *model,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* just fine the entry for this divecomputer */
|
|
||||||
static struct dcnicknamelist *get_dc_nicknameentry(int deviceid)
|
|
||||||
{
|
|
||||||
struct dcnicknamelist *known = nicknamelist;
|
|
||||||
while (known) {
|
|
||||||
if (known->deviceid == deviceid)
|
|
||||||
return known;
|
|
||||||
known = known->next;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no curly braces or commas, please */
|
/* no curly braces or commas, please */
|
||||||
static char *cleanedup_nickname(const char *nickname, int len)
|
static char *cleanedup_nickname(const char *nickname, int len)
|
||||||
{
|
{
|
||||||
|
@ -2114,16 +2115,18 @@ static char *cleanedup_nickname(const char *nickname, int len)
|
||||||
return clean;
|
return clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
void replace_nickname_nicknamestring(int deviceid, const char *nickname)
|
void replace_nickname_nicknamestring(const char *model, int deviceid, const char *nickname)
|
||||||
{
|
{
|
||||||
char buf[11];
|
char buf[11];
|
||||||
char *entry, *comma1, *comma2, *brace, *new_nn;
|
char *entry, *comma1, *comma2, *brace, *new_nn;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
if (!nickname)
|
||||||
|
nickname = "";
|
||||||
snprintf(buf, sizeof(buf), "{%08x,", deviceid);
|
snprintf(buf, sizeof(buf), "{%08x,", deviceid);
|
||||||
entry = strstr(nicknamestring, buf);
|
entry = strstr(nicknamestring, buf);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
/* this cannot happen as we know have an entry for this deviceid */
|
/* this cannot happen as we know we have an entry for this deviceid */
|
||||||
goto bail;
|
goto bail;
|
||||||
len = strlen(entry);
|
len = strlen(entry);
|
||||||
comma1 = g_utf8_strchr(entry, len, ',');
|
comma1 = g_utf8_strchr(entry, len, ',');
|
||||||
|
@ -2145,9 +2148,9 @@ void replace_nickname_nicknamestring(int deviceid, const char *nickname)
|
||||||
}
|
}
|
||||||
new_nn = malloc(len);
|
new_nn = malloc(len);
|
||||||
if (strlen(nickname))
|
if (strlen(nickname))
|
||||||
snprintf(new_nn, len, "%s,%s}%s", entry, nickname, brace + 1);
|
snprintf(new_nn, len, "%s,%s}%s", nicknamestring, nickname, brace + 1);
|
||||||
else
|
else
|
||||||
snprintf(new_nn, len, "%s}%s", entry, brace + 1);
|
snprintf(new_nn, len, "%s}%s", nicknamestring, brace + 1);
|
||||||
free(nicknamestring);
|
free(nicknamestring);
|
||||||
nicknamestring = new_nn;
|
nicknamestring = new_nn;
|
||||||
return;
|
return;
|
||||||
|
@ -2158,9 +2161,11 @@ bail:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void remember_dc(uint32_t deviceid, const char *model, const char *nickname, gboolean change_conf)
|
void remember_dc(const char *model, uint32_t deviceid, const char *nickname, gboolean change_conf)
|
||||||
{
|
{
|
||||||
if (!get_dc_nickname(deviceid)) {
|
if (!nickname)
|
||||||
|
nickname = "";
|
||||||
|
if (!get_dc_nickname(model, deviceid)) {
|
||||||
char buffer[160];
|
char buffer[160];
|
||||||
struct dcnicknamelist *nn_entry = malloc(sizeof(struct dcnicknamelist));
|
struct dcnicknamelist *nn_entry = malloc(sizeof(struct dcnicknamelist));
|
||||||
nn_entry->deviceid = deviceid;
|
nn_entry->deviceid = deviceid;
|
||||||
|
@ -2180,11 +2185,11 @@ void remember_dc(uint32_t deviceid, const char *model, const char *nickname, gbo
|
||||||
subsurface_set_conf("dc_nicknames", PREF_STRING, nicknamestring);
|
subsurface_set_conf("dc_nicknames", PREF_STRING, nicknamestring);
|
||||||
} else {
|
} else {
|
||||||
/* modify existing entry */
|
/* modify existing entry */
|
||||||
struct dcnicknamelist *nn_entry = get_dc_nicknameentry(deviceid);
|
struct dcnicknamelist *nn_entry = get_dc_nicknameentry(model, deviceid);
|
||||||
if (!nn_entry->model || !*nn_entry->model)
|
if (!nn_entry->model || !*nn_entry->model)
|
||||||
nn_entry->model = model;
|
nn_entry->model = model;
|
||||||
nn_entry->nickname = nickname;
|
nn_entry->nickname = nickname;
|
||||||
replace_nickname_nicknamestring(deviceid, nickname);
|
replace_nickname_nicknamestring(model, deviceid, nickname);
|
||||||
}
|
}
|
||||||
#if defined(NICKNAME_DEBUG)
|
#if defined(NICKNAME_DEBUG)
|
||||||
struct dcnicknamelist *nn_entry = nicknamelist;
|
struct dcnicknamelist *nn_entry = nicknamelist;
|
||||||
|
@ -2212,12 +2217,12 @@ void set_dc_nickname(struct dive *dive)
|
||||||
#if NICKNAME_DEBUG & 16
|
#if NICKNAME_DEBUG & 16
|
||||||
fprintf(debugfile, "set_dc_nickname for model %s deviceid %8x\n", dc->model ? : "", dc->deviceid);
|
fprintf(debugfile, "set_dc_nickname for model %s deviceid %8x\n", dc->model ? : "", dc->deviceid);
|
||||||
#endif
|
#endif
|
||||||
if (get_dc_nickname(dc->deviceid) == NULL) {
|
if (get_dc_nickname(dc->model, dc->deviceid) == NULL) {
|
||||||
struct dcnicknamelist *nn_entry = get_different_dc_nicknameentry(dc->model, dc->deviceid);
|
struct dcnicknamelist *nn_entry = get_different_dc_nicknameentry(dc->model, dc->deviceid);
|
||||||
if (!nn_entry) {
|
if (!nn_entry) {
|
||||||
/* just remember the dive computer without setting a nickname */
|
/* just remember the dive computer without setting a nickname */
|
||||||
if (dc->model)
|
if (dc->model)
|
||||||
remember_dc(dc->deviceid, dc->model, "", TRUE);
|
remember_dc(dc->model, dc->deviceid, "", TRUE);
|
||||||
} else {
|
} else {
|
||||||
dialog = gtk_dialog_new_with_buttons(
|
dialog = gtk_dialog_new_with_buttons(
|
||||||
_("Dive Computer Nickname"),
|
_("Dive Computer Nickname"),
|
||||||
|
@ -2255,9 +2260,43 @@ void set_dc_nickname(struct dive *dive)
|
||||||
name = cleanedup_nickname(gtk_entry_get_text(GTK_ENTRY(entry)), sizeof(nickname));
|
name = cleanedup_nickname(gtk_entry_get_text(GTK_ENTRY(entry)), sizeof(nickname));
|
||||||
}
|
}
|
||||||
gtk_widget_destroy(dialog);
|
gtk_widget_destroy(dialog);
|
||||||
remember_dc(dc->deviceid, dc->model, name, TRUE);
|
remember_dc(dc->model, dc->deviceid, name, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dc = dc->next;
|
dc = dc->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_dc_to_string(char **dc_xml, struct divecomputer *dc)
|
||||||
|
{
|
||||||
|
char *pattern, *tmp;
|
||||||
|
const char *nickname;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (!dc || !dc->model || !*dc->model)
|
||||||
|
/* we have no dc or no model information... nothing to do here */
|
||||||
|
return;
|
||||||
|
len = sizeof(" model='' deviceid=''") + strlen(dc->model) + 8;
|
||||||
|
pattern = malloc(len);
|
||||||
|
snprintf(pattern, len, " model='%s' deviceid='%08x'", dc->model, dc->deviceid);
|
||||||
|
if (*dc_xml && strstr(*dc_xml, pattern)) {
|
||||||
|
/* already have that one */
|
||||||
|
free(pattern);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nickname = get_dc_nickname(dc->model, dc->deviceid);
|
||||||
|
if (!nickname || !*nickname || !strcmp(dc->model, nickname)) {
|
||||||
|
/* we still want to store this entry as it explicitly tells us
|
||||||
|
* "no nickname needed, use model" */
|
||||||
|
len += strlen(*dc_xml) + sizeof("<divecomputerid/>\n");
|
||||||
|
tmp = malloc(len);
|
||||||
|
snprintf(tmp, len, "%s<divecomputerid%s/>\n", *dc_xml, pattern);
|
||||||
|
} else {
|
||||||
|
len += strlen(*dc_xml) + strlen(nickname) + sizeof("<divecomputerid nickname=''/>\n");
|
||||||
|
tmp = malloc(len);
|
||||||
|
snprintf(tmp, len, "%s<divecomputerid%s nickname='%s'/>\n", *dc_xml, pattern, nickname);
|
||||||
|
}
|
||||||
|
free(pattern);
|
||||||
|
free(*dc_xml);
|
||||||
|
*dc_xml = tmp;
|
||||||
|
}
|
||||||
|
|
51
parse-xml.c
51
parse-xml.c
|
@ -145,6 +145,14 @@ static struct {
|
||||||
int type, flags, value;
|
int type, flags, value;
|
||||||
const char *name;
|
const char *name;
|
||||||
} cur_event;
|
} cur_event;
|
||||||
|
static struct {
|
||||||
|
struct {
|
||||||
|
const char *model;
|
||||||
|
uint32_t deviceid;
|
||||||
|
const char *nickname;
|
||||||
|
} dc;
|
||||||
|
} cur_settings;
|
||||||
|
static gboolean in_settings = FALSE;
|
||||||
static struct tm cur_tm;
|
static struct tm cur_tm;
|
||||||
static int cur_cylinder_index, cur_ws_index;
|
static int cur_cylinder_index, cur_ws_index;
|
||||||
static int lastndl, laststoptime, laststopdepth, lastcns, lastpo2;
|
static int lastndl, laststoptime, laststopdepth, lastcns, lastpo2;
|
||||||
|
@ -592,6 +600,21 @@ static void eventtime(char *buffer, void *_duration)
|
||||||
duration->seconds += cur_sample->time.seconds;
|
duration->seconds += cur_sample->time.seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void try_to_fill_dc_settings(const char *name, char *buf)
|
||||||
|
{
|
||||||
|
int len = strlen(name);
|
||||||
|
|
||||||
|
start_match("divecomputerid", name, buf);
|
||||||
|
if (MATCH(".model", utf8_string, &cur_settings.dc.model))
|
||||||
|
return;
|
||||||
|
if (MATCH(".deviceid", hex_value, &cur_settings.dc.deviceid))
|
||||||
|
return;
|
||||||
|
if (MATCH(".nickname", utf8_string, &cur_settings.dc.nickname))
|
||||||
|
return;
|
||||||
|
|
||||||
|
nonmatch("divecomputerid", name, buf);
|
||||||
|
}
|
||||||
|
|
||||||
static void try_to_fill_event(const char *name, char *buf)
|
static void try_to_fill_event(const char *name, char *buf)
|
||||||
{
|
{
|
||||||
int len = strlen(name);
|
int len = strlen(name);
|
||||||
|
@ -988,6 +1011,29 @@ static void reset_dc_info(struct divecomputer *dc)
|
||||||
lastcns = lastpo2 = lastndl = laststoptime = laststopdepth = 0;
|
lastcns = lastpo2 = lastndl = laststoptime = laststopdepth = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reset_dc_settings(void)
|
||||||
|
{
|
||||||
|
free((void *)cur_settings.dc.model);
|
||||||
|
free((void *)cur_settings.dc.nickname);
|
||||||
|
cur_settings.dc.model = NULL;
|
||||||
|
cur_settings.dc.nickname = NULL;
|
||||||
|
cur_settings.dc.deviceid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dc_settings_start(void)
|
||||||
|
{
|
||||||
|
in_settings = TRUE;
|
||||||
|
reset_dc_settings();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dc_settings_end(void)
|
||||||
|
{
|
||||||
|
in_settings = FALSE;
|
||||||
|
if (cur_settings.dc.model)
|
||||||
|
remember_dc(cur_settings.dc.model, cur_settings.dc.deviceid, cur_settings.dc.nickname, TRUE);
|
||||||
|
reset_dc_settings();
|
||||||
|
}
|
||||||
|
|
||||||
static void dive_start(void)
|
static void dive_start(void)
|
||||||
{
|
{
|
||||||
if (cur_dive)
|
if (cur_dive)
|
||||||
|
@ -1137,6 +1183,10 @@ static void entry(const char *name, int size, const char *raw)
|
||||||
return;
|
return;
|
||||||
memcpy(buf, raw, size);
|
memcpy(buf, raw, size);
|
||||||
buf[size] = 0;
|
buf[size] = 0;
|
||||||
|
if (in_settings) {
|
||||||
|
try_to_fill_dc_settings(name, buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (cur_event.active) {
|
if (cur_event.active) {
|
||||||
try_to_fill_event(name, buf);
|
try_to_fill_event(name, buf);
|
||||||
return;
|
return;
|
||||||
|
@ -1271,6 +1321,7 @@ static struct nesting {
|
||||||
const char *name;
|
const char *name;
|
||||||
void (*start)(void), (*end)(void);
|
void (*start)(void), (*end)(void);
|
||||||
} nesting[] = {
|
} nesting[] = {
|
||||||
|
{ "divecomputerid", dc_settings_start, dc_settings_end },
|
||||||
{ "dive", dive_start, dive_end },
|
{ "dive", dive_start, dive_end },
|
||||||
{ "Dive", dive_start, dive_end },
|
{ "Dive", dive_start, dive_end },
|
||||||
{ "trip", trip_start, trip_end },
|
{ "trip", trip_start, trip_end },
|
||||||
|
|
|
@ -1879,7 +1879,7 @@ void plot(struct graphics_context *gc, struct dive *dive, scale_mode_t scale)
|
||||||
cairo_stroke(gc->cr);
|
cairo_stroke(gc->cr);
|
||||||
|
|
||||||
/* Put the dive computer name in the lower left corner */
|
/* Put the dive computer name in the lower left corner */
|
||||||
nickname = get_dc_nickname(dc->deviceid);
|
nickname = get_dc_nickname(dc->model, dc->deviceid);
|
||||||
if (!nickname || *nickname == '\0')
|
if (!nickname || *nickname == '\0')
|
||||||
nickname = dc->model;
|
nickname = dc->model;
|
||||||
if (nickname) {
|
if (nickname) {
|
||||||
|
|
17
save-xml.c
17
save-xml.c
|
@ -443,13 +443,14 @@ static void save_dive(FILE *f, struct dive *dive)
|
||||||
fprintf(f, "</dive>\n");
|
fprintf(f, "</dive>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VERSION 1
|
#define VERSION 2
|
||||||
|
|
||||||
void save_dives(const char *filename)
|
void save_dives(const char *filename)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct dive *dive;
|
struct dive *dive;
|
||||||
dive_trip_t *trip = NULL;
|
dive_trip_t *trip = NULL;
|
||||||
|
char *dc_xml = strdup("");
|
||||||
|
|
||||||
FILE *f = g_fopen(filename, "w");
|
FILE *f = g_fopen(filename, "w");
|
||||||
|
|
||||||
|
@ -459,8 +460,16 @@ void save_dives(const char *filename)
|
||||||
/* Flush any edits of current dives back to the dives! */
|
/* Flush any edits of current dives back to the dives! */
|
||||||
update_dive(current_dive);
|
update_dive(current_dive);
|
||||||
|
|
||||||
fprintf(f, "<dives>\n<program name='subsurface' version='%d'></program>\n", VERSION);
|
fprintf(f, "<divelog program='subsurface' version='%d'>\n<settings>\n", VERSION);
|
||||||
|
for_each_dive(i, dive) {
|
||||||
|
struct divecomputer *dc = &dive->dc;
|
||||||
|
while (dc) {
|
||||||
|
add_dc_to_string(&dc_xml, dc);
|
||||||
|
dc = dc->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(f, dc_xml);
|
||||||
|
fprintf(f, "</settings>\n<dives>\n");
|
||||||
/* save the dives */
|
/* save the dives */
|
||||||
for_each_dive(i, dive) {
|
for_each_dive(i, dive) {
|
||||||
dive_trip_t *thistrip = dive->divetrip;
|
dive_trip_t *thistrip = dive->divetrip;
|
||||||
|
@ -477,6 +486,6 @@ void save_dives(const char *filename)
|
||||||
}
|
}
|
||||||
if (trip)
|
if (trip)
|
||||||
fprintf(f, "</trip>\n");
|
fprintf(f, "</trip>\n");
|
||||||
fprintf(f, "</dives>\n");
|
fprintf(f, "</dives>\n</divelog>\n");
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue