The serial and fw_version strings of struct divecomputer were copied
by pointer. This worked because they were never freed or modified.
Instead, do a deep copy of the strings and free them when appropriate.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
On dive computer copy, the extra data (a list of key/value pairs)
was simply copied as a pointer. This worked because the list was
never freed nor modified. Copy and free the list on dive computer
copy and free, respectively.
This made it necessary to move the STRUCTURE_LIST_* macros up in
the dive.c file.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In commit e5dca8228e a fixed order
of the arguments to merge_dives() was introduced: first dive old,
second dive downloaded. This made the dl variable, which pointed
to the downloaded dive useless. One instance was forgotten, which
led to a null-dereference.
Remove.
Reported-by: Dirk Hohndel <dirk@hohndel.org>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
sanitize_cylinder_type(), which is indirectly called from fixup_dive(),
had ft^3 -> mliter conversion code, which was executed on the
condition "xml_parsing_units.volume == CUFT".
But nowhere in the code base would xml_parsing_units.volume ever be
set to non-metric. Moreover, xml_parsing_units reflects the units
of the latest parsed XML file, but fixup_dive() is called in numerous
contexts not related to XML parsing. Therefore, the whole piece of
code seems highly questionable.
Remove this code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
copy_dc_renumber() is an internal function to copy dive computers
and renumber the cylinders. Since only the structure was copied,
in the case of multi-dc dives, the merged dives shared the same
computer. If one of them was freed, use-after-free crashes would happen.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
On merging make a deep copy of the picture list, to avoid a use-after-free
crash after the orginal dive is deleted.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In commit 8c2383b495 dive merging was
changed to not modify the original dive. On import, dives were then
merged and the original deleted. The merge_weightsystem_info() was
not adapted accordingly (deep copy of string instead of pointer),
leading to a use-after-free crash.
Resolve this by doing a deep copy.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The global object displayed_dive_site is used a a backing-store
by the dive-site-edit widget. All external accesses were removed,
therefore make the object local to the widget.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For undo, it is crucial that commands don't modify existing dives.
Unfortunately, dive merging would write into the data-structures
of the to-be-merged dives. To prevent it from doing so, make the
input dives const-pointers.
This led to a whole cascade of functions that had to take const
and significant churn.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For this, an output-parameter was added to the backend merge_dives()
function. When non-zero, instead of adding the merged dive to
the preferred trip, the preferred trip is returned to the caller.
Since the new UndoObject, just like the delete-dives UndoObject,
needs to remove/readd a set of dives, the corresponding functionality
was split-off in a helper function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For this, the core functionality of the split_dive() and
split_dive_at_time() functions were split out into new
split_dive_dont_insert() and split_dive_at_time_dont_insert(),
which do not add the new dives to the log. Thus, the undo-command
can take ownership of these dives, without having to remove them
first.
The split-dive functionality is temporarily made desktop-only
until mobile also supports "UndoObjects".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Dive importing is now performed via a distinct table which is
merged into the main dive table. Thus, it is known which of the
dive is new and which is old. This information can now be
implicitely encoded in the parameter-position of merge_dive()
[i.e. pass old as first and new as second dive].
This makes marking of downloaded dives via a flag unnecessary.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Currently, we can only delete dives that are indexed in the main
dive table. In the future, we will have to delete dives outside
of this table (e.g. for undo). Therefore, split out the free_dive()
function from delete_single_dive(), which takes an index into
the main dive table.
In the process, adopt the dive freeing-code from clear_dive(),
which frees more data than the code in delete_single_dive().
This potentially fixes a memory-leak.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
On import of dive media, the timestamp is read from the
metadata to check if the image belongs to the selected dives.
The pictures are then listed in a dialog.
Currently, the metadata is read twice if images are outside
of a dive: once in picture_check_valid() and if it turns
out that the picture is not valid again in picture_get_time()
to display the proper timestamp.
Even though metadata-extraction is reasonably fast, this is
a bit of an embarrassment.
Instead, read the timestamps only once in the constructor of
the dialog and from then on only used these timestamps. Keep
the timestamps in a QVector. Rename the picture_check_valid()
function to picture_check_valid_time() and pass a timestamp
instead of a filename.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The merge_one_sample() function adds a sample to the destination
dive if dives are merged. For long periods between samples at surface
depths, it adds a surface interval.
To decrease the number of global objects, make the sample structure
non-static. Of course, initialization of an on-stack structure is
slower. Therefore move it into the corresponding if. Thus, the
structure will be initialized only once per surface-interval.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Commit f5b11daffd changed gasmix
arguments and return values to be passed by value instead of
using pointers.
Notably, get_gasmix() is fed a default-value and returns a
new value. In the old code, NULL was passed in in a first
loop iteration and non-NULL was always returned in the first
iteration. Thus, an equality comparison of passed-in an
returned gasmix would always fail in the first loop iteration.
The new code passed in air as default. Now if air was also
returned, then the matching gases were not calculated in
calculate_sac(). To revert to the old behavior, pass in
an invalid gasmix.
Moreover, give names to the invalid and air gasmixes.
Reported-by: tormento <turment@gmail.com>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
get_units() returns a pointer to the units struct in the preferences.
Callers should not modify the preferences via this struct, therefore
make the return value point to const.
This is a small step in constifying the global preferences structure.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is another entry in the series to make more things
"const-clean" with the ultimate goal of merge_dive() take
const pointers.
This concerns functions taking pointers to events and
the fallout from making these const.
The somewhat debatable part of this commit might be
that get_next_event() is split in a two distinct
(const and non-const) versions with different names,
since C doesn't allow overloading. The linker should
recognize that these functions are identical and remove
one of them.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Accessor-functions without noticeable logic, such as depth_to_bar()
can trivially be made "const-clean".
Moreover, let get_dive_location() return a "const char *". The
non-const version must have been an oversight, as the caller
must not free() or overwrite the string.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In a previous commit, the get_gasmix_* functions were changed to
return by value. For consistency, also pass gasmix by value.
Note that on common 64-bit platforms struct gasmix is the size
of a pointer [2 * 32 bit vs. 64 bit] and therefore uses the
same space on the stack. On 32-bit platforms, the stack use
is probably doubled, but in return a dereference is avoided.
Supporting arbitrary gas-mixes (H2, Ar, ...) will be such an
invasive change that going back to pointers is probably the
least of our worries.
This commit is a step in const-ifying input parameters (passing
by value is the ultimate way of signaling that the input parameter
will not be changed [unless there are references to said parameter]).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There were two functions for getting gas-mixes at a certain timestamp:
- get_gasmix() for repeated queries.
- get_gas_at_time() for a single query.
Since the latter is a special case of the former, simply call
the former in the latter. Moreover, rename to get_gasmix_at_time()
for consistency.
Replace on get_gasmix() call, which was outside of a loop by the
corresponding get_gasmix_at_time() call.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Currently, get_gasmix_from_event() and get_gasmix() return pointers
to either static or to (possibly changing) dive data. This seems like
a dangerous practice and the returned data should be used immediately.
Instead, return the gasmix by value. This is in preparation of
const-ifying input parameters of a number of core functions, which
will ultimately let the merge() function take const-arguments in
preparation of undo of dive-merging.
On common 64-bit systems gasmix (two "int"s) is the size of a pointer
and can be returned in a register.
On 32-bit systems a pointer to the struct to be filled out will be
passed.
Since get_gasmix() now returns a value, the first invocation is
tested by a NULL-initialized "struct event *". Document this in
a comment.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Conceptually, the doFilter() functions shouldn't modify the dive
they test. Therefore, make the argument const. To do this, constify
the parameter of get_dive_location(), which likewise seems to be
the right thing to do.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There were numerous inlined functions in dive.h. For many of them
inlining is dubious. Let's uninline most of them, with the exception
of trivial accessors and interpolate().
On current master, this gave a size reduction of 5 pages:
-rwxrwxr-x 1 bs bs 5863656 Jul 18 20:57 subsurface-inline
-rwxrwxr-x 1 bs bs 5843176 Jul 18 20:48 subsurface-noinline
-----------------------------------------------------------
20480
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
dive_getUniqID() is used to create unique dive ids, which are
stable during application lifetime. It was passed a dive, checked
that the id was not set (if it was that it is know to the application)
and set a new id (in contradiction to its name!) if it hadn't any.
There were three callers:
alloc_dive(): called the function on a zeroed dive struct.
fixup_dive(): called the function only if the dive had a 0 id.
MainWindow::setupForAddAndPlan(): called the function on a zeroed dive
struct.
Thus, in all three callers the id is guaranteed to be zero and
the whole keeping-track-of-ids logic is moot. Remove the logic,
don't pass a dive struct to dive_getUniqID() and move the function
to the C-backend.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Only the first computer is taken into account to find
surface intervals. All further dive computers are split
according to time.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
When we split a dive in two, we keep the dive computer ID for the dive,
but we should update the actual _time_ of the split dive to match the
split.
And when we look for "are these the exact same dives", we should check
not only that the dive computer dive ID matches, but also that the dive
computer time matches, so that we don't consider two parts of a dive
that has been split to be obviously the same dive.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The dive splitting was completely wrong, because we checked the time of
the previous sample by doing
sample[i - 1].time.seconds
which is entirely wrong. The 'sample' variable is the *current* sample,
so the time of the previous sample is simply
sample[-1].time.seconds
Alternatively, we could have started from the first sample, and done
dc->sample[i - 1].time.seconds
but mixing the two concepts up just gets you a random sample pointer
that is likely not a valid sample at all, and obviously does not have
the right time at all.
As a result, dive splitting was pretty much random. Sometimes it worked
purely by mistake, because the rest of the logic was right (ie we _had_
found the right point where we reached the surface in the dive etc, the
"previous sample time" was simply used to decide if the surface interval
was sufficient to split the dive up).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
When adding a picture to a dive, cache_picture() was called, which
calculated the hash of the picture in a background-thread.
This made tests occasionally fail, because the tests depended on
the filename-to-localfilename being overwritten in a call running
in a different thread. Depending on which thread finished first,
the test succeeded or failed.
The easiest way to circumvent this problem is to remove the cache_picture()
call. The hash will be calculated anyway with the thumbnails. And
the only function of the hash is the "find moved images" function. Which
is not an issue here, because the user just loaded the images from
disk.
Reported-by: Jan Iversen <jani@apache.org>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The code changes to standardise the named of divemodes and to
separate internal divemode names and UI divemode names introduced
a bug that caused non-backward compatability with existing
dive logs. The reason for this is the definition of the
divemode_text strings in dive.c
This change reverses that definition and brings about correct
loading of PSCR dive logs as well as correct parsing of bailout
events involving PSCR.
Signed-off-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
The former should be translated but not those that
go to xml/git.
... and fix capitalization of pSCR.
Suggested-by: Stefan Fuchs <sfuchs@gmx.de>
Signed-off-by: Robert C. Helling <helling@atdotde.de>
...as the usuage is not anymore about a computer but
a momentary dive mode. Rename the end indicator as well.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Under some conditions get_current_divemode() (in dive.c) returns an
erroneous divemode. This happens when there are several events at
the very beginning of the dive, as can happen in some CCR dive logs.
This commit fixes that bug.
Signed-off-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
Replaced a rather cumbersome function that that did the above. Upon
the suggestion of Robert Helling who proposed a much shorter way,
this new function replaced the previous ones. This necessitated
changes to divelist.c, profile.c and plannernotes.c, as well as
dive.c/h.
Signed-off-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
Function peek_next_divemodechange() is redundant if get_next_divemodechange()
has one additional parameter. Calls to get_next_divemodechange() were
updated in divelist.c, plannernotes.c and profile.c.
Signed-off-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
I removed the special event type that has been used for bailout events.
Bailout events are now just bookmarks with a specific name "e.g. OC,
CCR, PSCR). This removes a case where a segmentation error occurred
when trying to remove a bailout event from the dive profile.
Signed-off-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
This is the second step for implementing bailout. The indirect
calls to fill_pressures through add_segment() (in deco.c) are
addressed. Bailout is now fully implemented in the dive log but
not in the dive planner.
1) The parameters to add_segment() are changed to take a
divemode as the second last parameter, and not a *dive.
2) Call to add_segment() in profile.c and in divelist.c are
adapted. In divelist.c some calls to add_segment were left
using dc-> divemode instead of possible bailout. This appears
tp be the most appropriate route.
3) The functions get_divemode_from_time() and get_next_divemodechange()
in dive.c have had some small changes.
4) The calls to get_segment(0 in planner.c were changed to reflect
the new parameter list, but not updated to reflect bailout. This
is the next step.
Signed-off-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
This is a first step to interpret bailout events.
1) The event structures have a new attribute: divemode.
Currently interpreted dive modes are OC, CCR, PSCR.
2) When doing fill_pressures(), the calculation is aware
of divemode. When divemode is OC (==bailout), then
the appropriate calculations of gas pressures are done.
3) Two new functions get_next_divemodechange() and
get_divemode_at_time() are created to find divemode
changes in the events linked list and to determine
the dive mode at any point during the dive.
4) fill_pressures gets a small amendment to facilitate
the correct calculations, depending on divemode.
The cases where fill_pressures() is used *outside the planner*
are changed. The result is that, for dives with bailout, the
correct gas pressures are shown on the dive profile. The
deco for bailout dives is not yet correct. This is the
next step.
Signed-off-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
In imagedownloader.cpp the only thing we need from the picture struct
is the filename. Therefore, use QStrings instead of the picture struct.
This simplifies memory management.
Remove the clone_picture() function, which is not needed anymore.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
fake_dc() used to return a statically allocated dc with statically
allocated samples. This is of course a questionable practice in
the light of multi-threading / resource ownership. Once these
problems were recognized, the parameter "alloc" was added. If set
to true, the function would still return a statically allocated
dc, but heap-allocated samples, which could then be copied in
a different dc.
All in all an ownership nightmare and a recipie for disaster.
The returned static dc was only used as a pointer to the samples
anyway. There are four callers of fake_dc() and they all have access
to a dc-structure without samples. Therefore, change the semantics
of fake_dc() to fill out the passed in dc. If the caller does
not care about the samples, it can simply reset the sample number
to zero after work.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Previous taglist_get_tagstring signature/implementation did not allow
handling of cases where inputted buffer could not contain all tags.
New implementation allocates buffer based on pre-computed size allowing to
insert all tags in the returned string.
Added get_taglist_string in qthelper to handle conversion to QString
Added TestTagList with tests for taglist_get_tagstring
Signed-off-by: Jeremie Guichard <djebrest@gmail.com>
Thus, metadata has to be only read once and the picture_load_exif_data()
function can be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Make arguments to set_informational_units(), set_git_prefs(),
set_userid(), dive_remove_picture() and update_event_name()
"const char *" for consistency with the rest of core/dive.c.
This will allow replacing toUtf8().data() with the constData()
version in a subsequent commit.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This introduces a fixup function that walks all the samples and
populates the no_o2sensors if its zero and supposed to be something
else.
There is a bug somewhere which Willem hit, causing this to never be set.
Reported-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Anton Lundin <glance@acc.umu.se>
In the if case above, we already conclude its a OC dive, but its cleaner
to actually pass the current mode instead of a hard coded value.
This also makes the code less prune to future bugs.
Signed-off-by: Anton Lundin <glance@acc.umu.se>
The hash field in the picture-structure was in principle non-operational.
It was set on loading, but never actually changed. The authoritative
hash comes from the filename->hash map.
Therefore, make this explicit by removing the hash field from the
picture structure.
Instead of filling the picture structure on loading, add the
hash directly to the filename->hash map. This is done in the
register_hash() function, which does not overwrite old entries.
I.e. the local hash has priority over the save-file. This
policy might be refined in the future.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Change the strategy when to allow cylinder removal from a dive:
- Not remove when cylinder has gas switch events, in any other cases
allow removal
- Remove this whole "cylinder with same gas" thing being a criteria
for cylinder removal
When removing a cylinder which has corresponding pressure info in
samples, also remove this pressure info from the samples.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
Since all qt-helpers are defined in qthelper.cpp, there seems to be
no reason to have two include files. By unifying the two files,
duplication and inconsistencies are removed. The C++-only part is
simply compiled away with #ifdefs.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Mostly replace "return (expression);" by "return expression;" and one
case of "function((parameter))" by "function(parameter)".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
as otherwise there are warning on the descent.
The ICD line in the info box is generated for all
gas switches with decreasing He content.
Also change the presentation in the info box to align it
with the notes.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Move the above function from plannernotes.c to dive.c so that
it is available to be called from the dive log part of the
software, and not only from the planner. The following was done:
1) Edit the comment above the code to make it more accurate
2) Move the structure icd_data to dive.h
3) Create an external reference in dive.h for the above function
4) Copy the body of isobaric_counterdiffusion() to dive.c
Signed-off-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
There are ca. 50 constructs of the kind
same_string(s, "")
to test for empty or null strings. Replace them by the new helper
function empty_string().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The list iteration in dive_remove_picture() was buggy and would
crash if handled a picture that is not in the list.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Change the merging behavior for the following information:
Divemaster, buddy, suit:
From "(a) or (b)" to "a, b"
Notes:
From "(a) or (b)" to "a\n--\nb"
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
Make all char * pointers in pref.h const to make it clear that these
strings are not mutable. This meant adding a number of (void *) casts
in calls to free(). Apart from being the right thing to do, this commit
makes the code more consistent, as many of the strings in pref.h were
already const.
While touching core/qthelper.cpp turn three instances of (void*) into
(void *).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Fixup the NDL value to '-1' at the very beginning of a dive.
Some dive computer report a NDL of 0 at the very beginning of a dive
and then only some 10 seconds later they report the correct value
like 240 min for the first time.
Translate this 0 at the beginning of a dive into our internal '-1'
for no info available.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
Type duration_t changed from uint to int.
Default value of '-1' introduced for some of the values in struct sample:
NDL used -1 as default.
Bearing uses -1 as default (no bearing set).
Display pXX, EAD, END, density, MOD only if values are larger than 0.
In profile don't display data from two first and two last plot_data
entries in info box.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
The pressure information of cylinder should be kept intact when
copy-pasting other cylinder related information from other dive.
According to Dirk, the gas mix is wanted to be changed as technical
divers might have always the same multiple cylinders and wish to copy
the gasmix information over.
Fixes#689
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
In the planner if one adds two or more cylinders with the same gasmix
(e.g. back gas and bottom stage 18/45) the drop down and data in the
used gas column of the planner points table will be filled with a more
verbose string mentioning also the cyl number and the cyl type
description.
Makes it easier in such a case to select the right cylinder.
Introduces also a helper function which tells you if there is another
cylinder with the same gasmix as the provided cylinder.
This also has an option if it should consider unused cylinders or not.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
When planning a new dive (not replan!!!) based on an existing (planned)
dive, the cylinders from the existing selected dive are copied.
This patch guarantees that cylinders which had been marked as "unused"
are indeed copied as well. Sounds strange at the first moment but makes
sense because if one marks a cylinder explicitly as "unused" in the
planner instead of deleting it that does mean that one wants to keep
this cylinder to have it available and be able to reenable it later-on.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
When we merge dives, the sample_start and sample_end pressures are only
used in-memory for displaying data to the user. However, we should
update them as well as this will show the user the correct data in the
equipment/cylinder and i.e. SAC calculation.
Fixes#577
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
As these are probably manually entered dives with incomplete data, it is
better not to merge them.
See #561
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
The momentary SAC rate got broken by the multiple ressure handling too,
and always used just the first cylinder.
This uses the new "get_gasmix()" helper to see what you're breathing,
and will do the SAC rate over all the cylinders that contain that gas.
So it should now DTRT even for sidemount diving (assuming you had the
same gas in the sidemount cylinders).
NOTE! We could just do the SAC rate over *all* the gases you have
pressures for, and maybe that's the right thing to do. The ones you are
not breating from shouldn't have their pressure change. But maybe some
people add their drysuit argon gas to the gas list?
So this may need more work, but it's a step in the right direction.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This finally handles multiple cylinder pressures, both overlapping and
consecutive, and it seems to work on the nasty cases I've thrown at it.
Want to just track five different cylinders all at once, without any
pesky gas switch events? Sure, you can do that. It will show five
different gas pressures for your five cylinders, and they will go down
as you breathe down the cylinders.
I obviously don't have any real data for that case, but I do have a test
file with five actual cylinders that all have samples over the whole
course of the dive. The end result looks messy as hell, but what did
you expect?
HOWEVER.
The only way to do this sanely was
- actually make the "struct plot_info" have all the cylinder pressures
(so no "sensor index and pressure" - every cylinder has a pressure for
every plot info entry)
This obviously makes the plot_info much bigger. We used to have
MAX_CYLINDERS be a fairly generous 8, which seems sane. The planning
code made that 8 be 20. That seems questionable. But whatever.
The good news is that the plot-info should hopefully get freed, and
only be allocated one dive at a time, so the fact that it is big and
nasty shouldn't be a scaling issue, though.
- the "populate_pressure_information()" function had to be rewritten
quite a bit. The good news is that it's actually simpler now, although
I would not go so far as to really call it simple. It's still
complicated and suble, but now it explicitly just does one cylinder at
a time.
It *used* to have this insanely complicated "keep track of the pressure
ranges for every cylinder at once". I just couldn't stand that model
and keep my sanity, so it now just tracks one cylinder at a time, and
doesn't have an array of live data, instead the caller will just call
it for each cylinder.
- get rid of some of our hackier stuff, like the code that populates the
plot_info data code with the currently selected cylinder number, and
clears out any other pressures. That obviously does *not* work when you
may not have a single primary cylinder any more.
Now, the above sounds like all good things. Yeah, it mostly is.
BUT.
There's a few big downsides from the above:
- there's no sane way to do this as a series of small changes.
The change to make the plot_info take an array of cylinder pressures
rather than the sensor+pressure model really isn't amenable to "fix up
one use at a time". When you switch over to the new data structure
model, you have to switch over to the new way of populating the
pressure ranges. The two just go hand in hand.
- Some of our code *depended* on the "sensor+pressure" model. I fixed all
the ones I could sanely fix. There was one particular case that I just
couldn't sanely fix, and I didn't care enough about it to do something
insane.
So the only _known_ breakage is the "TankItem" profile widget. That's
the bar at the bottom of the profile that shows which cylinder is in
use right now. You'd think that would be trivial to fix up, and yes it
would be - I could just use the regular model of
firstcyl = explicit_first_cylinder(dive, dc)
.. then iterate over the gas change events to see the others ..
but the problem with the "TankItem" widget is that it does its own
model, and it has thrown away the dive and the dive computer
information. It just doesn't even know. It only knows what cylinders
there are, and the plot_info. And it just used to look at the sensor
number in the plot_info, and be done with that. That number no longer
exists.
- I have tested it, and I think the code is better, but hey, it's a
fairly large patch to some of the more complex code in our code base.
That "interpolate missing pressure fields" code really isn't pretty. It
may be prettier, but..
Anyway, without further ado, here's the patch. No sign-off yet, because I
do think people should look and comment. But I think the patch is fine,
and I'll fix anythign that anybody can find, *except* for that TankItem
thing that I will refuse to touch. That class is ugly. It needs to have
access to the actual dive.
Note how it actually does remove more lines than it adds, and that's
despite added comments etc. The code really is simpler, but there may be
cases in there that need more work.
Known missing pieces that don't currently take advantage of concurrent
cylinder pressure data:
- the momentary SAC rate coloring for dives will need more work
- dive merging (but we expect to generally normally not merge dive
computers, which is the main source of sensor data)
- actually taking advantage of different sensor data from different
dive computers
But most of all: Testing. Lots and lots of testing to find all the
corner cases.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We had a "add_sample_pressure()" helper functions that was local to just
the libdivecomputer downloading code, but it really is applicable to
pretty much any code that adds cylinder pressure data to a sample.
Also add another helper: "legacy_format_o2pressures()" which checks the
sample data to see if we can use the legacy format, and returns the o2
pressure sensor to use for that legacy format.
Because both the XML and the git save format will need a way to save the
compatible old-style information, when possible, but save an extended
format for when we have data from multiple concurrent sensors.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This tries to sanely handle the case of a dive computer reporting
multiple cylinder pressures concurrently.
NOTE! There are various "interesting" situations that this whole issue
brings up:
- some dive computers may report more cylinder pressures than we have
slots for.
Currently we will drop such pressures on the floor if they come for
the same sample, but if they end up being spread across multiple
samples we will end up re-using the slots with different sensor
indexes.
That kind of slot re-use may or may not end up confusing other
subsurface logic - for example, make things believe there was a
cylidner change event.
- some dive computers might send only one sample at a time, but switch
*which* sample they send on a gas switch event. If they also report
the correct sensor number, we'll now start reporting that pressure in
the second slot.
This should all be fine, and is the RightThing(tm) to do, but is
different from what we used to do when we only ever used a single
slot.
- When people actually use multiple sensors, our old save format will
start to need fixing. Right now our save format comes from the CCR
model where the second sensor was always the Oxygen sensor.
We save that pressure fine (except we save it as "o2pressure" - just
an odd historical naming artifact), but we do *not* save the actual
sensor index, because in our traditional format that was always
implicit in the data ("it's the oxygen cylinder").
so while this code hopefully makes our libdivecomputer download do the
right thing, there *will* be further fallout from having multiple
cylinder pressure sensors. We're not done yet.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This is a very timid start at making us actually use multiple sensors
without the magical special case for just CCR oxygen tracking.
It mainly does:
- turn the "sample->sensor" index into an array of two indexes, to
match the pressures themselves.
- get rid of dive->{oxygen_cylinder_index,diluent_cylinder_index},
since a CCR dive should now simply set the sample->sensor[] indices
correctly instead.
- in a couple of places, start actually looping over the sensors rather
than special-case the O2 case (although often the small "loops" are
just unrolled, since it's just two cases.
but in many cases we still end up only covering the zero sensor case,
because the CCR O2 sensor code coverage was fairly limited.
It's entirely possible (even likely) that this migth break some existing
case: it tries to be a fairly direct ("stupid") translation of the old
code, but unlike the preparatory patch this does actually does change
some semantics.
For example, right now the git loader code assumes that if the git save
data contains a o2pressure entry, it just hardcodes the O2 sensor index
to 1.
In fact, one issue is going to simply be that our file formats do not
have that multiple sensor format, but instead had very clearly encoded
things as being the CCR O2 pressure sensor.
But this is hopefully close to usable, and I will need feedback (and
maybe test cases) from people who have existing CCR dives with pressure
data.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We currently carry two pressures around for all the samples and plot
info, but the second pressure is reserved for CCR dives as the O2
cylinder pressure.
That's kind of annoying when we *could* use it for regular sidemount
dives as the secondary pressure.
So start prepping for that instead: don't make it "pressure" and
"o2pressure", make it just be an array of two pressure values.
NOTE! This is purely mindless prepwork. It literally just does a
search-and-replace, keeping the exact same semantics, so "pressure[1]"
is still just O2 pressure.
But at some future date, we can now start using it for a second sensor
value for sidemount instead.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The core to avoid adding redundant gas switch events was completely
buggered, and caused the result list to be corrupted if it ever
triggered. This should fix it.
Fixes: b5de08b7 ("No gas change event on merging dives with same gas")
Reported-by: Jan Mulder <jlmulder@xs4all.nl>
Cc: Miika Turkia <miika.turkia@gmail.com>
Cc: Dirk Hohndel <dirk@hohndel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
... for consistency, while we are at it.
There are still some internal depth variables which are ints
somebody might take a go at those.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
This is needed in the altitude pressure conversion as there
negative altitudes are possible (for diving in the netherlands
or the Dead Sea).
Signed-off-by: Robert C. Helling <helling@atdotde.de>