changeset 333:3bb9ebd283ce default tip

sync
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 01 Sep 2025 11:51:59 +0200
parents 059e7dc71287
children
files Resources/Orthanc/CMake/AutoGeneratedCode.cmake Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Resources/SyncOrthancFolder.py
diffstat 5 files changed, 474 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/Resources/Orthanc/CMake/AutoGeneratedCode.cmake	Mon Sep 01 11:51:03 2025 +0200
+++ b/Resources/Orthanc/CMake/AutoGeneratedCode.cmake	Mon Sep 01 11:51:59 2025 +0200
@@ -20,7 +20,7 @@
 # <http://www.gnu.org/licenses/>.
 
 
-set(EMBED_RESOURCES_PYTHON "${CMAKE_CURRENT_LIST_DIR}/../EmbedResources.py"
+set(EMBED_RESOURCES_PYTHON "${CMAKE_CURRENT_LIST_DIR}/EmbedResources.py"
   CACHE INTERNAL "Path to the EmbedResources.py script from Orthanc")
 set(AUTOGENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/AUTOGENERATED")
 set(AUTOGENERATED_SOURCES)
--- a/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake	Mon Sep 01 11:51:03 2025 +0200
+++ b/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake	Mon Sep 01 11:51:59 2025 +0200
@@ -171,6 +171,10 @@
         set(ORTHANC_FRAMEWORK_MD5 "0e971f32f4f3e4951e0f3b5de49a3da6")
       elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.7")
         set(ORTHANC_FRAMEWORK_MD5 "f27c27d7a7a694dab1fd7f0a99d9715a")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.8")
+        set(ORTHANC_FRAMEWORK_MD5 "eb1c719234338e8277b80d3453563e9f")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.12.9")
+        set(ORTHANC_FRAMEWORK_MD5 "66b5a2ee60706c4a502896083b9e1a01")
 
       # Below this point are development snapshots that were used to
       # release some plugin, before an official release of the Orthanc
@@ -515,7 +519,6 @@
   include(${CMAKE_CURRENT_LIST_DIR}/Compiler.cmake)
   include(${CMAKE_CURRENT_LIST_DIR}/DownloadPackage.cmake)
   include(${CMAKE_CURRENT_LIST_DIR}/AutoGeneratedCode.cmake)
-  set(EMBED_RESOURCES_PYTHON ${CMAKE_CURRENT_LIST_DIR}/EmbedResources.py)
 
   if (ORTHANC_FRAMEWORK_USE_SHARED)
     list(GET CMAKE_FIND_LIBRARY_PREFIXES 0 Prefix)
--- a/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp	Mon Sep 01 11:51:03 2025 +0200
+++ b/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp	Mon Sep 01 11:51:59 2025 +0200
@@ -23,6 +23,7 @@
 
 #include "OrthancPluginCppWrapper.h"
 
+#include <cassert>
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/move/unique_ptr.hpp>
 #include <boost/thread.hpp>
@@ -220,28 +221,6 @@
   }
 
 
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-  MemoryBuffer::MemoryBuffer(const void* buffer,
-                             size_t size)
-  {
-    uint32_t s = static_cast<uint32_t>(size);
-    if (static_cast<size_t>(s) != size)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory);
-    }
-    else if (OrthancPluginCreateMemoryBuffer(GetGlobalContext(), &buffer_, s) !=
-             OrthancPluginErrorCode_Success)
-    {
-      ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory);
-    }
-    else
-    {
-      memcpy(buffer_.data, buffer, size);
-    }
-  }
-#endif
-
-
   void MemoryBuffer::Clear()
   {
     if (buffer_.data != NULL)
@@ -253,6 +232,51 @@
   }
 
 
+#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
+  void MemoryBuffer::Assign(const void* buffer,
+                            size_t size)
+  {
+    uint32_t s = static_cast<uint32_t>(size);
+    if (static_cast<size_t>(s) != size)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory);
+    }
+
+    Clear();
+
+    if (OrthancPluginCreateMemoryBuffer(GetGlobalContext(), &buffer_, s) !=
+        OrthancPluginErrorCode_Success)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory);
+    }
+    else
+    {
+      if (size > 0)
+      {
+        memcpy(buffer_.data, buffer, size);
+      }
+    }
+  }
+#endif
+
+#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
+  void MemoryBuffer::Assign(const std::string& s)
+  {
+    Assign(s.empty() ? NULL : s.c_str(), s.size());
+  }
+#endif
+
+
+#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
+  void MemoryBuffer::AssignJson(const Json::Value& value)
+  {
+    std::string s;
+    WriteFastJson(s, value);
+    Assign(s);
+  }
+#endif
+
+
   void MemoryBuffer::Assign(OrthancPluginMemoryBuffer& other)
   {
     Clear();
@@ -673,7 +697,7 @@
   {
     OrthancString str;
     str.Assign(OrthancPluginDicomBufferToJson
-               (GetGlobalContext(), GetData(), GetSize(), format, flags, maxStringLength));
+               (GetGlobalContext(), reinterpret_cast<const char*>(GetData()), GetSize(), format, flags, maxStringLength));
     str.ToJson(target);
   }
 
@@ -1566,7 +1590,7 @@
     {
       if (!answer.IsEmpty())
       {
-        result.assign(answer.GetData(), answer.GetSize());
+        result.assign(reinterpret_cast<const char*>(answer.GetData()), answer.GetSize());
       }
       return true;
     }
@@ -2052,6 +2076,26 @@
             DoPost(target, index, uri, body, headers));
   }
 
+  bool OrthancPeers::DoPost(Json::Value& target,
+                            size_t index,
+                            const std::string& uri,
+                            const std::string& body,
+                            const HttpHeaders& headers, 
+                            unsigned int timeout) const
+  {
+    MemoryBuffer buffer;
+
+    if (DoPost(buffer, index, uri, body, headers, timeout))
+    {
+      buffer.ToJson(target);
+      return true;
+    }
+    else
+    {
+      return false;
+    }
+  }
+
 
   bool OrthancPeers::DoPost(Json::Value& target,
                             size_t index,
@@ -2099,6 +2143,17 @@
                             const std::string& body,
                             const HttpHeaders& headers) const
   {
+    return DoPost(target, index, uri, body, headers, timeout_);
+  }
+
+
+  bool OrthancPeers::DoPost(MemoryBuffer& target,
+                            size_t index,
+                            const std::string& uri,
+                            const std::string& body,
+                            const HttpHeaders& headers,
+                            unsigned int timeout) const
+  {
     if (index >= index_.size())
     {
       ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_ParameterOutOfRange);
@@ -2117,7 +2172,7 @@
     OrthancPluginErrorCode code = OrthancPluginCallPeerApi
       (GetGlobalContext(), *answer, NULL, &status, peers_,
        static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(),
-       pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), body.empty() ? NULL : body.c_str(), body.size(), timeout_);
+       pluginHeaders.GetSize(), pluginHeaders.GetKeys(), pluginHeaders.GetValues(), body.empty() ? NULL : body.c_str(), body.size(), timeout);
 
     if (code == OrthancPluginErrorCode_Success)
     {
@@ -4068,6 +4123,16 @@
   }
 #endif
 
+  void GetGetArguments(GetArguments& result, const OrthancPluginHttpRequest* request)
+  {
+    result.clear();
+
+    for (uint32_t i = 0; i < request->getCount; ++i)
+    {
+      result[request->getKeys[i]] = request->getValues[i];
+    }    
+  }
+
   void GetHttpHeaders(HttpHeaders& result, const OrthancPluginHttpRequest* request)
   {
     result.clear();
@@ -4168,6 +4233,11 @@
     {
       path_ += "?" + getArguments;
     }
+
+    if (request->bodySize > 0 && request->body != NULL)
+    {
+      requestBody_.assign(reinterpret_cast<const char*>(request->body), request->bodySize);
+    }
   }
 #endif
 
@@ -4189,6 +4259,15 @@
 
 
 #if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
+  void RestApiClient::SetRequestHeader(const std::string& key,
+                                       const std::string& value)
+  {
+    requestHeaders_[key] = value;
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1
   bool RestApiClient::Execute()
   {
     if (requestBody_.size() > 0xffffffffu)
@@ -4235,9 +4314,17 @@
     }
   }
 
-  void RestApiClient::Forward(OrthancPluginContext* context, OrthancPluginRestOutput* output)
-  {
-    if (Execute() && httpStatus_ == 200)
+  void RestApiClient::ExecuteAndForwardAnswer(OrthancPluginContext* context, OrthancPluginRestOutput* output)
+  {
+    if (Execute())
+    {
+      ForwardAnswer(context, output);
+    }
+  }
+
+  void RestApiClient::ForwardAnswer(OrthancPluginContext* context, OrthancPluginRestOutput* output)
+  {
+    if (httpStatus_ == 200)
     {
       const char* mimeType = NULL;
       for (HttpHeaders::const_iterator h = answerHeaders_.begin(); h != answerHeaders_.end(); ++h)
@@ -4316,4 +4403,209 @@
     }
   }
 #endif
+
+
+#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+  KeyValueStore::Iterator::Iterator(OrthancPluginKeysValuesIterator  *iterator) :
+    iterator_(iterator)
+  {
+    if (iterator_ == NULL)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
+    }
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+  KeyValueStore::Iterator::~Iterator()
+  {
+    OrthancPluginFreeKeysValuesIterator(OrthancPlugins::GetGlobalContext(), iterator_);
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+  bool KeyValueStore::Iterator::Next()
+  {
+    uint8_t done;
+    OrthancPluginErrorCode code = OrthancPluginKeysValuesIteratorNext(OrthancPlugins::GetGlobalContext(), &done, iterator_);
+
+    if (code != OrthancPluginErrorCode_Success)
+    {
+      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+    }
+    else
+    {
+      return (done != 0);
+    }
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+  std::string KeyValueStore::Iterator::GetKey() const
+  {
+    const char* s = OrthancPluginKeysValuesIteratorGetKey(OrthancPlugins::GetGlobalContext(), iterator_);
+    if (s == NULL)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
+    }
+    else
+    {
+      return s;
+    }
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+  void KeyValueStore::Iterator::GetValue(std::string& value) const
+  {
+    OrthancPlugins::MemoryBuffer valueBuffer;
+    OrthancPluginErrorCode code = OrthancPluginKeysValuesIteratorGetValue(OrthancPlugins::GetGlobalContext(), *valueBuffer, iterator_);
+
+    if (code != OrthancPluginErrorCode_Success)
+    {
+      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+    }
+    else
+    {
+      valueBuffer.ToString(value);
+    }
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+  void KeyValueStore::Store(const std::string& key,
+                            const void* value,
+                            size_t valueSize)
+  {
+    if (static_cast<size_t>(static_cast<uint32_t>(valueSize)) != valueSize)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory);
+    }
+
+    OrthancPluginErrorCode code = OrthancPluginStoreKeyValue(OrthancPlugins::GetGlobalContext(), storeId_.c_str(),
+                                                             key.c_str(), value, static_cast<uint32_t>(valueSize));
+    if (code != OrthancPluginErrorCode_Success)
+    {
+      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+    }
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+  bool KeyValueStore::GetValue(std::string& value,
+                               const std::string& key)
+  {
+    uint8_t found = false;
+    OrthancPlugins::MemoryBuffer valueBuffer;
+    OrthancPluginErrorCode code = OrthancPluginGetKeyValue(OrthancPlugins::GetGlobalContext(), &found,
+                                                           *valueBuffer, storeId_.c_str(), key.c_str());
+
+    if (code != OrthancPluginErrorCode_Success)
+    {
+      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+    }
+    else if (found)
+    {
+      valueBuffer.ToString(value);
+      return true;
+    }
+    else
+    {
+      return false;
+    }
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+  void KeyValueStore::DeleteKey(const std::string& key)
+  {
+    OrthancPluginErrorCode code = OrthancPluginDeleteKeyValue(OrthancPlugins::GetGlobalContext(),
+                                                              storeId_.c_str(), key.c_str());
+
+    if (code != OrthancPluginErrorCode_Success)
+    {
+      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+    }
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+  KeyValueStore::Iterator* KeyValueStore::CreateIterator()
+  {
+    return new Iterator(OrthancPluginCreateKeysValuesIterator(OrthancPlugins::GetGlobalContext(), storeId_.c_str()));
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_QUEUES == 1
+  void Queue::Enqueue(const void* value,
+                      size_t valueSize)
+  {
+    if (static_cast<size_t>(static_cast<uint32_t>(valueSize)) != valueSize)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(NotEnoughMemory);
+    }
+
+    OrthancPluginErrorCode code = OrthancPluginEnqueueValue(OrthancPlugins::GetGlobalContext(),
+                                                            queueId_.c_str(), value, static_cast<uint32_t>(valueSize));
+
+    if (code != OrthancPluginErrorCode_Success)
+    {
+      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+    }
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_QUEUES == 1
+  bool Queue::DequeueInternal(std::string& value,
+                              OrthancPluginQueueOrigin origin)
+  {
+    uint8_t found = false;
+    OrthancPlugins::MemoryBuffer valueBuffer;
+
+    OrthancPluginErrorCode code = OrthancPluginDequeueValue(OrthancPlugins::GetGlobalContext(), &found,
+                                                            *valueBuffer, queueId_.c_str(), origin);
+
+    if (code != OrthancPluginErrorCode_Success)
+    {
+      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+    }
+    else if (found)
+    {
+      valueBuffer.ToString(value);
+      return true;
+    }
+    else
+    {
+      return false;
+    }
+  }
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_QUEUES == 1
+  uint64_t Queue::GetSize()
+  {
+    uint64_t size = 0;
+    OrthancPluginErrorCode code = OrthancPluginGetQueueSize(OrthancPlugins::GetGlobalContext(), queueId_.c_str(), &size);
+
+    if (code != OrthancPluginErrorCode_Success)
+    {
+      ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
+    }
+    else
+    {
+      return size;
+    }
+  }
+#endif
 }
--- a/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h	Mon Sep 01 11:51:03 2025 +0200
+++ b/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h	Mon Sep 01 11:51:59 2025 +0200
@@ -134,6 +134,14 @@
 #  define HAS_ORTHANC_PLUGIN_LOG_MESSAGE  0
 #endif
 
+#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 8)
+#  define HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES  1
+#  define HAS_ORTHANC_PLUGIN_QUEUES            1
+#else
+#  define HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES  0
+#  define HAS_ORTHANC_PLUGIN_QUEUES            0
+#endif
+
 
 // Macro to tag a function as having been deprecated
 #if (__cplusplus >= 201402L)  // C++14
@@ -172,6 +180,8 @@
 {
   typedef std::map<std::string, std::string>  HttpHeaders;
 
+  typedef std::map<std::string, std::string>  GetArguments;
+
   typedef void (*RestCallback) (OrthancPluginRestOutput* output,
                                 const char* url,
                                 const OrthancPluginHttpRequest* request);
@@ -203,13 +213,6 @@
   public:
     MemoryBuffer();
 
-#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
-    // This constructor makes a copy of the given buffer in the memory
-    // handled by the Orthanc core
-    MemoryBuffer(const void* buffer,
-                 size_t size);
-#endif
-
     ~MemoryBuffer()
     {
       Clear();
@@ -220,6 +223,20 @@
       return &buffer_;
     }
 
+#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
+    // Copy of the given buffer into the memory managed by the Orthanc core
+    void Assign(const void* buffer,
+                size_t size);
+#endif
+
+#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
+    void Assign(const std::string& s);
+#endif
+
+#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 7, 0)
+    void AssignJson(const Json::Value& value);
+#endif
+
     // This transfers ownership from "other" to "this"
     void Assign(OrthancPluginMemoryBuffer& other);
 
@@ -227,11 +244,11 @@
 
     OrthancPluginMemoryBuffer Release();
 
-    const char* GetData() const
+    const void* GetData() const
     {
       if (buffer_.size > 0)
       {
-        return reinterpret_cast<const char*>(buffer_.data);
+        return buffer_.data;
       }
       else
       {
@@ -855,6 +872,13 @@
                 const HttpHeaders& headers) const;
 
     bool DoPost(MemoryBuffer& target,
+                size_t index,
+                const std::string& uri,
+                const std::string& body,
+                const HttpHeaders& headers,
+                unsigned int timeout) const;
+
+    bool DoPost(MemoryBuffer& target,
                 const std::string& name,
                 const std::string& uri,
                 const std::string& body,
@@ -867,6 +891,13 @@
                 const HttpHeaders& headers) const;
 
     bool DoPost(Json::Value& target,
+                size_t index,
+                const std::string& uri,
+                const std::string& body,
+                const HttpHeaders& headers,
+                unsigned int timeout) const;
+
+    bool DoPost(Json::Value& target,
                 const std::string& name,
                 const std::string& uri,
                 const std::string& body,
@@ -1402,6 +1433,9 @@
 // helper method to re-serialize the get arguments from the SDK into a string
 void SerializeGetArguments(std::string& output, const OrthancPluginHttpRequest* request);
 
+// helper method to convert Get arguments from the plugin SDK to a std::map
+void GetGetArguments(GetArguments& result, const OrthancPluginHttpRequest* request);
+
 #if HAS_ORTHANC_PLUGIN_WEBDAV == 1
   class IWebDavCollection : public boost::noncopyable
   {
@@ -1559,6 +1593,9 @@
     void AddRequestHeader(const std::string& key,
                           const std::string& value);
 
+    void SetRequestHeader(const std::string& key,
+                          const std::string& value);
+
     const HttpHeaders& GetRequestHeaders() const
     {
       return requestHeaders_;
@@ -1589,10 +1626,14 @@
       return requestBody_;
     }
 
+    // Execute only
     bool Execute();
 
+    // Forward response as is
+    void ForwardAnswer(OrthancPluginContext* context, OrthancPluginRestOutput* output);
+
     // Execute and forward the response as is
-    void Forward(OrthancPluginContext* context, OrthancPluginRestOutput* output);
+    void ExecuteAndForwardAnswer(OrthancPluginContext* context, OrthancPluginRestOutput* output);
 
     uint16_t GetHttpStatus() const;
 
@@ -1604,4 +1645,101 @@
     bool GetAnswerJson(Json::Value& output) const;
   };
 #endif
+
+
+#if HAS_ORTHANC_PLUGIN_KEY_VALUE_STORES == 1
+  class KeyValueStore : public boost::noncopyable
+  {
+  public:
+    class Iterator : public boost::noncopyable
+    {
+    private:
+      OrthancPluginKeysValuesIterator  *iterator_;
+
+    public:
+      explicit Iterator(OrthancPluginKeysValuesIterator *iterator);
+
+      ~Iterator();
+
+      bool Next();
+
+      std::string GetKey() const;
+
+      void GetValue(std::string& target) const;
+    };
+
+  private:
+    std::string storeId_;
+
+  public:
+    explicit KeyValueStore(const std::string& storeId) :
+      storeId_(storeId)
+    {
+    }
+
+    const std::string& GetStoreId() const
+    {
+      return storeId_;
+    }
+
+    void Store(const std::string& key,
+               const void* value,
+               size_t valueSize);
+
+    void Store(const std::string& key,
+               const std::string& value)
+    {
+      Store(key, value.empty() ? NULL : value.c_str(), value.size());
+    }
+
+    bool GetValue(std::string& value,
+                  const std::string& key);
+
+    void DeleteKey(const std::string& key);
+
+    Iterator* CreateIterator();
+  };
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_QUEUES == 1
+  class Queue : public boost::noncopyable
+  {
+  private:
+    std::string queueId_;
+
+    bool DequeueInternal(std::string& value, OrthancPluginQueueOrigin origin);
+
+  public:
+    explicit Queue(const std::string& queueId) :
+      queueId_(queueId)
+    {
+    }
+
+    const std::string& GetQueueId() const
+    {
+      return queueId_;
+    }
+
+    void Enqueue(const void* value,
+                 size_t valueSize);
+
+    void Enqueue(const std::string& value)
+    {
+      Enqueue(value.empty() ? NULL : value.c_str(), value.size());
+    }
+
+    bool DequeueBack(std::string& value)
+    {
+      return DequeueInternal(value, OrthancPluginQueueOrigin_Back);
+    }
+
+    bool DequeueFront(std::string& value)
+    {
+      return DequeueInternal(value, OrthancPluginQueueOrigin_Front);
+    }
+
+    uint64_t GetSize();
+  };
+#endif
 }
--- a/Resources/SyncOrthancFolder.py	Mon Sep 01 11:51:03 2025 +0200
+++ b/Resources/SyncOrthancFolder.py	Mon Sep 01 11:51:59 2025 +0200
@@ -19,8 +19,8 @@
     ('OrthancFramework/Resources/CMake/Compiler.cmake', 'CMake'),
     ('OrthancFramework/Resources/CMake/DownloadOrthancFramework.cmake', 'CMake'),
     ('OrthancFramework/Resources/CMake/DownloadPackage.cmake', 'CMake'),
+    ('OrthancFramework/Resources/CMake/EmbedResources.py', 'CMake'),
     ('OrthancFramework/Resources/CMake/GoogleTestConfiguration.cmake', 'CMake'),
-    ('OrthancFramework/Resources/EmbedResources.py', 'CMake'),
     ('OrthancFramework/Resources/Toolchains/LinuxStandardBaseToolchain.cmake', 'Toolchains'),
     ('OrthancFramework/Resources/Toolchains/MinGW-W64-Toolchain32.cmake', 'Toolchains'),
     ('OrthancFramework/Resources/Toolchains/MinGW-W64-Toolchain64.cmake', 'Toolchains'),