From: Good Guy Date: Sat, 19 May 2018 14:39:06 +0000 (-0600) Subject: add lv2ui support X-Git-Url: https://git.cinelerra-gg.org/git/?a=commitdiff_plain;h=efb3600851fd27b13d3053ffbdb6434535580bfd;p=goodguy%2Fhistory.git add lv2ui support --- diff --git a/cinelerra-5.1/Makefile.am b/cinelerra-5.1/Makefile.am index cd408349..5200484f 100644 --- a/cinelerra-5.1/Makefile.am +++ b/cinelerra-5.1/Makefile.am @@ -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)" . diff --git a/cinelerra-5.1/bld.sh b/cinelerra-5.1/bld.sh index a9b6e46c..b8a80d6b 100755 --- a/cinelerra-5.1/bld.sh +++ b/cinelerra-5.1/bld.sh @@ -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 diff --git a/cinelerra-5.1/bld_scripts/bld_prepare.sh b/cinelerra-5.1/bld_scripts/bld_prepare.sh index 929095bc..706749a1 100755 --- a/cinelerra-5.1/bld_scripts/bld_prepare.sh +++ b/cinelerra-5.1/bld_scripts/bld_prepare.sh @@ -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" diff --git a/cinelerra-5.1/cinelerra/Makefile b/cinelerra-5.1/cinelerra/Makefile index ee779981..4af6b1a1 100644 --- a/cinelerra-5.1/cinelerra/Makefile +++ b/cinelerra-5.1/cinelerra/Makefile @@ -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 index 00000000..8e87cb3d --- /dev/null +++ b/cinelerra-5.1/cinelerra/forkbase.C @@ -0,0 +1,239 @@ + +/* + * CINELERRA + * Copyright (C) 2009 Adam Williams + * + * 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 +#include +#include +#include +#include +#include +#include + +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 index 00000000..5502413d --- /dev/null +++ b/cinelerra-5.1/cinelerra/forkbase.h @@ -0,0 +1,92 @@ + +/* + * CINELERRA + * Copyright (C) 2009 Adam Williams + * + * 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 + +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 index 00000000..8f0266c2 --- /dev/null +++ b/cinelerra-5.1/cinelerra/forkbase.inc @@ -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 index 00000000..21acda44 --- /dev/null +++ b/cinelerra-5.1/cinelerra/lv2ui.C @@ -0,0 +1,143 @@ +#include + +#include +#include + +#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); +} + diff --git a/cinelerra-5.1/cinelerra/mwindow.C b/cinelerra-5.1/cinelerra/mwindow.C index 243f29a9..79ce0e3b 100644 --- a/cinelerra-5.1/cinelerra/mwindow.C +++ b/cinelerra-5.1/cinelerra/mwindow.C @@ -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 diff --git a/cinelerra-5.1/cinelerra/mwindow.h b/cinelerra-5.1/cinelerra/mwindow.h index 8c251e28..66f8f393 100644 --- a/cinelerra-5.1/cinelerra/mwindow.h +++ b/cinelerra-5.1/cinelerra/mwindow.h @@ -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(); diff --git a/cinelerra-5.1/cinelerra/pluginlv2client.C b/cinelerra-5.1/cinelerra/pluginlv2client.C index a508f46f..a2c0b51c 100644 --- a/cinelerra-5.1/cinelerra/pluginlv2client.C +++ b/cinelerra-5.1/cinelerra/pluginlv2client.C @@ -27,190 +27,33 @@ #include "language.h" #include "mwindow.h" #include "pluginlv2client.h" +#include "pluginlv2config.h" #include "pluginserver.h" #include "samples.h" #include #include -#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=0 && idxopt = 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; iget_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; isym, 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; iitem_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 = ↦ + 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; iset_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; isym, 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; isym, 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" diff --git a/cinelerra-5.1/cinelerra/pluginlv2client.h b/cinelerra-5.1/cinelerra/pluginlv2client.h index ee174acc..5100a712 100644 --- a/cinelerra-5.1/cinelerra/pluginlv2client.h +++ b/cinelerra-5.1/cinelerra/pluginlv2client.h @@ -22,76 +22,13 @@ #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 -#include -#include - -class PluginLV2UriTable : public ArrayList -{ -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 -{ -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 diff --git a/cinelerra-5.1/cinelerra/pluginlv2client.inc b/cinelerra-5.1/cinelerra/pluginlv2client.inc index 8f292c70..4950519c 100644 --- a/cinelerra-5.1/cinelerra/pluginlv2client.inc +++ b/cinelerra-5.1/cinelerra/pluginlv2client.inc @@ -22,11 +22,6 @@ #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 index 00000000..776f9d67 --- /dev/null +++ b/cinelerra-5.1/cinelerra/pluginlv2config.C @@ -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 +#include + +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=0 && idxopt = 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; iget_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; iidx)); + } +} + +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; iitem_value->update() ) ++ret; + } + return ret; +} + +void PluginLV2ClientConfig::dump(FILE *fp) +{ + fprintf(fp, "Controls:\n"); + for( int i=0; iidx, get(i)->get_symbol(), get(i)->get_value()); + } + fprintf(fp, "Ports:\n"); + for( int i=0; i + * + * 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 + +#ifdef HAVE_LV2UI +#include + +#define NS_UI "http://lv2plug.in/ns/extensions/ui#" +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 +{ +public: + Lv2Features() {} + ~Lv2Features() { remove_all_objects(); } + operator LV2_Feature **() { return (LV2_Feature **)&values[0]; } +}; + +class PluginLV2UriTable : public ArrayList +{ + 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 +{ +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 index 00000000..6c1f41de --- /dev/null +++ b/cinelerra-5.1/cinelerra/pluginlv2config.inc @@ -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 index 00000000..baa03f19 --- /dev/null +++ b/cinelerra-5.1/cinelerra/pluginlv2gui.C @@ -0,0 +1,306 @@ +#ifdef HAVE_LV2UI + +#include "file.h" +#include "language.h" +#include "pluginlv2gui.h" + +#include +#include + + +PluginLV2ChildGUI::PluginLV2ChildGUI() +{ + lv2_gui = 0; +} + +PluginLV2ChildGUI::~PluginLV2ChildGUI() +{ + delete lv2_gui; +} + +void PluginLV2ChildGUI::run() +{ + ArrayList 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; icallback_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(); iidx == 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(); iconfig[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; iidx; + float val = vals[idx]; + if( !force && ctls[idx] == val ) continue; + update_control(idx, sizeof(val), 0, &val); + ++ret; + } + for( int i=0; i + * + * 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 index 00000000..033986c3 --- /dev/null +++ b/cinelerra-5.1/cinelerra/pluginlv2gui.inc @@ -0,0 +1,8 @@ +#ifndef __PLUGINLV2GUI_INC__ +#define __PLUGINLV2GUI_INC__ + +class PluginLV2GUI; +class PluginLV2ParentGUI; +class PluginLV2ChildGUI; + +#endif diff --git a/cinelerra-5.1/configure.ac b/cinelerra-5.1/configure.ac index 84a983d7..374a233b 100644 --- a/cinelerra-5.1/configure.ac +++ b/cinelerra-5.1/configure.ac @@ -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) diff --git a/cinelerra-5.1/guicast/bcsignals.C b/cinelerra-5.1/guicast/bcsignals.C index a2bc0120..ed50cfb1 100644 --- a/cinelerra-5.1/guicast/bcsignals.C +++ b/cinelerra-5.1/guicast/bcsignals.C @@ -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,...) diff --git a/cinelerra-5.1/thirdparty/Makefile b/cinelerra-5.1/thirdparty/Makefile index 6e84efaa..9bcbab0d 100644 --- a/cinelerra-5.1/thirdparty/Makefile +++ b/cinelerra-5.1/thirdparty/Makefile @@ -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 index 00000000..58f4fc1a 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 index 00000000..1622ec37 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 index 00000000..23408e59 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 index 00000000..31f97f81 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 index 00000000..de31f0c9 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 index 00000000..efe8acfc Binary files /dev/null and b/cinelerra-5.1/thirdparty/src/suil-0.8.4.tar.xz differ