diff --git a/src/device-private.h b/src/device-private.h index 4ee4f20..056dd41 100644 --- a/src/device-private.h +++ b/src/device-private.h @@ -14,6 +14,9 @@ typedef struct device_backend_t device_backend_t; struct device_t { const device_backend_t *backend; + // Progress callback data. + progress_callback_t progress; + void *userdata; }; struct device_backend_t { @@ -34,6 +37,23 @@ struct device_backend_t { device_status_t (*close) (device_t *device); }; +#define INFINITE ((unsigned int)-1) + +typedef struct device_progress_state_t { + progress_callback_t callback; + void *userdata; + unsigned int current, maximum; +} device_progress_state_t; + +void +progress_init (device_progress_state_t *progress, device_t *device, unsigned int maximum); + +void +progress_event (device_progress_state_t *progress, device_event_t event, unsigned int value); + +void +progress_set_maximum (device_progress_state_t *progress, unsigned int value); + void device_init (device_t *device, const device_backend_t *backend); diff --git a/src/device.c b/src/device.c index de96168..2c1dfd5 100644 --- a/src/device.c +++ b/src/device.c @@ -1,3 +1,5 @@ +#include + #include "device-private.h" #define NULL 0 @@ -7,6 +9,8 @@ void device_init (device_t *device, const device_backend_t *backend) { device->backend = backend; + device->progress = NULL; + device->userdata = NULL; } @@ -20,6 +24,19 @@ device_get_type (device_t *device) } +device_status_t +device_set_progress (device_t *device, progress_callback_t callback, void *userdata) +{ + if (device == NULL) + return DEVICE_STATUS_UNSUPPORTED; + + device->progress = callback; + device->userdata = userdata; + + return DEVICE_STATUS_SUCCESS; +} + + device_status_t device_handshake (device_t *device, unsigned char data[], unsigned int size) { @@ -109,3 +126,53 @@ device_close (device_t *device) return device->backend->close (device); } + + +void +progress_init (device_progress_state_t *progress, device_t *device, unsigned int maximum) +{ + if (progress == NULL) + return; + + progress->callback = (device ? device->progress : NULL); + progress->userdata = (device ? device->userdata : NULL); + progress->maximum = maximum; + progress->current = 0; +} + + +void +progress_event (device_progress_state_t *progress, device_event_t event, unsigned int value) +{ + if (progress == NULL) + return; + + switch (event) { + case DEVICE_EVENT_WAITING: + break; + case DEVICE_EVENT_PROGRESS: + progress->current += value; + break; + default: + return; + } + + assert (progress->maximum != 0); + assert (progress->maximum >= progress->current); + + if (progress->callback) + progress->callback (event, progress->current, progress->maximum, progress->userdata); +} + + +void +progress_set_maximum (device_progress_state_t *progress, unsigned int value) +{ + if (progress == NULL) + return; + + assert (value <= progress->maximum); + assert (value >= progress->current); + + progress->maximum = value; +} diff --git a/src/device.h b/src/device.h index 88af6f6..b908425 100644 --- a/src/device.h +++ b/src/device.h @@ -30,12 +30,20 @@ typedef enum device_status_t { DEVICE_STATUS_MEMORY = -7 } device_status_t; +typedef enum device_event_t { + DEVICE_EVENT_WAITING, + DEVICE_EVENT_PROGRESS +} device_event_t; + typedef struct device_t device_t; typedef int (*dive_callback_t) (const unsigned char *data, unsigned int size, void *userdata); +typedef void (*progress_callback_t) (device_event_t event, unsigned int current, unsigned int maximum, void *userdata); device_type_t device_get_type (device_t *device); +device_status_t device_set_progress (device_t *device, progress_callback_t callback, void *userdata); + device_status_t device_handshake (device_t *device, unsigned char data[], unsigned int size); device_status_t device_version (device_t *device, unsigned char data[], unsigned int size);