add lv2ui support
authorGood Guy <good1.2guy@gmail.com>
Sat, 19 May 2018 14:39:06 +0000 (08:39 -0600)
committerGood Guy <good1.2guy@gmail.com>
Sat, 19 May 2018 14:39:06 +0000 (08:39 -0600)
28 files changed:
cinelerra-5.1/Makefile.am
cinelerra-5.1/bld.sh
cinelerra-5.1/bld_scripts/bld_prepare.sh
cinelerra-5.1/cinelerra/Makefile
cinelerra-5.1/cinelerra/forkbase.C [new file with mode: 0644]
cinelerra-5.1/cinelerra/forkbase.h [new file with mode: 0644]
cinelerra-5.1/cinelerra/forkbase.inc [new file with mode: 0644]
cinelerra-5.1/cinelerra/lv2ui.C [new file with mode: 0644]
cinelerra-5.1/cinelerra/mwindow.C
cinelerra-5.1/cinelerra/mwindow.h
cinelerra-5.1/cinelerra/pluginlv2client.C
cinelerra-5.1/cinelerra/pluginlv2client.h
cinelerra-5.1/cinelerra/pluginlv2client.inc
cinelerra-5.1/cinelerra/pluginlv2config.C [new file with mode: 0644]
cinelerra-5.1/cinelerra/pluginlv2config.h [new file with mode: 0644]
cinelerra-5.1/cinelerra/pluginlv2config.inc [new file with mode: 0644]
cinelerra-5.1/cinelerra/pluginlv2gui.C [new file with mode: 0644]
cinelerra-5.1/cinelerra/pluginlv2gui.h [new file with mode: 0644]
cinelerra-5.1/cinelerra/pluginlv2gui.inc [new file with mode: 0644]
cinelerra-5.1/configure.ac
cinelerra-5.1/guicast/bcsignals.C
cinelerra-5.1/thirdparty/Makefile
cinelerra-5.1/thirdparty/src/lilv-0.24.2.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/lv2-1.14.0.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/serd-0.28.0.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/sord-0.16.0.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/sratom-0.6.0.tar.xz [new file with mode: 0644]
cinelerra-5.1/thirdparty/src/suil-0.8.4.tar.xz [new file with mode: 0644]

index cd408349a9e03dd5e4c7c244e21cb5700ae0ee24..5200484f4fb1afb2f1be8c63740fbe6a3981fa40 100644 (file)
@@ -52,7 +52,7 @@ cinstall:
        cd bin; $(inst_sh) "$(DESTDIR)$(bindir)" "$(WANT_CIN)" \
                cin_db zmpeg3{cat,cc2txt,ifochk,show,toc}
        cd bin; $(inst_sh) "$(DESTDIR)$(WANT_CINLIB_DIR)" \
-               bdwrite cutads hveg2enc mpeg2enc mplex mplexlo
+               bdwrite cutads lv2ui hveg2enc mpeg2enc mplex mplexlo
        cd bin; $(inst_sh) "$(DESTDIR)$(datadir)/$(WANT_CIN)" \
                COPYING README models Cinelerra_factory ffmpeg msg info tips doc
        cd bin/locale; $(inst_sh) "$(DESTDIR)$(localedir)" .
index a9b6e46c5d5bc7ae36510d3de26621b43f3de2fa..b8a80d6bbaaa2d1b31b41ca84f46b7375a986367 100755 (executable)
@@ -1,7 +1,6 @@
 #!/bin/bash
-./autogen.sh
-./configure --with-single-user
-make 2>&1 | tee log
-make install
+( ./autogen.sh
+  ./configure --with-single-user
+  make && make install ) 2>&1 | tee log
 mv Makefile Makefile.cfg
 cp Makefile.devel Makefile
index 929095bc042165eed3a7f31cdef274424a4fe8f0..706749a1821543ff1af0d844cbdffe4c21f2729d 100755 (executable)
@@ -1,6 +1,5 @@
 #!/bin/bash
-# add lilv-devel for lv2 support
-#  also need lv2 plugins (eg. lv2-calf-plugin)
+#  need lv2 plugins (eg. lv2-calf-plugin)
 
 if [ `id -u` -ne 0 ]; then
   echo "you must be root"
@@ -27,7 +26,8 @@ case "$dir" in
     libavc1394 festival-devel libiec61883-devel flac-devel inkscape \
     libsndfile-devel libtheora-devel linux-firmware ivtv-firmware \
     libvorbis-devel texinfo xz-devel lzma-devel cmake udftools git \
-    autoconf automake rpm-build jbigkit-devel libvdpau-devel alsa-lib-devel
+    autoconf automake rpm-build jbigkit-devel libvdpau-devel alsa-lib-devel \
+    gtk2-devel
     yasm=yasm-1.3.0-3.fc24.x86_64.rpm
     release=http://archives.fedoraproject.org/pub/fedora/linux/releases/24
     url=$release/Everything/x86_64/os/Packages/y/$yasm
@@ -51,7 +51,7 @@ case "$dir" in
     ivtv-firmware libvorbis-devel texinfo xz-devel lzma-devel cmake git \
     ctags patch gcc-c++ perl-XML-XPath libtiff-devel python dvdauthor \
     gettext-devel inkscape udftools autoconf automake numactl-devel \
-    jbigkit-devel libvdpau-devel
+    jbigkit-devel libvdpau-devel gtk2-devel
   ;;
 "suse" | "leap")
   zypper -n install nasm gcc gcc-c++ zlib-devel texinfo libpng16-devel \
@@ -62,7 +62,7 @@ case "$dir" in
     libdvdnav-devel libdvdread-devel libiec61883-devel libuuid-devel \
     ilmbase-devel fftw3-devel libsndfile-devel libtheora-devel flac-devel \
     libtiff-devel inkscape cmake patch libnuma-devel lzma-devel udftools git \
-    yasm autoconf automake rpm-build libjbig-devel libvdpau-devel
+    yasm autoconf automake rpm-build libjbig-devel libvdpau-devel gtk2-devel
     if [ ! -f /usr/lib64/libtermcap.so ]; then
       ln -s libtermcap.so.2 /usr/lib64/libtermcap.so
     fi
@@ -76,7 +76,7 @@ case "$dir" in
     fonts-dejavu libopenexr-dev festival libfftw3-dev gdb \
     libdc1394-22-dev libesd0-dev libflac-dev libjbig-dev libvdpau-dev \
     inkscape libsndfile1-dev libtheora-dev cmake udftools libxml2-utils git \
-    autoconf automake debhelper
+    autoconf automake debhelper libgtk2.0-dev
   ;;
 #"ub16-10")
 #  apt-get -y install libx264-dev libx265-dev libvpx-dev libmjpegtools-dev
@@ -88,7 +88,7 @@ case "$dir" in
     fonts-dejavu libopenexr-dev libavc1394-dev festival-dev fftw3-dev gdb \
     libdc1394-22-dev libiec61883-dev libesd0-dev libflac-dev libjbig-dev \
     libvdpau-dev libsndfile1-dev libtheora-dev cmake udftools libxml2-utils \
-    git inkscape autoconf automake debhelper
+    git inkscape autoconf automake debhelper libgtk-2.0-dev
   ;;
  *)
   echo "unknown os: $dir"
index ee779981f7f909bf950c6a4a67f3fd7e80224e05..4af6b1a17eca753403ac3905b676472ce9f67f9d 100644 (file)
@@ -129,6 +129,7 @@ OBJS = \
        $(OBJDIR)/floatauto.o \
        $(OBJDIR)/floatautos.o \
        $(OBJDIR)/folderlistmenu.o \
+       $(OBJDIR)/forkbase.o \
        $(OBJDIR)/formatcheck.o \
        $(OBJDIR)/formatpopup.o \
        $(OBJDIR)/formatpresets.o \
@@ -223,7 +224,9 @@ OBJS = \
        $(OBJDIR)/pluginclient.o \
        $(OBJDIR)/plugindialog.o \
        $(OBJDIR)/pluginfclient.o \
+       $(OBJDIR)/pluginlv2config.o \
        $(OBJDIR)/pluginlv2client.o \
+       $(OBJDIR)/pluginlv2gui.o \
        $(OBJDIR)/plugin.o \
        $(OBJDIR)/pluginpopup.o \
        $(OBJDIR)/pluginserver.o \
@@ -356,7 +359,6 @@ LIBRARIES := \
        $(LIBZMPEG3)/$(OBJDIR)/libzmpeg3.a \
        $(MPEG2ENC)/$(OBJDIR)/hveg2enc.a \
        $(TDB)/$(OBJDIR)/db.a \
-       $(THEME_DATA) \
 
 LIBS := $(LIBRARIES)
 LIBS += $(libraries)
@@ -373,6 +375,15 @@ CUTLIBS = \
 BDWRITE = $(OBJDIR)/bdwrite
 BDWOBJS = $(OBJDIR)/bdwrite.o
 
+ifneq ($(WANT_LV2UI),no)
+LV2UI = $(OBJDIR)/lv2ui
+LV2OBJS = \
+       $(OBJDIR)/lv2ui.o \
+       $(OBJDIR)/pluginlv2gui.o \
+       $(OBJDIR)/pluginlv2config.o \
+       $(OBJDIR)/forkbase.o
+endif
+
 CFLAGS := \
        -I$(GUICAST) \
        -I$(LIBZMPEG3) \
@@ -411,14 +422,14 @@ endif
 
 $(shell mkdir -p $(OBJDIR))
 $(shell echo $(CFLAGS) > $(OBJDIR)/c_flags)
-$(shell echo $(LDFLAGS1) $(OBJS) $(DCRAW) $(LIBS) $(LDFLAGS2) > $(OBJDIR)/objs)
+$(shell echo $(LDFLAGS1) $(OBJS) $(THEME_DATA) $(DCRAW) $(LIBS) $(LDFLAGS2) > $(OBJDIR)/objs)
 
-all:   $(OUTPUT) $(CUTADS) $(BDWRITE)
+all:   $(OUTPUT) $(CUTADS) $(BDWRITE) $(LV2UI)
 
 # Static linking is not possible because the plugins depend on symbols
 # in the main executable.
 # Also VFS only overrides the C library when dynamic linking is used.
-$(OUTPUT): $(OBJS) $(DCRAW) $(FILEEXR) $(FILEFLAC) $(LIBRARIES)
+$(OUTPUT): $(OBJS) $(THEME_DATA) $(DCRAW) $(LIBRARIES)
        $(LINKER) `cat $(OBJDIR)/objs`
        $(if $(findstring -g,$(CFLAGS)),objcopy --only-keep-debug $(OUTPUT) $(OUTPUT_G))
        $(if $(findstring -ggdb,$(CFLAGS)),,strip $(OUTPUT))
@@ -430,12 +441,20 @@ $(CUTADS):        $(CUTOBJS) $(CUTLIBS) $(LIBRARIES)
        $(if $(findstring -g,$(CFLAGS)),objcopy --only-keep-debug $(CUTADS) $(CUTADS).debuginfo)
        $(if $(findstring -ggdb,$(CFLAGS)),,strip $(CUTADS))
 
+install-cutads:
+       cp -av $(OBJDIR)/cutads $(BINDIR)/.
+install:       install-cutads
+
 $(BDWRITE):    $(BDWOBJS) $(LIBRARIES)
        @echo g++ -o $@ $(BDWOBJS)
        @g++ $(CFLAGS) -pthread -o $@ $(BDWOBJS) $(LIBS)
        $(if $(findstring -g,$(CFLAGS)),objcopy --only-keep-debug $(BDWRITE) $(BDWRITE).debuginfo)
        $(if $(findstring -ggdb,$(CFLAGS)),,strip $(BDWRITE))
 
+install-bdwrite:
+       cp -av $(OBJDIR)/bdwrite $(BINDIR)/.
+install:       install-bdwrite
+
 ydiff: ydiff.C $(LIBRARIES)
        @echo g++ -o $@ ydiff.C
        @g++ $(CFLAGS) ydiff.C -o $@ $(LIBS)
@@ -443,9 +462,6 @@ ydiff:      ydiff.C $(LIBRARIES)
 clean:
        rm -rf $(OBJDIR)
 
-install:
-       cp -a $(OBJDIR)/cutads $(BINDIR)/.
-       cp -a $(OBJDIR)/bdwrite $(BINDIR)/.
 
 tags:
        ctags -R -h default --langmap=c:+.inc . ../guicast/ ../libzmpeg3 ../plugins ../thirdparty/ffmpeg-*
@@ -454,13 +470,39 @@ tags:
 $(OBJDIR)/%.o:         %.C
        $(CXX) `cat $(OBJDIR)/c_flags` -DMSGQUAL=$* -c $< -o $@
 
+
 $(OBJDIR)/fileexr.o:   fileexr.C
        $(CXX) `cat $(OBJDIR)/c_flags` -Wno-deprecated -DMSGQUAL=$* -c $< -o $@
 
 $(OBJDIR)/sha1.o:      sha1.C sha1.h
        $(CXX) `cat $(OBJDIR)/c_flags` -O3 -c $< -o $@
 
+#lv2
+ifneq ($(WANT_LV2UI),no)
+GTK2_INCS := `pkg-config --cflags gtk+-2.0`
+GTK2_LIBS := `pkg-config --libs gtk+-2.0`
+
+$(OBJDIR)/lv2ui.o:     lv2ui.C
+       $(CXX) `cat $(OBJDIR)/c_flags` $(GTK2_INCS) -DMSGQUAL=$* -c $< -o $@
+
+$(OBJDIR)/lv2ui: $(LV2OBJS)
+       @echo $(CXX) \`cat $(OBJDIR)/c_flags\` $^ -o $@
+       @$(CXX) `cat $(OBJDIR)/c_flags` $^ -o $@ $(LIBS) $(GTK2_LIBS)
+       $(if $(findstring -g,$(CFLAGS)),objcopy --only-keep-debug $(LV2UI) $(LV2UI).debuginfo)
+       $(if $(findstring -ggdb,$(CFLAGS)),,strip $(LV2UI))
+
+.PHONY:        lv2ui
+lv2ui: $(LV2UI)
+
+install-lv2ui:
+       cp -av $(LV2UI) $(BINDIR)/.
+install:       install-lv2ui
+endif
+
+$(OBJDIR)/pluginlv2gui.o:      pluginlv2gui.C
+       $(CXX) `cat $(OBJDIR)/c_flags` $(GTK2_INCS) -DMSGQUAL=$* -c $< -o $@
 
+#dcraw
 $(DCRAW): dcraw.C
        $(CXX) `cat $(OBJDIR)/c_flags` $(if $(findstring -ggdb,$(CFLAGS)),,-O4) -DNODEPS -DLOCALTIME \
                -Wno-misleading-indentation -Wno-sign-compare -Wno-narrowing dcraw.C -c -o $*.o
diff --git a/cinelerra-5.1/cinelerra/forkbase.C b/cinelerra-5.1/cinelerra/forkbase.C
new file mode 100644 (file)
index 0000000..8e87cb3
--- /dev/null
@@ -0,0 +1,239 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2009 Adam Williams <broadcast at earthling dot net>
+ * 
+ * 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
+ * 
+ */
+
+#include "bcsignals.h"
+#include "forkbase.h"
+#include "mwindow.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+ForkBase::ForkBase()
+{
+       pid = 0;
+       child = 0;
+
+       child_fd = -1;
+       child_token = 0;
+       child_bytes = 0;
+       child_allocated = 0;
+       child_data = 0;
+
+       parent_fd = -1;
+       parent_token = 0;
+       parent_bytes = 0;
+       parent_allocated = 0;
+       parent_data = 0;
+
+}
+
+ForkBase::~ForkBase()
+{
+       delete [] child_data;
+       delete [] parent_data;
+       if( child_fd >= 0 ) close(child_fd);
+       if( parent_fd >= 0 ) close(parent_fd);
+}
+
+int ForkChild::child_iteration()
+{
+       int ret = read_child(100);
+       if( ret <= 0 ) return ret;
+       return handle_child();
+}
+
+void ForkParent::start_child()
+{
+       lock->lock("ForkParent::new_child");
+       int sockets[2]; // Create the process & socket pair.
+       socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
+       child_fd = sockets[0];  parent_fd = sockets[1];
+       pid = fork();
+       if( !pid ) {    // child process
+               BC_Signals::reset_locks();
+               BC_Signals::set_sighup_exit(1);
+               TheList::reset();
+               ForkChild *child = new_fork();
+               child->child_fd = child_fd;
+               child->parent_fd = parent_fd;
+               child->run();
+               _exit(0);
+       }
+       lock->unlock();
+}
+
+// Return -1 if the parent is dead
+// Return  0 if timeout
+// Return  1 if success
+int ForkBase::read_timeout(int ms, int fd, void *data, int bytes)
+{
+       fd_set rfds;
+       struct timeval timeout_struct;
+       int bytes_read = 0;
+       uint8_t *bp = (uint8_t *)data;
+
+       while( bytes_read < bytes ) {
+               timeout_struct.tv_sec = ms / 1000;
+               timeout_struct.tv_usec = (ms % 1000) * 1000;
+               FD_ZERO(&rfds);
+               FD_SET(fd, &rfds);
+               int result = select(fd+1, &rfds, 0, 0, &timeout_struct);
+               if( result < 0 || !is_running() ) return -1;
+               if( !result && !bytes_read ) return 0;
+               int fragment = read(fd, bp + bytes_read, bytes - bytes_read);
+               if( fragment < 0 || !is_running() ) return -1;
+               if( fragment > 0 ) bytes_read += fragment;
+       }
+
+       return 1;
+}
+
+// return 1 if child, or if parent && child is running
+int ForkBase::is_running()
+{
+       int status = 0;
+       if( pid && waitpid(pid, &status, WNOHANG) < 0 ) return 0;
+       return !pid || !kill(pid, 0) ? 1 : 0;
+}
+
+int ForkBase::read_parent(int ms)
+{
+       token_bfr_t bfr;
+       int ret = read_timeout(ms, parent_fd, &bfr, sizeof(bfr));
+       if( ret > 0 ) {
+               parent_token = bfr.token;
+               parent_bytes = bfr.bytes;
+               if( parent_bytes && parent_allocated < parent_bytes ) {
+                       delete [] parent_data;
+                       parent_data = new uint8_t[parent_allocated = parent_bytes];
+               }
+               if( parent_bytes )
+                       ret = read_timeout(1000, parent_fd, parent_data, parent_bytes);
+       }
+//if( ret < 0 ) printf("read_parent timeout\n");
+       return ret;
+}
+
+int ForkBase::read_child(int ms)
+{
+       token_bfr_t bfr;
+       int ret = read_timeout(ms, child_fd, &bfr, sizeof(bfr));
+       if( ret > 0 ) {
+               child_token = bfr.token;
+               child_bytes = bfr.bytes;
+               if( child_bytes && child_allocated < child_bytes ) {
+                       delete [] child_data;
+                       child_data = new uint8_t[child_allocated = child_bytes];
+               }
+               if( child_bytes )
+                       ret = read_timeout(1000, child_fd, child_data, child_bytes);
+       }
+//if( ret < 0 ) printf("read_child timeout\n");
+       return ret;
+}
+
+int ForkBase::send_parent(int64_t token, const void *data, int bytes)
+{
+       token_bfr_t bfr;  memset(&bfr, 0, sizeof(bfr));
+       bfr.token = token;  bfr.bytes = bytes;
+       write(child_fd, &bfr, sizeof(bfr));
+       if( data && bytes ) write(child_fd, data, bytes);
+       return 0;
+}
+
+int ForkBase::send_child(int64_t token, const void *data, int bytes)
+{
+       token_bfr_t bfr;  memset(&bfr, 0, sizeof(bfr));
+       bfr.token = token;  bfr.bytes = bytes;
+       write(parent_fd, &bfr, sizeof(bfr));
+       if( data && bytes ) write(parent_fd, data, bytes);
+       return 0;
+}
+
+ForkChild::ForkChild()
+{
+       done = 0;
+}
+
+ForkChild::~ForkChild()
+{
+}
+
+int ForkChild::handle_child()
+{
+       printf("ForkChild::handle_child %d\n", __LINE__);
+       return 0;
+}
+
+ForkParent::ForkParent()
+ : Thread(1, 0, 0)
+{
+       lock = new Mutex("ForkParent::lock");
+       done = -1;
+}
+
+ForkParent::~ForkParent()
+{
+       delete lock;
+}
+
+// Return -1,0,1 if dead,timeout,success
+int ForkParent::parent_iteration()
+{
+       int ret = read_parent(100);
+       if( !ret ) return 0;
+       if( ret < 0 ) parent_token = EXIT_CODE;
+       return handle_parent();
+}
+
+int ForkParent::handle_parent()
+{
+       printf("ForkParent::handle_parent %d\n", __LINE__);
+       return 0;
+}
+
+void ForkParent::start()
+{
+       done = 0;
+       Thread::start();
+}
+
+void ForkParent::stop()
+{
+       if( is_running() ) {
+               send_child(EXIT_CODE, 0, 0);
+               int status = 0;
+               waitpid(pid, &status, 0);
+       }
+       join();
+}
+
+void ForkParent::run()
+{
+       while( !done && parent_iteration() >= 0 );
+       done = 1;
+}
+
diff --git a/cinelerra-5.1/cinelerra/forkbase.h b/cinelerra-5.1/cinelerra/forkbase.h
new file mode 100644 (file)
index 0000000..5502413
--- /dev/null
@@ -0,0 +1,92 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2009 Adam Williams <broadcast at earthling dot net>
+ * 
+ * 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
+ * 
+ */
+
+#ifndef __FORKBASE_H__
+#define __FORKBASE_H__
+
+#include "forkbase.inc"
+#include "mutex.h"
+#include "thread.h"
+
+// Utility functions for all the forking classes
+
+#include <stdint.h>
+
+class ForkBase
+{
+public:
+       enum { EXIT_CODE=0x7fff };
+       typedef struct { int64_t token; int bytes; } token_bfr_t;
+
+       ForkBase();
+       virtual ~ForkBase();
+
+       int is_running();
+       int read_timeout(int ms, int fd, void *data, int bytes);
+       int read_parent(int ms);
+       int send_parent(int64_t value, const void *data, int bytes);
+       int read_child(int ms);
+       int send_child(int64_t value, const void *data, int bytes);
+
+       int done, pid;
+       ForkChild *child;
+
+       int child_fd;
+       int64_t child_token;
+       int child_bytes;
+       int child_allocated;
+       uint8_t *child_data;
+
+       int parent_fd;
+       int64_t parent_token;
+       int parent_bytes;
+       int parent_allocated;
+       uint8_t *parent_data;
+};
+
+class ForkChild : public ForkBase
+{
+public:
+       ForkChild();
+       virtual ~ForkChild();
+       virtual void run() = 0;
+       virtual int handle_child();
+       int child_iteration();
+};
+
+class ForkParent : public Thread, public ForkBase
+{
+public:
+       ForkParent();
+       virtual ~ForkParent();
+       virtual int handle_parent();
+       virtual ForkChild *new_fork() = 0;
+
+       void start_child();
+       void start();
+       void stop();
+       void run();
+       int parent_iteration();
+
+       Mutex *lock;
+};
+
+#endif
diff --git a/cinelerra-5.1/cinelerra/forkbase.inc b/cinelerra-5.1/cinelerra/forkbase.inc
new file mode 100644 (file)
index 0000000..8f0266c
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __FORKBASE_INC__
+#define __FORKBASE_INC__
+
+class ForkBase;
+class ForkParent;
+class ForkChild;
+
+#endif
diff --git a/cinelerra-5.1/cinelerra/lv2ui.C b/cinelerra-5.1/cinelerra/lv2ui.C
new file mode 100644 (file)
index 0000000..21acda4
--- /dev/null
@@ -0,0 +1,143 @@
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "bcsignals.h"
+#include "pluginlv2client.h"
+#include "pluginlv2gui.h"
+
+static void lilv_destroy(GtkWidget* widget, gpointer data)
+{
+       PluginLV2GUI *the = (PluginLV2GUI*)data;
+       the->done = 1;
+}
+
+void PluginLV2GUI::start()
+{
+       GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       g_signal_connect(window, "destroy", G_CALLBACK(lilv_destroy), this);
+       gtk_window_set_title(GTK_WINDOW(window), title);
+
+       GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
+       gtk_window_set_role(GTK_WINDOW(window), "plugin_ui");
+       gtk_container_add(GTK_CONTAINER(window), vbox);
+
+       GtkWidget *alignment = gtk_alignment_new(0.5, 0.5, 1.0, 1.0);
+       gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0);
+       gtk_widget_show(alignment);
+       lv2ui_instantiate(alignment);
+       GtkWidget* widget = (GtkWidget*)suil_instance_get_widget(sinst);
+       gtk_container_add(GTK_CONTAINER(alignment), widget);
+       gtk_window_set_resizable(GTK_WINDOW(window), lv2ui_resizable());
+       gtk_widget_show_all(vbox);
+       gtk_widget_grab_focus(widget);
+
+       gtk_window_present(GTK_WINDOW(window));
+       running = -1;
+}
+
+void PluginLV2GUI::stop()
+{
+       running = 0;
+}
+
+void PluginLV2GUI::host_update(PluginLV2ChildGUI *child)
+{
+//printf("update\n");
+       last = updates;
+       if( !child ) return;
+// ignore reset update
+       if( child->lv2_gui->running < 0 ) { child->lv2_gui->running = 1;  return; }
+       child->send_parent(LV2_UPDATE, config.ctls, sizeof(float)*config.nb_ports);
+}
+
+void PluginLV2GUI::run_gui(PluginLV2ChildGUI *child)
+{
+       while( !done ) {
+               if( gtk_events_pending() ) {
+                       gtk_main_iteration();
+                       continue;
+               }
+               if( running && updates != last )
+                       host_update(child);
+               if( redraw ) {
+                       redraw = 0;
+                       update_lv2(config.ctls, 1);
+               }
+               if( !child ) usleep(10000);
+               else if( child->child_iteration() < 0 )
+                       done = 1;
+       }
+}
+
+int PluginLV2ChildGUI::handle_child()
+{
+       if( !lv2_gui ) return 0;
+
+       switch( child_token ) {
+       case LV2_OPEN: {
+               char *path = (char *)child_data;
+               if( lv2_gui->init_gui(path) ) exit(1);
+               break; }
+       case LV2_LOAD: {
+               lv2_gui->update_lv2((float*)child_data, 1);
+               break; }
+       case LV2_UPDATE: {
+               lv2_gui->update_lv2((float*)child_data, 0);
+               break; }
+       case LV2_START: {
+               lv2_gui->start();
+               break; }
+       case LV2_SET: {
+               if( !lv2_gui ) break;
+               control_t *bfr = (control_t *)child_data;
+               lv2_gui->config.ctls[bfr->idx] = bfr->value;
+               lv2_gui->redraw = 1;
+               break; }
+       case EXIT_CODE:
+               return -1;
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+int PluginLV2GUI::run(int ac, char **av)
+{
+       if( ac < 3 ) {
+               if( init_gui(av[1]) ) {
+                       fprintf(stderr," init_ui failed\n");
+                       return 1;
+               }
+               start();
+               run_gui();
+               stop();
+       }
+       else {
+               PluginLV2ChildGUI child;
+               child.lv2_gui = this;
+               child.child_fd = atoi(av[1]);
+               child.parent_fd = atoi(av[2]);
+               run_gui(&child);
+               stop();
+               child.lv2_gui = 0;
+       }
+       return 0;
+}
+
+int main(int ac, char **av)
+{
+       BC_Signals signals;
+       if( getenv("BC_TRAP_LV2_SEGV") ) {
+               signals.initialize("/tmp/lv2ui_%d.dmp");
+               BC_Signals::set_catch_segv(1);
+       }
+       gtk_set_locale();
+       gtk_init(&ac, &av);
+// to grab this task in the debugger
+//static int zbug = 1;  volatile int bug = zbug;
+//while( bug ) usleep(10000);
+       return PluginLV2GUI().run(ac, av);
+}
+
index 243f29a99afc00d58607321154c8275dfc7caac2..79ce0e3b53b4a7ddbbaa37a53caa35ee3be2a278 100644 (file)
@@ -210,7 +210,6 @@ MWindow::MWindow()
        strcpy(cin_lang,"en");
        channeldb_buz =  new ChannelDB;
        channeldb_v4l2jpeg =  new ChannelDB;
-       //file_server = 0;
        plugin_guis = 0;
        dead_plugins = 0;
        keyframe_threads = 0;
@@ -319,7 +318,6 @@ MWindow::~MWindow()
        delete gwindow;         gwindow = 0;
        delete cwindow;         cwindow = 0;
        delete gui;             gui = 0;
-       //delete file_server;  file_server = 0; // reusable
        delete mainindexes;     mainindexes = 0;
        delete mainprogress;    mainprogress = 0;
        delete audio_cache;     audio_cache = 0;  // delete the cache after the assets
@@ -2327,9 +2325,6 @@ void MWindow::create_objects(int want_gui,
        BC_Resources::init_fontconfig(string);
        if(debug) PRINT_TRACE
 
-// Initialize before too much else is running
-// Preferences & theme are required for building MPEG table of contents
-
 // Default project created here
        init_edl();
        if(debug) PRINT_TRACE
index 8c251e28b33af49078af7b31e018909efc40865b..66f8f39373898056052f1b8e40e21d475240e7ce 100644 (file)
@@ -633,10 +633,8 @@ public:
        Mutex *keyframe_gui_lock;
 // Lock during creation and destruction of brender so playback doesn't use it.
        Mutex *brender_lock;
-
 // Initialize shared memory
        void init_shm(const char *pfn, int64_t min);
-
 // Initialize channel DB's for playback
        void init_channeldb();
        void init_render();
index a508f46f5ba413592bdd41aba9439fc8dbe48b45..a2c0b51c524b8ce31f36d9fbc8a6b14443a5337c 100644 (file)
 #include "language.h"
 #include "mwindow.h"
 #include "pluginlv2client.h"
+#include "pluginlv2config.h"
 #include "pluginserver.h"
 #include "samples.h"
 
 #include <ctype.h>
 #include <string.h>
 
-#define LV2_SEQ_SIZE  9624
 
-PluginLV2UriTable::PluginLV2UriTable()
+PluginLV2ClientUI::
+PluginLV2ClientUI(PluginLV2ClientWindow *gui, int x, int y)
+ : BC_GenericButton(x, y, _("UI"))
 {
-       set_array_delete();
-}
-
-PluginLV2UriTable::~PluginLV2UriTable()
-{
-       remove_all_objects();
-}
-
-LV2_URID PluginLV2UriTable::map(const char *uri)
-{
-       for( int i=0; i<size(); ++i )
-               if( !strcmp(uri, get(i)) ) return i+1;
-       append(cstrdup(uri));
-       return size();
-}
-
-const char *PluginLV2UriTable::unmap(LV2_URID urid)
-{
-       int idx = urid - 1;
-       return idx>=0 && idx<size() ? get(idx) : 0;
-}
-
-PluginLV2Client_OptName:: PluginLV2Client_OptName(PluginLV2Client_Opt *opt)
-{
-       this->opt = opt;
-       set_text(opt->get_name());
-}
-
-PluginLV2Client_OptValue::PluginLV2Client_OptValue(PluginLV2Client_Opt *opt)
-{
-       this->opt = opt;
-       update();
-}
-
-int PluginLV2Client_OptValue::update()
-{
-       char val[BCSTRLEN];
-       sprintf(val, "%f", opt->get_value());
-       if( !strcmp(val, get_text()) ) return 0;
-       set_text(val);
-       return 1;
-}
-
-
-PluginLV2Client_Opt::PluginLV2Client_Opt(PluginLV2ClientConfig *conf, const char *sym, int idx)
-{
-       this->conf = conf;
-       this->idx = idx;
-       this->sym = cstrdup(sym);
-       item_name = new PluginLV2Client_OptName(this);
-       item_value = new PluginLV2Client_OptValue(this);
-}
-
-PluginLV2Client_Opt::~PluginLV2Client_Opt()
-{
-       delete [] sym;
-       delete item_name;
-       delete item_value;
-}
-
-float PluginLV2Client_Opt::get_value()
-{
-       return conf->ctls[idx];
-}
-
-void PluginLV2Client_Opt::set_value(float v)
-{
-       conf->ctls[idx] = v;
-}
-
-int PluginLV2Client_Opt::update(float v)
-{
-       set_value(v);
-       return item_value->update();
-}
-
-const char *PluginLV2Client_Opt::get_name()
-{
-       return conf->names[idx];
-}
-
-PluginLV2ClientConfig::PluginLV2ClientConfig()
-{
-       names = 0;
-       mins = 0;
-       maxs = 0;
-       ctls = 0;
-       nb_ports = 0;
-}
-
-PluginLV2ClientConfig::~PluginLV2ClientConfig()
-{
-       reset();
-       remove_all_objects();
+       this->gui = gui;
 }
 
-void PluginLV2ClientConfig::reset()
+PluginLV2ClientUI::
+~PluginLV2ClientUI()
 {
-       for( int i=0; i<nb_ports; ++i ) delete [] names[i];
-       delete [] names; names = 0;
-       delete [] mins;  mins = 0;
-       delete [] maxs;  maxs = 0;
-       delete [] ctls;  ctls = 0;
-       nb_ports = 0;
 }
 
-
-int PluginLV2ClientConfig::equivalent(PluginLV2ClientConfig &that)
+int PluginLV2ClientUI::handle_event()
 {
-       PluginLV2ClientConfig &conf = *this;
-       for( int i=0; i<that.size(); ++i ) {
-               PluginLV2Client_Opt *topt = conf[i], *vopt = that[i];
-               if( !EQUIV(topt->get_value(), vopt->get_value()) ) return 0;
-       }
+       if( !gui->plugin->open_lv2_gui(gui) )
+               flicker(8, 64);
        return 1;
 }
 
-void PluginLV2ClientConfig::copy_from(PluginLV2ClientConfig &that)
-{
-       if( nb_ports != that.nb_ports ) {
-               reset();
-               nb_ports = that.nb_ports;
-               names = new const char *[nb_ports];
-               for( int i=0; i<nb_ports; ++i ) names[i] = 0;
-               mins  = new float[nb_ports];
-               maxs  = new float[nb_ports];
-               ctls  = new float[nb_ports];
-       }
-       for( int i=0; i<nb_ports; ++i ) {
-               delete [] names[i];
-               names[i] = cstrdup(that.names[i]);
-               mins[i] = that.mins[i];
-               maxs[i] = that.maxs[i];
-               ctls[i] = that.ctls[i];
-       }
-       remove_all_objects();
-       for( int i=0; i<that.size(); ++i ) {
-               append(new PluginLV2Client_Opt(this, that[i]->sym, that[i]->idx));
-       }
-}
-
-void PluginLV2ClientConfig::interpolate(PluginLV2ClientConfig &prev, PluginLV2ClientConfig &next,
-       int64_t prev_frame, int64_t next_frame, int64_t current_frame)
-{
-       copy_from(prev);
-}
-
-void PluginLV2ClientConfig::init_lv2(const LilvPlugin *lilv)
-{
-       reset();
-       nb_ports = lilv_plugin_get_num_ports(lilv);
-       names = new const char *[nb_ports];
-       mins  = new float[nb_ports];
-       maxs  = new float[nb_ports];
-       ctls  = new float[nb_ports];
-       lilv_plugin_get_port_ranges_float(lilv, mins, maxs, ctls);
-       for( int i=0; i<nb_ports; ++i ) {
-               const LilvPort *lp = lilv_plugin_get_port_by_index(lilv, i);
-               LilvNode *pnm = lilv_port_get_name(lilv, lp);
-               names[i] = cstrdup(lilv_node_as_string(pnm));
-               lilv_node_free(pnm);
-       }
-}
-
-int PluginLV2ClientConfig::update()
-{
-       int ret = 0;
-       PluginLV2ClientConfig &conf = *this;
-       for( int i=0; i<size(); ++i ) {
-               if( conf[i]->item_value->update() ) ++ret;
-       }
-       return ret;
-}
-
 PluginLV2ClientReset::
 PluginLV2ClientReset(PluginLV2ClientWindow *gui, int x, int y)
  : BC_GenericButton(x, y, _("Reset"))
@@ -276,6 +119,7 @@ int PluginLV2ClientApply::handle_event()
 }
 
 
+
 PluginLV2Client_OptPanel::
 PluginLV2Client_OptPanel(PluginLV2ClientWindow *gui, int x, int y, int w, int h)
  : BC_ListBox(x, y, w, h, LISTBOX_TEXT), opts(items[0]), vals(items[1])
@@ -332,12 +176,18 @@ PluginLV2ClientWindow::~PluginLV2ClientWindow()
 void PluginLV2ClientWindow::create_objects()
 {
        BC_Title *title;
-       int x = 10, y = 10;
+       int x = 10, y = 10, x1;
        add_subwindow(title = new BC_Title(x, y, plugin->title));
+#ifdef HAVE_LV2UI
+       x1 = get_w() - BC_GenericButton::calculate_w(this, _("UI")) - 8;
+       add_subwindow(ui = new PluginLV2ClientUI(this, x1, y));
+#else
+       ui = 0;
+#endif
        y += title->get_h() + 10;
        add_subwindow(varbl = new BC_Title(x, y, ""));
        add_subwindow(range = new BC_Title(x+160, y, ""));
-       int x1 = get_w() - BC_GenericButton::calculate_w(this, _("Reset")) - 8;
+       x1 = get_w() - BC_GenericButton::calculate_w(this, _("Reset")) - 8;
        add_subwindow(reset = new PluginLV2ClientReset(this, x1, y));
        y += title->get_h() + 10;
        x1 = get_w() - BC_GenericButton::calculate_w(this, _("Apply")) - 8;
@@ -350,6 +200,8 @@ void PluginLV2ClientWindow::create_objects()
        y += pot->get_h() + 10;
 
        plugin->init_lv2();
+       plugin->load_configuration();
+       plugin->config.update();
 
        int panel_x = x, panel_y = y;
        int panel_w = get_w()-10 - panel_x;
@@ -362,7 +214,12 @@ void PluginLV2ClientWindow::create_objects()
 
 int PluginLV2ClientWindow::resize_event(int w, int h)
 {
-       int x1 = w - reset->get_w() - 8;
+       int x1;
+#ifdef HAVE_LV2UI
+       x1 = w - ui->get_w() - 8;
+       ui->reposition_window(x1, ui->get_y());
+#endif
+       x1 = w - reset->get_w() - 8;
        reset->reposition_window(x1, reset->get_y());
        x1 = w - apply->get_w() - 8;
        apply->reposition_window(x1, apply->get_y());
@@ -411,6 +268,12 @@ int PluginLV2ClientSlider::handle_event()
 void PluginLV2ClientWindow::update_selected()
 {
        update(selected);
+       if( selected && plugin->parent_gui ) {
+               control_t bfr;
+               bfr.idx = selected->idx;
+               bfr.value = selected->get_value();
+               plugin->parent_gui->send_child(LV2_SET, &bfr, sizeof(bfr));
+       }
 }
 
 int PluginLV2ClientWindow::scalar(float f, char *rp)
@@ -485,11 +348,11 @@ PluginLV2Client::PluginLV2Client(PluginServer *server)
        lv2_Optional = 0;
        atom_AtomPort = 0;
        atom_Sequence = 0;
-       urid_map = 0;
        powerOf2BlockLength = 0;
        fixedBlockLength = 0;
        boundedBlockLength = 0;
        seq_out = 0;
+       parent_gui = 0;
 }
 
 PluginLV2Client::~PluginLV2Client()
@@ -500,12 +363,12 @@ PluginLV2Client::~PluginLV2Client()
 
 void PluginLV2Client::reset_lv2()
 {
+       delete parent_gui;                    parent_gui = 0;
        if( instance ) lilv_instance_deactivate(instance);
        lilv_instance_free(instance);         instance = 0;
        lilv_node_free(powerOf2BlockLength);  powerOf2BlockLength = 0;
        lilv_node_free(fixedBlockLength);     fixedBlockLength = 0;
        lilv_node_free(boundedBlockLength);   boundedBlockLength = 0;
-       lilv_node_free(urid_map);             urid_map = 0;
        lilv_node_free(atom_Sequence);        atom_Sequence = 0;
        lilv_node_free(atom_AtomPort);        atom_AtomPort = 0;
        lilv_node_free(lv2_Optional);         lv2_Optional = 0;
@@ -568,7 +431,6 @@ int PluginLV2Client::init_lv2()
        lv2_Optional        = lilv_new_uri(world, LV2_CORE__connectionOptional);
        atom_AtomPort       = lilv_new_uri(world, LV2_ATOM__AtomPort);
        atom_Sequence       = lilv_new_uri(world, LV2_ATOM__Sequence);
-       urid_map            = lilv_new_uri(world, LV2_URID__map);
        powerOf2BlockLength = lilv_new_uri(world, LV2_BUF_SIZE__powerOf2BlockLength);
        fixedBlockLength    = lilv_new_uri(world, LV2_BUF_SIZE__fixedBlockLength);
        boundedBlockLength  = lilv_new_uri(world, LV2_BUF_SIZE__boundedBlockLength);
@@ -586,8 +448,7 @@ int PluginLV2Client::init_lv2()
                        continue;
                }
                if( is_input && lilv_port_is_a(lilv, lp, lv2_ControlPort) ) {
-                       const char *sym = lilv_node_as_string(lilv_port_get_symbol(lilv, lp));
-                       config.append(new PluginLV2Client_Opt(&config, sym, i));
+                       config.append(new PluginLV2Client_Opt(&config, i));
                        continue;
                }
                if( lilv_port_is_a(lilv, lp, lv2_AudioPort) ||
@@ -599,23 +460,14 @@ int PluginLV2Client::init_lv2()
 
        map.handle = (void*)&uri_table;
        map.map = uri_table_map;
-       map_feature.URI = LV2_URID_MAP_URI;
-       map_feature.data = &map;
+       features.append(new Lv2Feature(LV2_URID_MAP_URI, &map));
        unmap.handle = (void*)&uri_table;
        unmap.unmap  = uri_table_unmap;
-       unmap_feature.URI = LV2_URID_UNMAP_URI;
-       unmap_feature.data = &unmap;
-       features[0] = &map_feature;
-       features[1] = &unmap_feature;
-       static const LV2_Feature buf_size_features[3] = {
-               { LV2_BUF_SIZE__powerOf2BlockLength, NULL },
-               { LV2_BUF_SIZE__fixedBlockLength,    NULL },
-               { LV2_BUF_SIZE__boundedBlockLength,  NULL },
-       };
-       features[2] = &buf_size_features[0];
-       features[3] = &buf_size_features[1];
-       features[4] = &buf_size_features[2];
-       features[5] = 0;
+       features.append(new Lv2Feature(LV2_URID_UNMAP_URI, &unmap));
+       features.append(new Lv2Feature(LV2_BUF_SIZE__powerOf2BlockLength, 0));
+       features.append(new Lv2Feature(LV2_BUF_SIZE__fixedBlockLength,    0));
+       features.append(new Lv2Feature(LV2_BUF_SIZE__boundedBlockLength,  0));
+       features.append(0);
 
        instance = lilv_plugin_instantiate(lilv, sample_rate, features);
        if( !instance ) {
@@ -658,14 +510,49 @@ void PluginLV2Client::update_gui()
 {
        PluginClientThread *thread = get_thread();
        if( !thread ) return;
-       PluginLV2ClientWindow *window = (PluginLV2ClientWindow*)thread->get_window();
-       window->lock_window("PluginFClient::update_gui");
+       PluginLV2ClientWindow *gui = (PluginLV2ClientWindow*)thread->get_window();
+       gui->lock_window("PluginFClient::update_gui");
        load_configuration();
-       if( config.update() > 0 )
-               window->update_selected();
-       window->unlock_window();
+       if( config.update() > 0 ) {
+               gui->update_selected();
+               update_lv2();
+       }
+       gui->unlock_window();
 }
 
+void PluginLV2Client::update_lv2()
+{
+       if( !parent_gui ) return;
+       parent_gui->send_child(LV2_UPDATE, config.ctls, sizeof(float)*config.nb_ports);
+}
+
+void PluginLV2Client::lv2_update()
+{
+       PluginClientThread *thread = get_thread();
+       if( !thread ) return;
+       PluginLV2ClientWindow *gui = (PluginLV2ClientWindow*)thread->get_window();
+       gui->lock_window("PluginLV2ParentGUI::handle_parent");
+       int ret = config.update();
+       if( ret ) gui->update(0);
+       gui->unlock_window();
+       if( ret ) send_configure_change();
+}
+
+void PluginLV2Client::lv2_update(float *vals)
+{
+       int nb_ports = config.nb_ports;
+       float *ctls = config.ctls;
+       for( int i=0; i<nb_ports; ++i ) *ctls++ = *vals++;
+       lv2_update();
+}
+
+void PluginLV2Client::lv2_set(int idx, float val)
+{
+       config[idx]->set_value(val);
+       lv2_update();
+}
+
+
 int PluginLV2Client::is_realtime() { return 1; }
 int PluginLV2Client::is_multichannel() { return nb_inputs > 1 || nb_outputs > 1 ? 1 : 0; }
 const char* PluginLV2Client::plugin_title() { return title; }
@@ -689,7 +576,7 @@ void PluginLV2Client::save_data(KeyFrame *keyframe)
        output.tag.set_title(name);
        for( int i=0; i<config.size(); ++i ) {
                PluginLV2Client_Opt *opt = config[i];
-               output.tag.set_property(opt->sym, opt->get_value());
+               output.tag.set_property(opt->get_symbol(), opt->get_value());
        }
        output.append_tag();
        output.terminate_string();
@@ -705,7 +592,7 @@ void PluginLV2Client::read_data(KeyFrame *keyframe)
                if( !input.tag.title_is(name) ) continue;
                for( int i=0; i<config.size(); ++i ) {
                        PluginLV2Client_Opt *opt = config[i];
-                       float value = input.tag.get_property(opt->sym, 0.);
+                       float value = input.tag.get_property(opt->get_symbol(), 0.);
                        opt->set_value(value);
                }
        }
@@ -781,6 +668,22 @@ void PluginLV2Client::delete_buffers()
        bfrsz = 0;
 }
 
+int PluginLV2Client::open_lv2_gui(PluginLV2ClientWindow *gui)
+{
+#ifdef HAVE_LV2UI
+       if( parent_gui ) {
+               if( !parent_gui->done ) return 0;
+               delete parent_gui;
+       }
+       parent_gui = new PluginLV2ParentGUI(gui);
+       parent_gui->start_child();
+       parent_gui->start_parent();
+       return 1;
+#else
+       return 0;
+#endif
+}
+
 int PluginLV2Client::process_realtime(int64_t size,
        Samples *input_ptr, Samples *output_ptr)
 {
@@ -868,6 +771,64 @@ int MWindow::init_lv2_index(MWindow *mwindow, Preferences *preferences, FILE *fp
        return 0;
 }
 
+ForkChild *PluginLV2ParentGUI::new_fork()
+{
+#ifdef HAVE_LV2UI
+       return new PluginLV2ChildGUI();
+#else
+       return 0;
+#endif
+}
+
+PluginLV2ParentGUI::PluginLV2ParentGUI(PluginLV2ClientWindow *gui)
+{
+       this->gui = gui;
+}
+
+PluginLV2ParentGUI::~PluginLV2ParentGUI()
+{
+       stop();
+}
+
+void PluginLV2ParentGUI::start_parent()
+{
+       start();
+       const char *path = gui->plugin->server->path;
+       send_child(LV2_OPEN, path, strlen(path)+1);
+       PluginLV2ClientConfig &conf = gui->plugin->config;
+       send_child(LV2_START, 0, 0);
+       send_child(LV2_LOAD, conf.ctls, conf.nb_ports*sizeof(float));
+}
+
+int PluginLV2ParentGUI::handle_parent()
+{
+       int result = 1;
+
+       switch( parent_token ) {
+       case LV2_UPDATE:
+               gui->plugin->lv2_update((float *)parent_data);
+               break;
+       case LV2_SET: {
+               control_t *ctl = (control_t *)parent_data;
+               gui->plugin->lv2_set(ctl->idx, ctl->value);
+               break; }
+       case EXIT_CODE: {
+               result = -1;
+               break; }
+       default:
+               result = 0;
+               break;
+       }
+
+       return result;
+}
+
+// stub in parent
+int PluginLV2ChildGUI::handle_child()
+{
+       return 0;
+}
+
 #else
 #include "mwindow.h"
 #include "pluginserver.h"
index ee174accfe9b6b2b84c8675e3aa8a20d8264e2b7..5100a712c1520efba92404a580bde34138d02893 100644 (file)
 #ifndef PLUGINLV2CLIENT_H
 #define PLUGINLV2CLIENT_H
 
-#include "bcdisplayinfo.h"
-#include "guicast.h"
 #include "pluginaclient.h"
+#include "pluginlv2config.h"
 #include "pluginlv2client.inc"
+#include "pluginlv2gui.h"
 #include "samples.inc"
 
-#include <lilv/lilv.h>
-#include <lv2/lv2plug.in/ns/ext/atom/atom.h>
-#include <lv2/lv2plug.in/ns/ext/buf-size/buf-size.h>
-
-class PluginLV2UriTable : public ArrayList<const char *>
-{
-public:
-       PluginLV2UriTable();
-       ~PluginLV2UriTable();
-       LV2_URID map(const char *uri);
-       const char *unmap(LV2_URID urid);
-};
-
-class PluginLV2Client_OptName : public BC_ListBoxItem
-{
-public:
-       PluginLV2Client_Opt *opt;
-       PluginLV2Client_OptName(PluginLV2Client_Opt *opt);
-};
-
-class PluginLV2Client_OptValue : public BC_ListBoxItem
-{
-public:
-       PluginLV2Client_Opt *opt;
-       PluginLV2Client_OptValue(PluginLV2Client_Opt *opt);
-       int update();
-};
-
-class PluginLV2Client_Opt
-{
-public:
-       int idx;
-       const char *sym;
-       PluginLV2ClientConfig *conf;
-       PluginLV2Client_OptName *item_name;
-       PluginLV2Client_OptValue *item_value;
-       float get_value();
-       void set_value(float v);
-       int update(float v);
-       const char *get_name();
-
-       PluginLV2Client_Opt(PluginLV2ClientConfig *conf, const char *sym, int idx);
-       ~PluginLV2Client_Opt();
-};
-
-
-class PluginLV2ClientConfig : public ArrayList<PluginLV2Client_Opt *>
-{
-public:
-       PluginLV2ClientConfig();
-       ~PluginLV2ClientConfig();
-
-       int equivalent(PluginLV2ClientConfig &that);
-       void copy_from(PluginLV2ClientConfig &that);
-       void interpolate(PluginLV2ClientConfig &prev, PluginLV2ClientConfig &next,
-               int64_t prev_frame, int64_t next_frame, int64_t current_frame);
-       void reset();
-       void init_lv2(const LilvPlugin *lilv);
-       int update();
-
-       int nb_ports;
-       const char **names;
-       float *mins, *maxs, *ctls;
-};
+#define LV2_SEQ_SIZE  9624
 
 class PluginLV2Client_OptPanel : public BC_ListBox
 {
@@ -127,6 +64,15 @@ public:
        int handle_event();
 };
 
+class PluginLV2ClientUI : public BC_GenericButton {
+public:
+       PluginLV2ClientWindow *gui;
+
+       PluginLV2ClientUI(PluginLV2ClientWindow *gui, int x, int y);
+       ~PluginLV2ClientUI();
+       int handle_event();
+};
+
 class PluginLV2ClientApply : public BC_GenericButton {
 public:
        PluginLV2ClientWindow *gui;
@@ -166,6 +112,7 @@ public:
        void update(PluginLV2Client_Opt *opt);
 
        PluginLV2Client *plugin;
+       PluginLV2ClientUI *ui;
        PluginLV2ClientReset *reset;
        PluginLV2ClientApply *apply;
        PluginLV2ClientPot *pot;
@@ -190,7 +137,6 @@ public:
                Samples **input_ptr,
                Samples **output_ptr);
 // Update output pointers as well
-       void update_gui();
        int is_realtime();
        int is_multichannel();
        int is_synthesis();
@@ -201,6 +147,12 @@ public:
        void reset_lv2();
        int load_lv2(const char *path);
        int init_lv2();
+       int open_lv2_gui(PluginLV2ClientWindow *gui);
+       void update_gui();
+       void update_lv2();
+       void lv2_update();
+       void lv2_update(float *vals);
+       void lv2_set(int idx, float val);
 
        PLUGIN_CLASS_MEMBERS(PluginLV2ClientConfig)
        char title[BCSTRLEN];
@@ -224,7 +176,7 @@ public:
        LV2_Feature        map_feature;
        LV2_URID_Unmap     unmap;
        LV2_Feature        unmap_feature;
-       const LV2_Feature  *features[6];
+       Lv2Features        features;
        LV2_Atom_Sequence  seq_in[2];
        LV2_Atom_Sequence  *seq_out;
 
@@ -237,10 +189,11 @@ public:
        LilvNode *lv2_Optional;
        LilvNode *lv2_InputPort;
        LilvNode *lv2_OutputPort;
-       LilvNode *urid_map;
        LilvNode *powerOf2BlockLength;
        LilvNode *fixedBlockLength;
        LilvNode *boundedBlockLength;
+
+       PluginLV2ParentGUI *parent_gui;
 };
 
 #endif
index 8f292c701335ddf587027b6dc8bb8710d2449f11..4950519c31a54346633896914326ffb7807228d2 100644 (file)
 #ifndef PLUGINLV2CLIENT_INC
 #define PLUGINLV2CLIENT_INC
 
-class PluginLV2UriTable;
-class PluginLV2Client_OptName;
-class PluginLV2Client_OptValue;
-class PluginLV2Client_Opt;
-class PluginLV2ClientConfig;
 class PluginLV2Client_OptPanel;
 class PluginLV2ClientText;
 class PluginLV2ClientReset;
diff --git a/cinelerra-5.1/cinelerra/pluginlv2config.C b/cinelerra-5.1/cinelerra/pluginlv2config.C
new file mode 100644 (file)
index 0000000..776f9d6
--- /dev/null
@@ -0,0 +1,234 @@
+#ifdef HAVE_LV2
+
+/*
+ * CINELERRA
+ * Copyright (C) 2018 GG
+ *
+ * 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
+ *
+ */
+
+#include "arraylist.h"
+#include "cstrdup.h"
+#include "language.h"
+#include "pluginlv2config.h"
+
+#include <ctype.h>
+#include <string.h>
+
+PluginLV2UriTable::PluginLV2UriTable()
+{
+       set_array_delete();
+}
+
+PluginLV2UriTable::~PluginLV2UriTable()
+{
+       remove_all_objects();
+}
+
+LV2_URID PluginLV2UriTable::map(const char *uri)
+{
+       mLock locker(uri_table_lock);
+       for( int i=0; i<size(); ++i )
+               if( !strcmp(uri, get(i)) ) return i+1;
+       append(cstrdup(uri));
+       return size();
+}
+
+const char *PluginLV2UriTable::unmap(LV2_URID urid)
+{
+       mLock locker(uri_table_lock);
+       int idx = urid - 1;
+       return idx>=0 && idx<size() ? get(idx) : 0;
+}
+
+PluginLV2Client_OptName:: PluginLV2Client_OptName(PluginLV2Client_Opt *opt)
+{
+       this->opt = opt;
+       set_text(opt->get_name());
+}
+
+PluginLV2Client_OptValue::PluginLV2Client_OptValue(PluginLV2Client_Opt *opt)
+{
+       this->opt = opt;
+       update();
+}
+
+int PluginLV2Client_OptValue::update()
+{
+       char val[BCSTRLEN];
+       sprintf(val, "%f", opt->get_value());
+       if( !strcmp(val, get_text()) ) return 0;
+       set_text(val);
+       return 1;
+}
+
+
+PluginLV2Client_Opt::PluginLV2Client_Opt(PluginLV2ClientConfig *conf, int idx)
+{
+       this->conf = conf;
+       this->idx = idx;
+       item_name = new PluginLV2Client_OptName(this);
+       item_value = new PluginLV2Client_OptValue(this);
+}
+
+PluginLV2Client_Opt::~PluginLV2Client_Opt()
+{
+       delete item_name;
+       delete item_value;
+}
+
+float PluginLV2Client_Opt::get_value()
+{
+       return conf->ctls[idx];
+}
+
+const char *PluginLV2Client_Opt::get_symbol()
+{
+       return conf->syms[idx];
+}
+
+void PluginLV2Client_Opt::set_value(float v)
+{
+       conf->ctls[idx] = v;
+}
+
+int PluginLV2Client_Opt::update(float v)
+{
+       set_value(v);
+       return item_value->update();
+}
+
+const char *PluginLV2Client_Opt::get_name()
+{
+       return conf->names[idx];
+}
+
+PluginLV2ClientConfig::PluginLV2ClientConfig()
+{
+       names = 0;
+       syms = 0;
+       mins = 0;
+       maxs = 0;
+       ctls = 0;
+       nb_ports = 0;
+}
+
+PluginLV2ClientConfig::~PluginLV2ClientConfig()
+{
+       reset();
+       remove_all_objects();
+}
+
+void PluginLV2ClientConfig::reset()
+{
+       for( int i=0; i<nb_ports; ++i ) {
+               delete [] names[i];
+               delete [] syms[i];
+       }
+       delete [] names; names = 0;
+       delete [] mins;  mins = 0;
+       delete [] maxs;  maxs = 0;
+       delete [] ctls;  ctls = 0;
+       nb_ports = 0;
+}
+
+
+int PluginLV2ClientConfig::equivalent(PluginLV2ClientConfig &that)
+{
+       PluginLV2ClientConfig &conf = *this;
+       for( int i=0; i<that.size(); ++i ) {
+               PluginLV2Client_Opt *topt = conf[i], *vopt = that[i];
+               if( !EQUIV(topt->get_value(), vopt->get_value()) ) return 0;
+       }
+       return 1;
+}
+
+void PluginLV2ClientConfig::copy_from(PluginLV2ClientConfig &that)
+{
+       if( nb_ports != that.nb_ports ) {
+               reset();
+               nb_ports = that.nb_ports;
+               names = new const char *[nb_ports];
+               syms = new const char *[nb_ports];
+               for( int i=0; i<nb_ports; ++i ) names[i] = syms[i] = 0;
+               mins  = new float[nb_ports];
+               maxs  = new float[nb_ports];
+               ctls  = new float[nb_ports];
+       }
+       for( int i=0; i<nb_ports; ++i ) {
+               delete [] names[i];  names[i] = cstrdup(that.names[i]);
+               delete [] syms[i];   syms[i] = cstrdup(that.syms[i]);
+               mins[i] = that.mins[i];
+               maxs[i] = that.maxs[i];
+               ctls[i] = that.ctls[i];
+       }
+       remove_all_objects();
+       for( int i=0; i<that.size(); ++i ) {
+               append(new PluginLV2Client_Opt(this, that[i]->idx));
+       }
+}
+
+void PluginLV2ClientConfig::interpolate(PluginLV2ClientConfig &prev, PluginLV2ClientConfig &next,
+       int64_t prev_frame, int64_t next_frame, int64_t current_frame)
+{
+       copy_from(prev);
+}
+
+void PluginLV2ClientConfig::init_lv2(const LilvPlugin *lilv)
+{
+       reset();
+       nb_ports = lilv_plugin_get_num_ports(lilv);
+       names = new const char *[nb_ports];
+       syms = new const char *[nb_ports];
+       mins  = new float[nb_ports];
+       maxs  = new float[nb_ports];
+       ctls  = new float[nb_ports];
+       lilv_plugin_get_port_ranges_float(lilv, mins, maxs, ctls);
+       for( int i=0; i<nb_ports; ++i ) {
+               const LilvPort *lp = lilv_plugin_get_port_by_index(lilv, i);
+               LilvNode *pnm = lilv_port_get_name(lilv, lp);
+               names[i] = cstrdup(lilv_node_as_string(pnm));
+               lilv_node_free(pnm);
+               const LilvNode *sym = lilv_port_get_symbol(lilv, lp);
+               syms[i] = cstrdup(lilv_node_as_string(sym));
+       }
+}
+
+int PluginLV2ClientConfig::update()
+{
+       int ret = 0;
+       PluginLV2ClientConfig &conf = *this;
+       for( int i=0; i<size(); ++i ) {
+               if( conf[i]->item_value->update() ) ++ret;
+       }
+       return ret;
+}
+
+void PluginLV2ClientConfig::dump(FILE *fp)
+{
+       fprintf(fp, "Controls:\n");
+       for( int i=0; i<size(); ++i ) {
+               fprintf(fp, " %3d. (%3d)  %-24s  %f\n",
+                       i, get(i)->idx, get(i)->get_symbol(), get(i)->get_value());
+       }
+       fprintf(fp, "Ports:\n");
+       for( int i=0; i<nb_ports; ++i ) {
+               fprintf(fp, " %3d.  %-24s  %f  (%f - %f) %s\n",
+                       i, syms[i], ctls[i], mins[i], maxs[i], names[i]);
+       }
+}
+
+#endif /* HAVE_LV2 */
diff --git a/cinelerra-5.1/cinelerra/pluginlv2config.h b/cinelerra-5.1/cinelerra/pluginlv2config.h
new file mode 100644 (file)
index 0000000..c1ed9b9
--- /dev/null
@@ -0,0 +1,136 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * 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
+ *
+ */
+
+#ifndef PLUGINLV2CONFIG_H
+#define PLUGINLV2CONFIG_H
+
+#include "arraylist.h"
+#include "cstrdup.h"
+#include "guicast.h"
+#include "mutex.h"
+#include "pluginaclient.h"
+#include "pluginlv2config.inc"
+#include "samples.inc"
+
+#ifdef HAVE_LV2
+#include <lilv/lilv.h>
+
+#ifdef HAVE_LV2UI
+#include <suil/suil.h>
+
+#define NS_UI "http://lv2plug.in/ns/extensions/ui#"
+#include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
+#endif
+
+#include <lv2/lv2plug.in/ns/ext/atom/atom.h>
+#include <lv2/lv2plug.in/ns/ext/urid/urid.h>
+#include <lv2/lv2plug.in/ns/ext/state/state.h>
+#include <lv2/lv2plug.in/ns/ext/worker/worker.h>
+#include <lv2/lv2plug.in/ns/ext/log/log.h>
+#include <lv2/lv2plug.in/ns/ext/options/options.h>
+#include <lv2/lv2plug.in/ns/ext/buf-size/buf-size.h>
+#include <lv2/lv2plug.in/ns/ext/uri-map/uri-map.h>
+#include <lv2/lv2plug.in/ns/ext/data-access/data-access.h>
+
+
+class Lv2Feature : public LV2_Feature
+{
+public:
+       Lv2Feature(const char *uri, void *dp) {
+               this->URI = cstrdup(uri);  this->data = dp;
+       }
+       ~Lv2Feature() { delete [] URI; }
+};
+class Lv2Features : public ArrayList<Lv2Feature *>
+{
+public:
+       Lv2Features() {}
+       ~Lv2Features() { remove_all_objects(); }
+       operator LV2_Feature **() { return (LV2_Feature **)&values[0]; }
+};
+
+class PluginLV2UriTable : public ArrayList<const char *>
+{
+       Mutex uri_table_lock;
+public:
+       PluginLV2UriTable();
+       ~PluginLV2UriTable();
+       LV2_URID map(const char *uri);
+       const char *unmap(LV2_URID urid);
+};
+
+#endif
+
+class PluginLV2Client_OptName : public BC_ListBoxItem
+{
+public:
+       PluginLV2Client_Opt *opt;
+       PluginLV2Client_OptName(PluginLV2Client_Opt *opt);
+};
+
+class PluginLV2Client_OptValue : public BC_ListBoxItem
+{
+public:
+       PluginLV2Client_Opt *opt;
+       PluginLV2Client_OptValue(PluginLV2Client_Opt *opt);
+       int update();
+};
+
+class PluginLV2Client_Opt
+{
+public:
+       int idx;
+       const char *sym;
+       PluginLV2ClientConfig *conf;
+       PluginLV2Client_OptName *item_name;
+       PluginLV2Client_OptValue *item_value;
+       float get_value();
+       const char *get_symbol();
+       void set_value(float v);
+       int update(float v);
+       const char *get_name();
+
+       PluginLV2Client_Opt(PluginLV2ClientConfig *conf, int idx);
+       ~PluginLV2Client_Opt();
+};
+
+
+class PluginLV2ClientConfig : public ArrayList<PluginLV2Client_Opt *>
+{
+public:
+       PluginLV2ClientConfig();
+       ~PluginLV2ClientConfig();
+
+       int equivalent(PluginLV2ClientConfig &that);
+       void copy_from(PluginLV2ClientConfig &that);
+       void interpolate(PluginLV2ClientConfig &prev, PluginLV2ClientConfig &next,
+               int64_t prev_frame, int64_t next_frame, int64_t current_frame);
+       void reset();
+       void init_lv2(const LilvPlugin *lilv);
+       int update();
+       void dump(FILE *fp);
+
+       int nb_ports;
+       const char **names, **syms;
+       float *mins, *maxs, *ctls;
+};
+
+#endif
diff --git a/cinelerra-5.1/cinelerra/pluginlv2config.inc b/cinelerra-5.1/cinelerra/pluginlv2config.inc
new file mode 100644 (file)
index 0000000..6c1f41d
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __PLUGINLV2CONFIG_INC__
+#define __PLUGINLV2CONFIG_INC__
+
+class Lv2Feature;
+class Lv2Features;
+class PluginLV2UriTable;
+class PluginLV2Client_OptName;
+class PluginLV2Client_OptValue;
+class PluginLV2Client_Opt;
+class PluginLV2ClientConfig;
+
+#endif
diff --git a/cinelerra-5.1/cinelerra/pluginlv2gui.C b/cinelerra-5.1/cinelerra/pluginlv2gui.C
new file mode 100644 (file)
index 0000000..baa03f1
--- /dev/null
@@ -0,0 +1,306 @@
+#ifdef HAVE_LV2UI
+
+#include "file.h"
+#include "language.h"
+#include "pluginlv2gui.h"
+
+#include <ctype.h>
+#include <string.h>
+
+
+PluginLV2ChildGUI::PluginLV2ChildGUI()
+{
+       lv2_gui = 0;
+}
+
+PluginLV2ChildGUI::~PluginLV2ChildGUI()
+{
+       delete lv2_gui;
+}
+
+void PluginLV2ChildGUI::run()
+{
+       ArrayList<char *> av;
+       av.set_array_delete();
+       char arg[BCTEXTLEN];
+       const char *exec_path = File::get_cinlib_path();
+       snprintf(arg, sizeof(arg), "%s/%s", exec_path, "lv2ui");
+       av.append(cstrdup(arg));
+       sprintf(arg, "%d", child_fd);
+       av.append(cstrdup(arg));
+       sprintf(arg, "%d", parent_fd);
+       av.append(cstrdup(arg));
+       av.append(0);
+       execv(av[0], &av.values[0]);
+       fprintf(stderr, "execv failed: %s\n %m\n", av.values[0]);
+       av.remove_all_objects();
+       _exit(1);
+}
+
+
+#define NS_EXT "http://lv2plug.in/ns/ext/"
+
+PluginLV2GUI::PluginLV2GUI()
+{
+       world = 0;
+       lilv = 0;
+       uri_map = 0;
+       ext_data = 0;
+       inst = 0;
+       sinst = 0;
+       ui_host = 0;
+       uis = 0;
+       ui = 0;
+       ui_type = 0;
+       lv2_InputPort = 0;
+       lv2_ControlPort = 0;
+
+       updates = 0;
+       last = 0;
+       done = 0;
+       running = 0;
+       redraw = 0;
+
+// only gtk-2
+       gtk_type = "http://lv2plug.in/ns/extensions/ui#GtkUI";
+}
+
+PluginLV2GUI::~PluginLV2GUI ()
+{
+       reset_gui();
+       if( world ) lilv_world_free(world);
+}
+
+void PluginLV2GUI::reset_gui()
+{
+       if( inst ) lilv_instance_deactivate(inst);
+       if( uri_map )   { delete uri_map;             uri_map = 0; }
+       if( ext_data )  { delete ext_data;            ext_data = 0; }
+       if( inst )      { lilv_instance_free(inst);   inst = 0; }
+       if( sinst )     { suil_instance_free(sinst);  sinst = 0; }
+       if( ui_host )   { suil_host_free(ui_host);    ui_host = 0; }
+       if( uis )       { lilv_uis_free(uis);         uis = 0; }
+       if( lv2_InputPort )  { lilv_node_free(lv2_InputPort);   lv2_InputPort = 0; }
+       if( lv2_ControlPort ) { lilv_node_free(lv2_ControlPort);  lv2_ControlPort = 0; }
+       ui_features.remove_all_objects();
+       uri_table.remove_all_objects();
+       config.reset();
+       config.remove_all_objects();
+}
+
+int PluginLV2GUI::init_gui(const char *path)
+{
+       reset_gui();
+       if( !world )
+               world = lilv_world_new();
+       if( !world ) {
+               printf("lv2_gui: lilv_world_new failed");
+               return 1;
+       }
+       lilv_world_load_all(world);
+       LilvNode *uri = lilv_new_uri(world, path);
+       if( !uri ) {
+               printf("lv2_gui: lilv_new_uri(%s) failed", path);
+               return 1;
+       }
+
+       const LilvPlugins *all_plugins = lilv_world_get_all_plugins(world);
+       lilv = lilv_plugins_get_by_uri(all_plugins, uri);
+       lilv_node_free(uri);
+       if( !lilv ) {
+               printf("lv2_gui: lilv_plugins_get_by_uriPlugin(%s) failed", path);
+               return 1;
+       }
+
+       LilvNode *name = lilv_plugin_get_name(lilv);
+       const char *nm = lilv_node_as_string(name);
+       snprintf(title,sizeof(title),"L2_%s",nm);
+       lilv_node_free(name);
+
+       config.init_lv2(lilv);
+
+       lv2_InputPort  = lilv_new_uri(world, LV2_CORE__InputPort);
+       lv2_ControlPort = lilv_new_uri(world, LV2_CORE__ControlPort);
+
+       for( int i=0; i<config.nb_ports; ++i ) {
+               const LilvPort *lp = lilv_plugin_get_port_by_index(lilv, i);
+               if( lilv_port_is_a(lilv, lp, lv2_InputPort) &&
+                   lilv_port_is_a(lilv, lp, lv2_ControlPort) ) {
+                       config.append(new PluginLV2Client_Opt(&config, i));
+               }
+       }
+
+       uri_map = new LV2_URI_Map_Feature();
+       uri_map->callback_data = (LV2_URI_Map_Callback_Data)this;
+       uri_map->uri_to_id = uri_to_id;
+       ui_features.append(new Lv2Feature(NS_EXT "uri-map", uri_map));
+       map.handle = (void*)&uri_table;
+       map.map = uri_table_map;
+       ui_features.append(new Lv2Feature(LV2_URID__map, &map));
+       unmap.handle = (void*)&uri_table;
+       unmap.unmap  = uri_table_unmap;
+       ui_features.append(new Lv2Feature(LV2_URID__unmap, &unmap));
+       ui_features.append(0);
+
+       int sample_rate = 64; // cant be too low
+       inst = lilv_plugin_instantiate(lilv, sample_rate, ui_features);
+       if( !inst ) {
+               printf("lv2_gui: lilv_plugin_instantiate failed: %s\n", title);
+               return 1;
+       }
+
+       uis = lilv_plugin_get_uis(lilv);
+       if( gtk_type ) {
+               LilvNode *gui_type = lilv_new_uri(world, gtk_type);
+               LILV_FOREACH(uis, i, uis) {
+                       const LilvUI *gui = lilv_uis_get(uis, i);
+                       if( lilv_ui_is_supported(gui, suil_ui_supported, gui_type, &ui_type)) {
+                               ui = gui;
+                               break;
+                       }
+               }
+               lilv_node_free(gui_type);
+       }
+       if( !ui )
+               ui = lilv_uis_get(uis, lilv_uis_begin(uis));
+       if( !ui ) {
+               printf("lv2_gui: init_ui failed: %s\n", title);
+               return 1;
+       }
+
+       lilv_instance_activate(inst);
+       return 0;
+}
+
+void PluginLV2GUI::update_value(int idx, uint32_t bfrsz, uint32_t typ, const void *bfr)
+{
+       if( idx >= config.nb_ports ) return;
+       for( int i=0, sz=config.size(); i<sz; ++i ) {
+               PluginLV2Client_Opt *opt = config[i];
+               if( opt->idx == idx ) {
+                       opt->set_value(*(const float*)bfr);
+//printf("set %s = %f\n", opt->get_symbol(), opt->get_value());
+                       ++updates;
+                       break;
+               }
+       }
+}
+void PluginLV2GUI::write_from_ui(void *the, uint32_t idx,
+               uint32_t bfrsz, uint32_t typ, const void *bfr)
+{
+       ((PluginLV2GUI*)the)->update_value(idx, bfrsz, typ, bfr);
+}
+
+
+uint32_t PluginLV2GUI::port_index(void* obj, const char* sym)
+{
+       PluginLV2GUI *the = (PluginLV2GUI*)obj;
+       for( int i=0, sz=the->config.size(); i<sz; ++i ) {
+               PluginLV2Client_Opt *opt = the->config[i];
+               if( !strcmp(sym, opt->sym) ) return opt->idx;
+       }
+       return UINT32_MAX;
+}
+
+void PluginLV2GUI::update_control(int idx, uint32_t bfrsz, uint32_t typ, const void *bfr)
+{
+       if( !sinst || idx >= config.nb_ports ) return;
+       suil_instance_port_event(sinst, idx, bfrsz, typ, bfr);
+}
+
+
+#if 0
+void PluginLV2GUI::touch(void *obj, uint32_t pidx, bool grabbed)
+{
+       PluginLV2GUI* the = (PluginLV2GUI*)obj;
+       int idx = pidx;
+       if( idx >= the->config.nb_ports ) return;
+printf("%s %s(%u)\n", (grabbed? _("press") : _("release")),
+  the->config.names[idx], idx);
+}
+#endif
+
+uint32_t PluginLV2GUI::uri_to_id(LV2_URID_Map_Handle handle, const char *map, const char *uri)
+{
+       return ((PluginLV2UriTable *)handle)->map(uri);
+}
+
+LV2_URID PluginLV2GUI::uri_table_map(LV2_URID_Map_Handle handle, const char *uri)
+{
+       return ((PluginLV2UriTable *)handle)->map(uri);
+}
+
+const char *PluginLV2GUI::uri_table_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
+{
+       return ((PluginLV2UriTable *)handle)->unmap(urid);
+}
+
+void PluginLV2GUI::lv2ui_instantiate(void *parent)
+{
+       if ( !ui_host ) {
+               ui_host = suil_host_new(
+                       PluginLV2GUI::write_from_ui,
+                       PluginLV2GUI::port_index,
+                       0, 0);
+//             suil_host_set_touch_func(ui_host,
+//                     PluginLV2GUI::touch);
+       }
+
+       ui_features.remove();
+       LV2_Handle lilv_handle = lilv_instance_get_handle(inst);
+       ui_features.append(new Lv2Feature(NS_EXT "instance-access", lilv_handle));
+       const LV2_Descriptor *lilv_desc = lilv_instance_get_descriptor(inst);
+       ext_data = new LV2_Extension_Data_Feature();
+       ext_data->data_access = lilv_desc->extension_data;
+       ui_features.append(new Lv2Feature(LV2_DATA_ACCESS_URI, ext_data));
+       ui_features.append(new Lv2Feature(LV2_UI__parent, parent));
+       ui_features.append(new Lv2Feature(LV2_UI__idleInterface, 0));
+       ui_features.append(0);
+
+       const char* bundle_uri  = lilv_node_as_uri(lilv_ui_get_bundle_uri(ui));
+       char*       bundle_path = lilv_file_uri_parse(bundle_uri, NULL);
+       const char* binary_uri  = lilv_node_as_uri(lilv_ui_get_binary_uri(ui));
+       char*       binary_path = lilv_file_uri_parse(binary_uri, NULL);
+       sinst = suil_instance_new(ui_host, this, gtk_type,
+               lilv_node_as_uri(lilv_plugin_get_uri(lilv)),
+               lilv_node_as_uri(lilv_ui_get_uri(ui)),
+               lilv_node_as_uri(ui_type),
+               bundle_path, binary_path, ui_features);
+
+       lilv_free(binary_path);
+       lilv_free(bundle_path);
+}
+
+bool PluginLV2GUI::lv2ui_resizable()
+{
+       if( !ui ) return false;
+        const LilvNode* s   = lilv_ui_get_uri(ui);
+        LilvNode *p   = lilv_new_uri(world, LV2_CORE__optionalFeature);
+        LilvNode *fs  = lilv_new_uri(world, LV2_UI__fixedSize);
+        LilvNode *nrs = lilv_new_uri(world, LV2_UI__noUserResize);
+        LilvNodes *fs_matches = lilv_world_find_nodes(world, s, p, fs);
+        LilvNodes *nrs_matches = lilv_world_find_nodes(world, s, p, nrs);
+        lilv_nodes_free(nrs_matches);
+        lilv_nodes_free(fs_matches);
+        lilv_node_free(nrs);
+        lilv_node_free(fs);
+        lilv_node_free(p);
+        return !fs_matches && !nrs_matches;
+}
+
+int PluginLV2GUI::update_lv2(float *vals, int force)
+{
+       int ret = 0;
+       float *ctls = (float *)config.ctls;
+       for( int i=0; i<config.size(); ++i ) {
+               int idx = config[i]->idx;
+               float val = vals[idx];
+               if( !force && ctls[idx] == val ) continue;
+               update_control(idx, sizeof(val), 0, &val);
+               ++ret;
+       }
+       for( int i=0; i<config.nb_ports; ++i ) ctls[i] = vals[i];
+       return ret;
+}
+
+#endif /* HAVE_LV2UI */
diff --git a/cinelerra-5.1/cinelerra/pluginlv2gui.h b/cinelerra-5.1/cinelerra/pluginlv2gui.h
new file mode 100644 (file)
index 0000000..eed7143
--- /dev/null
@@ -0,0 +1,121 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * 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
+ *
+ */
+
+#ifndef __PLUGINLV2UI_H__
+#define __PLUGINLV2UI_H__
+
+#include "forkbase.h"
+#include "pluginlv2gui.inc"
+#include "pluginlv2client.h"
+
+class PluginLV2GUI
+{
+public:
+       PluginLV2GUI();
+       ~PluginLV2GUI();
+
+       void reset_gui(void);
+       int init_gui(const char *path);
+       void update_value(int idx, uint32_t bfrsz, uint32_t typ, const void *bfr);
+       static void write_from_ui(void *the, uint32_t idx, uint32_t bfrsz,uint32_t typ,const void *bfr);
+       void update_control(int idx, uint32_t bfrsz, uint32_t typ, const void *bfr);
+       static uint32_t port_index(void *obj,const char *sym);
+       static void touch(void *obj,uint32_t pidx,bool grabbed);
+       static uint32_t uri_to_id(LV2_URID_Map_Handle handle, const char *map, const char *uri);
+       static LV2_URID uri_table_map(LV2_URID_Map_Handle handle, const char *uri);
+       static const char *uri_table_unmap(LV2_URID_Map_Handle handle, LV2_URID urid);
+       void lv2ui_instantiate(void *parent);
+       bool lv2ui_resizable();
+       void host_update(PluginLV2ChildGUI *child);
+       int run(int ac, char **av);
+
+       PluginLV2ClientConfig config;
+       PluginLV2UriTable  uri_table;
+       LV2_URI_Map_Feature *uri_map;
+       LV2_Extension_Data_Feature *ext_data;
+       LV2_URID_Map       map;
+       LV2_URID_Unmap     unmap;
+       Lv2Features        ui_features;
+       LilvNode *lv2_InputPort;
+       LilvNode *lv2_ControlPort;
+
+       LilvWorld *world;
+        const LilvPlugin *lilv;
+       LilvInstance *inst;
+        LilvUIs* uis;
+       const LilvUI *ui;
+        const LilvNode *ui_type;
+
+#ifdef HAVE_LV2UI
+       SuilInstance *sinst;
+       SuilHost *ui_host;
+#endif
+
+       char title[BCSTRLEN];
+       const char *gtk_type;
+       uint32_t last, updates;
+       int done, running;
+
+       void start();
+       void stop();
+       int update_lv2(float *vals, int force);
+       int redraw;
+
+       void run_gui(PluginLV2ChildGUI *child=0);
+};
+
+enum { NO_COMMAND,
+       LV2_OPEN,
+       LV2_LOAD,
+       LV2_UPDATE,
+       LV2_START,
+       LV2_SET,
+       NB_COMMANDS };
+
+typedef struct { int idx;  float value; } control_t;
+
+class PluginLV2ParentGUI : public ForkParent
+{
+public:
+       PluginLV2ParentGUI(PluginLV2ClientWindow *gui);
+       ~PluginLV2ParentGUI();
+       ForkChild* new_fork();
+       void start_parent();
+
+       int handle_parent();
+       PluginLV2ClientWindow *gui;
+};
+
+class PluginLV2ChildGUI : public ForkChild
+{
+public:
+       PluginLV2ChildGUI();
+       ~PluginLV2ChildGUI();
+
+       int handle_child();
+       void run();
+       int run(int ac, char **av);
+
+       PluginLV2GUI *lv2_gui;
+// Command tokens
+};
+
+#endif
diff --git a/cinelerra-5.1/cinelerra/pluginlv2gui.inc b/cinelerra-5.1/cinelerra/pluginlv2gui.inc
new file mode 100644 (file)
index 0000000..033986c
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __PLUGINLV2GUI_INC__
+#define __PLUGINLV2GUI_INC__
+
+class PluginLV2GUI;
+class PluginLV2ParentGUI;
+class PluginLV2ChildGUI;
+
+#endif
index 84a983d7005266037a13f797932eeba6779d3b93..374a233ba8ee2b2506757929d16a5c1131f9b14a 100644 (file)
@@ -33,6 +33,7 @@ CHECK_WITH([exec-name],[binary executable name],[CIN],[cin])
 CHECK_WITH([single-user],[to install cin in bin],[CINBIN_BUILD],[no])
 CHECK_WITH([ladspa-build],[build ladspa library],[LADSPA_BUILD],[yes])
 CHECK_WITH([lv2],[lv2 library support],[LV2],[yes])
+CHECK_WITH([lv2ui],[lv2 ui support],[LV2UI],[yes])
 CHECK_WITH([cinlib],[cinelerra library path],[CINLIB_DIR],[auto])
 CHECK_WITH([cindat],[cinelerra share path],[CINDAT_DIR],[auto])
 CHECK_WITH([plugin-dir],[plugin install dir],[PLUGIN_DIR],[auto])
@@ -41,6 +42,18 @@ CHECK_WITH([config-dir],[.bcast config dir],[CONFIG_DIR],[$$HOME/.bcast5])
 CHECK_WITH([browser],[cin_browser path],[CIN_BROWSER],[firefox])
 CHECK_WITH([git-ffmpeg],[git ffmpeg using url],[GIT_FFMPEG],[no])
 
+if test "x$WANT_LV2" != "xno"; then
+  if test "x$WANT_LV2UI" != "xno"; then
+    GTK2_LIBS=`pkg-config --libs gtk+-2.0`
+    AC_CHECK_LIB([m], [gtk_init], [HAVE_gtk=yes], [HAVE_gtk=no], [$GTK2_LIBS])
+    test "x$HAVE_gtk" != "xno" && test -z "`pkg-config --cflags gtk+-2.0`" && HAVE_gtk=no
+    test "x$HAVE_gtk" != "xno" && test -z "`pkg-config --libs gtk+-2.0`" && HAVE_gtk=no
+    if test "x$HAVE_gtk" = "xno"; then
+      AC_MSG_ERROR([LV2UI requires gtk+-2.0 support.])
+    fi
+  fi
+fi
+
 if test "x$WANT_CINBIN_BUILD" = "xyes"; then
   WANT_LOCALE_DIR='$$CIN_LIB/locale'
   test "x$WANT_CINDAT_DIR" = "xauto" && WANT_CINDAT_DIR='$$CIN_PATH'
@@ -323,6 +336,36 @@ PKG_3RD([libvpx],[auto],
   [ libvpx.a ],
   [ . ])
 
+PKG_3RD([lv2],[auto],
+  [lv2-1.14.0],
+  [ ],
+  [ usr/local/include usr/local/lib64/lv2 usr/local/lib/lv2 ])
+
+PKG_3RD([sratom],[auto],
+  [sratom-0.6.0],
+  [ usr/local/lib/libsratom-0.a ],
+  [ usr/local/include ])
+
+PKG_3RD([serd],[auto],
+  [serd-0.28.0],
+  [ usr/local/lib/libserd-0.a ],
+  [ usr/local/include ])
+
+PKG_3RD([sord],[auto],
+  [sord-0.16.0],
+  [ usr/local/lib/libsord-0.a ],
+  [ usr/local/include ])
+
+PKG_3RD([lilv],[auto],
+  [lilv-0.24.2],
+  [ usr/local/lib/liblilv-0.a ],
+  [ usr/local/include ])
+
+PKG_3RD([suil],[auto],
+  [suil-0.8.4],
+  [ usr/local/lib/libsuil-0.a ],
+  [ usr/local/include ])
+
 AC_SUBST(STATIC_PKGS)
 
 AC_DEFUN([CHECK_ENABLE], [
@@ -482,11 +525,11 @@ CHECK_LIB([vdpau], [vdpau], [vdp_device_create_x11])
 
 AC_DEFUN([CHECK_WANT], [
 RESULT=yes
+# WANT_$1
+if test "x$WANT_$1" != "xyes" -a "x$WANT_$1" != "xno" ; then
 AC_ARG_WITH(m4_tolower([$1]),
  AC_HELP_STRING([m4_join([-],[--with],m4_tolower([$1]))], [$3] (auto)),
   [WANT_$1=$withval],[WANT_$1=$2])
-# WANT_$1
-if test "x$WANT_$1" != "xno" ; then
  m4_quote($4)
  if test "x$RESULT" = "xno" -a "x$PKG_$1" = "x"; then
   echo "=== want $1 Failed."
@@ -549,21 +592,31 @@ CHECK_WANT([LIBOPUS], [auto], [use libopus], [
  CHECK_HEADERS([opus], [libopus headers], [opus/opus_multistream.h])])
 
 CHECK_WANT([LV2], [auto], [use lv2], [
- CHECK_LIB([lv2], [lilv-0], [lilv_world_new])
+ saved_CFLAGS="$CFLAGS"
+ CHECK_LIB([lilv], [lilv-0], [lilv_world_new])
  CHECK_LIB([sord], [sord-0], [sord_world_new])
  CHECK_LIB([serd], [serd-0], [serd_reader_new])
  CHECK_LIB([sratom], [sratom-0], [sratom_new])
- saved_CFLAGS="$CXXFLAGS"
  CFLAGS="-I/usr/include/lilv-0"
  CHECK_HEADERS([lv2], [lilv headers], [lilv/lilv.h])
- CFLAGS="$saved_CXXFLAGS"])
+ CFLAGS="$saved_CFLAGS"])
+
+if test "x$WANT_LV2" = "xno"; then
+ WANT_LV2UI=no
+fi
+
+CHECK_WANT([LV2UI], [auto], [use lv2ui], [
+ CHECK_LIB([suil], [suil-0], [suil_instance_new])
+ CFLAGS="-I/usr/include/suil-0"
+ CHECK_HEADERS([lv2ui], [suil headers], [suil/suil.h])
+ CFLAGS="$saved_CFLAGS"])
 
 CHECK_WANT([DL], [auto], [system has libdl], [
  CHECK_LIB([DL], [dl], [dlopen])])
 
 CHECK_WANT([EXR], [auto], [use exr], [])
+
 CHECK_WANT([OPENCV], [no], [opencv=sys/sta/dyn,git/tar=url], [
- WANT_OPENCV="$withval"
 ])
 
 CHECK_WANT([NUMA], [auto], [system has libnuma], [
@@ -695,6 +748,15 @@ PKG_PROVIDE([x264])
 PKG_PROVIDE([x265])
 PKG_PROVIDE([libvpx])
 PKG_PROVIDE([opus], [$WANT_OPUS])
+PKG_PROVIDE([lv2], [$WANT_LV2])
+PKG_PROVIDE([lilv], [$WANT_LV2])
+PKG_PROVIDE([sratom], [$WANT_LV2])
+PKG_PROVIDE([serd], [$WANT_LV2])
+PKG_PROVIDE([sord], [$WANT_LV2])
+PKG_PROVIDE([suil], [$WANT_LV2UI])
+
+test "x$WANT_LV2"   = "xyes" && test "x$BUILD_lilv" = "x0" && CFG_CFLAGS+=' -I/usr/include/lilv-0'
+test "x$WANT_LV2UI" = "xyes" && test "x$BUILD_suil" = "x0" && CFG_CFLAGS+=' -I/usr/include/suil-0'
 
 AC_SUBST(STATIC_BLDS)
 AC_SUBST(SHARED_LIBS)
@@ -706,7 +768,7 @@ AC_SUBST(SYSTEM_LIBS)
 
 echo ""
 for v in GL XFT XXF86VM OSS ALSA FIREWIRE DV DVB \
-        VIDEO4LINUX2 ESOUND PACTL OPENEXR LV2; do
+        VIDEO4LINUX2 ESOUND PACTL OPENEXR LV2 LV2UI; do
   eval vv="\$WANT_$v"
   if test "x$vv" != "xno"; then
     CFG_CFLAGS+=" -DHAVE_$v"
@@ -752,9 +814,6 @@ if test "x$HAVE_opus" = "xyes"; then
   CFG_CFLAGS+=' -I/usr/include/opus'
   FFMPEG_EXTRA_CFG+=' --enable-libopus'
 fi
-if test "x$HAVE_lv2" = "xyes"; then
-  CFG_CFLAGS+=' -I/usr/include/lilv-0'
-fi
 
 AC_SUBST(EXTRA_LIBS)
 AC_SUBST(FFMPEG_EXTRA_CFG)
index a2bc012050a04a889f4aa8e18a6ed17bb2bdd3e8..ed50cfb15d9e8ac38c630c3096c9ab2b77fce477 100644 (file)
@@ -88,14 +88,14 @@ void BC_Signals::set_catch_segv(bool v) {
        if( v == trap_sigsegv ) return;
        if( v ) catch_segv();
        else uncatch_segv();
-       v = trap_sigsegv;
+       trap_sigsegv = v;
 }
 
 void BC_Signals::set_catch_intr(bool v) {
        if( v == trap_sigintr ) return;
        if( v ) catch_intr();
        else uncatch_intr();
-       v = trap_sigintr;
+       trap_sigintr = v;
 }
 
 static void bc_copy_textfile(int lines, FILE *ofp, const char *fmt,...)
index 6e84efaa0b263290ec7179bf693a2984952e218b..9bcbab0deb9799f17544325c13cb16d6e301737d 100644 (file)
@@ -213,6 +213,46 @@ x265.cfg_vars?=$(call cmake_config,source)
 x265.cfg_params?= -DENABLE_SHARED=no
 libvpx.cfg_params?= --enable-pic
 
+DS:=$$$$$$$$
+pkg_cfg=$(call bld_path,$(1),usr/local/lib/pkgconfig):
+LV2_PKGCFG:=$(subst : ,:,$(foreach p,lv2 serd sord sratom lilv suil,$(call pkg_cfg,$(p))))
+
+# lv2
+define waf-setup
+$(1).cfg_vars+=echo 'exec ./waf configure "$(DS)@"' > ./configure; chmod +x \
+ ./configure;  PKG_CONFIG_PATH=$(LV2_PKGCFG) LD_LIBRARY_PATH=$(LV2_LIBPATH) 
+$(1).cfg_params+=\
+ CFLAGS="-I$(call bld_path,lv2) $(foreach f,$(2), $(call inc_path,$(f))) -fPIC "\
+ LDFLAGS="-lm $(foreach f,$(2), $(call ld_path,$(f),usr/local/lib)) "
+$(1).mak_vars=(echo "all:"; echo "     ./waf -v build") > $(call bld_path,$(1),Makefile); 
+$(1).mak_params+=; ( cd $(1)*; ./waf install --destdir=$(call bld_path,$(1)) )
+endef
+
+SYS_LIB:=$(notdir $(lastword $(wildcard /usr/lib /usrlib32 /usr/lib64)))
+SYS_LV2:=$(lastword $(wildcard /usr/$(SYS_LIB)/lv2 /usr/local/$(SYS_LIB)/lv2))
+$(if $(SYS_LV2),,$(eval SYS_LV2:=/usr/$(SYS_LIB)/lv2))
+lv2.cfg_params?= --lv2dir=$(SYS_LV2)
+SYS_LV2_PATH:=/usr/$(SYS_LIB)/lv2: /usr/local/$(SYS_LIB)/lv2:
+DFT_LV2_PATH:= /usr/lib64/lv2: /usr/lib/lv2: /usr/local/lib64/lv2: /usr/local/lib/lv2: 
+LV2_PATH:=$(subst : ,:,$(SYS_LV2_PATH)$(filter-out $(SYS_LV2_PATH),$(DFT_LV2_PATH)))
+lilv.cfg_params?= --static --default-lv2-path=$(LV2_PATH)
+sratom.cfg_params?= --static --no-shared
+serd.cfg_params?= --static --no-shared
+sord.cfg_params?= --static --no-shared
+lilv.cfg_params?= --static --dyn-manifest
+suil.cfg_params?= --static --no-qt
+
+$(eval $(call waf-setup,lv2))
+$(eval $(call waf-setup,serd))
+$(eval $(call waf-setup,sord, serd))
+$(eval $(call waf-setup,sratom, serd sord))
+$(eval $(call waf-setup,lilv, lv2 sratom serd sord))
+$(eval $(call waf-setup,suil, lv2))
+
+# add softlinks for legacy paths
+waf_link=$(1).mak_params+=; (cd $(1)*; ln -s $(1)-0/$(1) usr/local/include/.)
+$(foreach p,sratom serd sord lilv suil,$(eval $(call waf_link,$(p))))
+
 # compile flag vars
 $(foreach tgt,$(TARGETS), \
        $(if $($(tgt).cflags),$(eval $(tgt).cfg_vars+=CFLAGS+=$($(tgt).cflags))))
@@ -267,6 +307,12 @@ $(call rules,$(call std-build,twolame))
 $(call rules,$(call std-build,x264))
 $(call rules,$(call std-build,x265))
 $(call rules,$(call std-build,libvpx))
+$(call rules,$(call std-build,lv2))
+$(call rules,$(call std-build,serd))
+$(call rules,$(call std-build,sord, serd))
+$(call rules,$(call std-build,sratom, serd sord))
+$(call rules,$(call std-build,lilv, lv2 sratom serd sord))
+$(call rules,$(call std-build,suil, lv2))
 
 # specialize festival, multiple tarballs
 festival:
diff --git a/cinelerra-5.1/thirdparty/src/lilv-0.24.2.tar.xz b/cinelerra-5.1/thirdparty/src/lilv-0.24.2.tar.xz
new file mode 100644 (file)
index 0000000..58f4fc1
Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/lilv-0.24.2.tar.xz differ
diff --git a/cinelerra-5.1/thirdparty/src/lv2-1.14.0.tar.xz b/cinelerra-5.1/thirdparty/src/lv2-1.14.0.tar.xz
new file mode 100644 (file)
index 0000000..1622ec3
Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/lv2-1.14.0.tar.xz differ
diff --git a/cinelerra-5.1/thirdparty/src/serd-0.28.0.tar.xz b/cinelerra-5.1/thirdparty/src/serd-0.28.0.tar.xz
new file mode 100644 (file)
index 0000000..23408e5
Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/serd-0.28.0.tar.xz differ
diff --git a/cinelerra-5.1/thirdparty/src/sord-0.16.0.tar.xz b/cinelerra-5.1/thirdparty/src/sord-0.16.0.tar.xz
new file mode 100644 (file)
index 0000000..31f97f8
Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/sord-0.16.0.tar.xz differ
diff --git a/cinelerra-5.1/thirdparty/src/sratom-0.6.0.tar.xz b/cinelerra-5.1/thirdparty/src/sratom-0.6.0.tar.xz
new file mode 100644 (file)
index 0000000..de31f0c
Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/sratom-0.6.0.tar.xz differ
diff --git a/cinelerra-5.1/thirdparty/src/suil-0.8.4.tar.xz b/cinelerra-5.1/thirdparty/src/suil-0.8.4.tar.xz
new file mode 100644 (file)
index 0000000..efe8acf
Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/suil-0.8.4.tar.xz differ