profile: C++-ify plot_info

Use more C++ style memory management for plot_info: Use std::vector
for array data. Return the plot_info instead of filling an output
parameter. Add a constructor/destructor pair so that the caller
isn't bothered with memory management.

The bulk of the commit is replacement of pointers with references,
which is kind of gratuitous. But I started and then went on...

Default initializiation of gas_pressures made it necessary to convert
gas.c to c++, though with minimal changes to the code.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-05-03 18:51:03 +02:00 committed by bstoeger
parent aaab5157d4
commit 48f7828d10
14 changed files with 635 additions and 670 deletions

View file

@ -99,7 +99,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
format.h
fulltext.cpp
fulltext.h
gas.c
gas.cpp
gas.h
gas-model.cpp
gaspressures.cpp

View file

@ -5,6 +5,7 @@
#include "gettext.h"
#include <stdio.h>
#include <string.h>
#include <QtGlobal> // for QT_TRANSLATE_NOOP
/* Perform isobaric counterdiffusion calculations for gas changes in trimix dives.
* Here we use the rule-of-fifths where, during a change involving trimix gas, the increase in nitrogen

View file

@ -60,9 +60,11 @@ static inline int get_n2(struct gasmix mix)
int pscr_o2(const double amb_pressure, struct gasmix mix);
#ifdef __cplusplus
struct gas_pressures {
double o2, n2, he;
double o2 = 0.0, n2 = 0.0, he = 0.0;
};
#endif
extern void sanitize_gasmix(struct gasmix *mix);
extern int gasmix_distance(struct gasmix a, struct gasmix b);

View file

@ -86,8 +86,6 @@ static void dump_pr_track(int cyl, std::vector<pr_track_t> &track_pr)
*/
static void fill_missing_segment_pressures(std::vector<pr_track_t> &list, enum interpolation_strategy strategy)
{
double magic;
for (auto it = list.begin(); it != list.end(); ++it) {
int start = it->start, end;
int pt_sum = 0, pt = 0;
@ -134,7 +132,7 @@ static void fill_missing_segment_pressures(std::vector<pr_track_t> &list, enum i
break;
case TIME:
if (it->t_end && (tmp->t_start - tmp->t_end)) {
magic = (it->t_start - tmp->t_end) / (tmp->t_start - tmp->t_end);
double magic = (it->t_start - tmp->t_end) / (tmp->t_start - tmp->t_end);
it->end = lrint(start - (start - end) * magic);
} else {
it->end = start;
@ -155,35 +153,33 @@ void dump_pr_interpolate(int i, pr_interpolate_t interpolate_pr)
#endif
static pr_interpolate_t get_pr_interpolate_data(const pr_track_t &segment, struct plot_info *pi, int cur)
{ // cur = index to pi->entry corresponding to t_end of segment;
static pr_interpolate_t get_pr_interpolate_data(const pr_track_t &segment, struct plot_info &pi, int cur)
{ // cur = index to pi.entry corresponding to t_end of segment;
pr_interpolate_t interpolate;
int i;
struct plot_data *entry;
interpolate.start = segment.start;
interpolate.end = segment.end;
interpolate.acc_pressure_time = 0;
interpolate.pressure_time = 0;
for (i = 0; i < pi->nr; i++) {
entry = pi->entry + i;
for (i = 0; i < pi.nr; i++) {
const plot_data &entry = pi.entry[i];
if (entry->sec < segment.t_start)
if (entry.sec < segment.t_start)
continue;
interpolate.pressure_time += entry->pressure_time;
if (entry->sec >= segment.t_end)
interpolate.pressure_time += entry.pressure_time;
if (entry.sec >= segment.t_end)
break;
if (i <= cur)
interpolate.acc_pressure_time += entry->pressure_time;
interpolate.acc_pressure_time += entry.pressure_time;
}
return interpolate;
}
static void fill_missing_tank_pressures(const struct dive *dive, struct plot_info *pi, std::vector<pr_track_t> &track_pr, int cyl)
static void fill_missing_tank_pressures(const struct dive *dive, struct plot_info &pi, std::vector<pr_track_t> &track_pr, int cyl)
{
int i;
struct plot_data *entry;
pr_interpolate_t interpolate = { 0, 0, 0, 0 };
int cur_pr;
enum interpolation_strategy strategy;
@ -214,13 +210,10 @@ static void fill_missing_tank_pressures(const struct dive *dive, struct plot_inf
* The first two pi structures are "fillers", but in case we don't have a sample
* at time 0 we need to process the second of them here, therefore i=1 */
auto last_segment = track_pr.end();
for (i = 1; i < pi->nr; i++) { // For each point on the profile:
double magic;
int pressure;
for (i = 1; i < pi.nr; i++) { // For each point on the profile:
const struct plot_data &entry = pi.entry[i];
entry = pi->entry + i;
pressure = get_plot_pressure(pi, i, cyl);
int pressure = get_plot_pressure(pi, i, cyl);
if (pressure) { // If there is a valid pressure value,
last_segment = track_pr.end(); // get rid of interpolation data,
@ -230,15 +223,15 @@ static void fill_missing_tank_pressures(const struct dive *dive, struct plot_inf
// If there is NO valid pressure value..
// Find the pressure segment corresponding to this entry..
auto it = track_pr.begin();
while (it != track_pr.end() && it->t_end < entry->sec) // Find the track_pr with end time..
++it; // ..that matches the plot_info time (entry->sec)
while (it != track_pr.end() && it->t_end < entry.sec) // Find the track_pr with end time..
++it; // ..that matches the plot_info time (entry.sec)
// After last segment? All done.
if (it == track_pr.end())
break;
// Before first segment, or between segments.. Go on, no interpolation.
if (it->t_start > entry->sec)
if (it->t_start > entry.sec)
continue;
if (!it->pressure_time) { // Empty segment?
@ -249,7 +242,7 @@ static void fill_missing_tank_pressures(const struct dive *dive, struct plot_inf
// If there is a valid segment but no tank pressure ..
if (it == last_segment) {
interpolate.acc_pressure_time += entry->pressure_time;
interpolate.acc_pressure_time += entry.pressure_time;
} else {
// Set up an interpolation structure
interpolate = get_pr_interpolate_data(*it, pi, i);
@ -261,14 +254,14 @@ static void fill_missing_tank_pressures(const struct dive *dive, struct plot_inf
/* if this segment has pressure_time, then calculate a new interpolated pressure */
if (interpolate.pressure_time) {
/* Overall pressure change over total pressure-time for this segment*/
magic = (interpolate.end - interpolate.start) / (double)interpolate.pressure_time;
double magic = (interpolate.end - interpolate.start) / (double)interpolate.pressure_time;
/* Use that overall pressure change to update the current pressure */
cur_pr = lrint(interpolate.start + magic * interpolate.acc_pressure_time);
}
} else {
magic = (interpolate.end - interpolate.start) / (it->t_end - it->t_start);
cur_pr = lrint(it->start + magic * (entry->sec - it->t_start));
double magic = (interpolate.end - interpolate.start) / (it->t_end - it->t_start);
cur_pr = lrint(it->start + magic * (entry.sec - it->t_start));
}
set_plot_pressure_data(pi, i, INTERPOLATED_PR, cyl, cur_pr); // and store the interpolated data in plot_info
}
@ -285,10 +278,10 @@ static void fill_missing_tank_pressures(const struct dive *dive, struct plot_inf
* scale pressures, so it ends up being a unitless scaling
* factor.
*/
static inline int calc_pressure_time(const struct dive *dive, struct plot_data *a, struct plot_data *b)
static inline int calc_pressure_time(const struct dive *dive, const struct plot_data &a, const struct plot_data &b)
{
int time = b->sec - a->sec;
int depth = (a->depth + b->depth) / 2;
int time = b.sec - a.sec;
int depth = (a.depth + b.depth) / 2;
if (depth <= SURFACE_THRESHOLD)
return 0;
@ -298,10 +291,10 @@ static inline int calc_pressure_time(const struct dive *dive, struct plot_data *
#ifdef PRINT_PRESSURES_DEBUG
// A CCR debugging tool that prints the gas pressures in cylinder 0 and in the diluent cylinder, used in populate_pressure_information():
static void debug_print_pressures(struct plot_info *pi)
static void debug_print_pressures(struct plot_info &pi)
{
int i;
for (i = 0; i < pi->nr; i++)
for (i = 0; i < pi.nr; i++)
printf("%5d |%9d | %9d |\n", i, get_plot_sensor_pressure(pi, i), get_plot_interpolated_pressure(pi, i));
}
#endif
@ -315,8 +308,7 @@ static void debug_print_pressures(struct plot_info *pi)
* calculates the summed pressure-time value for the duration of the dive and stores these in the pr_track_t
* structures. This function is called by create_plot_info_new() in profile.cpp
*/
extern "C"
void populate_pressure_information(const struct dive *dive, const struct divecomputer *dc, struct plot_info *pi, int sensor)
void populate_pressure_information(const struct dive *dive, const struct divecomputer *dc, struct plot_info &pi, int sensor)
{
int first, last, cyl;
cylinder_t *cylinder = get_cylinder(dive, sensor);
@ -337,7 +329,7 @@ void populate_pressure_information(const struct dive *dive, const struct divecom
/* Get a rough range of where we have any pressures at all */
first = last = -1;
for (int i = 0; i < pi->nr; i++) {
for (int i = 0; i < pi.nr; i++) {
int pressure = get_plot_sensor_pressure(pi, i, sensor);
if (!pressure)
@ -366,9 +358,9 @@ void populate_pressure_information(const struct dive *dive, const struct divecom
b_ev = get_next_event(dc->events, "modechange");
for (int i = first; i <= last; i++) {
struct plot_data *entry = pi->entry + i;
struct plot_data &entry = pi.entry[i];
int pressure = get_plot_sensor_pressure(pi, i, sensor);
int time = entry->sec;
int time = entry.sec;
while (ev && ev->time.seconds <= time) { // Find 1st gaschange event after
cyl = get_cylinder_index(dive, ev); // the current gas change.
@ -383,9 +375,9 @@ void populate_pressure_information(const struct dive *dive, const struct divecom
}
if (current != std::string::npos) { // calculate pressure-time, taking into account the dive mode for this specific segment.
entry->pressure_time = (int)(calc_pressure_time(dive, entry - 1, entry) * gasfactor[dmode] + 0.5);
track[current].pressure_time += entry->pressure_time;
track[current].t_end = entry->sec;
entry.pressure_time = (int)(calc_pressure_time(dive, pi.entry[i - 1], entry) * gasfactor[dmode] + 0.5);
track[current].pressure_time += entry.pressure_time;
track[current].t_end = entry.sec;
if (pressure)
track[current].end = pressure;
}
@ -422,7 +414,7 @@ void populate_pressure_information(const struct dive *dive, const struct divecom
// missing entries that need to be interpolated.
// Or maybe we didn't have a previous one at all,
// and this is the first pressure entry.
track.emplace_back(pressure, entry->sec);
track.emplace_back(pressure, entry.sec);
current = track.size() - 1;
dense = 1;
}

View file

@ -3,12 +3,8 @@
#define GASPRESSURES_H
#ifdef __cplusplus
extern "C" {
#endif
void populate_pressure_information(const struct dive *, const struct divecomputer *, struct plot_info *, int);
void populate_pressure_information(const struct dive *, const struct divecomputer *, struct plot_info &, int);
#ifdef __cplusplus
}
#endif
#endif // GASPRESSURES_H

File diff suppressed because it is too large Load diff

View file

@ -2,20 +2,22 @@
#ifndef PROFILE_H
#define PROFILE_H
#include "dive.h"
#include "sample.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
#include "gas.h" // gas_pressures
#include "sample.h" // MAX_O2_SENSORS
#include <memory>
#include <string>
#include <vector>
enum velocity_t {
STABLE,
SLOW,
MODERATE,
FAST,
CRAZY
} velocity_t;
};
enum plot_pressure {
SENSOR_PR = 0,
@ -25,6 +27,7 @@ enum plot_pressure {
struct membuffer;
struct deco_state;
struct dive;
struct divecomputer;
/*
@ -35,72 +38,74 @@ struct plot_pressure_data {
};
struct plot_data {
unsigned int in_deco : 1;
int sec;
int temperature;
bool in_deco = false;
int sec = 0;
int temperature = 0;
/* Depth info */
int depth;
int ceiling;
int ceilings[16];
int percentages[16];
int ndl;
int tts;
int rbt;
int stoptime;
int stopdepth;
int cns;
int smoothed;
int sac;
int running_sum;
int depth = 0;
int ceiling = 0;
int ceilings[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int percentages[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int ndl = 0;
int tts = 0;
int rbt = 0;
int stoptime = 0;
int stopdepth = 0;
int cns = 0;
int smoothed = 0;
int sac = 0;
int running_sum = 0;
struct gas_pressures pressures;
pressure_t o2pressure; // for rebreathers, this is consensus measured po2, or setpoint otherwise. 0 for OC.
pressure_t o2sensor[MAX_O2_SENSORS]; //for rebreathers with several sensors
pressure_t o2setpoint;
pressure_t scr_OC_pO2;
int mod, ead, end, eadd;
velocity_t velocity;
int speed;
// TODO: make pressure_t default to 0
pressure_t o2pressure = { 0 }; // for rebreathers, this is consensus measured po2, or setpoint otherwise. 0 for OC.
pressure_t o2sensor[MAX_O2_SENSORS] = {{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }}; //for rebreathers with several sensors
pressure_t o2setpoint = { 0 };
pressure_t scr_OC_pO2 = { 0 };
int mod = 0, ead = 0, end = 0, eadd = 0;
velocity_t velocity = STABLE;
int speed = 0;
/* values calculated by us */
unsigned int in_deco_calc : 1;
int ndl_calc;
int tts_calc;
int stoptime_calc;
int stopdepth_calc;
int pressure_time;
int heartbeat;
int bearing;
double ambpressure;
double gfline;
double surface_gf;
double current_gf;
double density;
bool icd_warning;
bool in_deco_calc = false;
int ndl_calc = 0;
int tts_calc = 0;
int stoptime_calc = 0;
int stopdepth_calc = 0;
int pressure_time = 0;
int heartbeat = 0;
int bearing = 0;
double ambpressure = 0.0;
double gfline = 0.0;
double surface_gf = 0.0;
double current_gf = 0.0;
double density = 0.0;
bool icd_warning = false;
};
/* Plot info with smoothing, velocity indication
* and one-, two- and three-minute minimums and maximums */
struct plot_info {
int nr;
int nr_cylinders;
int maxtime;
int meandepth, maxdepth;
int minpressure, maxpressure;
int minhr, maxhr;
int mintemp, maxtemp;
enum {AIR, NITROX, TRIMIX, FREEDIVING} dive_type;
double endtempcoord;
double maxpp;
bool waypoint_above_ceiling;
struct plot_data *entry;
struct plot_pressure_data *pressures; /* cylinders.nr blocks of nr entries. */
int nr = 0; // TODO: remove - redundant with entry.size()
int nr_cylinders = 0;
int maxtime = 0;
int meandepth = 0, maxdepth = 0;
int minpressure = 0, maxpressure = 0;
int minhr = 0, maxhr = 0;
int mintemp = 0, maxtemp = 0;
enum {AIR, NITROX, TRIMIX, FREEDIVING} dive_type = AIR;
double endtempcoord = 0.0;
double maxpp = 0.0;
bool waypoint_above_ceiling = false;
std::vector<plot_data> entry;
std::vector<plot_pressure_data> pressures; /* cylinders.nr blocks of nr entries. */
plot_info();
~plot_info();
};
#define AMB_PERCENTAGE 50.0
extern void init_plot_info(struct plot_info *pi);
/* when planner_dc is non-null, this is called in planner mode. */
extern void create_plot_info_new(const struct dive *dive, const struct divecomputer *dc, struct plot_info *pi, const struct deco_state *planner_ds);
extern void free_plot_info_data(struct plot_info *pi);
extern struct plot_info create_plot_info_new(const struct dive *dive, const struct divecomputer *dc, const struct deco_state *planner_ds);
/*
* When showing dive profiles, we scale things to the
@ -110,46 +115,40 @@ extern void free_plot_info_data(struct plot_info *pi);
* We also need to add 180 seconds at the end so the min/max
* plots correctly
*/
extern int get_maxtime(const struct plot_info *pi);
extern int get_maxtime(const struct plot_info &pi);
/* get the maximum depth to which we want to plot */
extern int get_maxdepth(const struct plot_info *pi);
extern int get_maxdepth(const struct plot_info &pi);
static inline int get_plot_pressure_data(const struct plot_info *pi, int idx, enum plot_pressure sensor, int cylinder)
static inline int get_plot_pressure_data(const struct plot_info &pi, int idx, enum plot_pressure sensor, int cylinder)
{
return pi->pressures[cylinder + idx * pi->nr_cylinders].data[sensor];
return pi.pressures[cylinder + idx * pi.nr_cylinders].data[sensor];
}
static inline void set_plot_pressure_data(struct plot_info *pi, int idx, enum plot_pressure sensor, int cylinder, int value)
static inline void set_plot_pressure_data(struct plot_info &pi, int idx, enum plot_pressure sensor, int cylinder, int value)
{
pi->pressures[cylinder + idx * pi->nr_cylinders].data[sensor] = value;
pi.pressures[cylinder + idx * pi.nr_cylinders].data[sensor] = value;
}
static inline int get_plot_sensor_pressure(const struct plot_info *pi, int idx, int cylinder)
static inline int get_plot_sensor_pressure(const struct plot_info &pi, int idx, int cylinder)
{
return get_plot_pressure_data(pi, idx, SENSOR_PR, cylinder);
}
static inline int get_plot_interpolated_pressure(const struct plot_info *pi, int idx, int cylinder)
static inline int get_plot_interpolated_pressure(const struct plot_info &pi, int idx, int cylinder)
{
return get_plot_pressure_data(pi, idx, INTERPOLATED_PR, cylinder);
}
static inline int get_plot_pressure(const struct plot_info *pi, int idx, int cylinder)
static inline int get_plot_pressure(const struct plot_info &pi, int idx, int cylinder)
{
int res = get_plot_sensor_pressure(pi, idx, cylinder);
return res ? res : get_plot_interpolated_pressure(pi, idx, cylinder);
}
#ifdef __cplusplus
}
// C++ only formatting functions
#include <string>
#include <vector>
// Returns index of sample and array of strings describing the dive details at given time
std::pair<int, std::vector<std::string>> get_plot_details_new(const struct dive *d, const struct plot_info *pi, int time);
std::vector<std::string> compare_samples(const struct dive *d, const struct plot_info *pi, int idx1, int idx2, bool sum);
std::pair<int, std::vector<std::string>> get_plot_details_new(const struct dive *d, const struct plot_info &pi, int time);
std::vector<std::string> compare_samples(const struct dive *d, const struct plot_info &pi, int idx1, int idx2, bool sum);
#endif
#endif // PROFILE_H

View file

@ -1,9 +1,10 @@
#include "core/save-profiledata.h"
#include "core/dive.h"
#include "core/profile.h"
#include "core/errorhelper.h"
#include "core/file.h"
#include "core/membuffer.h"
#include "core/subsurface-string.h"
#include "core/save-profiledata.h"
#include "core/version.h"
#include <errno.h>
@ -41,45 +42,45 @@ static void put_video_time(struct membuffer *b, int secs)
put_format(b, "%d:%02d:%02d.000,", hours, mins, secs);
}
static void put_pd(struct membuffer *b, const struct plot_info *pi, int idx)
static void put_pd(struct membuffer *b, const struct plot_info &pi, int idx)
{
const struct plot_data *entry = pi->entry + idx;
const struct plot_data &entry = pi.entry[idx];
put_int(b, entry->in_deco);
put_int(b, entry->sec);
for (int c = 0; c < pi->nr_cylinders; c++) {
put_int(b, entry.in_deco);
put_int(b, entry.sec);
for (int c = 0; c < pi.nr_cylinders; c++) {
put_int(b, get_plot_sensor_pressure(pi, idx, c));
put_int(b, get_plot_interpolated_pressure(pi, idx, c));
}
put_int(b, entry->temperature);
put_int(b, entry->depth);
put_int(b, entry->ceiling);
put_int(b, entry.temperature);
put_int(b, entry.depth);
put_int(b, entry.ceiling);
for (int i = 0; i < 16; i++)
put_int(b, entry->ceilings[i]);
put_int(b, entry.ceilings[i]);
for (int i = 0; i < 16; i++)
put_int(b, entry->percentages[i]);
put_int(b, entry->ndl);
put_int(b, entry->tts);
put_int(b, entry->rbt);
put_int(b, entry->stoptime);
put_int(b, entry->stopdepth);
put_int(b, entry->cns);
put_int(b, entry->smoothed);
put_int(b, entry->sac);
put_int(b, entry->running_sum);
put_double(b, entry->pressures.o2);
put_double(b, entry->pressures.n2);
put_double(b, entry->pressures.he);
put_int(b, entry->o2pressure.mbar);
put_int(b, entry.percentages[i]);
put_int(b, entry.ndl);
put_int(b, entry.tts);
put_int(b, entry.rbt);
put_int(b, entry.stoptime);
put_int(b, entry.stopdepth);
put_int(b, entry.cns);
put_int(b, entry.smoothed);
put_int(b, entry.sac);
put_int(b, entry.running_sum);
put_double(b, entry.pressures.o2);
put_double(b, entry.pressures.n2);
put_double(b, entry.pressures.he);
put_int(b, entry.o2pressure.mbar);
for (int i = 0; i < MAX_O2_SENSORS; i++)
put_int(b, entry->o2sensor[i].mbar);
put_int(b, entry->o2setpoint.mbar);
put_int(b, entry->scr_OC_pO2.mbar);
put_int(b, entry->mod);
put_int(b, entry->ead);
put_int(b, entry->end);
put_int(b, entry->eadd);
switch (entry->velocity) {
put_int(b, entry.o2sensor[i].mbar);
put_int(b, entry.o2setpoint.mbar);
put_int(b, entry.scr_OC_pO2.mbar);
put_int(b, entry.mod);
put_int(b, entry.ead);
put_int(b, entry.end);
put_int(b, entry.eadd);
switch (entry.velocity) {
case STABLE:
put_csv_string(b, "STABLE");
break;
@ -96,20 +97,20 @@ static void put_pd(struct membuffer *b, const struct plot_info *pi, int idx)
put_csv_string(b, "CRAZY");
break;
}
put_int(b, entry->speed);
put_int(b, entry->in_deco_calc);
put_int(b, entry->ndl_calc);
put_int(b, entry->tts_calc);
put_int(b, entry->stoptime_calc);
put_int(b, entry->stopdepth_calc);
put_int(b, entry->pressure_time);
put_int(b, entry->heartbeat);
put_int(b, entry->bearing);
put_double(b, entry->ambpressure);
put_double(b, entry->gfline);
put_double(b, entry->surface_gf);
put_double(b, entry->density);
put_int_with_nl(b, entry->icd_warning ? 1 : 0);
put_int(b, entry.speed);
put_int(b, entry.in_deco_calc);
put_int(b, entry.ndl_calc);
put_int(b, entry.tts_calc);
put_int(b, entry.stoptime_calc);
put_int(b, entry.stopdepth_calc);
put_int(b, entry.pressure_time);
put_int(b, entry.heartbeat);
put_int(b, entry.bearing);
put_double(b, entry.ambpressure);
put_double(b, entry.gfline);
put_double(b, entry.surface_gf);
put_double(b, entry.density);
put_int_with_nl(b, entry.icd_warning ? 1 : 0);
}
static void put_headers(struct membuffer *b, int nr_cylinders)
@ -166,36 +167,36 @@ static void put_headers(struct membuffer *b, int nr_cylinders)
put_csv_string_with_nl(b, "icd_warning");
}
static void put_st_event(struct membuffer *b, struct plot_data *entry, int offset, int length)
static void put_st_event(struct membuffer *b, const plot_data &entry, const plot_data &next_entry, int offset, int length)
{
double value;
int decimals;
const char *unit;
if (entry->sec < offset || entry->sec > offset + length)
if (entry.sec < offset || entry.sec > offset + length)
return;
put_format(b, "Dialogue: 0,");
put_video_time(b, entry->sec - offset);
put_video_time(b, (entry+1)->sec - offset < length ? (entry+1)->sec - offset : length);
put_video_time(b, entry.sec - offset);
put_video_time(b, next_entry.sec - offset < length ? next_entry.sec - offset : length);
put_format(b, "Default,,0,0,0,,");
put_format(b, "%d:%02d ", FRACTION_TUPLE(entry->sec, 60));
value = get_depth_units(entry->depth, &decimals, &unit);
put_format(b, "%d:%02d ", FRACTION_TUPLE(entry.sec, 60));
value = get_depth_units(entry.depth, &decimals, &unit);
put_format(b, "D=%02.2f %s ", value, unit);
if (entry->temperature) {
value = get_temp_units(entry->temperature, &unit);
if (entry.temperature) {
value = get_temp_units(entry.temperature, &unit);
put_format(b, "T=%.1f%s ", value, unit);
}
// Only show NDL if it is not essentially infinite, show TTS for mandatory stops.
if (entry->ndl_calc < 3600) {
if (entry->ndl_calc > 0)
put_format(b, "NDL=%d:%02d ", FRACTION_TUPLE(entry->ndl_calc, 60));
if (entry.ndl_calc < 3600) {
if (entry.ndl_calc > 0)
put_format(b, "NDL=%d:%02d ", FRACTION_TUPLE(entry.ndl_calc, 60));
else
if (entry->tts_calc > 0)
put_format(b, "TTS=%d:%02d ", FRACTION_TUPLE(entry->tts_calc, 60));
if (entry.tts_calc > 0)
put_format(b, "TTS=%d:%02d ", FRACTION_TUPLE(entry.tts_calc, 60));
}
if (entry->surface_gf > 0.0) {
put_format(b, "sGF=%.1f%% ", entry->surface_gf);
if (entry.surface_gf > 0.0) {
put_format(b, "sGF=%.1f%% ", entry.surface_gf);
}
put_format(b, "\n");
}
@ -204,30 +205,25 @@ static void save_profiles_buffer(struct membuffer *b, bool select_only)
{
int i;
struct dive *dive;
struct plot_info pi;
struct deco_state *planner_deco_state = NULL;
init_plot_info(&pi);
for_each_dive(i, dive) {
if (select_only && !dive->selected)
continue;
create_plot_info_new(dive, &dive->dc, &pi, planner_deco_state);
plot_info pi = create_plot_info_new(dive, &dive->dc, planner_deco_state);
put_headers(b, pi.nr_cylinders);
for (int i = 0; i < pi.nr; i++)
put_pd(b, &pi, i);
put_pd(b, pi, i);
put_format(b, "\n");
free_plot_info_data(&pi);
}
}
void save_subtitles_buffer(struct membuffer *b, struct dive *dive, int offset, int length)
{
struct plot_info pi;
struct deco_state *planner_deco_state = NULL;
init_plot_info(&pi);
create_plot_info_new(dive, &dive->dc, &pi, planner_deco_state);
plot_info pi = create_plot_info_new(dive, &dive->dc, planner_deco_state);
put_format(b, "[Script Info]\n");
put_format(b, "; Script generated by Subsurface %s\n", subsurface_canonical_version());
@ -236,12 +232,9 @@ void save_subtitles_buffer(struct membuffer *b, struct dive *dive, int offset, i
put_format(b, "Style: Default,Arial,12,&Hffffff,&Hffffff,&H0,&H0,0,0,0,0,100,100,0,0,1,1,0,7,10,10,10,0\n\n");
put_format(b, "[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n");
for (int i = 0; i < pi.nr; i++) {
put_st_event(b, &pi.entry[i], offset, length);
}
for (int i = 0; i + 1 < pi.nr; i++)
put_st_event(b, pi.entry[i], pi.entry[i + 1], offset, length);
put_format(b, "\n");
free_plot_info_data(&pi);
}
int save_profiledata(const char *filename, bool select_only)