diff --git a/DeviceAdapters/CNCMicroscope/RAMPSStage/XYStage.h b/DeviceAdapters/CNCMicroscope/RAMPSStage/XYStage.h index c8d671de3..a340f38c8 100644 --- a/DeviceAdapters/CNCMicroscope/RAMPSStage/XYStage.h +++ b/DeviceAdapters/CNCMicroscope/RAMPSStage/XYStage.h @@ -66,7 +66,6 @@ class RAMPSXYStage : public CXYStageBase int IsXYStageSequenceable(bool& isSequenceable) const; - // action interface // ---------------- int OnPosition(MM::PropertyBase* pProp, MM::ActionType eAct); diff --git a/DeviceAdapters/Cephla/Squid.h b/DeviceAdapters/Cephla/Squid.h index 9de90b272..b1bf35020 100644 --- a/DeviceAdapters/Cephla/Squid.h +++ b/DeviceAdapters/Cephla/Squid.h @@ -284,6 +284,7 @@ class SquidXYStage : public CXYStageBase int IsXYStageSequenceable(bool& isSequenceable) const { isSequenceable = false; return DEVICE_OK; } + int UsesOnXYStagePositionChanged(bool& result) const { result = true; return DEVICE_OK; } // action interface // ---------------- @@ -354,6 +355,8 @@ class SquidZStage : public CStageBase } bool IsContinuousFocusDrive() const { return false; }; + int UsesOnStagePositionChanged(bool& result) const { result = true; return DEVICE_OK; } + int OnAcceleration(MM::PropertyBase* pProp, MM::ActionType eAct); int OnMaxVelocity(MM::PropertyBase* pProp, MM::ActionType eAct); diff --git a/DeviceAdapters/ChuoSeiki_MD5000/ChuoSeiki_MD_XYZ.h b/DeviceAdapters/ChuoSeiki_MD5000/ChuoSeiki_MD_XYZ.h index d8e5c3aba..83ad90796 100644 --- a/DeviceAdapters/ChuoSeiki_MD5000/ChuoSeiki_MD_XYZ.h +++ b/DeviceAdapters/ChuoSeiki_MD5000/ChuoSeiki_MD_XYZ.h @@ -119,6 +119,7 @@ class MD_SingleStage: // Checking device functions int IsStageSequenceable(bool& isSequenceable) const {isSequenceable = false; return DEVICE_OK;} bool IsContinuousFocusDrive() const {return DEVICE_OK;} + int UsesOnStagePositionChanged(bool& result) const { result = true; return DEVICE_OK; } bool SupportsDeviceDetection(void); MM::DeviceDetectionStatus DetectDevice(void); diff --git a/DeviceAdapters/DemoCamera/DemoCamera.h b/DeviceAdapters/DemoCamera/DemoCamera.h index a3dc46c20..dabf6c82a 100644 --- a/DeviceAdapters/DemoCamera/DemoCamera.h +++ b/DeviceAdapters/DemoCamera/DemoCamera.h @@ -556,6 +556,8 @@ class CDemoStage : public CStageBase bool IsContinuousFocusDrive() const {return false;} + int UsesOnStagePositionChanged(bool& result) const { result = true; return DEVICE_OK; } + // action interface // ---------------- int OnPosition(MM::PropertyBase* pProp, MM::ActionType eAct); @@ -636,6 +638,7 @@ class CDemoXYStage : public CXYStageBase int IsXYStageSequenceable(bool& isSequenceable) const {isSequenceable = false; return DEVICE_OK;} + int UsesOnXYStagePositionChanged(bool& result) const { result = true; return DEVICE_OK; } // action interface // ---------------- diff --git a/DeviceAdapters/ESP32/esp32.h b/DeviceAdapters/ESP32/esp32.h index 60101a955..892f58995 100644 --- a/DeviceAdapters/ESP32/esp32.h +++ b/DeviceAdapters/ESP32/esp32.h @@ -389,6 +389,8 @@ class CESP32XYStage : public CXYStageBase int IsXYStageSequenceable(bool& isSequenceable) const { isSequenceable = false; return DEVICE_OK; } + int UsesOnXYStagePositionChanged(bool& result) const { result = true; return DEVICE_OK; } + int OnXStageMinPos(MM::PropertyBase* pProp, MM::ActionType eAct); int OnXStageMaxPos(MM::PropertyBase* pProp, MM::ActionType eAct); int OnYStageMinPos(MM::PropertyBase* pProp, MM::ActionType eAct); diff --git a/DeviceAdapters/OpenFlexure/OpenFlexure.h b/DeviceAdapters/OpenFlexure/OpenFlexure.h index c72e8bd81..103139cb8 100644 --- a/DeviceAdapters/OpenFlexure/OpenFlexure.h +++ b/DeviceAdapters/OpenFlexure/OpenFlexure.h @@ -165,6 +165,7 @@ class ZStage : public CStageBase int GetLimits(double& lower, double& upper) { return DEVICE_UNSUPPORTED_COMMAND;} // nah int IsStageSequenceable(bool& isSequenceable) const { isSequenceable = false; return DEVICE_OK;} bool IsContinuousFocusDrive() const { return false; } + bool Busy() { return false; } // Helper functions diff --git a/DeviceAdapters/PriorPureFocus/PureFocus.h b/DeviceAdapters/PriorPureFocus/PureFocus.h index 5e94fd27a..bdb901d55 100644 --- a/DeviceAdapters/PriorPureFocus/PureFocus.h +++ b/DeviceAdapters/PriorPureFocus/PureFocus.h @@ -170,6 +170,7 @@ class PureFocusOffset : public CStageBase { bool IsContinuousFocusDrive() const { return false; }; + void CallbackPositionSteps(long steps); void RemoveHub() { pHub_ = 0; }; diff --git a/DeviceAdapters/PyDevice/PyStage.h b/DeviceAdapters/PyDevice/PyStage.h index dc0fa9430..4ac22f728 100644 --- a/DeviceAdapters/PyDevice/PyStage.h +++ b/DeviceAdapters/PyDevice/PyStage.h @@ -118,6 +118,11 @@ class CPyXYStage : public PyXYStageClass { return DEVICE_UNSUPPORTED_COMMAND; } + int UsesOnXYStagePositionChanged(bool& result) const override { + result = false; + return DEVICE_OK; + } + protected: double origin_x_ = 0.0; double origin_y_ = 0.0; diff --git a/DeviceAdapters/StandaStage/StandaStage.h b/DeviceAdapters/StandaStage/StandaStage.h index ae20308cc..d5feac1da 100644 --- a/DeviceAdapters/StandaStage/StandaStage.h +++ b/DeviceAdapters/StandaStage/StandaStage.h @@ -266,7 +266,6 @@ class CStandaXYStage : public CXYStageBase int IsXYStageSequenceable(bool& isSequenceable) const {isSequenceable = false; return DEVICE_OK;} - // action interface // ---------------- diff --git a/DeviceAdapters/WieneckeSinske/ZPiezoCanDevice.h b/DeviceAdapters/WieneckeSinske/ZPiezoCanDevice.h index 889e6c613..c22daaf05 100644 --- a/DeviceAdapters/WieneckeSinske/ZPiezoCanDevice.h +++ b/DeviceAdapters/WieneckeSinske/ZPiezoCanDevice.h @@ -77,7 +77,6 @@ class ZPiezoCANDevice : public CStageBase int SetOrigin(); int IsStageSequenceable(bool& isSequenceable) const {isSequenceable = false; return DEVICE_OK;} - // action interface // ---------------- int OnPort(MM::PropertyBase* pProp, MM::ActionType eAct); diff --git a/DeviceAdapters/WieneckeSinske/ZPiezoWSDevice.h b/DeviceAdapters/WieneckeSinske/ZPiezoWSDevice.h index e99c444a7..1a47c3b1d 100644 --- a/DeviceAdapters/WieneckeSinske/ZPiezoWSDevice.h +++ b/DeviceAdapters/WieneckeSinske/ZPiezoWSDevice.h @@ -77,7 +77,6 @@ class ZPiezoWSDevice : public CStageBase int SetOrigin(); int IsStageSequenceable(bool& isSequenceable) const {isSequenceable = false; return DEVICE_OK;} - // action interface // ---------------- int OnPort(MM::PropertyBase* pProp, MM::ActionType eAct); diff --git a/DeviceAdapters/ZeissCAN29/ZeissCAN29.h b/DeviceAdapters/ZeissCAN29/ZeissCAN29.h index 79ef67051..f251d11d3 100644 --- a/DeviceAdapters/ZeissCAN29/ZeissCAN29.h +++ b/DeviceAdapters/ZeissCAN29/ZeissCAN29.h @@ -836,6 +836,8 @@ class Axis : public CStageBase, public ZeissAxis int IsStageSequenceable(bool& isSequenceable) const {isSequenceable = false; return DEVICE_OK;} bool IsContinuousFocusDrive() const {return false;} + int UsesOnStagePositionChanged(bool& result) const { result = true; return DEVICE_OK; } + // action interface // ---------------- int OnPosition(MM::PropertyBase* pProp, MM::ActionType eAct); @@ -890,6 +892,8 @@ class XYStage : public CXYStageBase, public ZeissAxis double GetStepSizeYUm() {return stepSize_um_;} int IsXYStageSequenceable(bool& isSequenceable) const {isSequenceable = false; return DEVICE_OK;} + int UsesOnXYStagePositionChanged(bool& result) const { result = true; return DEVICE_OK; } + // action interface // ---------------- int OnMoveMode(MM::PropertyBase* pProp, MM::ActionType eAct); diff --git a/MMCore/CircularBuffer.cpp b/MMCore/CircularBuffer.cpp index 448e6f9a0..9db6b396e 100644 --- a/MMCore/CircularBuffer.cpp +++ b/MMCore/CircularBuffer.cpp @@ -192,18 +192,12 @@ static std::string FormatLocalTime(std::chrono::time_pointProcess(const_cast(buf), width, height, byteDepth); - } - } - if (core_->cbuf_->InsertImage(buf, width, height, byteDepth, &md)) - return DEVICE_OK; - else - return DEVICE_BUFFER_OVERFLOW; - } - catch (CMMError& /*e*/) - { - return DEVICE_INCOMPATIBLE_IMAGE; - } + return InsertImage(caller, buf, width, height, bytesPerPixel, 1, serializedMetadata); } -int CoreCallback::InsertImage(const MM::Device* caller, const unsigned char* buf, unsigned width, unsigned height, unsigned byteDepth, unsigned nComponents, const char* serializedMetadata, const bool doProcess) +int CoreCallback::InsertImage(const MM::Device* caller, const unsigned char* buf, + unsigned width, unsigned height, unsigned bytesPerPixel, unsigned nComponents, + const char* serializedMetadata) { Metadata origMd; if (serializedMetadata) @@ -261,15 +239,12 @@ int CoreCallback::InsertImage(const MM::Device* caller, const unsigned char* buf { Metadata md = AddCameraMetadata(caller, &origMd); - if(doProcess) - { MM::ImageProcessor* ip = GetImageProcessor(caller); if( NULL != ip) { - ip->Process(const_cast(buf), width, height, byteDepth); + ip->Process(const_cast(buf), width, height, bytesPerPixel); } - } - if (core_->cbuf_->InsertImage(buf, width, height, byteDepth, nComponents, &md)) + if (core_->cbuf_->InsertImage(buf, width, height, bytesPerPixel, nComponents, &md)) return DEVICE_OK; else return DEVICE_BUFFER_OVERFLOW; diff --git a/MMCore/CoreCallback.h b/MMCore/CoreCallback.h index e31e8966d..74bb1f10b 100644 --- a/MMCore/CoreCallback.h +++ b/MMCore/CoreCallback.h @@ -84,8 +84,12 @@ class CoreCallback : public MM::Core void Sleep(const MM::Device* caller, double intervalMs); // continuous acquisition support - int InsertImage(const MM::Device* caller, const unsigned char* buf, unsigned width, unsigned height, unsigned byteDepth, const char* serializedMetadata, const bool doProcess = true); - int InsertImage(const MM::Device* caller, const unsigned char* buf, unsigned width, unsigned height, unsigned byteDepth, unsigned nComponents, const char* serializedMetadata, const bool doProcess = true); + int InsertImage(const MM::Device* caller, const unsigned char* buf, + unsigned width, unsigned height, unsigned bytesPerPixel, + const char* serializedMetadata); + int InsertImage(const MM::Device* caller, const unsigned char* buf, + unsigned width, unsigned height, unsigned bytesPerPixel, unsigned nComponents, + const char* serializedMetadata); bool InitializeImageBuffer(unsigned channels, unsigned slices, unsigned int w, unsigned int h, unsigned int pixDepth); int AcqFinished(const MM::Device* caller, int statusCode); diff --git a/MMCore/Devices/StageInstance.cpp b/MMCore/Devices/StageInstance.cpp index 666f8f9b0..d620f7116 100644 --- a/MMCore/Devices/StageInstance.cpp +++ b/MMCore/Devices/StageInstance.cpp @@ -60,6 +60,7 @@ StageInstance::SetFocusDirection(MM::FocusDirection direction) focusDirectionHasBeenSet_ = true; } +int StageInstance::UsesOnStagePositionChanged(bool& result) const { RequireInitialized(__func__); return GetImpl()->UsesOnStagePositionChanged(result); } int StageInstance::IsStageSequenceable(bool& isSequenceable) const { RequireInitialized(__func__); return GetImpl()->IsStageSequenceable(isSequenceable); } int StageInstance::IsStageLinearSequenceable(bool& isSequenceable) const { RequireInitialized(__func__); return GetImpl()->IsStageLinearSequenceable(isSequenceable); } bool StageInstance::IsContinuousFocusDrive() const { RequireInitialized(__func__); return GetImpl()->IsContinuousFocusDrive(); } diff --git a/MMCore/Devices/StageInstance.h b/MMCore/Devices/StageInstance.h index b94b1e6bf..b4e2cff93 100644 --- a/MMCore/Devices/StageInstance.h +++ b/MMCore/Devices/StageInstance.h @@ -57,6 +57,7 @@ class StageInstance : public DeviceInstanceBase int GetLimits(double& lower, double& upper); MM::FocusDirection GetFocusDirection(); void SetFocusDirection(MM::FocusDirection direction); + int UsesOnStagePositionChanged(bool& result) const; int IsStageSequenceable(bool& isSequenceable) const; int IsStageLinearSequenceable(bool& isSequenceable) const; bool IsContinuousFocusDrive() const; diff --git a/MMCore/Devices/XYStageInstance.cpp b/MMCore/Devices/XYStageInstance.cpp index 56f06844a..0b18bce63 100644 --- a/MMCore/Devices/XYStageInstance.cpp +++ b/MMCore/Devices/XYStageInstance.cpp @@ -42,6 +42,7 @@ int XYStageInstance::SetYOrigin() { RequireInitialized(__func__); return GetImpl int XYStageInstance::GetStepLimits(long& xMin, long& xMax, long& yMin, long& yMax) { RequireInitialized(__func__); return GetImpl()->GetStepLimits(xMin, xMax, yMin, yMax); } double XYStageInstance::GetStepSizeXUm() { RequireInitialized(__func__); return GetImpl()->GetStepSizeXUm(); } double XYStageInstance::GetStepSizeYUm() { RequireInitialized(__func__); return GetImpl()->GetStepSizeYUm(); } +int XYStageInstance::UsesOnXYStagePositionChanged(bool& result) const { RequireInitialized(__func__); return GetImpl()->UsesOnXYStagePositionChanged(result); } int XYStageInstance::IsXYStageSequenceable(bool& isSequenceable) const { RequireInitialized(__func__); return GetImpl()->IsXYStageSequenceable(isSequenceable); } int XYStageInstance::GetXYStageSequenceMaxLength(long& nrEvents) const { RequireInitialized(__func__); return GetImpl()->GetXYStageSequenceMaxLength(nrEvents); } int XYStageInstance::StartXYStageSequence() { RequireInitialized(__func__); return GetImpl()->StartXYStageSequence(); } diff --git a/MMCore/Devices/XYStageInstance.h b/MMCore/Devices/XYStageInstance.h index 9dd21a46e..b6819359f 100644 --- a/MMCore/Devices/XYStageInstance.h +++ b/MMCore/Devices/XYStageInstance.h @@ -56,6 +56,7 @@ class XYStageInstance : public DeviceInstanceBase int GetStepLimits(long& xMin, long& xMax, long& yMin, long& yMax); double GetStepSizeXUm(); double GetStepSizeYUm(); + int UsesOnXYStagePositionChanged(bool& result) const; int IsXYStageSequenceable(bool& isSequenceable) const; int GetXYStageSequenceMaxLength(long& nrEvents) const; int StartXYStageSequence(); diff --git a/MMCore/MMCore.cpp b/MMCore/MMCore.cpp index 3472b293a..be69f5798 100644 --- a/MMCore/MMCore.cpp +++ b/MMCore/MMCore.cpp @@ -106,7 +106,7 @@ namespace mmi = mmcore::internal; * (Keep the 3 numbers on one line to make it easier to look at diffs when * merging/rebasing.) */ -const int MMCore_versionMajor = 11, MMCore_versionMinor = 13, MMCore_versionPatch = 0; +const int MMCore_versionMajor = 11, MMCore_versionMinor = 14, MMCore_versionPatch = 0; /////////////////////////////////////////////////////////////////////////////// @@ -2265,6 +2265,24 @@ void CMMCore::loadExposureSequence(const char* cameraLabel, std::vector throw CMMError(getDeviceErrorText(ret, pCamera)); } +/** +* Queries whether this stage uses callbacks to signal position changes +* When false, use polling to stay updated about the positionf of the stage +*/ +bool CMMCore::isStageUsingCallbacks(const char* label) MMCORE_LEGACY_THROW(CMMError) +{ + std::shared_ptr pStage = + deviceManager_->GetDeviceOfType(label); + + mmi::DeviceModuleLockGuard guard(pStage); + + bool result; + int ret = pStage->UsesOnStagePositionChanged(result); + if (ret != DEVICE_OK) + throw CMMError(getDeviceErrorText(ret, pStage)); + return result; +} + /** * Queries stage if it can be used in a sequence @@ -2417,6 +2435,26 @@ void CMMCore::setStageLinearSequence(const char* label, double dZ_um, int nSlice throw CMMError(getDeviceErrorText(ret, pStage)); } + +/** +* Queries whether this XYStage uses callbacks to signal position changes +* When false, use polling to stay updated about the positionf of the stage +*/ +bool CMMCore::isXYStageUsingCallbacks(const char* label) MMCORE_LEGACY_THROW(CMMError) +{ + std::shared_ptr pStage = + deviceManager_->GetDeviceOfType(label); + + mmi::DeviceModuleLockGuard guard(pStage); + + bool result; + int ret = pStage->UsesOnXYStagePositionChanged(result); + if (ret != DEVICE_OK) + throw CMMError(getDeviceErrorText(ret, pStage)); + + return result; +} + /** * Queries XY stage if it can be used in a sequence * @param label the XY stage device label diff --git a/MMCore/MMCore.h b/MMCore/MMCore.h index 1ecf3f0e2..b5bb557d3 100644 --- a/MMCore/MMCore.h +++ b/MMCore/MMCore.h @@ -493,6 +493,7 @@ class CMMCore void setFocusDirection(const char* stageLabel, int sign); int getFocusDirection(const char* stageLabel) MMCORE_LEGACY_THROW(CMMError); + bool isStageUsingCallbacks(const char* stageLabel) MMCORE_LEGACY_THROW(CMMError); bool isStageSequenceable(const char* stageLabel) MMCORE_LEGACY_THROW(CMMError); bool isStageLinearSequenceable(const char* stageLabel) MMCORE_LEGACY_THROW(CMMError); void startStageSequence(const char* stageLabel) MMCORE_LEGACY_THROW(CMMError); @@ -530,6 +531,7 @@ class CMMCore double newXUm, double newYUm) MMCORE_LEGACY_THROW(CMMError); void setAdapterOriginXY(double newXUm, double newYUm) MMCORE_LEGACY_THROW(CMMError); + bool isXYStageUsingCallbacks(const char* xyStageLabel) MMCORE_LEGACY_THROW(CMMError); bool isXYStageSequenceable(const char* xyStageLabel) MMCORE_LEGACY_THROW(CMMError); void startXYStageSequence(const char* xyStageLabel) MMCORE_LEGACY_THROW(CMMError); void stopXYStageSequence(const char* xyStageLabel) MMCORE_LEGACY_THROW(CMMError); diff --git a/MMCoreJ_wrap/pom.xml b/MMCoreJ_wrap/pom.xml index f9f8836f3..3cdddd539 100644 --- a/MMCoreJ_wrap/pom.xml +++ b/MMCoreJ_wrap/pom.xml @@ -6,7 +6,7 @@ org.micro-manager.mmcorej MMCoreJ - 11.13.0 + 11.14.0 MMCore Java API Java bindings for MMCore, the device abstraction layer of Micro-Manager, the microscope control and acquisition platform. diff --git a/MMDevice/DeviceBase.h b/MMDevice/DeviceBase.h index be7c80203..b7fb2db85 100644 --- a/MMDevice/DeviceBase.h +++ b/MMDevice/DeviceBase.h @@ -1422,23 +1422,11 @@ class CCameraBase : public CDeviceBase */ virtual int StopSequenceAcquisition() = 0; - // It appears that this function was never used by MMCore and is slated for - // removal. Concrete cameras should not override. - double GetPixelSizeUm() const final { return 0.0; } - virtual unsigned GetNumberOfComponents() const { return 1; // Default to monochrome (ie not RGB) } - // To be removed (never used by MMCore); devices should not override. - virtual int GetComponentName(unsigned channel, char* name) final - { - (void)channel; - CDeviceUtils::CopyLimitedString(name, ""); - return DEVICE_OK; - } - /** * @brief Return the number of channels. * @@ -1494,9 +1482,6 @@ class CCameraBase : public CDeviceBase CDeviceUtils::CopyLimitedString(serializedMetadata, md.Serialize()); } - // To be removed; devices should no longer override. - virtual int PrepareSequenceAcqusition() final {return DEVICE_OK;} - /** * @brief Start sequence acquisition. */ @@ -1905,6 +1890,15 @@ class CStageBase : public CDeviceBase return DEVICE_OK; } + /** + * @brief Return true when your device adapter uses OnStagePositionChanged callbacks. + */ + virtual int UsesOnStagePositionChanged(bool& result) const + { + result = false; + return DEVICE_OK; + } + virtual int IsStageLinearSequenceable(bool& isSequenceable) const { isSequenceable = false; @@ -2113,6 +2107,15 @@ class CXYStageBase : public CDeviceBase return this->SetPositionSteps(xSteps+x, ySteps+y); } + /** + * @brief Return true when your device adapter uses OnXYStagePositionChanged callbacks. + */ + virtual int UsesOnXYStagePositionChanged(bool& result) const + { + result = false; + return DEVICE_OK; + } + virtual int Move(double /*vx*/, double /*vy*/) { return DEVICE_UNSUPPORTED_COMMAND; diff --git a/MMDevice/MMDevice.h b/MMDevice/MMDevice.h index f7ab56a18..f08472be6 100644 --- a/MMDevice/MMDevice.h +++ b/MMDevice/MMDevice.h @@ -28,7 +28,7 @@ // Header version // If any of the class definitions changes, the interface version // must be incremented -#define DEVICE_INTERFACE_VERSION 74 +#define DEVICE_INTERFACE_VERSION 75 /////////////////////////////////////////////////////////////////////////////// // N.B. @@ -373,9 +373,6 @@ namespace MM { */ virtual unsigned GetNumberOfComponents() const = 0; - /** Unused; to be removed. */ - virtual int GetComponentName(unsigned component, char* name) = 0; - /** * @brief Return the number of simultaneous channels that camera is capable of. * @@ -422,10 +419,6 @@ namespace MM { * Required by the MM::Camera API. */ virtual unsigned GetBitDepth() const = 0; - /** - * @brief Unused and slated for removal. Implemented in DeviceBase.h. - */ - virtual double GetPixelSizeUm() const = 0; /** * @brief Return the current binning factor. */ @@ -488,10 +481,6 @@ namespace MM { * @brief Stop an ongoing sequence acquisition. */ virtual int StopSequenceAcquisition() = 0; - /** - * @brief Set up the camera so that Sequence acquisition can start without delay. - */ - virtual int PrepareSequenceAcqusition() = 0; /** * @brief Indicate whether sequence acquisition is currently running. * @@ -602,6 +591,17 @@ namespace MM { virtual int SetOrigin() = 0; virtual int GetLimits(double& lower, double& upper) = 0; + /** + * @brief Stages can use the OnStagePositionChanged callback to signal + * updates about their position. Some adapters do so, others do not, + * in which case the UI code should use polling. This function signals whether + * the device adapters uses callbacks, so that the UI knows it does not need + * to poll this device. It is best practice to not change the result of this + * function (i.e. use a const value) as the UI will query the function + * only once. + */ + virtual int UsesOnStagePositionChanged(bool& result) const = 0; + /** * @brief Return the focus direction. * @@ -708,6 +708,17 @@ namespace MM { virtual int Home() = 0; virtual int Stop() = 0; + /** + * @brief XY stages can use the OnXYStagePositionChanged callback to signal + * updates about their position. Some stage adapters do so, others do not, + * in which case the UI code can use polling. This function signals whether + * the device adapters uses callbacks, so that the UI knows it does not need + * to poll this device. It is best practice to not change the result of this + * function (i.e. use a const value) as the UI will query the function + * only once. + */ + virtual int UsesOnXYStagePositionChanged(bool &result) const = 0; + /** * @brief Define the current position as the (hardware) origin (0, 0). */ @@ -1682,14 +1693,15 @@ namespace MM { * Cameras must call this function during sequence acquisition to send * each frame to the Core. * - * byteDepth: 1 or 2 for grayscale images; 4 for BGR_ + * bytesPerPixel: 1 or 2 for grayscale images; 4 or 8 for BGRx * - * nComponents: 1 for grayscale; 4 for BGR_ (_: unused component) + * nComponents: 1 for grayscale; 4 for BGRx (x: an unused component) * - * serializedMetadata: must be the result of md.serialize().c_str() (md - * being an instance of Metadata) + * (8-byte BGRx may not be supported by the Micro-Manager GUI) * - * doProcess: must be true, except for the case mentioned below + * serializedMetadata: must be the result of md.Serialize() (md + * being an instance of MM::CameraImageMetadata) + * or nullptr (= no tags) * * Legacy note: Previously, cameras were required to perform special * handling when InsertImage() returns DEVICE_BUFFER_OVERFLOW and @@ -1698,7 +1710,9 @@ namespace MM { * cameras should always just stop the acquisition if InsertImage() * returns any error. */ - virtual int InsertImage(const Device* caller, const unsigned char* buf, unsigned width, unsigned height, unsigned byteDepth, unsigned nComponents, const char* serializedMetadata, const bool doProcess = true) = 0; + virtual int InsertImage(const Device* caller, const unsigned char* buf, + unsigned width, unsigned height, unsigned bytePerPixel, unsigned nComponents, + const char* serializedMetadata = nullptr) = 0; /** * @brief Send a grayscale frame to the Core during sequence acquisition. @@ -1706,7 +1720,9 @@ namespace MM { * Same as the overload with the added nComponents parameter. * Assumes nComponents == 1 (grayscale). */ - virtual int InsertImage(const Device* caller, const unsigned char* buf, unsigned width, unsigned height, unsigned byteDepth, const char* serializedMetadata = nullptr, const bool doProcess = true) = 0; + virtual int InsertImage(const Device* caller, const unsigned char* buf, + unsigned width, unsigned height, unsigned bytePerPixel, + const char* serializedMetadata = nullptr) = 0; /** * @brief Prepare the sequence buffer for the given image size and pixel format.