no longer need ffmpeg patch0 which was for Termux
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / pluginlv2.C
index d1c5a8c4022e7362ba613d70d94fed5b5e3a425d..8b52aa61f98a5f42bb0b1bf943387aae3ee2483e 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * CINELERRA
+ * Copyright (C) 2016-2020 William Morrow
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
 #ifdef HAVE_LV2
 
 #include "bctrace.h"
@@ -22,6 +42,7 @@ PluginLV2::PluginLV2()
 
        samplerate = 44100;
        refreshrate = 30.;
+       min_block_length = 1;
        block_length = 4096;
        midi_buf_size = 8192;
 
@@ -51,6 +72,8 @@ PluginLV2::PluginLV2()
        schedule.schedule_work = lv2_worker_schedule;
        worker_iface = 0;  worker_done = -1;
        pthread_mutex_init(&worker_lock, 0);
+       pthread_mutex_init(&startup_lock, 0);
+       pthread_mutex_lock(&startup_lock);
        pthread_cond_init(&worker_ready, 0);
        work_avail = 0;   work_input = 0;
        work_output = 0;  work_tail = &work_output;
@@ -167,6 +190,12 @@ int PluginLV2::init_lv2(PluginLV2ClientConfig &conf, int sample_rate, int bfrsz)
                }
        }
 
+       if( !nb_inputs || !nb_outputs ) {
+               printf(": Unsupported lv2 plugin, missing audio input or output\n");
+               reset_lv2();
+               return 1;
+       }
+
        uri_map.handle = (LV2_URID_Map_Handle)this;
        uri_map.map = map_uri;
        features.append(new Lv2Feature(LV2_URID__map, &uri_map));
@@ -189,9 +218,10 @@ int PluginLV2::init_lv2(PluginLV2ClientConfig &conf, int sample_rate, int bfrsz)
        ui_updateRate = uri_table.map(LV2_UI__updateRate);
 
        samplerate = sample_rate;
-       block_length = bfrsz;
        options.add(param_sampleRate, sizeof(float), atom_float, &samplerate);
-       options.add(bufsz_minBlockLength, sizeof(int), atom_int, &block_length);
+       if( min_block_length > bfrsz ) min_block_length = bfrsz;
+       options.add(bufsz_minBlockLength, sizeof(int), atom_int, &min_block_length);
+       block_length = bfrsz;
        options.add(bufsz_maxBlockLength, sizeof(int), atom_int, &block_length);
        options.add(bufsz_sequenceSize, sizeof(int), atom_int, &midi_buf_size);
        options.add(ui_updateRate, sizeof(float),  atom_float, &refreshrate);
@@ -205,7 +235,15 @@ int PluginLV2::init_lv2(PluginLV2ClientConfig &conf, int sample_rate, int bfrsz)
                printf("lv2: lilv_plugin_instantiate failed\n");
                return 1;
        }
-
+       
+// After instantiate, some plugins require fields to be filled in before
+// activate is called. This is done via ConnectPort, which connects a
+// port to a data structure in the host (CinGG). So these have to be
+// allocated first.
+
+       init_buffer(bfrsz);
+       connect_ports(conf, PORTS_ALL);
+       
        const LV2_Descriptor *lilv_desc = inst->lv2_descriptor;
        worker_iface = !lilv_desc->extension_data ? 0 :
                (LV2_Worker_Interface*)lilv_desc->extension_data(LV2_WORKER__interface);
@@ -218,6 +256,7 @@ int PluginLV2::init_lv2(PluginLV2ClientConfig &conf, int sample_rate, int bfrsz)
                (lilv_plugin_has_feature(lilv, powerOf2BlockLength) ||
                 lilv_plugin_has_feature(lilv, fixedBlockLength) ||
                 lilv_plugin_has_feature(lilv, boundedBlockLength)) ? 4096 : 0;
+
        return 0;
 }
 
@@ -414,6 +453,7 @@ PluginLV2Work *PluginLV2::get_work()
 void *PluginLV2::worker_func()
 {
        pthread_mutex_lock(&worker_lock);
+       pthread_mutex_unlock(&startup_lock);
        for(;;) {
                while( !worker_done && !work_input )
                        pthread_cond_wait(&worker_ready, &worker_lock);
@@ -437,6 +477,7 @@ void *PluginLV2::worker_func(void* vp)
 void PluginLV2::worker_start()
 {
        pthread_create(&worker_thread, 0, worker_func, this);
+       pthread_mutex_lock(&startup_lock);
 }
 
 void PluginLV2::worker_stop()