summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dive.h3
-rw-r--r--gtk-gui.c2
-rw-r--r--libdivecomputer.c24
-rw-r--r--parse-xml.c15
-rw-r--r--profile.c173
-rw-r--r--save-xml.c27
6 files changed, 151 insertions, 93 deletions
diff --git a/dive.h b/dive.h
index 0e358b35f..746d2a9fc 100644
--- a/dive.h
+++ b/dive.h
@@ -223,6 +223,9 @@ struct sample {
temperature_t temperature;
pressure_t cylinderpressure;
int cylinderindex;
+ duration_t ndl;
+ duration_t stoptime;
+ depth_t stopdepth;
};
/*
diff --git a/gtk-gui.c b/gtk-gui.c
index f7936f6b4..f25631f44 100644
--- a/gtk-gui.c
+++ b/gtk-gui.c
@@ -1274,7 +1274,7 @@ static gboolean profile_tooltip (GtkWidget *widget, gint x, gint y,
gint tx = x - drawing_area->x; /* get transformed coordinates */
gint ty = y - drawing_area->y;
gint width, height, time = -1;
- char buffer[80], plot[80];
+ char buffer[256], plot[256];
const char *event = "";
if (tx < 0 || ty < 0)
diff --git a/libdivecomputer.c b/libdivecomputer.c
index dba6e6fe5..2162c0fff 100644
--- a/libdivecomputer.c
+++ b/libdivecomputer.c
@@ -10,6 +10,7 @@
#include "display-gtk.h"
#include "libdivecomputer.h"
+#include "libdivecomputer/version.h"
/* Christ. Libdivecomputer has the worst configuration system ever. */
#ifdef HW_FROG_H
@@ -86,7 +87,7 @@ static void handle_event(struct divecomputer *dc, struct sample *sample, dc_samp
};
const int nr_events = sizeof(events) / sizeof(const char *);
const char *name;
-
+ static int stoptime = 0, stopdepth = 0, ndl = 0;
/*
* Just ignore surface events. They are pointless. What "surface"
* means depends on the dive computer (and possibly even settings
@@ -96,6 +97,27 @@ static void handle_event(struct divecomputer *dc, struct sample *sample, dc_samp
if (value.event.type == SAMPLE_EVENT_SURFACE)
return;
+ /* libdivecomputer 0.3 provides us with deco / ndl information for at least
+ * the OSTC. Sadly, it does so through events - so we convert this into our
+ * preferred sample format here */
+#if DC_VERSION_CHECK(0, 3, 0)
+ if (value.event.type == SAMPLE_EVENT_DECOSTOP) {
+ /* packed value - time in seconds in high 16 bit
+ * depth in m(!) in low 16 bits */
+ stoptime = value.event.value >> 16;
+ stopdepth = (value.event.value && 0xFFFF) * 1000;
+ ndl = 0;
+ }
+ if (value.event.type == SAMPLE_EVENT_NDL) {
+ stopdepth = 0;
+ stoptime = 0;
+ ndl = value.event.value;
+ }
+ sample->stoptime.seconds = stoptime;
+ sample->stopdepth.mm = stopdepth;
+ sample->ndl.seconds = ndl;
+#endif
+
/*
* Other evens might be more interesting, but for now we just print them out.
*/
diff --git a/parse-xml.c b/parse-xml.c
index 9226aa63d..2470f8bb4 100644
--- a/parse-xml.c
+++ b/parse-xml.c
@@ -168,6 +168,7 @@ static struct {
} cur_event;
static struct tm cur_tm;
static int cur_cylinder_index, cur_ws_index;
+static int lastndl, laststoptime, laststopdepth;
static enum import_source {
UNKNOWN,
@@ -668,6 +669,12 @@ static void try_to_fill_sample(struct sample *sample, const char *name, char *bu
return;
if (MATCH(".sample.time", sampletime, &sample->time))
return;
+ if (MATCH(".sample.ndl", sampletime, &sample->ndl))
+ return;
+ if (MATCH(".sample.stoptime", sampletime, &sample->stoptime))
+ return;
+ if (MATCH(".sample.stopdepth", depth, &sample->stopdepth))
+ return;
switch (import_source) {
case DIVINGLOG:
@@ -1027,6 +1034,9 @@ static void ws_end(void)
static void sample_start(void)
{
cur_sample = prepare_sample(get_dc());
+ cur_sample->ndl.seconds = lastndl;
+ cur_sample->stoptime.seconds = laststoptime;
+ cur_sample->stopdepth.mm = laststopdepth;
}
static void sample_end(void)
@@ -1035,6 +1045,9 @@ static void sample_end(void)
return;
finish_sample(get_dc());
+ lastndl = cur_sample->ndl.seconds;
+ laststoptime = cur_sample->stoptime.seconds;
+ laststopdepth = cur_sample->stopdepth.mm;
cur_sample = NULL;
}
@@ -1058,6 +1071,8 @@ static void divecomputer_start(void)
/* .. this is the one we'll use */
cur_dc = dc;
+
+ lastndl = laststoptime = laststopdepth = 0;
}
static void divecomputer_end(void)
diff --git a/profile.c b/profile.c
index 5b2334a42..b225f7357 100644
--- a/profile.c
+++ b/profile.c
@@ -37,6 +37,7 @@ struct plot_info {
int endpressure, maxpressure;
int mintemp, maxtemp, endtemp;
double endtempcoord;
+ gboolean has_ndl;
struct plot_data {
unsigned int same_cylinder:1;
unsigned int cylinderindex;
@@ -47,7 +48,9 @@ struct plot_info {
int temperature;
/* Depth info */
int depth;
- int ceiling;
+ int ndl;
+ int stoptime;
+ int stopdepth;
int smoothed;
double po2, pn2, phe;
velocity_t velocity;
@@ -194,15 +197,17 @@ static void dump_pi (struct plot_info *pi)
" maxpressure:%d mintemp:%d maxtemp:%d\n",
pi->nr, pi->maxtime, pi->meandepth, pi->maxdepth,
pi->maxpressure, pi->mintemp, pi->maxtemp);
- for (i = 0; i < pi->nr; i++)
+ for (i = 0; i < pi->nr; i++) {
+ struct plot_data *entry = &pi->entry[i];
printf(" entry[%d]:{same_cylinder:%d cylinderindex:%d sec:%d pressure:{%d,%d}\n"
- " time:%d:%02d temperature:%d depth:%d ceiling:%d smoothed:%d po2:%lf phe:%lf pn2:%lf sum-pp %lf}\n",
- i, pi->entry[i].same_cylinder, pi->entry[i].cylinderindex, pi->entry[i].sec,
- pi->entry[i].pressure[0], pi->entry[i].pressure[1],
- pi->entry[i].sec / 60, pi->entry[i].sec % 60,
- pi->entry[i].temperature, pi->entry[i].depth, pi->entry[i].ceiling, pi->entry[i].smoothed,
- pi->entry[i].po2, pi->entry[i].phe, pi->entry[i].pn2,
- pi->entry[i].po2 + pi->entry[i].phe + pi->entry[i].pn2);
+ " time:%d:%02d temperature:%d depth:%d stopdepth:%d stoptime:%d ndl:%d smoothed:%d po2:%lf phe:%lf pn2:%lf sum-pp %lf}\n",
+ i, entry->same_cylinder, entry->cylinderindex, entry->sec,
+ entry->pressure[0], entry->pressure[1],
+ entry->sec / 60, entry->sec % 60,
+ entry->temperature, entry->depth, entry->stopdepth, entry->stoptime, entry->ndl, entry->smoothed,
+ entry->po2, entry->phe, entry->pn2,
+ entry->po2 + entry->phe + entry->pn2);
+ }
printf(" }\n");
}
@@ -370,50 +375,27 @@ static void plot_one_event(struct graphics_context *gc, struct plot_info *pi, st
break;
depth = data->depth;
}
- /* don't draw NDL event triangles */
- if (strcmp(event->name, "non stop time")) {
- /* draw a little triangular marker and attach tooltip */
- x = SCALEX(gc, event->time.seconds);
- y = SCALEY(gc, depth);
- set_source_rgba(gc, ALERT_BG);
- cairo_move_to(gc->cr, x-15, y+6);
- cairo_line_to(gc->cr, x-3 , y+6);
- cairo_line_to(gc->cr, x-9, y-6);
- cairo_line_to(gc->cr, x-15, y+6);
- cairo_stroke_preserve(gc->cr);
- cairo_fill(gc->cr);
- set_source_rgba(gc, ALERT_FG);
- cairo_move_to(gc->cr, x-9, y-3);
- cairo_line_to(gc->cr, x-9, y+1);
- cairo_move_to(gc->cr, x-9, y+4);
- cairo_line_to(gc->cr, x-9, y+4);
- cairo_stroke(gc->cr);
- }
+ /* draw a little triangular marker and attach tooltip */
+ x = SCALEX(gc, event->time.seconds);
+ y = SCALEY(gc, depth);
+ set_source_rgba(gc, ALERT_BG);
+ cairo_move_to(gc->cr, x-15, y+6);
+ cairo_line_to(gc->cr, x-3 , y+6);
+ cairo_line_to(gc->cr, x-9, y-6);
+ cairo_line_to(gc->cr, x-15, y+6);
+ cairo_stroke_preserve(gc->cr);
+ cairo_fill(gc->cr);
+ set_source_rgba(gc, ALERT_FG);
+ cairo_move_to(gc->cr, x-9, y-3);
+ cairo_line_to(gc->cr, x-9, y+1);
+ cairo_move_to(gc->cr, x-9, y+4);
+ cairo_line_to(gc->cr, x-9, y+4);
+ cairo_stroke(gc->cr);
/* we display the event on screen - so translate */
- if (event->value) {
- if (event->type == SAMPLE_EVENT_DECOSTOP) {
- /* deal with the packed depth / time data */
- int seconds = (event->value >> 16) % 60;
- if (seconds)
- snprintf(buffer, sizeof(buffer), "%s: %dmin %ds @ %dm", _(event->name), (event->value >> 16) / 60,
- seconds, event->value & 0xFFFF);
- else
- snprintf(buffer, sizeof(buffer), "%s: %dmin @ %dm", _(event->name), (event->value >> 16) / 60,
- event->value & 0xFFFF);
-#if DC_VERSION_CHECK(0, 3, 0)
- } else if (event->type == SAMPLE_EVENT_NDL) {
- int seconds = event->value % 60;
- if (seconds)
- snprintf(buffer, sizeof(buffer), "%s: %dmin %ds", _(event->name), event->value / 60, seconds);
- else
- snprintf(buffer, sizeof(buffer), "%s: %dmin", _(event->name), event->value / 60);
-#endif
- } else {
- snprintf(buffer, sizeof(buffer), "%s: %d", _(event->name), event->value);
- }
- } else {
+ if (event->value)
+ snprintf(buffer, sizeof(buffer), "%s: %d", _(event->name), event->value);
+ else
snprintf(buffer, sizeof(buffer), "%s", _(event->name));
- }
attach_tooltip(x-15, y-6, 12, 12, buffer);
}
@@ -1026,8 +1008,11 @@ static void plot_depth_profile(struct graphics_context *gc, struct plot_info *pi
/* Show any ceiling we may have encountered */
for (i = pi->nr - 1; i >= 0; i--, entry--) {
- if (entry->ceiling < entry->depth) {
- line_to(gc, entry->sec, entry->ceiling);
+ if (entry->ndl) {
+ /* non-zero NDL implies this is a safety stop, no ceiling */
+ line_to(gc, entry->sec, 0);
+ } else if (entry->stopdepth < entry->depth) {
+ line_to(gc, entry->sec, entry->stopdepth);
} else {
line_to(gc, entry->sec, entry->depth);
}
@@ -1047,8 +1032,8 @@ static void plot_depth_profile(struct graphics_context *gc, struct plot_info *pi
line_to(gc, entry->sec, entry->depth);
for (i = pi->nr - 1; i >= 0; i--, entry--) {
- if (entry->ceiling > entry->depth) {
- line_to(gc, entry->sec, entry->ceiling);
+ if (entry->ndl == 0 && entry->stopdepth > entry->depth) {
+ line_to(gc, entry->sec, entry->stopdepth);
} else {
line_to(gc, entry->sec, entry->depth);
}
@@ -1707,14 +1692,14 @@ static struct plot_info *create_plot_info(struct dive *dive, struct divecomputer
{
int cylinderindex = -1;
int lastdepth, lastindex;
- int i, pi_idx, nr, sec, cyl, ceiling = 0;
+ int i, pi_idx, nr, sec, cyl, stoptime, ndl, stopdepth;
size_t alloc_size;
struct plot_info *pi;
pr_track_t *track_pr[MAX_CYLINDERS] = {NULL, };
pr_track_t *pr_track, *current;
gboolean missing_pr = FALSE;
struct plot_data *entry = NULL;
- struct event *ev, *deco_ev, *ndl_ev;
+ struct event *ev;
double amb_pressure;
/* we want to potentially add synthetic plot_info elements for the gas changes */
@@ -1739,9 +1724,6 @@ static struct plot_info *create_plot_info(struct dive *dive, struct divecomputer
/* we already have a sample at the time of the event */
ev = get_next_event(ev->next, "gaschange");
}
- /* find the first deco/ceiling event (if any) */
- deco_ev = get_next_event(dc->events, "deco stop");
- ndl_ev = get_next_event(dc->events, "non stop time");
sec = 0;
lastindex = 0;
lastdepth = -1;
@@ -1756,22 +1738,10 @@ static struct plot_info *create_plot_info(struct dive *dive, struct divecomputer
continue;
}
entry = pi->entry + i + pi_idx;
- while (deco_ev && deco_ev->time.seconds <= sample->time.seconds) {
- struct event *next_deco_ev = get_next_event(deco_ev->next, "deco stop");
- if (!next_deco_ev || next_deco_ev->time.seconds > sample->time.seconds)
- break;
- deco_ev = next_deco_ev;
- }
- if (deco_ev)
- ndl_ev = get_next_event(deco_ev, "non stop time");
- /* if there is an NDL event that comes after the latest deco stop event but
- * prior to this sample, then deco has ended */
- if (ndl_ev && ndl_ev->time.seconds <= sample->time.seconds) {
- ceiling = 0;
- } else if (deco_ev && deco_ev->time.seconds <= sample->time.seconds) {
- ceiling = 1000 * (deco_ev->value & 0xffff);
- deco_ev = get_next_event(deco_ev->next, "deco stop");
- }
+ ndl = sample->ndl.seconds;
+ pi->has_ndl |= ndl;
+ stopdepth = sample->stopdepth.mm;
+ stoptime = sample->stoptime.seconds;
while (ev && ev->time.seconds < sample->time.seconds) {
/* insert two fake plot info structures for the end of
* the old tank and the start of the new tank */
@@ -1789,8 +1759,12 @@ static struct plot_info *create_plot_info(struct dive *dive, struct divecomputer
} else
entry->depth = sample->depth.mm;
(entry + 1)->depth = entry->depth;
- entry->ceiling = ceiling;
- (entry + 1)->ceiling = ceiling;
+ entry->stopdepth = stopdepth;
+ entry->stoptime = stoptime;
+ entry->ndl = ndl;
+ (entry + 1)->stopdepth = stopdepth;
+ (entry + 1)->stoptime = stoptime;
+ (entry + 1)->ndl = ndl;
pi_idx += 2;
entry = pi->entry + i + pi_idx;
ev = get_next_event(ev->next, "gaschange");
@@ -1801,7 +1775,9 @@ static struct plot_info *create_plot_info(struct dive *dive, struct divecomputer
* real even by one second (to keep time monotonous) */
entry->sec = ev->time.seconds;
entry->depth = sample->depth.mm;
- entry->ceiling = ceiling;
+ entry->stopdepth = stopdepth;
+ entry->stoptime = stoptime;
+ entry->ndl = ndl;
pi_idx++;
entry = pi->entry + i + pi_idx;
ev = get_next_event(ev->next, "gaschange");
@@ -1809,7 +1785,9 @@ static struct plot_info *create_plot_info(struct dive *dive, struct divecomputer
}
sec = entry->sec = sample->time.seconds + delay;
depth = entry->depth = sample->depth.mm;
- entry->ceiling = ceiling;
+ entry->stopdepth = stopdepth;
+ entry->stoptime = stoptime;
+ entry->ndl = ndl;
entry->cylinderindex = sample->cylinderindex;
SENSOR_PRESSURE(entry) = sample->cylinderpressure.mbar;
entry->temperature = sample->temperature.mkelvin;
@@ -2061,7 +2039,8 @@ void plot(struct graphics_context *gc, struct dive *dive, scale_mode_t scale)
}
}
-static void plot_string(struct plot_data *entry, char *buf, size_t bufsize, int depth, int pressure, int temp)
+static void plot_string(struct plot_data *entry, char *buf, size_t bufsize,
+ int depth, int pressure, int temp, gboolean has_ndl)
{
int pressurevalue;
const char *depth_unit, *pressure_unit, *temp_unit;
@@ -2080,6 +2059,30 @@ static void plot_string(struct plot_data *entry, char *buf, size_t bufsize, int
memcpy(buf2, buf, bufsize);
snprintf(buf, bufsize, "%s\nT:%.1f %s", buf2, tempvalue, temp_unit);
}
+ if (entry->stopdepth) {
+ depthvalue = get_depth_units(entry->stopdepth, NULL, &depth_unit);
+ memcpy(buf2, buf, bufsize);
+ if (entry->ndl) {
+ /* this is a safety stop as we still have ndl */
+ if (entry->stoptime)
+ snprintf(buf, bufsize, "%s\nSafetystop:%umin @ %.0f %s", buf2, entry->stoptime / 60,
+ depthvalue, depth_unit);
+ else
+ snprintf(buf, bufsize, "%s\nSafetystop:unkn time @ %.0f %s", buf2,
+ depthvalue, depth_unit);
+ } else {
+ /* actual deco stop */
+ if (entry->stoptime)
+ snprintf(buf, bufsize, "%s\nDeco:%umin @ %.0f %s", buf2, entry->stoptime / 60,
+ depthvalue, depth_unit);
+ else
+ snprintf(buf, bufsize, "%s\nDeco:unkn time @ %.0f %s", buf2,
+ depthvalue, depth_unit);
+ }
+ } else if (has_ndl) {
+ memcpy(buf2, buf, bufsize);
+ snprintf(buf, bufsize, "%s\nNDL:%umin", buf2, entry->ndl / 60);
+ }
if (partial_pressure_graphs.po2) {
memcpy(buf2, buf, bufsize);
snprintf(buf, bufsize, "%s\npO" UTF8_SUBSCRIPT_2 ":%.1f", buf2, entry->po2);
@@ -2110,11 +2113,9 @@ void get_plot_details(struct graphics_context *gc, int time, char *buf, size_t b
temp = entry->temperature;
if (GET_PRESSURE(entry))
pressure = GET_PRESSURE(entry);
- if (entry->sec >= time) {
- plot_string(entry, buf, bufsize, entry->depth, pressure, temp);
- return;
- }
+ if (entry->sec >= time)
+ break;
}
- plot_string(entry, buf, bufsize, entry->depth, pressure, temp);
+ plot_string(entry, buf, bufsize, entry->depth, pressure, temp, pi->has_ndl);
}
}
diff --git a/save-xml.c b/save-xml.c
index 8d7d7f889..d4bc36cab 100644
--- a/save-xml.c
+++ b/save-xml.c
@@ -293,7 +293,7 @@ static void show_index(FILE *f, int value, const char *pre, const char *post)
fprintf(f, " %s%d%s", pre, value, post);
}
-static void save_sample(FILE *f, struct sample *sample)
+static void save_sample(FILE *f, struct sample *sample, const struct sample *prev)
{
fprintf(f, " <sample time='%u:%02u min'", FRACTION(sample->time.seconds,60));
show_milli(f, " depth='", sample->depth.mm, " m", "'");
@@ -301,6 +301,13 @@ static void save_sample(FILE *f, struct sample *sample)
show_pressure(f, sample->cylinderpressure, " pressure='", "'");
if (sample->cylinderindex)
fprintf(f, " cylinderindex='%d'", sample->cylinderindex);
+ /* the deco/ndl values are stored whenever they change */
+ if (sample->ndl.seconds != prev->ndl.seconds)
+ fprintf(f, " ndl='%u:%02u min'", FRACTION(sample->ndl.seconds, 60));
+ if (sample->stoptime.seconds != prev->stoptime.seconds)
+ fprintf(f, " stoptime='%u:%02u min'", FRACTION(sample->stoptime.seconds, 60));
+ if (sample->stopdepth.mm != prev->stopdepth.mm)
+ show_milli(f, " stopdepth='", sample->stopdepth.mm, " m", "'");
fprintf(f, " />\n");
}
@@ -346,10 +353,20 @@ static void save_trip(FILE *f, dive_trip_t *trip)
show_utf8(f, trip->notes, "<notes>","</notes>\n", 0);
}
-static void save_dc(FILE *f, struct dive *dive, struct divecomputer *dc)
+static void save_samples(FILE *f, int nr, struct sample *s)
{
- int i;
+ static const struct sample empty_sample;
+ const struct sample *prev = &empty_sample;
+
+ while (--nr >= 0) {
+ save_sample(f, s, prev);
+ prev = s;
+ s++;
+ }
+}
+static void save_dc(FILE *f, struct dive *dive, struct divecomputer *dc)
+{
fprintf(f, " <divecomputer");
if (dc->model)
show_utf8(f, dc->model, " model='", "'", 1);
@@ -361,8 +378,8 @@ static void save_dc(FILE *f, struct dive *dive, struct divecomputer *dc)
show_date(f, dc->when);
fprintf(f, ">\n");
save_events(f, dc->events);
- for (i = 0; i < dc->samples; i++)
- save_sample(f, dc->sample+i);
+ save_samples(f, dc->samples, dc->sample);
+
fprintf(f, " </divecomputer>\n");
}