diff options
-rw-r--r-- | dive.h | 3 | ||||
-rw-r--r-- | gtk-gui.c | 2 | ||||
-rw-r--r-- | libdivecomputer.c | 24 | ||||
-rw-r--r-- | parse-xml.c | 15 | ||||
-rw-r--r-- | profile.c | 173 | ||||
-rw-r--r-- | save-xml.c | 27 |
6 files changed, 151 insertions, 93 deletions
@@ -223,6 +223,9 @@ struct sample { temperature_t temperature; pressure_t cylinderpressure; int cylinderindex; + duration_t ndl; + duration_t stoptime; + depth_t stopdepth; }; /* @@ -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) @@ -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"); } |