OpenScanDeviceLib
OpenScan Device Programming Interface
Todo List
Global OScDev_Acquisition_GetClockSource (OScDev_Acquisition *acq, OScDev_ClockSource *clock)
This is redundant with OScDev_Acquisition_IsClockRequested(). Remove.
Global OScDev_DeviceImpl::Arm )(OScDev_Device *device, OScDev_Acquisition *acq)
Currently, state change after the device is armed is handled in a variable way depending on what triggers the state change (especially stop of acquisition). We should replace this with a simpler interface where the device calls new functions OScDev_Acquisition_NotifyStart() and OScDev_Acquisition_NotifyStop(). The start notification will be purely informational, used e.g. so that the GUI can show "waiting for start trigger" vs "acquisition running". The stop trigger will indicate that all action has finished and the device is ready to be disarmed. (Disarm() should be a mandatory function distinct from Stop(), which should behave as a software trigger for cancellation.) There should also be a way for a device to declare that it is not capable of issuing a start notification (in which case arrival of data can be used as a proxy for display purposes). Stop(), unlike Disarm(), need not be called when OpenScanLib has already received a stop notification.
Global OScDev_DeviceImpl::EnumerateInstances )(OScDev_PtrArray **devices)
Provide an alternative mechanism to instantiate devices that cannot be enumerated. Rather than imitating Micro-Manager's leaky "pre-init property" mechanism, we should use dedicated "device loader" objects, which can have settings such as port numbers.
Global OScDev_DeviceImpl::GetActualPixelRate )(OScDev_Device *device, double nominalRateHz, double *actualRateHz)
It is not clear if this is the best method of matching pixel rates. At the very least, this does allow OpenScanLib to quantify the error, so that the user might establish a discrete set of usable rates. That's probably better than any sort of poorly thought-through automagical matching.
Global OScDev_DeviceImpl::IsRunning )(OScDev_Device *device, bool *isRunning)
This function should be replaced with a callback-based interface to avoid polling and simplify device module implementation.
Global OScDev_DeviceImpl::Start )(OScDev_Device *device)
Better to rename to SoftwareTriggerStart()?
Global OScDev_DeviceImpl::Stop )(OScDev_Device *device)

This function should be split into two separate functions, SoftwareTriggerStop() and Disarm(), with very different roles. The former should merely be an asynchronous signal that the device should ignore any subsequent start triggers and stop as soon as possible. Actual completion of stopping should be notified via a callback (see Todo at Arm). The latter (Disarm()) should mainly handle cleanup, and should be guaranteed to be called exactly once per armed acquisition, after all processes have stopped.

SoftwareTriggerStop() can be optional to implement; we should additionally provide bool OScDev_Acquisition_SoftwareStopTriggered() which can be called any time between Arm() and Disarm(); this will supersede the bool return value of OScDev_Acquisition_CallFrameCalback().

Global OScDev_DeviceImpl::Wait )(OScDev_Device *device)
This function should be removed, because it leads to reinvention of condition variable code in each device module. Better to report state changes using a callback interface.
Global OScDev_SettingImpl::GetNumericConstraintType )(OScDev_Setting *setting, OScDev_ValueConstraint *constraintType)
We cannot realistically allow the constraint type to change, so this should be a static data field.