LV2/midnam tweaks - fix race conditions
[ardour.git] / libs / ardour / lv2_plugin.cc
index e556886c34d1f57b51661b9cd3debdedac771b26..b51db6548526efd1184ae173a602342d731c6c92 100644 (file)
 #include "pbd/replace_all.h"
 #include "pbd/xml++.h"
 
+#ifdef PLATFORM_WINDOWS
+#include <shlobj.h> // CSIDL_*
+#include "pbd/windows_special_dirs.h"
+#endif
+
 #include "libardour-config.h"
 
 #include "ardour/audio_buffer.h"
@@ -225,19 +230,36 @@ work_respond(LV2_Worker_Respond_Handle handle,
 
 #ifdef LV2_EXTENDED
 /* inline display extension */
-static void
-queue_draw (LV2_Inline_Display_Handle handle)
+void
+LV2Plugin::queue_draw (LV2_Inline_Display_Handle handle)
 {
        LV2Plugin* plugin = (LV2Plugin*)handle;
        plugin->QueueDraw(); /* EMIT SIGNAL */
 }
 
-static void
-midnam_update (LV2_Midnam_Handle handle)
+void
+LV2Plugin::midnam_update (LV2_Midnam_Handle handle)
 {
        LV2Plugin* plugin = (LV2Plugin*)handle;
+       plugin->_midnam_dirty = true;
        plugin->UpdateMidnam (); /* EMIT SIGNAL */
 }
+
+void
+LV2Plugin::bankpatch_notify (LV2_BankPatch_Handle handle, uint8_t chn, uint32_t bank, uint8_t pgm)
+{
+       LV2Plugin* plugin = (LV2Plugin*)handle;
+       if (chn > 15) {
+               return;
+       }
+       plugin->seen_bankpatch = true;
+       if (pgm > 127 || bank > 16383) {
+               plugin->_bankpatch[chn] = UINT32_MAX;
+       } else {
+               plugin->_bankpatch[chn] = (bank << 7) | pgm;
+       }
+       plugin->BankPatchChange (chn); /* EMIT SIGNAL */
+}
 #endif
 
 /* log extension */
@@ -324,6 +346,7 @@ struct LV2Plugin::Impl {
 #ifdef LV2_EXTENDED
        LV2_Inline_Display*          queue_draw;
        LV2_Midnam*                  midnam;
+       LV2_BankPatch*               bankpatch;
 #endif
 };
 
@@ -417,7 +440,7 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate)
        lilv_node_free(state_uri);
        lilv_node_free(state_iface_uri);
 
-       _features    = (LV2_Feature**)calloc(13, sizeof(LV2_Feature*));
+       _features    = (LV2_Feature**)calloc(14, sizeof(LV2_Feature*));
        _features[0] = &_instance_access_feature;
        _features[1] = &_data_access_feature;
        _features[2] = &_make_path_feature;
@@ -452,6 +475,15 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate)
        _midnam_feature.URI  = LV2_MIDNAM__update;
        _midnam_feature.data = _impl->midnam;
        _features[n_features++]  = &_midnam_feature;
+
+       _impl->bankpatch = (LV2_BankPatch*)
+               malloc (sizeof(LV2_BankPatch));
+       _impl->bankpatch->handle = this;
+       _impl->bankpatch->notify = bankpatch_notify;
+
+       _bankpatch_feature.URI  = LV2_BANKPATCH__notify;
+       _bankpatch_feature.data = _impl->bankpatch;
+       _features[n_features++]  = &_bankpatch_feature;
 #endif
 
 #ifdef HAVE_LV2_1_2_0
@@ -485,6 +517,13 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate)
        _features[n_features++] = &_options_feature;
 #endif
 
+#ifdef LV2_EXTENDED
+       seen_bankpatch = false;
+       for (uint32_t chn = 0; chn < 16; ++chn) {
+               _bankpatch[chn] = UINT32_MAX;
+       }
+#endif
+
        LV2_State_Make_Path* make_path = (LV2_State_Make_Path*)malloc(
                sizeof(LV2_State_Make_Path));
        make_path->handle = this;
@@ -552,6 +591,7 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate)
        _midname_interface = (const LV2_Midnam_Interface*)
                extension_data (LV2_MIDNAM__interface);
        if (_midname_interface) {
+               _midnam_dirty = true;
                read_midnam ();
        }
 #endif
@@ -895,6 +935,7 @@ LV2Plugin::~LV2Plugin ()
 #ifdef LV2_EXTENDED
        free(_impl->queue_draw);
        free(_impl->midnam);
+       free(_impl->bankpatch);
 #endif
 
        free(_features);
@@ -990,7 +1031,7 @@ LV2Plugin::has_midnam () {
 bool
 LV2Plugin::read_midnam () {
        bool rv = false;
-       if (!_midname_interface) {
+       if (!_midname_interface || !_midnam_dirty) {
                return rv;
        }
        char* midnam = _midname_interface->midnam ((void*)_impl->instance->lv2_handle);
@@ -1008,6 +1049,10 @@ LV2Plugin::read_midnam () {
        }
 #endif
        _midname_interface->free (midnam);
+       if (rv) {
+               UpdatedMidnam ();
+               _midnam_dirty = false;
+       }
        return rv;
 }
 
@@ -1511,8 +1556,7 @@ LV2Plugin::do_save_preset(string name)
                return "";
        }
        const string bundle = Glib::build_filename (
-                       appdata, "LV2",
-                       Glib::build_filename(prefix + "_" + base_name + ".lv2"));
+                       appdata, "LV2", prefix + "_" + base_name + ".lv2");
 #else
        /* while macOS/OSX user-specific path is
         *