diff --git a/src/shearwater_common.c b/src/shearwater_common.c index c6dafbb..d4b8297 100644 --- a/src/shearwater_common.c +++ b/src/shearwater_common.c @@ -342,7 +342,7 @@ shearwater_common_transfer (shearwater_common_device_t *device, const unsigned c dc_status_t -shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int address, unsigned int size, unsigned int compression) +shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int address, unsigned int size, unsigned int compression, dc_event_progress_t *progress) { dc_device_t *abstract = (dc_device_t *) device; dc_status_t rc = DC_STATUS_SUCCESS; @@ -370,9 +370,11 @@ shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buf } // Enable progress notifications. - dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER; - progress.maximum = 3 + size + 1; - device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + unsigned int initial = 0, current = 0, maximum = 3 + size + 1; + if (progress) { + initial = progress->current; + device_event_emit (abstract, DC_EVENT_PROGRESS, progress); + } // Transfer the init request. rc = shearwater_common_transfer (device, req_init, sizeof (req_init), response, 3, &n); @@ -387,8 +389,11 @@ shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buf } // Update and emit a progress event. - progress.current += 3; - device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + if (progress) { + current += 3; + progress->current = initial + STEP (current, maximum); + device_event_emit (abstract, DC_EVENT_PROGRESS, progress); + } unsigned int done = 0; unsigned char block = 1; @@ -415,8 +420,11 @@ shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buf } // Update and emit a progress event. - progress.current += length; - device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + if (progress) { + current += length; + progress->current = initial + STEP (current, maximum); + device_event_emit (abstract, DC_EVENT_PROGRESS, progress); + } if (compression) { if (shearwater_common_decompress_lre (response + 2, length, buffer, &done) != 0) { @@ -454,8 +462,11 @@ shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buf } // Update and emit a progress event. - progress.current += 1; - device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + if (progress) { + current += 1; + progress->current = initial + STEP (current, maximum); + device_event_emit (abstract, DC_EVENT_PROGRESS, progress); + } return DC_STATUS_SUCCESS; } diff --git a/src/shearwater_common.h b/src/shearwater_common.h index 2283154..4253a00 100644 --- a/src/shearwater_common.h +++ b/src/shearwater_common.h @@ -39,6 +39,9 @@ extern "C" { #define PERDIX 5 #define PERDIXAI 6 +#define NSTEPS 10000 +#define STEP(i,n) ((NSTEPS * (i) + (n) / 2) / (n)) + typedef struct shearwater_common_device_t { dc_device_t base; dc_serial_t *port; @@ -54,7 +57,7 @@ dc_status_t shearwater_common_transfer (shearwater_common_device_t *device, const unsigned char input[], unsigned int isize, unsigned char output[], unsigned int osize, unsigned int *actual); dc_status_t -shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int address, unsigned int size, unsigned int compression); +shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int address, unsigned int size, unsigned int compression, dc_event_progress_t *progress); dc_status_t shearwater_common_identifier (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id); diff --git a/src/shearwater_petrel.c b/src/shearwater_petrel.c index 3b60bf4..46a7582 100644 --- a/src/shearwater_petrel.c +++ b/src/shearwater_petrel.c @@ -168,6 +168,11 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call return DC_STATUS_NOMEMORY; } + // Enable progress notifications. + unsigned int current = 0, maximum = 0; + dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + // Read the serial number. rc = shearwater_common_identifier (&device->base, buffer, ID_SERIAL); if (rc != DC_STATUS_SUCCESS) { @@ -240,8 +245,16 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo); while (1) { + // Update the progress state. + // Assume the worst case scenario of a full manifest, and adjust the + // value with the actual number of dives after the manifest has been + // processed. + maximum += 1 + RECORD_COUNT; + // Download a manifest. - rc = shearwater_common_download (&device->base, buffer, MANIFEST_ADDR, MANIFEST_SIZE, 0); + progress.current = NSTEPS * current; + progress.maximum = NSTEPS * maximum; + rc = shearwater_common_download (&device->base, buffer, MANIFEST_ADDR, MANIFEST_SIZE, 0, &progress); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to download the manifest."); dc_buffer_free (buffer); @@ -270,6 +283,10 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call count++; } + // Update the progress state. + current += 1; + maximum -= RECORD_COUNT - count; + // Append the manifest records to the main buffer. if (!dc_buffer_append (manifests, data, count * RECORD_SIZE)) { ERROR (abstract->context, "Insufficient buffer space available."); @@ -283,6 +300,11 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call break; } + // Update and emit a progress event. + progress.current = NSTEPS * current; + progress.maximum = NSTEPS * maximum; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + // Cache the buffer pointer and size. unsigned char *data = dc_buffer_get_data (manifests); unsigned int size = dc_buffer_get_size (manifests); @@ -293,7 +315,9 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call unsigned int address = array_uint32_be (data + offset + 20); // Download the dive. - rc = shearwater_common_download (&device->base, buffer, DIVE_ADDR + address, DIVE_SIZE, 1); + progress.current = NSTEPS * current; + progress.maximum = NSTEPS * maximum; + rc = shearwater_common_download (&device->base, buffer, DIVE_ADDR + address, DIVE_SIZE, 1, &progress); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to download the dive."); dc_buffer_free (buffer); @@ -301,6 +325,9 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call return rc; } + // Update the progress state. + current += 1; + unsigned char *buf = dc_buffer_get_data (buffer); unsigned int len = dc_buffer_get_size (buffer); if (callback && !callback (buf, len, buf + 12, sizeof (device->fingerprint), userdata)) @@ -309,6 +336,11 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call offset += RECORD_SIZE; } + // Update and emit a progress event. + progress.current = NSTEPS * current; + progress.maximum = NSTEPS * maximum; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + dc_buffer_free (manifests); dc_buffer_free (buffer); diff --git a/src/shearwater_predator.c b/src/shearwater_predator.c index 3cc79f1..a47d414 100644 --- a/src/shearwater_predator.c +++ b/src/shearwater_predator.c @@ -133,7 +133,12 @@ shearwater_predator_device_dump (dc_device_t *abstract, dc_buffer_t *buffer) return DC_STATUS_NOMEMORY; } - return shearwater_common_download (device, buffer, 0xDD000000, SZ_MEMORY, 0); + // Enable progress notifications. + dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER; + progress.current = 0; + progress.maximum = NSTEPS; + + return shearwater_common_download (device, buffer, 0xDD000000, SZ_MEMORY, 0, &progress); }