VendorLibrary

VendorLibrary is the abstract base class for all dynamically loaded vendor driver wrappers. Blackchirp is built and distributed without compile-time dependencies on vendor SDKs; instead, each VendorLibrary subclass uses QLibrary to locate and load the vendor library at runtime. If the library is absent or cannot be loaded, Blackchirp starts normally and the dependent hardware drivers report themselves as unavailable.

The loading sequence is:

  1. Try the user-provided path (setUserProvidedPath), if set.

  2. Try user-specified search directories (setUserSearchPaths), then platform-specific default paths (defaultSearchPaths), if automatic discovery is enabled.

  3. Resolve function pointers by calling the subclass loadFunctions() implementation.

  4. Validate that all required symbols were found.

The staged-configuration API separates UI interaction from live hardware use. UI code calls setStagedUserProvidedPath, setStagedSearchPaths, and setStagedAutoDiscoveryEnabled to accumulate changes without affecting running hardware, then calls applyChanges() to promote the staged settings, persist them, and reload the library. revertChanges() discards any staged edits. hasUnstagedChanges() allows the surrounding dialog to enable or disable its Apply button. The LibraryStatusWidget in the Application Settings dialog uses this API to manage library paths safely without requiring a hardware restart until the user explicitly applies the changes.

Hardware drivers that depend on a vendor library register the dependency with REGISTER_LIBRARY (see HardwareRegistry). The HardwareRegistry tracks these dependencies so HardwareManager can destroy and recreate affected hardware objects around a library reload.

Concrete subclasses

LabjackLibrary

Loads the LabJack U3 driver. On Linux and macOS the driver is the LJUSB transport library (liblabjackusb.so / .dylib); on Windows it is the UD high-level library (LabJackUD.dll, 64-bit). The BC::Labjack facade in labjackdriver.h abstracts the platform difference and is the preferred entry point for hardware code. The cross-platform architecture is described in Vendor Libraries.

SpectrumLibrary

Loads the Spectrum Instrumentation driver (spcm_linux / spcm64.dll). Used by M4i digitizer drivers for FTMW acquisition. Because the Spectrum library maintains global state, a single instance is enforced via the singleton pattern. M4i driver code reaches the resolved symbols through the singleton accessor:

SpectrumLibrary &lib = SpectrumLibrary::instance();
if (lib.isAvailable()) {
    void *handle = lib.spcm_hOpen("/dev/spcm0");
    // ... use other Spectrum functions
}

API Reference

class VendorLibrary : public QObject, public SettingsStorage

Subclassed by LabjackLibrary, SpectrumLibrary

Public Functions

explicit VendorLibrary(const QString &libraryKey, QObject *parent = nullptr)

Construct a VendorLibrary with the given settings key.

Parameters:
  • libraryKeySettingsStorage key used to persist this library’s configuration

  • parent – Parent QObject for ownership; defaults to none.

virtual ~VendorLibrary() = default

Destroy the VendorLibrary and release any loaded library resources.

virtual bool isAvailable() const = 0

Check if the vendor library is available and loaded.

Returns:

true if library is loaded and all functions resolved

virtual QString errorString() const = 0

Get error message if library loading failed.

Returns:

Error string describing why library is not available

virtual QString libraryName() const = 0

Get the base name of the library being loaded.

Returns:

Base library name (e.g., “spcm”, “labjackusb”)

virtual QStringList platformLibraryNames() const = 0

Get platform-specific library names to try.

This allows handling libraries that have different names on different platforms (e.g., “spcm_linux” on Linux, “spcm64.dll” on Windows)

Returns:

List of library names with platform-specific variations

virtual QStringList defaultSearchPaths() const = 0

Get default search paths for automatic discovery.

This should return platform-specific default paths where the library is typically installed. User-specified paths take priority over these.

Returns:

List of default search paths for this library type

inline virtual QString getVersionInfo() const

Get library version information.

This method attempts to query version information from the loaded library. Implementation is library-specific and may require temporary device access.

Returns:

Version string if available, empty string if not available or not supported

virtual QString getInstallationInstructions() const = 0

Get platform-specific installation instructions for this library.

This method returns detailed, platform-specific instructions for installing the vendor library. The instructions should include download links, installation commands, and common troubleshooting information tailored to the current platform.

Returns:

HTML-formatted installation instructions for the current platform

QString loadedLibraryPath() const

Get the full path where library was found (if loaded successfully)

Returns:

Full path to loaded library, empty if not loaded

inline bool wasLoadingAttempted() const

Check if library loading was attempted.

Returns:

true if loading was attempted (successfully or not)

void setUserProvidedPath(const QString &path)

Set user-provided library path.

This path takes priority over automatic discovery. If the path is invalid or the library cannot be loaded, automatic discovery will be used as fallback (if enabled).

Parameters:

path – Full path to library file provided by user

QString getUserProvidedPath() const

Get user-provided library path.

Returns:

User-specified library path, empty if none set

void addUserSearchPath(const QString &path)

Add user-specified search path.

User-specified search paths are tried before default search paths.

Parameters:

path – Directory path to add to search paths

void setUserSearchPaths(const QStringList &paths)

Set user-specified search paths.

Parameters:

paths – List of directory paths to search

QStringList getUserSearchPaths() const

Get user-specified search paths.

Returns:

List of user-specified search directories

void setAutoDiscoveryEnabled(bool enabled)

Enable or disable automatic discovery.

When disabled, only user-provided paths are used. When enabled (default), automatic discovery is used if user-provided paths fail.

Parameters:

enabled – Whether to use automatic discovery as fallback

bool isAutoDiscoveryEnabled() const

Check if automatic discovery is enabled.

Returns:

true if automatic discovery is enabled

bool reloadLibrary()

Force reload of library with current settings.

This can be called after changing user settings to attempt loading with the new configuration.

Returns:

true if library was successfully loaded

void setStagedUserProvidedPath(const QString &path)

Set staged user-provided library path.

This modifies the staged configuration without immediately affecting the active configuration used by hardware. Changes must be applied via applyChanges() to take effect.

Parameters:

path – Full path to library file provided by user

void setStagedSearchPaths(const QStringList &paths)

Set staged user-specified search paths.

This modifies the staged configuration without immediately affecting the active configuration used by hardware.

Parameters:

paths – List of directory paths to search

void setStagedAutoDiscoveryEnabled(bool enabled)

Set staged automatic discovery setting.

This modifies the staged configuration without immediately affecting the active configuration used by hardware.

Parameters:

enabled – Whether to use automatic discovery as fallback

QString getStagedUserProvidedPath() const

Get staged user-provided library path.

Returns:

Staged user-specified library path, empty if none set

QStringList getStagedSearchPaths() const

Get staged user-specified search paths.

Returns:

List of staged user-specified search directories

bool isStagedAutoDiscoveryEnabled() const

Check if staged automatic discovery is enabled.

Returns:

true if staged automatic discovery is enabled

bool hasUnstagedChanges() const

Check if there are unstaged changes.

Returns:

true if staged configuration differs from active configuration

bool applyChanges()

Apply staged changes to active configuration.

This promotes the staged configuration to become the active configuration, saves the settings to persistent storage, and reloads the library with the new configuration.

Returns:

true if changes were applied successfully and library reloaded

void revertChanges()

Revert staged changes to match active configuration.

This discards any staged changes and resets the staged configuration to match the current active configuration.

QString getActiveUserProvidedPath() const

Get active user-provided library path.

Returns:

Active user-specified library path, empty if none set

QStringList getActiveSearchPaths() const

Get active user-specified search paths.

Returns:

List of active user-specified search directories

bool isActiveAutoDiscoveryEnabled() const

Check if active automatic discovery is enabled.

Returns:

true if active automatic discovery is enabled

Protected Functions

bool loadLibrary()

Attempt to load library using platform-specific names and paths.

This method tries each platform-specific library name in combination with each search path until the library loads successfully. It handles both absolute paths and library names for system path searching.

Returns:

true if library was successfully loaded

QFunctionPointer resolveFunction(const char *functionName)

Resolve a function symbol to a function pointer.

This is a convenience method for subclasses to resolve function symbols. The library must be successfully loaded before calling this method.

Parameters:

functionName – Name of function symbol to resolve

Returns:

Function pointer or nullptr if not found

virtual void loadFunctions() = 0

Called by subclasses to load their specific function pointers.

Subclasses must implement this method to resolve all required function symbols after the library has been successfully loaded. If any required function cannot be resolved, this method should set d_libraryLoaded to false and update d_errorString with appropriate error information.

Protected Attributes

QLibrary d_library

Qt library loader

bool d_libraryLoaded

Whether library is loaded and ready

bool d_loadingAttempted

Whether loading was attempted

QString d_errorString

Error message if loading failed

QStringList d_attemptedPaths

Paths that were tried during loading

QString d_libraryKey

Settings key for this library

QString d_activeUserPath

Active user-provided library path

QStringList d_activeSearchPaths

Active user search paths

bool d_activeAutoDiscovery

Active auto-discovery setting

QString d_stagedUserPath

Staged user-provided library path

QStringList d_stagedSearchPaths

Staged user search paths

bool d_stagedAutoDiscovery

Staged auto-discovery setting

bool d_hasUnstagedChanges

Track if staging differs from active

Private Functions

QStringList buildSearchPathList() const

Build complete search path priority list.

Returns:

Ordered list of paths to try (user paths first, then defaults)

void saveSuccessfulLoad(const QString &successfulPath)

Save successful load information to settings.

Parameters:

successfulPath – Path that successfully loaded the library

Private Slots

void onLibraryDestroyed()

Handle library unloading.

Connected to QLibrary destroyed signal to clean up state when library is unloaded (e.g., during application shutdown).

class LabjackLibrary : public VendorLibrary

Public Types

typedef float (*LJUSB_GetLibraryVersion_t)(void)
typedef unsigned int (*LJUSB_GetDevCount_t)(unsigned long ProductID)
typedef void *(*LJUSB_OpenDevice_t)(unsigned int DevNum, unsigned int dwReserved, unsigned long ProductID)
typedef void (*LJUSB_CloseDevice_t)(void *hDevice)
typedef unsigned long (*LJUSB_Write_t)(void *hDevice, const unsigned char *pBuff, unsigned long count)
typedef unsigned long (*LJUSB_Read_t)(void *hDevice, unsigned char *pBuff, unsigned long count)
typedef bool (*LJUSB_IsHandleValid_t)(void *hDevice)
typedef bool (*LJUSB_ResetConnection_t)(void *hDevice)

Public Functions

inline virtual bool isAvailable() const override

Check if the LabJack driver library is loaded and ready.

Returns:

true if library symbols were resolved successfully

inline virtual QString errorString() const override

Get error message if library loading failed.

Returns:

Error string describing why the library is not available

virtual QString getVersionInfo() const override

Get library version string.

Returns:

Version string from the loaded driver, or empty string if unavailable

virtual QString getInstallationInstructions() const override

Get platform-specific installation instructions for the LabJack driver.

Returns:

HTML-formatted instructions for installing the LabJack driver on the current platform

inline virtual QString libraryName() const override

Get the base name of the LabJack driver library.

Returns:

Base library name string

virtual QStringList platformLibraryNames() const override

Get platform-specific library file names to try when loading.

Returns:

List of library names with platform-specific variations

virtual QStringList defaultSearchPaths() const override

Get default search paths for automatic LabJack driver discovery.

Returns:

List of default directories to search for the library

Public Members

LJUSB_GetLibraryVersion_t LJUSB_GetLibraryVersion = nullptr
LJUSB_GetDevCount_t LJUSB_GetDevCount = nullptr
LJUSB_OpenDevice_t LJUSB_OpenDevice = nullptr
LJUSB_CloseDevice_t LJUSB_CloseDevice = nullptr
LJUSB_Write_t LJUSB_Write = nullptr
LJUSB_Read_t LJUSB_Read = nullptr
LJUSB_IsHandleValid_t LJUSB_IsHandleValid = nullptr
LJUSB_ResetConnection_t LJUSB_ResetConnection = nullptr

Public Static Functions

static LabjackLibrary &instance()

Get singleton instance of LabjackLibrary.

Returns:

Reference to the single LabjackLibrary instance

Protected Functions

virtual void loadFunctions() override

Resolve LabJack driver function symbols after the library has loaded.

Private Functions

explicit LabjackLibrary(QObject *parent = nullptr)
~LabjackLibrary() override = default
LabjackLibrary(const LabjackLibrary&) = delete
LabjackLibrary &operator=(const LabjackLibrary&) = delete

Private Static Attributes

static LabjackLibrary *s_instance = nullptr
class SpectrumLibrary : public VendorLibrary

Dynamic loader for the Spectrum Instrumentation driver library (spcm_linux / spcm64.dll).

Singleton, because the Spectrum library maintains global state that cannot be duplicated. Used by the M4i digitizer implementations.

Public Types

typedef void *(*spcm_hOpen_t)(const char *szDeviceName)

Open Spectrum device Function pointer for spcm_hOpen()

typedef void (*spcm_vClose_t)(void *hDevice)

Close Spectrum

device

Function pointer for

spcm_vClose()

typedef std::int32_t (*spcm_dwSetParam_i32_t)(void *hDevice, std::int32_t lRegister, std::int32_t lValue)

Set 32-bit integer parameter Function pointer for spcm_dwSetParam_i32()

typedef std::int32_t (*spcm_dwGetParam_i32_t)(void *hDevice, std::int32_t lRegister, std::int32_t *plValue)

Get 32-bit integer parameter Function pointer for spcm_dwGetParam_i32()

typedef std::int32_t (*spcm_dwSetParam_i64_t)(void *hDevice, std::int32_t lRegister, std::int64_t llValue)

Set 64-bit integer parameter Function pointer for spcm_dwSetParam_i64()

typedef std::int32_t (*spcm_dwGetParam_i64_t)(void *hDevice, std::int32_t lRegister, std::int64_t *pllValue)

Get 64-bit integer parameter Function pointer for spcm_dwGetParam_i64()

typedef std::int32_t (*spcm_dwDefTransfer_i64_t)(void *hDevice, std::int32_t lBufType, std::int32_t lDirection, std::int32_t lNotifySize, void *pvDataBuffer, std::int64_t qwOffset, std::int64_t qwLength)

Define transfer buffer Function pointer for spcm_dwDefTransfer_i64()

typedef std::int32_t (*spcm_dwInvalidateBuf_t)(void *hDevice, std::int32_t lBufType)

Start transfer Function pointer for spcm_dwInvalidateBuf()

typedef std::int32_t (*spcm_dwGetErrorInfo_i32_t)(void *hDevice, std::int32_t *plErrorReg, std::int32_t *plErrorValue, char *szErrorText)

Get error information Function pointer for spcm_dwGetErrorInfo_i32()

Public Functions

inline virtual bool isAvailable() const override

Check if the Spectrum driver library is loaded and ready.

Returns:

true if library symbols were resolved successfully

inline virtual QString errorString() const override

Get error message if library loading failed.

Returns:

Error string describing why the library is not available

inline virtual QString libraryName() const override

Get the base name of the Spectrum driver library.

Returns:

Base library name string (“spcm”)

virtual QStringList platformLibraryNames() const override

Get platform-specific library file names to try when loading.

Returns:

List of library names with platform-specific variations

virtual QStringList defaultSearchPaths() const override

Get default search paths for automatic Spectrum driver discovery.

Returns:

List of default directories to search for the library

virtual QString getVersionInfo() const override

Get Spectrum driver version string.

Returns:

Version string from the loaded driver, or empty string if unavailable

virtual QString getInstallationInstructions() const override

Get platform-specific installation instructions for the Spectrum driver.

Returns:

HTML-formatted instructions for installing the Spectrum driver on the current platform

Public Members

spcm_hOpen_t spcm_hOpen = nullptr
spcm_vClose_t spcm_vClose = nullptr
spcm_dwSetParam_i32_t spcm_dwSetParam_i32 = nullptr
spcm_dwGetParam_i32_t spcm_dwGetParam_i32 = nullptr
spcm_dwSetParam_i64_t spcm_dwSetParam_i64 = nullptr
spcm_dwGetParam_i64_t spcm_dwGetParam_i64 = nullptr
spcm_dwDefTransfer_i64_t spcm_dwDefTransfer_i64 = nullptr
spcm_dwInvalidateBuf_t spcm_dwInvalidateBuf = nullptr
spcm_dwGetErrorInfo_i32_t spcm_dwGetErrorInfo_i32 = nullptr

Public Static Functions

static SpectrumLibrary &instance()

Get singleton instance of SpectrumLibrary.

Returns:

Reference to the single SpectrumLibrary instance

Protected Functions

virtual void loadFunctions() override

Resolve Spectrum driver function symbols after the library has loaded.

Private Functions

explicit SpectrumLibrary(QObject *parent = nullptr)
~SpectrumLibrary() = default
SpectrumLibrary(const SpectrumLibrary&) = delete
SpectrumLibrary &operator=(const SpectrumLibrary&) = delete

Private Static Attributes

static SpectrumLibrary *s_instance = nullptr