Control: tags 1131331 + patch
Control: tags 1131331 + pending

Dear maintainer,

I've prepared an NMU for zynaddsubfx (versioned as 3.0.6-7.2) and 
uploaded it to DELAYED/7. Please feel free to tell me if I should
cancel it.

cu
Adrian
diffstat for zynaddsubfx-3.0.6 zynaddsubfx-3.0.6

 changelog                                     |    8 
 patches/0001-Support-MXML4-if-available.patch |  325 ++++++++++++++++++++++++++
 patches/fix_ftbfs_on_riscv64.patch            |   17 -
 patches/series                                |    2 
 rules                                         |    2 
 5 files changed, 335 insertions(+), 19 deletions(-)

diff -Nru zynaddsubfx-3.0.6/debian/changelog zynaddsubfx-3.0.6/debian/changelog
--- zynaddsubfx-3.0.6/debian/changelog	2025-10-26 18:52:52.000000000 +0200
+++ zynaddsubfx-3.0.6/debian/changelog	2026-03-31 12:24:21.000000000 +0300
@@ -1,3 +1,11 @@
+zynaddsubfx (3.0.6-7.2) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * Backport upstream fix for FTBFS with mxml 4. (Closes: #1131331)
+  * Remove no longer needed libatomic linking on riscv64.
+
+ -- Adrian Bunk <[email protected]>  Tue, 31 Mar 2026 12:24:21 +0300
+
 zynaddsubfx (3.0.6-7.1) unstable; urgency=medium
 
   * Non-maintainer upload.
diff -Nru zynaddsubfx-3.0.6/debian/patches/0001-Support-MXML4-if-available.patch zynaddsubfx-3.0.6/debian/patches/0001-Support-MXML4-if-available.patch
--- zynaddsubfx-3.0.6/debian/patches/0001-Support-MXML4-if-available.patch	1970-01-01 02:00:00.000000000 +0200
+++ zynaddsubfx-3.0.6/debian/patches/0001-Support-MXML4-if-available.patch	2026-03-31 12:12:28.000000000 +0300
@@ -0,0 +1,325 @@
+From c6a83f2175b9de877cad64464bd3d699795909b7 Mon Sep 17 00:00:00 2001
+From: Johannes Lorenz <[email protected]>
+Date: Sun, 12 Jan 2025 15:33:11 +0100
+Subject: Support MXML4, if available
+
+Improve comments
+
+MXML4: Free memory
+
+Fixup test, so it works on mxml3 and 4
+
+Fix MessageTest for MXML4
+---
+ src/CMakeLists.txt        |  5 ++-
+ src/Misc/XMLwrapper.cpp   | 93 +++++++++++++++++++++++++++++++--------
+ src/Tests/MessageTest.cpp | 16 +++----
+ src/Tests/PluginTest.cpp  | 21 ++++++++-
+ 4 files changed, 104 insertions(+), 31 deletions(-)
+
+diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
+index ecfe7545..44f48445 100644
+--- a/src/CMakeLists.txt
++++ b/src/CMakeLists.txt
+@@ -28,7 +28,10 @@ if(PKG_CONFIG_FOUND AND NOT (${CMAKE_SYSTEM_NAME} STREQUAL "Windows"))
+     pkg_check_modules(NTK_IMAGES ntk_images)
+ 
+     pkg_check_modules(FFTW3F REQUIRED fftw3f)
+-    pkg_check_modules(MXML REQUIRED mxml)
++    pkg_check_modules(MXML mxml4)
++    if(NOT MXML_FOUND)
++        pkg_check_modules(MXML REQUIRED mxml)
++    endif()
+ 
+     pkg_search_module(LASH lash-1.0)
+     mark_as_advanced(LASH_LIBRARIES)
+diff --git a/src/Misc/XMLwrapper.cpp b/src/Misc/XMLwrapper.cpp
+index e1c55a49..b34c843c 100644
+--- a/src/Misc/XMLwrapper.cpp
++++ b/src/Misc/XMLwrapper.cpp
+@@ -32,9 +32,30 @@ namespace zyn {
+ int  xml_k   = 0;
+ bool verbose = false;
+ 
+-const char *XMLwrapper_whitespace_callback(mxml_node_t *node, int where)
++#if MXML_MAJOR_VERSION <= 3
++// Mimic datatypes present in mxml4 for compatibility
++typedef int mxml_ws_t;
++typedef int mxml_descend_t;
++// Mimic typenames present in mxml4 for compatibility
++constexpr int MXML_DESCEND_ALL = MXML_DESCEND;
++constexpr int MXML_DESCEND_NONE = MXML_NO_DESCEND;
++constexpr int MXML_TYPE_OPAQUE = MXML_OPAQUE;
++constexpr int MXML_TYPE_ELEMENT = MXML_ELEMENT;
++constexpr int MXML_TYPE_TEXT = MXML_TEXT;
++#endif
++
++const char *XMLwrapper_whitespace_callback(void*, mxml_node_t *node, mxml_ws_t where)
+ {
++#if MXML_MAJOR_VERSION >= 4
++    // New node types in MXL4
++    if(mxmlGetDirective(node))  // "?xml" directive
++        return "\n";
++    else if(mxmlGetDeclaration(node))  // "!DOCTYPE" declaration
++        return nullptr;
++#endif
++
+     const char *name = mxmlGetElement(node);
++    assert(name);
+ 
+     if((where == MXML_WS_BEFORE_OPEN) && (!strcmp(name, "?xml")))
+         return NULL;
+@@ -67,13 +88,21 @@ const char *XMLwrapper_whitespace_callback(mxml_node_t *node, int where)
+     return 0;
+ }
+ 
++#if MXML_MAJOR_VERSION <= 3
++// Wrapper, because int and mxml_ws_t are different types
++inline const char *XMLwrapper_whitespace_callback(mxml_node_t *node, int where)
++{
++    return XMLwrapper_whitespace_callback(nullptr, node, where);
++}
++#endif
++
+ //temporary const overload of mxmlFindElement
+ const mxml_node_t *mxmlFindElement(const mxml_node_t *node,
+                                    const mxml_node_t *top,
+                                    const char *name,
+                                    const char *attr,
+                                    const char *value,
+-                                   int descend)
++                                   mxml_descend_t descend)
+ {
+     return const_cast<const mxml_node_t *>(mxmlFindElement(
+                                                const_cast<mxml_node_t *>(node),
+@@ -92,16 +121,22 @@ XMLwrapper::XMLwrapper()
+     minimal = true;
+     SaveFullXml=false;
+ 
+-    node = tree = mxmlNewElement(MXML_NO_PARENT,
+-                                 "?xml version=\"1.0f\" encoding=\"UTF-8\"?");
++    node = tree = mxmlNewXML("1.0");
++    assert(node);
+     /*  for mxml 2.1f (and older)
+         tree=mxmlNewElement(MXML_NO_PARENT,"?xml");
+         mxmlElementSetAttr(tree,"version","1.0f");
+         mxmlElementSetAttr(tree,"encoding","UTF-8");
+     */
+ 
+-    mxml_node_t *doctype = mxmlNewElement(tree, "!DOCTYPE");
+-    mxmlElementSetAttr(doctype, "ZynAddSubFX-data", NULL);
++    mxml_node_t *doctype =
++#if MXML_MAJOR_VERSION <= 3
++        mxmlNewElement(tree, "!DOCTYPE");
++        mxmlElementSetAttr(doctype, "ZynAddSubFX-data", NULL);
++#else
++        mxmlNewDeclaration(tree, "DOCTYPE ZynAddSubFX-data");
++#endif
++    assert(doctype);
+ 
+     node = root = addparams("ZynAddSubFX-data", 4,
+                             "version-major", stringFrom<int>(
+@@ -164,7 +199,7 @@ bool XMLwrapper::hasPadSynth() const
+                                        "INFORMATION",
+                                        NULL,
+                                        NULL,
+-                                       MXML_DESCEND);
++                                       MXML_DESCEND_ALL);
+ 
+     mxml_node_t *parameter = mxmlFindElement(tmp,
+                                              tmp,
+@@ -204,7 +239,15 @@ char *XMLwrapper::getXMLdata() const
+ {
+     xml_k = 0;
+ 
++#if MXML_MAJOR_VERSION <= 3
+     char *xmldata = mxmlSaveAllocString(tree, XMLwrapper_whitespace_callback);
++#else
++    mxml_options_t *options = mxmlOptionsNew();
++    mxmlOptionsSetWhitespaceCallback(options, XMLwrapper_whitespace_callback, /*cbdata*/nullptr);
++    char *xmldata = mxmlSaveAllocString(tree, options);
++    mxmlOptionsDelete(options);
++#endif
++
+ 
+     return xmldata;
+ }
+@@ -317,8 +360,15 @@ int XMLwrapper::loadXMLfile(const string &filename)
+     if(xmldata == NULL)
+         return -1;  //the file could not be loaded or uncompressed
+ 
++#if MXML_MAJOR_VERSION <= 3
+     root = tree = mxmlLoadString(NULL, trimLeadingWhite(
+-                                     xmldata), MXML_OPAQUE_CALLBACK);
++                                           xmldata), MXML_OPAQUE_CALLBACK);
++#else
++    mxml_options_t *options = mxmlOptionsNew();
++    mxmlOptionsSetTypeValue(options, MXML_TYPE_OPAQUE);
++    root = tree = mxmlLoadString(NULL, options, trimLeadingWhite(xmldata));
++    mxmlOptionsDelete(options);
++#endif
+ 
+     delete[] xmldata;
+ 
+@@ -330,7 +380,7 @@ int XMLwrapper::loadXMLfile(const string &filename)
+                                   "ZynAddSubFX-data",
+                                   NULL,
+                                   NULL,
+-                                  MXML_DESCEND);
++                                  MXML_DESCEND_ALL);
+     if(root == NULL)
+         return -3;  //the XML doesn't embbed zynaddsubfx data
+ 
+@@ -384,8 +434,15 @@ bool XMLwrapper::putXMLdata(const char *xmldata)
+     if(xmldata == NULL)
+         return false;
+ 
++#if MXML_MAJOR_VERSION <= 3
+     root = tree = mxmlLoadString(NULL, trimLeadingWhite(
+-                                     xmldata), MXML_OPAQUE_CALLBACK);
++                                           xmldata), MXML_OPAQUE_CALLBACK);
++#else
++    mxml_options_t *options = mxmlOptionsNew();
++    mxmlOptionsSetTypeValue(options, MXML_TYPE_OPAQUE);
++    root = tree = mxmlLoadString(NULL, options, trimLeadingWhite(xmldata));
++    mxmlOptionsDelete(options);
++#endif
+     if(tree == NULL)
+         return false;
+ 
+@@ -394,7 +451,7 @@ bool XMLwrapper::putXMLdata(const char *xmldata)
+                                   "ZynAddSubFX-data",
+                                   NULL,
+                                   NULL,
+-                                  MXML_DESCEND);
++                                  MXML_DESCEND_ALL);
+     if(root == NULL)
+         return false;
+ 
+@@ -531,11 +588,11 @@ void XMLwrapper::getparstr(const string &name, char *par, int maxstrlen) const
+         return;
+     if(mxmlGetFirstChild(tmp) == NULL)
+         return;
+-    if(mxmlGetType(mxmlGetFirstChild(tmp)) == MXML_OPAQUE) {
++    if(mxmlGetType(mxmlGetFirstChild(tmp)) == MXML_TYPE_OPAQUE) {
+         snprintf(par, maxstrlen, "%s", mxmlGetOpaque(mxmlGetFirstChild(tmp)));
+         return;
+     }
+-    if((mxmlGetType(mxmlGetFirstChild(tmp)) == MXML_TEXT)
++    if((mxmlGetType(mxmlGetFirstChild(tmp)) == MXML_TYPE_TEXT)
+        && (mxmlGetFirstChild(tmp) != NULL)) {
+         snprintf(par, maxstrlen, "%s", mxmlGetText(mxmlGetFirstChild(tmp),NULL));
+         return;
+@@ -555,11 +612,11 @@ string XMLwrapper::getparstr(const string &name,
+     if((tmp == NULL) || (mxmlGetFirstChild(tmp) == NULL))
+         return defaultpar;
+ 
+-    if(mxmlGetType(mxmlGetFirstChild(tmp)) == MXML_OPAQUE
++    if(mxmlGetType(mxmlGetFirstChild(tmp)) == MXML_TYPE_OPAQUE
+        && (mxmlGetOpaque(mxmlGetFirstChild(tmp)) != NULL))
+         return mxmlGetOpaque(mxmlGetFirstChild(tmp));
+ 
+-    if(mxmlGetType(mxmlGetFirstChild(tmp)) == MXML_TEXT
++    if(mxmlGetType(mxmlGetFirstChild(tmp)) == MXML_TYPE_TEXT
+        && (mxmlGetText(mxmlGetFirstChild(tmp),NULL) != NULL))
+         return mxmlGetText(mxmlGetFirstChild(tmp),NULL);
+ 
+@@ -684,8 +741,8 @@ std::vector<XmlNode> XMLwrapper::getBranch(void) const
+     std::vector<XmlNode> res;
+     mxml_node_t *current = mxmlGetFirstChild(node);
+     while(current) {
+-        if(mxmlGetType(current) == MXML_ELEMENT) {
+-#if MXML_MAJOR_VERSION == 3
++        if(mxmlGetType(current) == MXML_TYPE_ELEMENT) {
++#if MXML_MAJOR_VERSION >= 3
+             XmlNode n(mxmlGetElement(current));
+             int count = mxmlElementGetAttrCount(current);
+             const char *name;
+@@ -705,7 +762,7 @@ std::vector<XmlNode> XMLwrapper::getBranch(void) const
+ #endif
+             res.push_back(n);
+         }
+-        current = mxmlWalkNext(current, node, MXML_NO_DESCEND);
++        current = mxmlWalkNext(current, node, MXML_DESCEND_NONE);
+     }
+     return res;
+ }
+diff --git a/src/Tests/MessageTest.cpp b/src/Tests/MessageTest.cpp
+index ef7558df..f6810a2f 100644
+--- a/src/Tests/MessageTest.cpp
++++ b/src/Tests/MessageTest.cpp
+@@ -105,22 +105,16 @@ class MessageTest
+             mw->transmitMsg("/presets/copy", "s", "/part0/kit0/adpars/VoicePar0/FMSmp/");
+ 
+             TS_ASSERT_EQUAL_STR("Poscilgen", mw->getPresetsStore().clipboard.type.c_str());
+-            // a regex would be better here...
+-            // hopefully, mxml will not change its whitespace behavior
+-            assert_non_null(strstr(mw->getPresetsStore().clipboard.data.c_str(), "<par name=\"base_function_par\" value=\"32\" />"),
+-                    "base_function_par at right value", __LINE__);
+-
+-            /* // better test this without string comparison:
++	    //Use XMLwrapper to validate copied XML
+             {
+                 XMLwrapper xml;
+                 bool couldPutXml = xml.putXMLdata(mw->getPresetsStore().clipboard.data.c_str());
+                 TS_ASSERT(couldPutXml);
++		xml.enterbranch("Poscilgen");
+                 unsigned char copiedBasefuncPar = xml.getpar127("base_function_par", 0);
+-                TS_ASSERT_EQUALS(copiedBasefuncPar, 32);
+-            }*/
+-
+-            //printf("clipboard type: %s\n",mw->getPresetsStore().clipboard.type.c_str());
+-            //printf("clipboard data:\n%s\n",mw->getPresetsStore().clipboard.data.c_str());
++		xml.exitbranch();
++                TS_ASSERT_EQUAL_INT(+copiedBasefuncPar, 32);
++            }
+ 
+             TS_ASSERT_EQUAL_INT(osc_dst.Pbasefuncpar, 64);
+             TS_ASSERT_EQUAL_INT(osc_oth.Pbasefuncpar, 64);
+diff --git a/src/Tests/PluginTest.cpp b/src/Tests/PluginTest.cpp
+index 665a7311..dd0c4214 100644
+--- a/src/Tests/PluginTest.cpp
++++ b/src/Tests/PluginTest.cpp
+@@ -15,6 +15,7 @@
+ #include <cstdlib>
+ #include <iostream>
+ #include <fstream>
++#include <regex>
+ #include <string>
+ #include "../Misc/MiddleWare.h"
+ #include "../Misc/Master.h"
+@@ -228,12 +229,30 @@ class PluginTest
+ 
+         void testLoadSave(void)
+         {
++            // Do the load/save
+             const string fname = string(SOURCE_DIR) + "/guitar-adnote.xmz";
+-            const string fdata = loadfile(fname);
++            string fdata = loadfile(fname);
+             char *result = NULL;
+             master[0]->putalldata((char*)fdata.c_str());
+             int res = master[0]->getalldata(&result);
+ 
++            // Fixup, because d44dc9b corrupted guitar-adnote.xmz:
++            // Replace "1.0f" with "1.0" and "UTF-8" with "utf-8" in `<?xml...`
++            fdata = std::regex_replace(fdata,
++                                       std::regex(R"(<\?xml version="1\.0f" encoding="UTF-8"\?>)"),
++                                       R"(<?xml version="1.0" encoding="utf-8"?>)");
++
++            // Fixups, because guitar-adnote.xmz was saved with MXML3
++#if MXML_MAJOR_VERSION >= 4
++            // guitar-adnote has tags ending on " />" - we remove the space
++            fdata = std::regex_replace(fdata, std::regex(" />"), "/>");
++            // Remove trailing newline
++            if (fdata.size() >= 1 && fdata[fdata.size() - 1] == '\n') {
++                fdata.pop_back();
++            }
++#endif
++
++            // Checks
+             TS_ASSERT_EQUAL_INT((int)(fdata.length()+1), res);
+             TS_ASSERT(fdata == result);
+             if(fdata != result)
+-- 
+2.47.3
+
diff -Nru zynaddsubfx-3.0.6/debian/patches/fix_ftbfs_on_riscv64.patch zynaddsubfx-3.0.6/debian/patches/fix_ftbfs_on_riscv64.patch
--- zynaddsubfx-3.0.6/debian/patches/fix_ftbfs_on_riscv64.patch	2022-10-31 16:06:53.000000000 +0200
+++ zynaddsubfx-3.0.6/debian/patches/fix_ftbfs_on_riscv64.patch	1970-01-01 02:00:00.000000000 +0200
@@ -1,17 +0,0 @@
-Author: Eric Long <[email protected]>
-Description: Fix FTBFS on riscv64
-Forwarded: not-yet
-
---- a/src/CMakeLists.txt
-+++ b/src/CMakeLists.txt
-@@ -583,6 +583,10 @@
-     ${PTHREAD_LIBRARY}
-     rtosc rtosc-cpp)
- 
-+if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "riscv64")
-+    target_link_libraries(zynaddsubfx_core atomic)
-+endif()
-+
- if(IwyuErr)
-     message (STATUS "Include what you use: ${IwyuErr}")
- else()
diff -Nru zynaddsubfx-3.0.6/debian/patches/series zynaddsubfx-3.0.6/debian/patches/series
--- zynaddsubfx-3.0.6/debian/patches/series	2025-10-26 18:52:52.000000000 +0200
+++ zynaddsubfx-3.0.6/debian/patches/series	2026-03-31 12:24:21.000000000 +0300
@@ -1,6 +1,6 @@
 0001-added-German-translation-to-desktop-files.patch
 bash-completion-path.patch
 disable-tests.patch
-fix_ftbfs_on_riscv64.patch
 fix-gcc-13.patch
 cmake-4.patch
+0001-Support-MXML4-if-available.patch
diff -Nru zynaddsubfx-3.0.6/debian/rules zynaddsubfx-3.0.6/debian/rules
--- zynaddsubfx-3.0.6/debian/rules	2025-05-04 00:25:21.000000000 +0300
+++ zynaddsubfx-3.0.6/debian/rules	2026-03-31 12:24:21.000000000 +0300
@@ -2,7 +2,7 @@
 
 export DEB_BUILD_MAINT_OPTIONS = hardening=+all
 
-noatomicarch = $(shell dpkg-architecture -qDEB_HOST_ARCH | egrep -x "(armel|powerpc|m68k|sh4|riscv64)")
+noatomicarch = $(shell dpkg-architecture -qDEB_HOST_ARCH | egrep -x "(armel|powerpc|m68k|sh4)")
 # link with libatomic on architectures without built-in atomic
 ifeq ($(if $(noatomicarch),atomic), atomic)
 	LIBS += -latomic

Reply via email to