Mercurial > hg > orthanc-python
diff Sources/DicomScpCallbacks.cpp @ 157:a8408ef2b2d8
merge cmove2 -> default
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Thu, 16 May 2024 10:38:22 +0200 |
parents | 71d305c29cfa a6b4e0abe532 |
children | 6fada29b6759 |
line wrap: on
line diff
--- a/Sources/DicomScpCallbacks.cpp Sat Apr 06 17:28:00 2024 +0200 +++ b/Sources/DicomScpCallbacks.cpp Thu May 16 10:38:22 2024 +0200 @@ -30,6 +30,12 @@ static PyObject* moveScpCallback_ = NULL; static PyObject* worklistScpCallback_ = NULL; +// version 2 of Move callbacks +static PyObject* createMoveScpDriverCallback_ = NULL; +static PyObject* getMoveSizeCallback_ = NULL; +static PyObject* applyMoveCallback_ = NULL; +static PyObject* freeMoveCallback_ = NULL; + static PyObject *GetFindQueryTag(sdk_OrthancPluginFindQuery_Object* self, PyObject *args, @@ -399,6 +405,226 @@ } +static void* CreateMoveCallback2(OrthancPluginResourceType resourceType, + const char *patientId, + const char *accessionNumber, + const char *studyInstanceUid, + const char *seriesInstanceUid, + const char *sopInstanceUid, + const char *originatorAet, + const char *sourceAet, + const char *targetAet, + uint16_t originatorId) +{ + assert(createMoveScpDriverCallback_ != NULL); + + try + { + std::string _patientId, _accessionNumber, _studyInstanceUid, _seriesInstanceUid, _sopInstanceUid, _originatorAet, _sourceAet, _targetAet; + if (patientId != NULL) + { + _patientId.assign(patientId); + } + + if (accessionNumber != NULL) + { + _accessionNumber.assign(accessionNumber); + } + + if (studyInstanceUid != NULL) + { + _studyInstanceUid.assign(studyInstanceUid); + } + + if (seriesInstanceUid != NULL) + { + _seriesInstanceUid.assign(seriesInstanceUid); + } + + if (sopInstanceUid != NULL) + { + _sopInstanceUid.assign(sopInstanceUid); + } + + if (originatorAet != NULL) + { + _originatorAet.assign(originatorAet); + } + + if (sourceAet != NULL) + { + _sourceAet.assign(sourceAet); + } + + if (targetAet != NULL) + { + _targetAet.assign(targetAet); + } + + PythonLock lock; + + PythonObject kw(lock, PyDict_New()); + + std::string level; + switch (resourceType) + { + case OrthancPluginResourceType_Patient: + level = "PATIENT"; + break; + + case OrthancPluginResourceType_Study: + level = "STUDY"; + break; + + case OrthancPluginResourceType_Series: + level = "SERIES"; + break; + + case OrthancPluginResourceType_Instance: + level = "INSTANCE"; + break; + + default: + throw OrthancPlugins::PluginException(OrthancPluginErrorCode_ParameterOutOfRange); + } + + { + PythonString tmp(lock, level); + PyDict_SetItemString(kw.GetPyObject(), "Level", tmp.GetPyObject()); + } + + { + PythonString tmp(lock, _patientId); + PyDict_SetItemString(kw.GetPyObject(), "PatientID", tmp.GetPyObject()); + } + + { + PythonString tmp(lock, _accessionNumber); + PyDict_SetItemString(kw.GetPyObject(), "AccessionNumber", tmp.GetPyObject()); + } + + { + PythonString tmp(lock, _studyInstanceUid); + PyDict_SetItemString(kw.GetPyObject(), "StudyInstanceUID", tmp.GetPyObject()); + } + + { + PythonString tmp(lock, _seriesInstanceUid); + PyDict_SetItemString(kw.GetPyObject(), "SeriesInstanceUID", tmp.GetPyObject()); + } + + { + PythonString tmp(lock, _sopInstanceUid); + PyDict_SetItemString(kw.GetPyObject(), "SOPInstanceUID", tmp.GetPyObject()); + } + + { + PythonString tmp(lock, _originatorAet); + PyDict_SetItemString(kw.GetPyObject(), "OriginatorAET", tmp.GetPyObject()); + } + + { + PythonString tmp(lock, _sourceAet); + PyDict_SetItemString(kw.GetPyObject(), "SourceAET", tmp.GetPyObject()); + } + + { + PythonString tmp(lock, _targetAet); + PyDict_SetItemString(kw.GetPyObject(), "TargetAET", tmp.GetPyObject()); + } + + { + PythonObject tmp(lock, PyLong_FromUnsignedLong(originatorId)); + PyDict_SetItemString(kw.GetPyObject(), "OriginatorID", tmp.GetPyObject()); + } + + PythonObject args(lock, PyTuple_New(0)); + + // Note: the result is not attached to the PythonLock because we want it to survive after this call since + // the result is the python move driver that will be passed as first argument to GetMoveSize, Apply and Free. + // After the PyObject_Call, result's ref count is 1 -> no need to add a reference but we need to decref explicitely + // to delete the object at the end of the move. + PyObject* result = PyObject_Call(createMoveScpDriverCallback_, args.GetPyObject(), kw.GetPyObject()); + + OrthancPluginErrorCode code = lock.CheckCallbackSuccess("Python C-MOVE SCP callback (Create)"); + if (code != OrthancPluginErrorCode_Success) + { + throw OrthancPlugins::PluginException(code); + } + + return result; + } + catch (OrthancPlugins::PluginException& e) + { + return NULL; + } +} + + +static uint32_t GetMoveSize2(void *moveDriver) +{ + assert(moveDriver != NULL); + assert(getMoveSizeCallback_ != NULL); + + PythonLock lock; + + PythonObject args(lock, PyTuple_New(1)); + PyTuple_SetItem(args.GetPyObject(), 0, reinterpret_cast<PyObject*>(moveDriver)); + Py_INCREF(moveDriver); // because PyTuple_SetItem steals a reference and we need to keep the object alive + + PythonObject result(lock, PyObject_CallObject(getMoveSizeCallback_, args.GetPyObject())); + + OrthancPluginErrorCode code = lock.CheckCallbackSuccess("Python C-MOVE SCP callback (GetMoveSize)"); + if (code != OrthancPluginErrorCode_Success) + { + throw OrthancPlugins::PluginException(code); + } + + if (!PyLong_Check(result.GetPyObject())) + { + throw OrthancPlugins::PluginException(OrthancPluginErrorCode_BadParameterType); + } + + return static_cast<uint32_t>(PyLong_AsLong(result.GetPyObject())); +} + + +OrthancPluginErrorCode ApplyMove2(void *moveDriver) +{ + assert(moveDriver != NULL); + assert(applyMoveCallback_ != NULL); + + PythonLock lock; + + PythonObject args(lock, PyTuple_New(1)); + PyTuple_SetItem(args.GetPyObject(), 0, reinterpret_cast<PyObject*>(moveDriver)); + Py_INCREF(moveDriver); // because PyTuple_SetItem steals a reference and we need to keep the object alive + + PythonObject result(lock, PyObject_CallObject(applyMoveCallback_, args.GetPyObject())); + + OrthancPluginErrorCode code = lock.CheckCallbackSuccess("Python C-MOVE SCP callback (Apply)"); + return code; +} + + +void FreeMove2(void *moveDriver) +{ + assert(moveDriver != NULL); + + PythonLock lock; + + PythonObject args(lock, PyTuple_New(1)); + PyTuple_SetItem(args.GetPyObject(), 0, reinterpret_cast<PyObject*>(moveDriver)); + Py_INCREF(moveDriver); // because PyTuple_SetItem steals a reference and we need to keep the object alive + + assert(freeMoveCallback_ != NULL); + PythonObject result(lock, PyObject_CallObject(freeMoveCallback_, args.GetPyObject())); + + lock.CheckCallbackSuccess("Python C-MOVE SCP callback (Free)"); + + Py_DECREF(moveDriver); // remove the initial reference -> this will delete the Python Object when we exit this function +} + OrthancPluginErrorCode WorklistCallback(OrthancPluginWorklistAnswers *answers, const OrthancPluginWorklistQuery *query, @@ -487,6 +713,25 @@ } +PyObject* RegisterMoveCallback2(PyObject* module, PyObject* args) +{ + // The GIL is locked at this point (no need to create "PythonLock") + + class Registration : public ICallbackRegistration + { + public: + virtual void Register() ORTHANC_OVERRIDE + { + OrthancPluginRegisterMoveCallback( + OrthancPlugins::GetGlobalContext(), CreateMoveCallback2, GetMoveSize2, ApplyMove2, FreeMove2); + } + }; + + Registration registration; + return ICallbackRegistration::Apply4( + registration, args, createMoveScpDriverCallback_, getMoveSizeCallback_, applyMoveCallback_, freeMoveCallback_, "Python C-MOVE SCP callback (2)"); +} + PyObject* RegisterWorklistCallback(PyObject* module, PyObject* args) { // The GIL is locked at this point (no need to create "PythonLock") @@ -511,4 +756,9 @@ ICallbackRegistration::Unregister(findScpCallback_); ICallbackRegistration::Unregister(moveScpCallback_); ICallbackRegistration::Unregister(worklistScpCallback_); + + ICallbackRegistration::Unregister(createMoveScpDriverCallback_); + ICallbackRegistration::Unregister(getMoveSizeCallback_); + ICallbackRegistration::Unregister(applyMoveCallback_); + ICallbackRegistration::Unregister(freeMoveCallback_); }