Hi,
Now that we are discussing major api improvements, let's also have a look at the sample parsing api. The current api generates a stream of sample values, where the time value is special in the sense that it starts a new sample. I think it would be cleaner to somehow return an opaque sample, and then get all the values available for that sample. Something similar to this:
void sample_cb (dc_sample_t *sample, void *userdata) { dc_sample_get_time (sample, ...); dc_sample_get_depth (sample, ...); dc_sample_get_something (sample, ...); ... }
Let's discuss this a bit in more detail.
1. Sample types
The first question is of course which sample types do we want to support? The absolute minimum to support is:
* time * depth * pressure * temperature
At the moment we also have:
* events: Anything that happens only at specific point in time. All other sample types are typically measurements obtained from a sensor (or calculations based on them), with values available for each sample point (or at least every x sample points). But that is not the case for events. Typical examples are warnings, gas changes, etc. At the moment many events are supported, but the api sucks. The current plan is remove the events, use the vendor type instead (see below), and then add back support for the important events with a better api. The details of this last part are still unclear, but support for gas switches is definitely high on the list.
* rbt: The RBT (remaining bottom time) is the time you can spend at the current depth and still have enough gas supply to make a safe ascent. It's currently available for the Uwatec Smart/Galileo only. Other air integrated dive computers often support a similar concept, so I think we can just keep this. Maybe rename it to the less cryptic "airtime"? Note that the actual interpretation may vary between models, depending on whether factors like the safety reserve, the ascent time, decompression time, etc are taking into account or not.
* heartbeat: Another Uwatec Smart/Galileo feature. Although I don't know any other model that supports a heart monitor sensor, but it doesn't cause any trouble either. So I think we can keep this one too. BTW, is the correct name heartbeat or heartrate? I think it's heartrate, expressed in beats per minute (bpm). It's a bit confusing because both have the same translation in my native language.
* bearing: Yet another Uwatec Smart/Galileo feature. There are several other models that have a digital compass, but they usually report it as an event, not a sample type. I also believe it makes more sense to consider a change in the compass bearing as an event. It's a setting you change, not some sensor that is polled every sample. I don't think any dive computer will ever generate a continuous stream with compass bearings. So I think we should drop this. BTW, is the correct name comnpass bearing or heading?
* vendor: A vendor specific extension. This is intended for all samples that don't fit well into one of the types supported by the libdivecomputer library. The application is responsible for parsing the raw data, but at least it doesn't have to care about where and how the samples are stored. There are actually two variants of the vendor type today. For the first variant each piece of info gets its own vendor sample. That means a dc_sample_t can contain multiple vendor values. The second variant is the raw data representing the entire dc_sample_t data. Both have their use, so I propose to reserve the vendor type for the first case, and add a new raw type for the second case.
What else should we support? Some common requests I get are:
* gas switches * no decompression time * decompression stops * ...
Decompression is a bit troublesome. Some models have just a simple deco flag. Others provide a time and depth, which is typically the time to surface (TTS) (e.g. total time for all stops and ascent combined) and the depth of the current stop. But their are plenty of other interpretations possible too. I won't be surprised some of the more technical dive computers provide a full decoplan (e.g. time at each depth). I have no idea how to support something like this in a clean way.
Note that an alternative solution would be to implement a decompression algorithm in the application and calculate all kinds of deco related parameters (tissue saturation, deco stops, etc) that way. It won't necessary match with your dive computer, but at least you would get a consistent application experience, regardless of the type of dive computer you have. Personally, I think this makes more sense for a general purpose logbook application, but not everyone may agree with that of course.
2. Which sample types are present?
With the current callback api, you just get all the sample types pushed to the application. With the new proposal the application needs to retrieve each sample value manually. Thus somehow we need a mechanism to query which sample types are available in the dc_sample_t object. Suggestions are welcome.
Also, how do we deal with sample types that can occur multiple times (e.g. vendor extensions, pressure values for multiple tanks, alarms, etc)?
3. Memory management
To be consistent with the dc_dive_t object, the dc_sample_t object should be allocated by the dc_dive_t object and freed by the application. However I'm not convinced that is a good idea. The number of samples is usually relative large (e.g. 3600 samples for a 1 hour dive at a 1 second sample rate) and in the typical scenario there is no reason to retain the sample object after having extracting the values (e.g. you call free right before leaving the callback function). Thus you end up with several hundreds or thousands of tiny objects that are allocated and immediately freed again. That's just very inefficient if you ask me!
A possible workaround would be to make the objects reference counted. Then, if the application doesn't keep a reference to the object, we can re-use the previous one, instead of creating a new one from scratch. But the drawback is that if we want to support passing objects between threads (see my previous email) the reference counting should be made thread-safe too.
Note that I'm not an export on multi-threading, so please correct me if I'm writing nonsense! Also everything I wrote so far is open for discussion. Feedback is highly appreciated!
Jef