mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-01 00:13:24 +00:00
libdivecomputer.c: Split dive_cb() callback in two
dive_cb() needs a defined device to work as it's built for DC download tasks. Move part of the functionality of dive_cb() to a new function libdc_header_parser() which can be used to parse headers from raw data buffers with no device set. Obviously dive_cb() will call the new funtion for header parsing too. Two changes in logic: 1- In parse_gasmixes() set data pointer to NULL. This pointer is passed to the function, but it's not used. While this data pointer exists in DC import, via dive_cb(), it doesn't in file import as data has previously been set in the parser. 2- While parsing gas mixes do not return on rc = DC_STATUS_UNSUPORTED because it would end our dive parsing just if the device doesn't support gases, which seems undesirable in both, DC or file import. Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
e276ec65ba
commit
0fe21637ad
1 changed files with 157 additions and 137 deletions
|
@ -434,6 +434,157 @@ static void parse_string_field(struct dive *dive, dc_field_string_t *str)
|
|||
}
|
||||
#endif
|
||||
|
||||
static dc_status_t libdc_header_parser(dc_parser_t *parser, struct device_data_t *devdata, struct dive *dive)
|
||||
{
|
||||
dc_status_t rc = 0;
|
||||
dc_datetime_t dt = { 0 };
|
||||
struct tm tm;
|
||||
|
||||
rc = dc_parser_get_datetime(parser, &dt);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error parsing the datetime"));
|
||||
return rc;
|
||||
}
|
||||
|
||||
dive->dc.deviceid = devdata->deviceid;
|
||||
|
||||
if (rc == DC_STATUS_SUCCESS) {
|
||||
tm.tm_year = dt.year;
|
||||
tm.tm_mon = dt.month - 1;
|
||||
tm.tm_mday = dt.day;
|
||||
tm.tm_hour = dt.hour;
|
||||
tm.tm_min = dt.minute;
|
||||
tm.tm_sec = dt.second;
|
||||
dive->when = dive->dc.when = utc_mktime(&tm);
|
||||
}
|
||||
|
||||
// Parse the divetime.
|
||||
dev_info(devdata, translate("gettextFromC", "Dive %d: %s"), import_dive_number, get_dive_date_c_string(dive->when));
|
||||
unsigned int divetime = 0;
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_DIVETIME, 0, &divetime);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error parsing the divetime"));
|
||||
return rc;
|
||||
}
|
||||
if (rc == DC_STATUS_SUCCESS)
|
||||
dive->dc.duration.seconds = divetime;
|
||||
|
||||
// Parse the maxdepth.
|
||||
double maxdepth = 0.0;
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_MAXDEPTH, 0, &maxdepth);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error parsing the maxdepth"));
|
||||
return rc;
|
||||
}
|
||||
if (rc == DC_STATUS_SUCCESS)
|
||||
dive->dc.maxdepth.mm = rint(maxdepth * 1000);
|
||||
|
||||
#if DC_VERSION_CHECK(0, 5, 0) && defined(DC_GASMIX_UNKNOWN)
|
||||
// if this is defined then we have a fairly late version of libdivecomputer
|
||||
// from the 0.5 development cylcle - most likely temperatures and tank sizes
|
||||
// are supported
|
||||
|
||||
// Parse temperatures
|
||||
double temperature;
|
||||
dc_field_type_t temp_fields[] = {DC_FIELD_TEMPERATURE_SURFACE,
|
||||
DC_FIELD_TEMPERATURE_MAXIMUM,
|
||||
DC_FIELD_TEMPERATURE_MINIMUM};
|
||||
for (int i = 0; i < 3; i++) {
|
||||
rc = dc_parser_get_field(parser, temp_fields[i], 0, &temperature);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error parsing temperature"));
|
||||
return rc;
|
||||
}
|
||||
if (rc == DC_STATUS_SUCCESS)
|
||||
switch(i) {
|
||||
case 0:
|
||||
dive->dc.airtemp.mkelvin = C_to_mkelvin(temperature);
|
||||
break;
|
||||
case 1: // we don't distinguish min and max water temp here, so take min if given, max otherwise
|
||||
case 2:
|
||||
dive->dc.watertemp.mkelvin = C_to_mkelvin(temperature);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Parse the gas mixes.
|
||||
unsigned int ngases = 0;
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_GASMIX_COUNT, 0, &ngases);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error parsing the gas mix count"));
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if DC_VERSION_CHECK(0, 3, 0)
|
||||
// Check if the libdivecomputer version already supports salinity & atmospheric
|
||||
dc_salinity_t salinity = {
|
||||
.type = DC_WATER_SALT,
|
||||
.density = SEAWATER_SALINITY / 10.0
|
||||
};
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_SALINITY, 0, &salinity);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error obtaining water salinity"));
|
||||
return rc;
|
||||
}
|
||||
if (rc == DC_STATUS_SUCCESS)
|
||||
dive->dc.salinity = rint(salinity.density * 10.0);
|
||||
|
||||
double surface_pressure = 0;
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_ATMOSPHERIC, 0, &surface_pressure);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error obtaining surface pressure"));
|
||||
return rc;
|
||||
}
|
||||
if (rc == DC_STATUS_SUCCESS)
|
||||
dive->dc.surface_pressure.mbar = rint(surface_pressure * 1000.0);
|
||||
#endif
|
||||
|
||||
#ifdef DC_FIELD_STRING
|
||||
// The dive parsing may give us more device information
|
||||
int idx;
|
||||
for (idx = 0; idx < 100; idx++) {
|
||||
dc_field_string_t str = { NULL };
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_STRING, idx, &str);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
break;
|
||||
if (!str.desc || !str.value)
|
||||
break;
|
||||
parse_string_field(dive, &str);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DC_VERSION_CHECK(0, 5, 0) && defined(DC_GASMIX_UNKNOWN)
|
||||
dc_divemode_t divemode;
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_DIVEMODE, 0, &divemode);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error obtaining divemode"));
|
||||
return rc;
|
||||
}
|
||||
if (rc == DC_STATUS_SUCCESS)
|
||||
switch(divemode) {
|
||||
case DC_DIVEMODE_FREEDIVE:
|
||||
dive->dc.divemode = FREEDIVE;
|
||||
break;
|
||||
case DC_DIVEMODE_GAUGE:
|
||||
case DC_DIVEMODE_OC: /* Open circuit */
|
||||
dive->dc.divemode = OC;
|
||||
break;
|
||||
case DC_DIVEMODE_CC: /* Closed circuit */
|
||||
dive->dc.divemode = CCR;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = parse_gasmixes(devdata, dive, parser, ngases, NULL);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error parsing the gas mix"));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* returns true if we want libdivecomputer's dc_device_foreach() to continue,
|
||||
* false otherwise */
|
||||
static int dive_cb(const unsigned char *data, unsigned int size,
|
||||
|
@ -465,148 +616,17 @@ static int dive_cb(const unsigned char *data, unsigned int size,
|
|||
|
||||
import_dive_number++;
|
||||
dive = alloc_dive();
|
||||
rc = dc_parser_get_datetime(parser, &dt);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error parsing the datetime"));
|
||||
goto error_exit;
|
||||
}
|
||||
dive->dc.model = strdup(devdata->model);
|
||||
dive->dc.deviceid = devdata->deviceid;
|
||||
dive->dc.diveid = calculate_diveid(fingerprint, fsize);
|
||||
|
||||
if (rc == DC_STATUS_SUCCESS) {
|
||||
tm.tm_year = dt.year;
|
||||
tm.tm_mon = dt.month - 1;
|
||||
tm.tm_mday = dt.day;
|
||||
tm.tm_hour = dt.hour;
|
||||
tm.tm_min = dt.minute;
|
||||
tm.tm_sec = dt.second;
|
||||
dive->when = dive->dc.when = utc_mktime(&tm);
|
||||
}
|
||||
// Parse the divetime.
|
||||
dev_info(devdata, translate("gettextFromC", "Dive %d: %s"), import_dive_number, get_dive_date_c_string(dive->when));
|
||||
unsigned int divetime = 0;
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_DIVETIME, 0, &divetime);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error parsing the divetime"));
|
||||
goto error_exit;
|
||||
}
|
||||
if (rc == DC_STATUS_SUCCESS)
|
||||
dive->dc.duration.seconds = divetime;
|
||||
|
||||
// Parse the maxdepth.
|
||||
double maxdepth = 0.0;
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_MAXDEPTH, 0, &maxdepth);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error parsing the maxdepth"));
|
||||
goto error_exit;
|
||||
}
|
||||
if (rc == DC_STATUS_SUCCESS)
|
||||
dive->dc.maxdepth.mm = rint(maxdepth * 1000);
|
||||
|
||||
#if DC_VERSION_CHECK(0, 5, 0) && defined(DC_GASMIX_UNKNOWN)
|
||||
// if this is defined then we have a fairly late version of libdivecomputer
|
||||
// from the 0.5 development cylcle - most likely temperatures and tank sizes
|
||||
// are supported
|
||||
|
||||
// Parse temperatures
|
||||
double temperature;
|
||||
dc_field_type_t temp_fields[] = {DC_FIELD_TEMPERATURE_SURFACE,
|
||||
DC_FIELD_TEMPERATURE_MAXIMUM,
|
||||
DC_FIELD_TEMPERATURE_MINIMUM};
|
||||
for (int i = 0; i < 3; i++) {
|
||||
rc = dc_parser_get_field(parser, temp_fields[i], 0, &temperature);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error parsing temperature"));
|
||||
goto error_exit;
|
||||
}
|
||||
if (rc == DC_STATUS_SUCCESS)
|
||||
switch(i) {
|
||||
case 0:
|
||||
dive->dc.airtemp.mkelvin = C_to_mkelvin(temperature);
|
||||
break;
|
||||
case 1: // we don't distinguish min and max water temp here, so take min if given, max otherwise
|
||||
case 2:
|
||||
dive->dc.watertemp.mkelvin = C_to_mkelvin(temperature);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Parse the gas mixes.
|
||||
unsigned int ngases = 0;
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_GASMIX_COUNT, 0, &ngases);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error parsing the gas mix count"));
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
#if DC_VERSION_CHECK(0, 3, 0)
|
||||
// Check if the libdivecomputer version already supports salinity & atmospheric
|
||||
dc_salinity_t salinity = {
|
||||
.type = DC_WATER_SALT,
|
||||
.density = SEAWATER_SALINITY / 10.0
|
||||
};
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_SALINITY, 0, &salinity);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error obtaining water salinity"));
|
||||
goto error_exit;
|
||||
}
|
||||
if (rc == DC_STATUS_SUCCESS)
|
||||
dive->dc.salinity = rint(salinity.density * 10.0);
|
||||
|
||||
double surface_pressure = 0;
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_ATMOSPHERIC, 0, &surface_pressure);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error obtaining surface pressure"));
|
||||
goto error_exit;
|
||||
}
|
||||
if (rc == DC_STATUS_SUCCESS)
|
||||
dive->dc.surface_pressure.mbar = rint(surface_pressure * 1000.0);
|
||||
#endif
|
||||
|
||||
#ifdef DC_FIELD_STRING
|
||||
// The dive parsing may give us more device information
|
||||
int idx;
|
||||
for (idx = 0; idx < 100; idx++) {
|
||||
dc_field_string_t str = { NULL };
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_STRING, idx, &str);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
break;
|
||||
if (!str.desc || !str.value)
|
||||
break;
|
||||
parse_string_field(dive, &str);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DC_VERSION_CHECK(0, 5, 0) && defined(DC_GASMIX_UNKNOWN)
|
||||
dc_divemode_t divemode;
|
||||
rc = dc_parser_get_field(parser, DC_FIELD_DIVEMODE, 0, &divemode);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error obtaining divemode"));
|
||||
goto error_exit;
|
||||
}
|
||||
if (rc == DC_STATUS_SUCCESS)
|
||||
switch(divemode) {
|
||||
case DC_DIVEMODE_FREEDIVE:
|
||||
dive->dc.divemode = FREEDIVE;
|
||||
break;
|
||||
case DC_DIVEMODE_GAUGE:
|
||||
case DC_DIVEMODE_OC: /* Open circuit */
|
||||
dive->dc.divemode = OC;
|
||||
break;
|
||||
case DC_DIVEMODE_CC: /* Closed circuit */
|
||||
dive->dc.divemode = CCR;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = parse_gasmixes(devdata, dive, parser, ngases, data);
|
||||
// Parse the dive's header data
|
||||
rc = libdc_header_parser (parser, devdata, dive);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
dev_info(devdata, translate("gettextFromC", "Error parsing the gas mix"));
|
||||
dev_info(devdata, translate("getextFromC", "Error parsing the header"));
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
dive->dc.model = strdup(devdata->model);
|
||||
dive->dc.diveid = calculate_diveid(fingerprint, fsize);
|
||||
|
||||
// Initialize the sample data.
|
||||
rc = parse_samples(devdata, &dive->dc, parser);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
|
|
Loading…
Add table
Reference in a new issue