Skip to content

Mac adjustments and update to latest SDK version 11.3.0 #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jun 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.vscode
*.pro.user

/openigtlink/debug/
/openigtlink/release/
openigtlink/build/
.DS_Store
examples/solum_qt/CMakeLists.txt.user
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,17 @@ How to obtain a probe certificate:
```
curl -H "Authorization: OEM-API-Key <your key>" "https://cloud.clarius.com/api/public/v0/devices/oem/"
```


## Deploy with all dependencies of QT

[windeployqt](https://doc.qt.io/qt-6/windows-deployment.html) needs to be executed in order to copy all required QT dependencies into the directory of the executable:


For example, open a terminal where the solum.exe was build and enter the following command:

```
C:\Qt\6.6.0\msvc2019_64\bin\windeployqt.exe solum.exe
```

This copies all required dependencies into the same folder. **The solum.dll file though needs to be copied manually in addition.**
2 changes: 1 addition & 1 deletion examples/solum_qt/solum/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ qt_add_executable(solum_qt
set_target_properties(solum_qt PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/../macos/Info.plist
MACOSX_BUNDLE_GUI_IDENTIFIER "me.clarius.sdk.solum_qt"
)

Expand Down
19 changes: 16 additions & 3 deletions examples/solum_qt/solum/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ int main(int argc, char *argv[])
}
#endif

QCoreApplication::setOrganizationName(QStringLiteral("Clarius"));
QCoreApplication::setOrganizationDomain(QStringLiteral("clarius.com"));
QCoreApplication::setApplicationName(QStringLiteral("Solum Demo"));
QCoreApplication::setOrganizationName(QStringLiteral("Siemens Healthineers AG"));
QCoreApplication::setOrganizationDomain(QStringLiteral("healthineers.com"));
QCoreApplication::setApplicationName(QStringLiteral("Clarius Server"));

const int width = 640; // width of the rendered image
const int height = 480; // height of the rendered image
Expand Down Expand Up @@ -139,6 +139,19 @@ int main(int argc, char *argv[])
memcpy(_spectrum.data(), img, sz);
QApplication::postEvent(_solum.get(), new event::SpectrumImage(_spectrum.data(), nfo->lines, nfo->samples, nfo->bitsPerSample));
},
// new imu port callback
[](int port)
{
QApplication::postEvent(_solum.get(), new event::ImuPort(port));
},
// new imu data callback
[](const CusPosInfo* pos)
{
QQuaternion imu;
if (pos)
imu = QQuaternion(static_cast<float>(pos->qw), static_cast<float>(pos->qx), static_cast<float>(pos->qy), static_cast<float>(pos->qz));
QApplication::postEvent(_solum.get(), new event::Imu(IMU_EVENT, imu));
},
// imaging state change callback
[](CusImagingState state, int imaging)
{
Expand Down
31 changes: 28 additions & 3 deletions examples/solum_qt/solum/solumqt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ Solum::Solum(QWidget *parent) : QMainWindow(parent), imaging_(false), teeConnect
reflectMode(BMode);
ui_._tabs->setTabEnabled(ui_._tabs->indexOf(ui_._3d), false);

settings_ = std::make_unique<QSettings>(QStringLiteral("settings.ini"), QSettings::IniFormat);
// settings.ini file needs to be at a location the application can write to.
// Writing directly into the application directory (using 'settings.ini') does not work on some systems (e.g. macos).
QString p = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
settings_ = std::make_unique<QSettings>(p + "/settings.ini", QSettings::IniFormat);

ui_.token->setText(settings_->value("token").toString());
settings_->beginGroup("Probes");
for (const auto& probe: settings_->childGroups())
Expand Down Expand Up @@ -296,6 +300,7 @@ Solum::Solum(QWidget *parent) : QMainWindow(parent), imaging_(false), teeConnect
if (f.size())
{
ret = f[0];
ret = ret.replace("\"", QString{});
ret.replace(field + QStringLiteral(" "), QString{});
}
return ret;
Expand Down Expand Up @@ -335,8 +340,28 @@ Solum::Solum(QWidget *parent) : QMainWindow(parent), imaging_(false), teeConnect

imagingState(ImagingNotReady, false);

// Automatically trigger a BLE search at startup
ui_.blesearch->click();
#if QT_CONFIG(permissions)
QBluetoothPermission bluetoothPermission;
switch (qApp->checkPermission(bluetoothPermission)) {
case Qt::PermissionStatus::Undetermined:
qApp->requestPermission(bluetoothPermission, this, [this]()
{
qDebug() << "bluetooth permission granted";
ui_.blesearch->setEnabled(true);
// Automatically trigger a BLE search at startup
ui_.blesearch->click();
});
return;
case Qt::PermissionStatus::Denied:
qDebug() << "bluetooth permission was denied";
return;
case Qt::PermissionStatus::Granted:
// Automatically trigger a BLE search at startup
ui_.blesearch->setEnabled(true);
ui_.blesearch->click();
break; // Proceed
}
#endif
}

/// destructor
Expand Down
56 changes: 42 additions & 14 deletions examples/solum_qt/solum/solumqt.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,25 @@ class RfSignal;
class Prescan;
class ProbeRender;

#define CONNECT_EVENT static_cast<QEvent::Type>(QEvent::User + 1)
#define CERT_EVENT static_cast<QEvent::Type>(QEvent::User + 2)
#define POWER_EVENT static_cast<QEvent::Type>(QEvent::User + 3)
#define SWUPDATE_EVENT static_cast<QEvent::Type>(QEvent::User + 4)
#define LIST_EVENT static_cast<QEvent::Type>(QEvent::User + 5)
#define IMAGE_EVENT static_cast<QEvent::Type>(QEvent::User + 6)
#define PRESCAN_EVENT static_cast<QEvent::Type>(QEvent::User + 7)
#define SPECTRUM_EVENT static_cast<QEvent::Type>(QEvent::User + 8)
#define RF_EVENT static_cast<QEvent::Type>(QEvent::User + 9)
#define IMAGING_EVENT static_cast<QEvent::Type>(QEvent::User + 10)
#define BUTTON_EVENT static_cast<QEvent::Type>(QEvent::User + 11)
#define ERROR_EVENT static_cast<QEvent::Type>(QEvent::User + 12)
#define PROGRESS_EVENT static_cast<QEvent::Type>(QEvent::User + 13)
#define TEE_EVENT static_cast<QEvent::Type>(QEvent::User + 14)
#define CONNECT_EVENT static_cast<QEvent::Type>(QEvent::User + 1)
#define CERT_EVENT static_cast<QEvent::Type>(QEvent::User + 2)
#define POWER_EVENT static_cast<QEvent::Type>(QEvent::User + 3)
#define SWUPDATE_EVENT static_cast<QEvent::Type>(QEvent::User + 4)
#define LIST_EVENT static_cast<QEvent::Type>(QEvent::User + 5)
#define IMAGE_EVENT static_cast<QEvent::Type>(QEvent::User + 6)
#define PRESCAN_EVENT static_cast<QEvent::Type>(QEvent::User + 7)
#define SPECTRUM_EVENT static_cast<QEvent::Type>(QEvent::User + 8)
#define RF_EVENT static_cast<QEvent::Type>(QEvent::User + 9)
#define IMAGING_EVENT static_cast<QEvent::Type>(QEvent::User + 10)
#define BUTTON_EVENT static_cast<QEvent::Type>(QEvent::User + 11)
#define ERROR_EVENT static_cast<QEvent::Type>(QEvent::User + 12)
#define PROGRESS_EVENT static_cast<QEvent::Type>(QEvent::User + 13)
#define TEE_EVENT static_cast<QEvent::Type>(QEvent::User + 14)
#define IMU_EVENT static_cast<QEvent::Type>(QEvent::User + 15)
#define RAWAVAIL_EVENT static_cast<QEvent::Type>(QEvent::User + 16)
#define RAWREADY_EVENT static_cast<QEvent::Type>(QEvent::User + 17)
#define RAWDOWNLOADED_EVENT static_cast<QEvent::Type>(QEvent::User + 18)
#define IMU_PORT_EVENT static_cast<QEvent::Type>(QEvent::User + 19)

namespace event
{
Expand Down Expand Up @@ -211,6 +216,29 @@ namespace event
QString exam_; ///< exam id
};

/// wrapper for new imu data events that can be posted from the api callbacks
class ImuPort : public QEvent
{
public:
/// default constructor
/// @param[in] port latest imu port
explicit ImuPort(int port) : QEvent(IMU_PORT_EVENT), port_(port) { }

int port_; ///< latest imu port
};

/// wrapper for new imu data events that can be posted from the api callbacks
class Imu : public QEvent
{
public:
/// default constructor
/// @param[in] evt the event type
/// @param[in] imu latest imu data
Imu(QEvent::Type evt, const QQuaternion& imu) : QEvent(evt), imu_(imu) { }

QQuaternion imu_; ///< latest imu position
};

/// wrapper for error events that can be posted from the api callbacks
class Error : public QEvent
{
Expand Down
7 changes: 5 additions & 2 deletions examples/solum_qt/solum/solumqt.ui
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Solum Tester</string>
<string>Clarius Server</string>
</property>
<widget class="QWidget" name="_central">
<layout class="QVBoxLayout" name="verticalLayout">
Expand Down Expand Up @@ -41,7 +41,7 @@
<item>
<widget class="QTabWidget" name="_tabs">
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<widget class="QWidget" name="_certs">
<attribute name="title">
Expand Down Expand Up @@ -141,6 +141,9 @@
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="JobButton" name="blesearch">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximumSize">
<size>
<width>100</width>
Expand Down
59 changes: 54 additions & 5 deletions include/solum/solum.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ extern "C"
/// @param[in] newProcessedImage new processed image callback (scan-converted image)
/// @param[in] newRawImage new raw image callback - (pre scan-converted image)
/// @param[in] newSpectralImage new processed spectral image callback
/// @param[in] newImuPort new imu UDP port callback
/// @param[in] newImuData new imu data callback
/// @param[in] imaging imaging state callback
/// @param[in] btn button press callback
/// @param[in] err error message callback
Expand All @@ -26,9 +28,27 @@ extern "C"
SOLUM_EXPORT int solumInit(int argc, char** argv, const char* dir,
CusConnectFn connect, CusCertFn cert, CusPowerDownFn power,
CusNewProcessedImageFn newProcessedImage, CusNewRawImageFn newRawImage,
CusNewSpectralImageFn newSpectralImage, CusImagingFn imaging, CusButtonFn btn, CusErrorFn err,
CusNewSpectralImageFn newSpectralImage, CusNewImuPortFn newImuPort, CusNewImuDataFn newImuData,
CusImagingFn imaging, CusButtonFn btn, CusErrorFn err,
int width, int height);

/// initializes the solum module with a minimal set of callbacks
/// @param[in] connect connection status callback
/// @param[in] cert certificate status callback
/// @param[in] power probe power down callback
/// @param[in] imaging imaging state callback
/// @param[in] btn button press callback
/// @param[in] err error message callback
/// @param[in] newProcessedImage new processed image callback (scan-converted image)
/// @param[in] width the width of the output buffer
/// @param[in] height the height of the output buffer
/// @return success of the call
/// @retval 0 the initialization was successful
/// @retval -1 the initialization was not successful
/// @note must be called before any other functions will succeed
SOLUM_EXPORT int solumInitMinimal(CusConnectFn connect, CusCertFn cert, CusPowerDownFn power, CusImagingFn imaging, CusButtonFn btn, CusErrorFn err,
CusNewProcessedImageFn newProcessedImage, int width, int height);

/// cleans up memory allocated by the solum module
/// @retval 0 the destroy attempt was successful
/// @retval -1 the destroy attempt was not successful
Expand All @@ -43,6 +63,8 @@ extern "C"
SOLUM_EXPORT int solumSetTeeFn(CusTeeConnectFn tee);

/// retrieves the firmware version for a given platform
/// @note this is the version supported by the sdk, not the version of any connected probe,
/// use this string to download the firmware binary from clarius cloud and update the probe
/// @param[in] platform the platform to retrieve the firmware version for
/// @param[out] version holds the firmware version for the given platform
/// @param[in] sz size of the version string buffer, suggest at least 32 bytes allocated
Expand Down Expand Up @@ -203,6 +225,14 @@ extern "C"
/// @retval -1 tgc set request could not be made
SOLUM_EXPORT int solumGetTgc(CusTgc* tgc);

/// retrieves the active region for the grayscale image
/// @param[out] points holds a vector of points in x/y format
/// @param[in] count the number of points to generate (points buffer must be count x 2 or larger)
/// @return success of the call
/// @retval 0 roi was retrieved
/// @retval -1 roi could not be retrieved
SOLUM_EXPORT int solumGetActiveRegion(double* points, int count);

/// retrieves the roi for the current mode if valid
/// @param[out] points holds a vector of points in x/y format
/// @param[in] count the number of points to generate (points buffer must be count x 2 or larger)
Expand Down Expand Up @@ -284,26 +314,35 @@ extern "C"
/// @retval -1 the reset could not be performed
SOLUM_EXPORT int solumResetProbe(CusProbeReset reset);

/// makes a request to return the availability of all the raw data currently buffered on the probe
/// @param[in] fn result callback function that will return all the timestamps of the data blocks that are buffered
/// @return success of the call
/// @retval 0 the request was successfully made
/// @retval -1 the request could not be made
/// @note the probe must be frozen with raw data buffering enabled prior to calling the function
SOLUM_EXPORT int solumRawDataAvailability(CusRawAvailabilityFn fn);

/// makes a request for raw data from the probe
/// @param[in] start the first frame to request, as determined by timestamp in nanoseconds, set to 0 along with end to requests all data in buffer
/// @param[in] end the last frame to request, as determined by timestamp in nanoseconds, set to 0 along with start to requests all data in buffer
/// @param[in] res result callback function, will return size of buffer required upon success, 0 if no raw data was buffered, or -1 if request could not be made,
/// @param[in] lzo flag to specify a tarball with lzo compressed raw data inside (default) vs no compression of raw data
/// @param[in] fn result callback function, will return size of buffer required upon success, 0 if no raw data was buffered, or -1 if request could not be made
/// @return success of the call
/// @retval 0 the request was successfully made
/// @retval -1 the request could not be made
/// @note the probe must be frozen and in a raw data buffering mode in order for the call to succeed
SOLUM_EXPORT int solumRequestRawData(long long int start, long long int end, CusRawFn res);
SOLUM_EXPORT int solumRequestRawData(long long int start, long long int end, int lzo, CusRawRequestFn fn);

/// retrieves raw data from a previous request
/// @param[out] data a pointer to a buffer that has been allocated to read the raw data into, this must be pre-allocated with
/// the size returned from a previous call to solumRequestRawData
/// @param[in] res result callback function, will return size of buffer required upon success, 0 if no raw data was buffered, or -1 if request could not be made,
/// @param[in] fn result callback function, will return size of buffer required upon success, 0 if no raw data was buffered, or -1 if request could not be made,
/// @param[in] progress download progress callback function that outputs the progress in percent
/// @return success of the call
/// @retval 0 the read request was successfully made
/// @retval -1 the read request could not be made
/// @note the probe must be frozen and a successful call to solumRequestRawData must have taken place in order for the call to succeed
SOLUM_EXPORT int solumReadRawData(void** data, CusRawFn res, CusProgressFn progress);
SOLUM_EXPORT int solumReadRawData(void** data, CusRawFn fn, CusProgressFn progress);

/// sets a low level parameter to a specific value to gain access to lower level device control
/// @param[in] prm the parameter to change
Expand All @@ -312,6 +351,7 @@ extern "C"
/// @retval 0 the call was successful
/// @retval -1 the call was not successful
/// @note see external documentation for supported parameters
/// @warning changing parameters through this function may result in unstable operation, degradation of image quality, or operation outside of the safety limits that clarius tests to
SOLUM_EXPORT int solumSetLowLevelParam(const char* prm, double val);

/// enables or disables a low level parameter to gain access to lower device control
Expand All @@ -321,6 +361,7 @@ extern "C"
/// @retval 0 the call was successful
/// @retval -1 the call was not successful
/// @note see external documentation for supported parameters
/// @warning changing parameters through this function may result in unstable operation, degradation of image quality, or operation outside of the safety limits that clarius tests to
SOLUM_EXPORT int solumEnableLowLevelParam(const char* prm, int en);

/// sets a pulse shape parameter to a specific value to gain access to lower level device control
Expand All @@ -330,6 +371,7 @@ extern "C"
/// @retval 0 the call was successful
/// @retval -1 the call was not successful
/// @note see external documentation for supported parameters
/// @warning changing parameters through this function may result in unstable operation, degradation of image quality, or operation outside of the safety limits that clarius tests to
SOLUM_EXPORT int solumSetLowLevelPulse(const char* prm, const char* shape);

/// retrieves a low level parameter value
Expand All @@ -338,6 +380,13 @@ extern "C"
/// @retval -1 if the parameter value retrieval could not be made
SOLUM_EXPORT double solumGetLowLevelParam(const char* prm);

/// retrieves the acoustic indices for the loaded application, imaging mode, and parameter settings
/// @param[out] indices the acoustic index values
/// @return success of the call
/// @retval 0 the call was successful
/// @retval -1 the call was not successful
SOLUM_EXPORT int solumGetAcousticIndices(CusAcoustic* indices);

/// set the tee exam info for a connected probe
/// @param[in] id the patient id
/// @param[in] name the patient name
Expand Down
Loading