Move events and samples into a 'struct divecomputer'

For now we only have one fixed divecomputer associated with each dive,
so this doesn't really change any current semantics.  But it will make
it easier for us to associate a dive with multiple dive computers.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Linus Torvalds 2012-11-23 16:51:27 -10:00 committed by Dirk Hohndel
parent a9786564c2
commit 25b4fee655
9 changed files with 144 additions and 144 deletions

103
dive.c
View file

@ -6,7 +6,7 @@
#include "dive.h" #include "dive.h"
void add_event(struct dive *dive, int time, int type, int flags, int value, const char *name) void add_event(struct divecomputer *dc, int time, int type, int flags, int value, const char *name)
{ {
struct event *ev, **p; struct event *ev, **p;
unsigned int size, len = strlen(name); unsigned int size, len = strlen(name);
@ -23,7 +23,7 @@ void add_event(struct dive *dive, int time, int type, int flags, int value, cons
ev->value = value; ev->value = value;
ev->next = NULL; ev->next = NULL;
p = &dive->events; p = &dc->events;
while (*p) while (*p)
p = &(*p)->next; p = &(*p)->next;
*p = ev; *p = ev;
@ -154,32 +154,32 @@ struct dive *alloc_dive(void)
return dive; return dive;
} }
struct sample *prepare_sample(struct dive *dive) struct sample *prepare_sample(struct divecomputer *dc)
{ {
if (dive) { if (dc) {
int nr = dive->samples; int nr = dc->samples;
int alloc_samples = dive->alloc_samples; int alloc_samples = dc->alloc_samples;
struct sample *sample; struct sample *sample;
if (nr >= alloc_samples) { if (nr >= alloc_samples) {
struct sample *newsamples; struct sample *newsamples;
alloc_samples = (alloc_samples * 3)/2 + 10; alloc_samples = (alloc_samples * 3)/2 + 10;
newsamples = realloc(dive->sample, alloc_samples * sizeof(struct sample)); newsamples = realloc(dc->sample, alloc_samples * sizeof(struct sample));
if (!newsamples) if (!newsamples)
return NULL; return NULL;
dive->alloc_samples = alloc_samples; dc->alloc_samples = alloc_samples;
dive->sample = newsamples; dc->sample = newsamples;
} }
sample = dive->sample + nr; sample = dc->sample + nr;
memset(sample, 0, sizeof(*sample)); memset(sample, 0, sizeof(*sample));
return sample; return sample;
} }
return NULL; return NULL;
} }
void finish_sample(struct dive *dive) void finish_sample(struct divecomputer *dc)
{ {
dive->samples++; dc->samples++;
} }
/* /*
@ -380,9 +380,9 @@ static gboolean is_potentially_redundant(struct event *event)
} }
/* match just by name - we compare the details in the code that uses this helper */ /* match just by name - we compare the details in the code that uses this helper */
static struct event *find_previous_event(struct dive *dive, struct event *event) static struct event *find_previous_event(struct divecomputer *dc, struct event *event)
{ {
struct event *ev = dive->events; struct event *ev = dc->events;
struct event *previous = NULL; struct event *previous = NULL;
if (!event->name) if (!event->name)
@ -406,6 +406,7 @@ struct dive *fixup_dive(struct dive *dive)
int lastdepth = 0; int lastdepth = 0;
int lasttemp = 0, lastpressure = 0; int lasttemp = 0, lastpressure = 0;
int pressure_delta[MAX_CYLINDERS] = {INT_MAX, }; int pressure_delta[MAX_CYLINDERS] = {INT_MAX, };
struct divecomputer *dc;
struct event *event; struct event *event;
add_people(dive->buddy); add_people(dive->buddy);
@ -413,8 +414,9 @@ struct dive *fixup_dive(struct dive *dive)
add_location(dive->location); add_location(dive->location);
add_suit(dive->suit); add_suit(dive->suit);
sanitize_cylinder_info(dive); sanitize_cylinder_info(dive);
for (i = 0; i < dive->samples; i++) { dc = &dive->dc;
struct sample *sample = dive->sample + i; for (i = 0; i < dc->samples; i++) {
struct sample *sample = dc->sample + i;
int time = sample->time.seconds; int time = sample->time.seconds;
int depth = sample->depth.mm; int depth = sample->depth.mm;
int temp = sample->temperature.mkelvin; int temp = sample->temperature.mkelvin;
@ -491,9 +493,9 @@ struct dive *fixup_dive(struct dive *dive)
for (j = 0; j < MAX_CYLINDERS; j++) { for (j = 0; j < MAX_CYLINDERS; j++) {
if (abs(pressure_delta[j]) != INT_MAX) { if (abs(pressure_delta[j]) != INT_MAX) {
cylinder_t *cyl = dive->cylinder + j; cylinder_t *cyl = dive->cylinder + j;
for (i = 0; i < dive->samples; i++) for (i = 0; i < dc->samples; i++)
if (dive->sample[i].cylinderindex == j) if (dc->sample[i].cylinderindex == j)
dive->sample[i].cylinderpressure.mbar = 0; dc->sample[i].cylinderpressure.mbar = 0;
if (! cyl->start.mbar) if (! cyl->start.mbar)
cyl->start.mbar = cyl->sample_start.mbar; cyl->start.mbar = cyl->sample_start.mbar;
if (! cyl->end.mbar) if (! cyl->end.mbar)
@ -552,11 +554,11 @@ struct dive *fixup_dive(struct dive *dive)
* profile with) * profile with)
* We first only mark the events for deletion so that we * We first only mark the events for deletion so that we
* still know when the previous event happened. */ * still know when the previous event happened. */
event = dive->events; event = dc->events;
while (event) { while (event) {
struct event *prev; struct event *prev;
if (is_potentially_redundant(event)) { if (is_potentially_redundant(event)) {
prev = find_previous_event(dive, event); prev = find_previous_event(dc, event);
if (prev && prev->value == event->value && if (prev && prev->value == event->value &&
prev->flags == event->flags && prev->flags == event->flags &&
event->time.seconds - prev->time.seconds < 61) event->time.seconds - prev->time.seconds < 61)
@ -564,7 +566,7 @@ struct dive *fixup_dive(struct dive *dive)
} }
event = event->next; event = event->next;
} }
event = dive->events; event = dc->events;
while (event) { while (event) {
if (event->next && event->next->deleted) { if (event->next && event->next->deleted) {
struct event *nextnext = event->next->next; struct event *nextnext = event->next->next;
@ -587,14 +589,14 @@ struct dive *fixup_dive(struct dive *dive)
#define MERGE_MAX_PREFDL(res, dl, a, b, n) res->n = (dl && dl->n) ? dl->n : MAX(a->n, b->n) #define MERGE_MAX_PREFDL(res, dl, a, b, n) res->n = (dl && dl->n) ? dl->n : MAX(a->n, b->n)
#define MERGE_MIN_PREFDL(res, dl, a, b, n) res->n = (dl && dl->n) ? dl->n : (a->n)?(b->n)?MIN(a->n, b->n):(a->n):(b->n) #define MERGE_MIN_PREFDL(res, dl, a, b, n) res->n = (dl && dl->n) ? dl->n : (a->n)?(b->n)?MIN(a->n, b->n):(a->n):(b->n)
static struct sample *add_sample(struct sample *sample, int time, struct dive *dive) static struct sample *add_sample(struct sample *sample, int time, struct divecomputer *dc)
{ {
struct sample *p = prepare_sample(dive); struct sample *p = prepare_sample(dc);
if (p) { if (p) {
*p = *sample; *p = *sample;
p->time.seconds = time; p->time.seconds = time;
finish_sample(dive); finish_sample(dc);
} }
return p; return p;
} }
@ -607,25 +609,25 @@ static struct sample *add_sample(struct sample *sample, int time, struct dive *d
* that the time in between the dives is at the surface, not some "last * that the time in between the dives is at the surface, not some "last
* sample that happened to be at a depth of 1.2m". * sample that happened to be at a depth of 1.2m".
*/ */
static void merge_one_sample(struct sample *sample, int time, struct dive *dive) static void merge_one_sample(struct sample *sample, int time, struct divecomputer *dc)
{ {
int last = dive->samples-1; int last = dc->samples-1;
if (last >= 0) { if (last >= 0) {
static struct sample surface; static struct sample surface;
int last_time = dive->sample[last].time.seconds; int last_time = dc->sample[last].time.seconds;
if (time > last_time + 60) { if (time > last_time + 60) {
add_sample(&surface, last_time+20, dive); add_sample(&surface, last_time+20, dc);
add_sample(&surface, time - 20, dive); add_sample(&surface, time - 20, dc);
} }
} }
add_sample(sample, time, dive); add_sample(sample, time, dc);
} }
/* /*
* Merge samples. Dive 'a' is "offset" seconds before Dive 'b' * Merge samples. Dive 'a' is "offset" seconds before Dive 'b'
*/ */
static struct dive *merge_samples(struct dive *res, struct dive *a, struct dive *b, int offset) static void merge_samples(struct divecomputer *res, struct divecomputer *a, struct divecomputer *b, int offset)
{ {
int asamples = a->samples; int asamples = a->samples;
int bsamples = b->samples; int bsamples = b->samples;
@ -652,14 +654,14 @@ static struct dive *merge_samples(struct dive *res, struct dive *a, struct dive
struct sample sample; struct sample sample;
if (!res) if (!res)
return NULL; return;
at = asamples ? as->time.seconds : -1; at = asamples ? as->time.seconds : -1;
bt = bsamples ? bs->time.seconds + offset : -1; bt = bsamples ? bs->time.seconds + offset : -1;
/* No samples? All done! */ /* No samples? All done! */
if (at < 0 && bt < 0) if (at < 0 && bt < 0)
return fixup_dive(res); return;
/* Only samples from a? */ /* Only samples from a? */
if (bt < 0) { if (bt < 0) {
@ -704,20 +706,6 @@ add_sample_b:
} }
} }
static struct dive *copy_samples(struct dive *res, struct dive *src)
{
int samples = src->samples;
struct sample *s = src->sample;
while (samples) {
if (!res)
return NULL;
add_sample(s, s->time.seconds, res);
s++;
samples--;
}
return fixup_dive(res);
}
static char *merge_text(const char *a, const char *b) static char *merge_text(const char *a, const char *b)
{ {
char *res; char *res;
@ -747,14 +735,14 @@ static int sort_event(struct event *a, struct event *b)
return strcmp(a->name, b->name); return strcmp(a->name, b->name);
} }
static void merge_events(struct dive *res, struct dive *src1, struct dive *src2, int offset) static void merge_events(struct divecomputer *res, struct divecomputer *src1, struct divecomputer *src2, int offset)
{ {
struct event *a, *b; struct event *a, *b;
struct event **p = &res->events; struct event **p = &res->events;
/* Always use positive offsets */ /* Always use positive offsets */
if (offset < 0) { if (offset < 0) {
struct dive *tmp; struct divecomputer *tmp;
offset = -offset; offset = -offset;
tmp = src1; tmp = src1;
@ -933,7 +921,7 @@ static int compare_sample(struct sample *s, struct sample *a, struct sample *b,
* the offset in seconds between them. Use this to find the best * the offset in seconds between them. Use this to find the best
* match of samples between two different dive computers. * match of samples between two different dive computers.
*/ */
static unsigned long sample_difference(struct dive *a, struct dive *b, int offset) static unsigned long sample_difference(struct divecomputer *a, struct divecomputer *b, int offset)
{ {
int asamples = a->samples; int asamples = a->samples;
int bsamples = b->samples; int bsamples = b->samples;
@ -1017,7 +1005,7 @@ static unsigned long sample_difference(struct dive *a, struct dive *b, int offse
* *
* If we cannot find a shared offset, don't try to merge. * If we cannot find a shared offset, don't try to merge.
*/ */
static int find_sample_offset(struct dive *a, struct dive *b) static int find_sample_offset(struct divecomputer *a, struct divecomputer *b)
{ {
int offset, best; int offset, best;
unsigned long max; unsigned long max;
@ -1073,7 +1061,7 @@ struct dive *try_to_merge(struct dive *a, struct dive *b, gboolean prefer_downlo
return NULL; return NULL;
if (!prefer_downloaded) { if (!prefer_downloaded) {
/* Dive 'a' is 'offset' seconds before dive 'b' */ /* Dive 'a' is 'offset' seconds before dive 'b' */
offset = find_sample_offset(a, b); offset = find_sample_offset(&a->dc, &b->dc);
if (offset > 120 || offset < -120) if (offset > 120 || offset < -120)
return NULL; return NULL;
} }
@ -1114,10 +1102,11 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset, gboolean pr
MERGE_MIN_PREFDL(res, dl, a, b, watertemp.mkelvin); MERGE_MIN_PREFDL(res, dl, a, b, watertemp.mkelvin);
merge_equipment(res, a, b); merge_equipment(res, a, b);
if (dl) { if (dl) {
res->events = dl->events; res->dc = dl->dc;
return copy_samples(res, dl);
} else { } else {
merge_events(res, a, b, offset); merge_events(&res->dc, &a->dc, &b->dc, offset);
return merge_samples(res, a, b, offset); merge_samples(&res->dc, &a->dc, &b->dc, offset);
} }
fixup_dive(res);
return res;
} }

19
dive.h
View file

@ -237,6 +237,13 @@ struct event {
char name[]; char name[];
}; };
struct divecomputer {
int samples, alloc_samples;
struct sample *sample;
struct event *events;
};
#define MAX_CYLINDERS (8) #define MAX_CYLINDERS (8)
#define MAX_WEIGHTSYSTEMS (4) #define MAX_WEIGHTSYSTEMS (4)
#define W_IDX_PRIMARY 0 #define W_IDX_PRIMARY 0
@ -279,9 +286,9 @@ struct dive {
weightsystem_t weightsystem[MAX_WEIGHTSYSTEMS]; weightsystem_t weightsystem[MAX_WEIGHTSYSTEMS];
char *suit; char *suit;
int sac, otu; int sac, otu;
struct event *events;
int samples, alloc_samples; /* Eventually we'll do multiple dive computers */
struct sample *sample; struct divecomputer dc;
}; };
/* Pa = N/m^2 - so we determine the weight (in N) of the mass of 10m /* Pa = N/m^2 - so we determine the weight (in N) of the mass of 10m
@ -422,8 +429,8 @@ extern struct dive *alloc_dive(void);
extern void record_dive(struct dive *dive); extern void record_dive(struct dive *dive);
extern void delete_dive(struct dive *dive); extern void delete_dive(struct dive *dive);
extern struct sample *prepare_sample(struct dive *dive); extern struct sample *prepare_sample(struct divecomputer *dc);
extern void finish_sample(struct dive *dive); extern void finish_sample(struct divecomputer *dc);
extern void report_dives(gboolean imported, gboolean prefer_imported); extern void report_dives(gboolean imported, gboolean prefer_imported);
extern struct dive *fixup_dive(struct dive *dive); extern struct dive *fixup_dive(struct dive *dive);
@ -432,7 +439,7 @@ extern struct dive *try_to_merge(struct dive *a, struct dive *b, gboolean prefer
extern void renumber_dives(int nr); extern void renumber_dives(int nr);
extern void add_event(struct dive *dive, int time, int type, int flags, int value, const char *name); extern void add_event(struct divecomputer *dc, int time, int type, int flags, int value, const char *name);
/* UI related protopypes */ /* UI related protopypes */

View file

@ -697,15 +697,15 @@ static void otu_data_func(GtkTreeViewColumn *col,
} }
/* calculate OTU for a dive */ /* calculate OTU for a dive */
static int calculate_otu(struct dive *dive) static int calculate_otu(struct dive *dive, struct divecomputer *dc)
{ {
int i; int i;
double otu = 0.0; double otu = 0.0;
for (i = 1; i < dive->samples; i++) { for (i = 1; i < dc->samples; i++) {
int t; int t;
double po2; double po2;
struct sample *sample = dive->sample + i; struct sample *sample = dc->sample + i;
struct sample *psample = sample - 1; struct sample *psample = sample - 1;
t = sample->time.seconds - psample->time.seconds; t = sample->time.seconds - psample->time.seconds;
int o2 = dive->cylinder[sample->cylinderindex].gasmix.o2.permille; int o2 = dive->cylinder[sample->cylinderindex].gasmix.o2.permille;
@ -744,7 +744,7 @@ static double calculate_airuse(struct dive *dive)
return airuse; return airuse;
} }
static int calculate_sac(struct dive *dive) static int calculate_sac(struct dive *dive, struct divecomputer *dc)
{ {
double airuse, pressure, sac; double airuse, pressure, sac;
int duration, i; int duration, i;
@ -757,16 +757,16 @@ static int calculate_sac(struct dive *dive)
/* find and eliminate long surface intervals */ /* find and eliminate long surface intervals */
duration = dive->duration.seconds; duration = dive->duration.seconds;
for (i = 0; i < dive->samples; i++) { for (i = 0; i < dc->samples; i++) {
if (dive->sample[i].depth.mm < 100) { /* less than 10cm */ if (dc->sample[i].depth.mm < 100) { /* less than 10cm */
int end = i + 1; int end = i + 1;
while (end < dive->samples && dive->sample[end].depth.mm < 100) while (end < dc->samples && dc->sample[end].depth.mm < 100)
end++; end++;
/* we only want the actual surface time during a dive */ /* we only want the actual surface time during a dive */
if (end < dive->samples) { if (end < dc->samples) {
end--; end--;
duration -= dive->sample[end].time.seconds - duration -= dc->sample[end].time.seconds -
dive->sample[i].time.seconds; dc->sample[i].time.seconds;
i = end + 1; i = end + 1;
} }
} }
@ -782,8 +782,8 @@ static int calculate_sac(struct dive *dive)
void update_cylinder_related_info(struct dive *dive) void update_cylinder_related_info(struct dive *dive)
{ {
if (dive != NULL) { if (dive != NULL) {
dive->sac = calculate_sac(dive); dive->sac = calculate_sac(dive, &dive->dc);
dive->otu = calculate_otu(dive); dive->otu = calculate_otu(dive, &dive->dc);
} }
} }
@ -1931,7 +1931,7 @@ void delete_single_dive(int idx)
dive_table.nr--; dive_table.nr--;
if (dive->selected) if (dive->selected)
amount_selected--; amount_selected--;
free(dive->sample); free(dive->dc.sample);
free(dive); free(dive);
} }

4
file.c
View file

@ -204,10 +204,10 @@ static int try_to_open_csv(const char *filename, struct memblock *mem, enum csv_
if (errno) if (errno)
break; break;
sample = prepare_sample(dive); sample = prepare_sample(&dive->dc);
sample->time.seconds = time; sample->time.seconds = time;
add_sample_data(sample, type, val); add_sample_data(sample, type, val);
finish_sample(dive); finish_sample(&dive->dc);
time++; time++;
dive->duration.seconds = time; dive->duration.seconds = time;

View file

@ -71,7 +71,7 @@ static int parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_parser_t
return DC_STATUS_SUCCESS; return DC_STATUS_SUCCESS;
} }
static void handle_event(struct dive *dive, struct sample *sample, dc_sample_value_t value) static void handle_event(struct divecomputer *dc, struct sample *sample, dc_sample_value_t value)
{ {
int type, time; int type, time;
/* we mark these for translation here, but we store the untranslated strings /* we mark these for translation here, but we store the untranslated strings
@ -108,27 +108,27 @@ static void handle_event(struct dive *dive, struct sample *sample, dc_sample_val
if (sample) if (sample)
time += sample->time.seconds; time += sample->time.seconds;
add_event(dive, time, type, value.event.flags, value.event.value, name); add_event(dc, time, type, value.event.flags, value.event.value, name);
} }
void void
sample_cb(dc_sample_type_t type, dc_sample_value_t value, void *userdata) sample_cb(dc_sample_type_t type, dc_sample_value_t value, void *userdata)
{ {
int i; int i;
struct dive *dive = userdata; struct divecomputer *dc = userdata;
struct sample *sample; struct sample *sample;
/* /*
* We fill in the "previous" sample - except for DC_SAMPLE_TIME, * We fill in the "previous" sample - except for DC_SAMPLE_TIME,
* which creates a new one. * which creates a new one.
*/ */
sample = dive->samples ? dive->sample+dive->samples-1 : NULL; sample = dc->samples ? dc->sample+dc->samples-1 : NULL;
switch (type) { switch (type) {
case DC_SAMPLE_TIME: case DC_SAMPLE_TIME:
sample = prepare_sample(dive); sample = prepare_sample(dc);
sample->time.seconds = value.time; sample->time.seconds = value.time;
finish_sample(dive); finish_sample(dc);
break; break;
case DC_SAMPLE_DEPTH: case DC_SAMPLE_DEPTH:
sample->depth.mm = value.depth * 1000 + 0.5; sample->depth.mm = value.depth * 1000 + 0.5;
@ -141,7 +141,7 @@ sample_cb(dc_sample_type_t type, dc_sample_value_t value, void *userdata)
sample->temperature.mkelvin = (value.temperature + 273.15) * 1000 + 0.5; sample->temperature.mkelvin = (value.temperature + 273.15) * 1000 + 0.5;
break; break;
case DC_SAMPLE_EVENT: case DC_SAMPLE_EVENT:
handle_event(dive, sample, value); handle_event(dc, sample, value);
break; break;
case DC_SAMPLE_RBT: case DC_SAMPLE_RBT:
printf(" <rbt>%u</rbt>\n", value.rbt); printf(" <rbt>%u</rbt>\n", value.rbt);
@ -176,10 +176,10 @@ static void dev_info(device_data_t *devdata, const char *fmt, ...)
static int import_dive_number = 0; static int import_dive_number = 0;
static int parse_samples(device_data_t *devdata, struct dive *dive, dc_parser_t *parser) static int parse_samples(device_data_t *devdata, struct divecomputer *dc, dc_parser_t *parser)
{ {
// Parse the sample data. // Parse the sample data.
return dc_parser_samples_foreach(parser, sample_cb, dive); return dc_parser_samples_foreach(parser, sample_cb, dc);
} }
/* /*
@ -302,7 +302,7 @@ static int dive_cb(const unsigned char *data, unsigned int size,
} }
// Initialize the sample data. // Initialize the sample data.
rc = parse_samples(devdata, dive, parser); rc = parse_samples(devdata, &dive->dc, parser);
if (rc != DC_STATUS_SUCCESS) { if (rc != DC_STATUS_SUCCESS) {
dev_info(devdata, _("Error parsing the samples")); dev_info(devdata, _("Error parsing the samples"));
dc_parser_destroy(parser); dc_parser_destroy(parser);

View file

@ -1199,7 +1199,7 @@ static void try_to_fill_trip(dive_trip_t **dive_trip_p, const char *name, char *
static gboolean is_dive(void) static gboolean is_dive(void)
{ {
return (cur_dive && return (cur_dive &&
(cur_dive->location || cur_dive->when || cur_dive->samples)); (cur_dive->location || cur_dive->when || cur_dive->dc.samples));
} }
static void dive_start(void) static void dive_start(void)
@ -1254,7 +1254,7 @@ static void event_start(void)
static void event_end(void) static void event_end(void)
{ {
if (cur_event.name && strcmp(cur_event.name, "surface") != 0) if (cur_event.name && strcmp(cur_event.name, "surface") != 0)
add_event(cur_dive, cur_event.time.seconds, add_event(&cur_dive->dc, cur_event.time.seconds,
cur_event.type, cur_event.flags, cur_event.type, cur_event.flags,
cur_event.value, cur_event.name); cur_event.value, cur_event.name);
cur_event.active = 0; cur_event.active = 0;
@ -1280,7 +1280,7 @@ static void ws_end(void)
static void sample_start(void) static void sample_start(void)
{ {
cur_sample = prepare_sample(cur_dive); cur_sample = prepare_sample(&cur_dive->dc);
} }
static void sample_end(void) static void sample_end(void)
@ -1288,7 +1288,7 @@ static void sample_end(void)
if (!cur_dive) if (!cur_dive)
return; return;
finish_sample(cur_dive); finish_sample(&cur_dive->dc);
cur_sample = NULL; cur_sample = NULL;
} }

View file

@ -393,10 +393,10 @@ static void plot_one_event(struct graphics_context *gc, struct plot_info *pi, st
attach_tooltip(x-15, y-6, 12, 12, buffer); attach_tooltip(x-15, y-6, 12, 12, buffer);
} }
static void plot_events(struct graphics_context *gc, struct plot_info *pi, struct dive *dive) static void plot_events(struct graphics_context *gc, struct plot_info *pi, struct divecomputer *dc)
{ {
static const text_render_options_t tro = {14, EVENTS, CENTER, TOP}; static const text_render_options_t tro = {14, EVENTS, CENTER, TOP};
struct event *event = dive->events; struct event *event = dc->events;
if (gc->printer) if (gc->printer)
return; return;
@ -1643,10 +1643,10 @@ static int set_cylinder_index(struct plot_info *pi, int i, int cylinderindex, un
return i; return i;
} }
static void check_gas_change_events(struct dive *dive, struct plot_info *pi) static void check_gas_change_events(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
{ {
int i = 0, cylinderindex = 0; int i = 0, cylinderindex = 0;
struct event *ev = get_next_event(dive->events, "gaschange"); struct event *ev = get_next_event(dc->events, "gaschange");
if (!ev) if (!ev)
return; return;
@ -1660,10 +1660,10 @@ static void check_gas_change_events(struct dive *dive, struct plot_info *pi)
} }
/* for computers that track gas changes through events */ /* for computers that track gas changes through events */
static int count_gas_change_events(struct dive *dive) static int count_gas_change_events(struct divecomputer *dc)
{ {
int count = 0; int count = 0;
struct event *ev = get_next_event(dive->events, "gaschange"); struct event *ev = get_next_event(dc->events, "gaschange");
while (ev) { while (ev) {
count++; count++;
@ -1679,7 +1679,7 @@ static int count_gas_change_events(struct dive *dive)
* sides, so that you can do end-points without having to worry * sides, so that you can do end-points without having to worry
* about it. * about it.
*/ */
static struct plot_info *create_plot_info(struct dive *dive, int nr_samples, struct sample *dive_sample) static struct plot_info *create_plot_info(struct dive *dive, struct divecomputer *dc)
{ {
int cylinderindex = -1; int cylinderindex = -1;
int lastdepth, lastindex; int lastdepth, lastindex;
@ -1694,7 +1694,7 @@ static struct plot_info *create_plot_info(struct dive *dive, int nr_samples, str
double amb_pressure; double amb_pressure;
/* we want to potentially add synthetic plot_info elements for the gas changes */ /* we want to potentially add synthetic plot_info elements for the gas changes */
nr = nr_samples + 4 + 2 * count_gas_change_events(dive); nr = dc->samples + 4 + 2 * count_gas_change_events(dc);
alloc_size = plot_info_size(nr); alloc_size = plot_info_size(nr);
pi = malloc(alloc_size); pi = malloc(alloc_size);
if (!pi) if (!pi)
@ -1703,27 +1703,27 @@ static struct plot_info *create_plot_info(struct dive *dive, int nr_samples, str
pi->nr = nr; pi->nr = nr;
pi_idx = 2; /* the two extra events at the start */ pi_idx = 2; /* the two extra events at the start */
/* check for gas changes before the samples start */ /* check for gas changes before the samples start */
ev = get_next_event(dive->events, "gaschange"); ev = get_next_event(dive->dc.events, "gaschange");
while (ev && ev->time.seconds < dive_sample->time.seconds) { while (ev && ev->time.seconds < dc->sample->time.seconds) {
entry = pi->entry + pi_idx; entry = pi->entry + pi_idx;
entry->sec = ev->time.seconds; entry->sec = ev->time.seconds;
entry->depth = 0; /* is that always correct ? */ entry->depth = 0; /* is that always correct ? */
pi_idx++; pi_idx++;
ev = get_next_event(ev->next, "gaschange"); ev = get_next_event(ev->next, "gaschange");
} }
if (ev && ev->time.seconds == dive_sample->time.seconds) { if (ev && ev->time.seconds == dc->sample->time.seconds) {
/* we already have a sample at the time of the event */ /* we already have a sample at the time of the event */
ev = get_next_event(ev->next, "gaschange"); ev = get_next_event(ev->next, "gaschange");
} }
/* find the first deco/ceiling event (if any) */ /* find the first deco/ceiling event (if any) */
ceil_ev = get_next_event(dive->events, "ceiling"); ceil_ev = get_next_event(dive->dc.events, "ceiling");
sec = 0; sec = 0;
lastindex = 0; lastindex = 0;
lastdepth = -1; lastdepth = -1;
for (i = 0; i < nr_samples; i++) { for (i = 0; i < dc->samples; i++) {
int depth; int depth;
int delay = 0; int delay = 0;
struct sample *sample = dive_sample+i; struct sample *sample = dc->sample+i;
if ((dive->start > -1 && sample->time.seconds < dive->start) || if ((dive->start > -1 && sample->time.seconds < dive->start) ||
(dive->end > -1 && sample->time.seconds > dive->end)) { (dive->end > -1 && sample->time.seconds > dive->end)) {
@ -1799,8 +1799,8 @@ static struct plot_info *create_plot_info(struct dive *dive, int nr_samples, str
entry = pi->entry + i + pi_idx; entry = pi->entry + i + pi_idx;
ev = get_next_event(ev->next, "gaschange"); ev = get_next_event(ev->next, "gaschange");
} }
nr = nr_samples + pi_idx - 2; nr = dc->samples + pi_idx - 2;
check_gas_change_events(dive, pi); check_gas_change_events(dive, dc, pi);
for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) /* initialize the start pressures */ for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) /* initialize the start pressures */
track_pr[cyl] = pr_track_alloc(dive->cylinder[cyl].start.mbar, -1); track_pr[cyl] = pr_track_alloc(dive->cylinder[cyl].start.mbar, -1);
@ -1934,14 +1934,18 @@ static void plot_set_scale(scale_mode_t scale)
void plot(struct graphics_context *gc, struct dive *dive, scale_mode_t scale) void plot(struct graphics_context *gc, struct dive *dive, scale_mode_t scale)
{ {
struct plot_info *pi; struct plot_info *pi;
static struct sample fake[4]; struct divecomputer *dc = &dive->dc;
struct sample *sample = dive->sample;
cairo_rectangle_t *drawing_area = &gc->drawing_area; cairo_rectangle_t *drawing_area = &gc->drawing_area;
int nr = dive->samples;
plot_set_scale(scale); plot_set_scale(scale);
if (!nr) { if (!dc->samples) {
static struct sample fake[4];
static struct divecomputer fakedc = {
.sample = fake,
.samples = 4
};
/* The dive has no samples, so create a few fake ones. This assumes an /* The dive has no samples, so create a few fake ones. This assumes an
ascent/descent rate of 9 m/min, which is just below the limit for FAST. */ ascent/descent rate of 9 m/min, which is just below the limit for FAST. */
int duration = dive->duration.seconds; int duration = dive->duration.seconds;
@ -1949,16 +1953,15 @@ void plot(struct graphics_context *gc, struct dive *dive, scale_mode_t scale)
int asc_desc_time = dive->maxdepth.mm*60/9000; int asc_desc_time = dive->maxdepth.mm*60/9000;
if (asc_desc_time * 2 >= duration) if (asc_desc_time * 2 >= duration)
asc_desc_time = duration / 2; asc_desc_time = duration / 2;
sample = fake;
fake[1].time.seconds = asc_desc_time; fake[1].time.seconds = asc_desc_time;
fake[1].depth.mm = maxdepth; fake[1].depth.mm = maxdepth;
fake[2].time.seconds = duration - asc_desc_time; fake[2].time.seconds = duration - asc_desc_time;
fake[2].depth.mm = maxdepth; fake[2].depth.mm = maxdepth;
fake[3].time.seconds = duration * 1.00; fake[3].time.seconds = duration * 1.00;
nr = 4; dc = &fakedc;
} }
pi = create_plot_info(dive, nr, sample); pi = create_plot_info(dive, dc);
/* shift the drawing area so we have a nice margin around it */ /* shift the drawing area so we have a nice margin around it */
cairo_translate(gc->cr, drawing_area->x, drawing_area->y); cairo_translate(gc->cr, drawing_area->x, drawing_area->y);
@ -1978,7 +1981,7 @@ void plot(struct graphics_context *gc, struct dive *dive, scale_mode_t scale)
/* Depth profile */ /* Depth profile */
plot_depth_profile(gc, pi); plot_depth_profile(gc, pi);
plot_events(gc, pi, dive); plot_events(gc, pi, dc);
/* Temperature profile */ /* Temperature profile */
plot_temperature_profile(gc, pi); plot_temperature_profile(gc, pi);

View file

@ -372,9 +372,9 @@ static void save_dive(FILE *f, struct dive *dive)
save_overview(f, dive); save_overview(f, dive);
save_cylinder_info(f, dive); save_cylinder_info(f, dive);
save_weightsystem_info(f, dive); save_weightsystem_info(f, dive);
save_events(f, dive->events); save_events(f, dive->dc.events);
for (i = 0; i < dive->samples; i++) for (i = 0; i < dive->dc.samples; i++)
save_sample(f, dive->sample+i); save_sample(f, dive->dc.sample+i);
fprintf(f, "</dive>\n"); fprintf(f, "</dive>\n");
} }

51
uemis.c
View file

@ -113,50 +113,50 @@ static gboolean in_deco;
* when we write them to the XML file we'll always have the English strings, * when we write them to the XML file we'll always have the English strings,
* regardless of locale * regardless of locale
*/ */
void uemis_event(struct dive *dive, struct sample *sample, uemis_sample_t *u_sample) static void uemis_event(struct dive *dive, struct divecomputer *dc, struct sample *sample, uemis_sample_t *u_sample)
{ {
uint8_t *flags = u_sample->flags; uint8_t *flags = u_sample->flags;
if (flags[1] & 0x01) if (flags[1] & 0x01)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("Safety Stop Violation")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("Safety Stop Violation"));
if (flags[1] & 0x08) if (flags[1] & 0x08)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("Speed Alarm")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("Speed Alarm"));
#if WANT_CRAZY_WARNINGS #if WANT_CRAZY_WARNINGS
if (flags[1] & 0x06) /* both bits 1 and 2 are a warning */ if (flags[1] & 0x06) /* both bits 1 and 2 are a warning */
add_event(dive, sample->time.seconds, 0, 0, 0, N_("Speed Warning")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("Speed Warning"));
if (flags[1] & 0x10) if (flags[1] & 0x10)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("PO2 Green Warning")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("PO2 Green Warning"));
#endif #endif
if (flags[1] & 0x20) if (flags[1] & 0x20)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("PO2 Ascend Warning")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("PO2 Ascend Warning"));
if (flags[1] & 0x40) if (flags[1] & 0x40)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("PO2 Ascend Alarm")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("PO2 Ascend Alarm"));
/* flags[2] reflects the deco / time bar /* flags[2] reflects the deco / time bar
* flags[3] reflects more display details on deco and pO2 */ * flags[3] reflects more display details on deco and pO2 */
if (flags[4] & 0x01) if (flags[4] & 0x01)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("Tank Pressure Info")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("Tank Pressure Info"));
if (flags[4] & 0x04) if (flags[4] & 0x04)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("RGT Warning")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("RGT Warning"));
if (flags[4] & 0x08) if (flags[4] & 0x08)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("RGT Alert")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("RGT Alert"));
if (flags[4] & 0x40) if (flags[4] & 0x40)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("Tank Change Suggested")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("Tank Change Suggested"));
if (flags[4] & 0x80) if (flags[4] & 0x80)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("Depth Limit Exceeded")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("Depth Limit Exceeded"));
if (flags[5] & 0x01) if (flags[5] & 0x01)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("Max Deco Time Warning")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("Max Deco Time Warning"));
if (flags[5] & 0x04) if (flags[5] & 0x04)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("Dive Time Info")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("Dive Time Info"));
if (flags[5] & 0x08) if (flags[5] & 0x08)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("Dive Time Alert")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("Dive Time Alert"));
if (flags[5] & 0x10) if (flags[5] & 0x10)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("Marker")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("Marker"));
if (flags[6] & 0x02) if (flags[6] & 0x02)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("No Tank Data")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("No Tank Data"));
if (flags[6] & 0x04) if (flags[6] & 0x04)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("Low Battery Warning")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("Low Battery Warning"));
if (flags[6] & 0x08) if (flags[6] & 0x08)
add_event(dive, sample->time.seconds, 0, 0, 0, N_("Low Battery Alert")); add_event(dc, sample->time.seconds, 0, 0, 0, N_("Low Battery Alert"));
/* flags[7] reflects the little on screen icons that remind of previous /* flags[7] reflects the little on screen icons that remind of previous
* warnings / alerts - not useful for events */ * warnings / alerts - not useful for events */
@ -164,14 +164,14 @@ void uemis_event(struct dive *dive, struct sample *sample, uemis_sample_t *u_sam
if (u_sample->p_amb_tol > dive->surface_pressure.mbar && if (u_sample->p_amb_tol > dive->surface_pressure.mbar &&
u_sample->hold_time && u_sample->hold_time &&
u_sample->hold_time < 99) { u_sample->hold_time < 99) {
add_event(dive, sample->time.seconds, SAMPLE_EVENT_CEILING, SAMPLE_FLAGS_BEGIN, add_event(dc, sample->time.seconds, SAMPLE_EVENT_CEILING, SAMPLE_FLAGS_BEGIN,
u_sample->hold_depth * 10, N_("ceiling")); u_sample->hold_depth * 10, N_("ceiling"));
add_event(dive, sample->time.seconds, SAMPLE_EVENT_DECOSTOP, 0, add_event(dc, sample->time.seconds, SAMPLE_EVENT_DECOSTOP, 0,
u_sample->hold_time * 60, N_("deco")); u_sample->hold_time * 60, N_("deco"));
in_deco = TRUE; in_deco = TRUE;
} else if (in_deco) { } else if (in_deco) {
in_deco = FALSE; in_deco = FALSE;
add_event(dive, sample->time.seconds, SAMPLE_EVENT_CEILING, SAMPLE_FLAGS_END, add_event(dc, sample->time.seconds, SAMPLE_EVENT_CEILING, SAMPLE_FLAGS_END,
0, N_("ceiling")); 0, N_("ceiling"));
} }
} }
@ -186,6 +186,7 @@ void uemis_parse_divelog_binary(char *base64, void *datap) {
struct sample *sample; struct sample *sample;
uemis_sample_t *u_sample; uemis_sample_t *u_sample;
struct dive *dive = datap; struct dive *dive = datap;
struct divecomputer *dc = &dive->dc;
int template, gasoffset; int template, gasoffset;
in_deco = FALSE; in_deco = FALSE;
@ -235,15 +236,15 @@ void uemis_parse_divelog_binary(char *base64, void *datap) {
* duration in the header is a) in minutes and b) up to 3 minutes short */ * duration in the header is a) in minutes and b) up to 3 minutes short */
if (u_sample->dive_time > dive->duration.seconds + 180) if (u_sample->dive_time > dive->duration.seconds + 180)
break; break;
sample = prepare_sample(dive); sample = prepare_sample(dc);
sample->time.seconds = u_sample->dive_time; sample->time.seconds = u_sample->dive_time;
sample->depth.mm = rel_mbar_to_depth(u_sample->water_pressure, dive); sample->depth.mm = rel_mbar_to_depth(u_sample->water_pressure, dive);
sample->temperature.mkelvin = (u_sample->dive_temperature * 100) + 273150; sample->temperature.mkelvin = (u_sample->dive_temperature * 100) + 273150;
sample->cylinderindex = u_sample->active_tank; sample->cylinderindex = u_sample->active_tank;
sample->cylinderpressure.mbar = sample->cylinderpressure.mbar =
(u_sample->tank_pressure_high * 256 + u_sample->tank_pressure_low) * 10; (u_sample->tank_pressure_high * 256 + u_sample->tank_pressure_low) * 10;
uemis_event(dive, sample, u_sample); uemis_event(dive, dc, sample, u_sample);
finish_sample(dive); finish_sample(dc);
i += 0x25; i += 0x25;
u_sample++; u_sample++;
} }