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)" .
#!/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
#!/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"
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
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 \
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
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
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"
$(OBJDIR)/floatauto.o \
$(OBJDIR)/floatautos.o \
$(OBJDIR)/folderlistmenu.o \
+ $(OBJDIR)/forkbase.o \
$(OBJDIR)/formatcheck.o \
$(OBJDIR)/formatpopup.o \
$(OBJDIR)/formatpresets.o \
$(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 \
$(LIBZMPEG3)/$(OBJDIR)/libzmpeg3.a \
$(MPEG2ENC)/$(OBJDIR)/hveg2enc.a \
$(TDB)/$(OBJDIR)/db.a \
- $(THEME_DATA) \
LIBS := $(LIBRARIES)
LIBS += $(libraries)
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) \
$(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))
$(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)
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-*
$(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
--- /dev/null
+
+/*
+ * 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;
+}
+
--- /dev/null
+
+/*
+ * 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
--- /dev/null
+#ifndef __FORKBASE_INC__
+#define __FORKBASE_INC__
+
+class ForkBase;
+class ForkParent;
+class ForkChild;
+
+#endif
--- /dev/null
+#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);
+}
+
strcpy(cin_lang,"en");
channeldb_buz = new ChannelDB;
channeldb_v4l2jpeg = new ChannelDB;
- //file_server = 0;
plugin_guis = 0;
dead_plugins = 0;
keyframe_threads = 0;
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
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
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();
#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"))
}
+
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])
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;
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;
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());
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)
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()
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;
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);
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) ||
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 ) {
{
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; }
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();
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);
}
}
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)
{
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"
#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
{
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;
void update(PluginLV2Client_Opt *opt);
PluginLV2Client *plugin;
+ PluginLV2ClientUI *ui;
PluginLV2ClientReset *reset;
PluginLV2ClientApply *apply;
PluginLV2ClientPot *pot;
Samples **input_ptr,
Samples **output_ptr);
// Update output pointers as well
- void update_gui();
int is_realtime();
int is_multichannel();
int is_synthesis();
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];
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;
LilvNode *lv2_Optional;
LilvNode *lv2_InputPort;
LilvNode *lv2_OutputPort;
- LilvNode *urid_map;
LilvNode *powerOf2BlockLength;
LilvNode *fixedBlockLength;
LilvNode *boundedBlockLength;
+
+ PluginLV2ParentGUI *parent_gui;
};
#endif
#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;
--- /dev/null
+#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 */
--- /dev/null
+
+/*
+ * 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
--- /dev/null
+#ifndef __PLUGINLV2CONFIG_INC__
+#define __PLUGINLV2CONFIG_INC__
+
+class Lv2Feature;
+class Lv2Features;
+class PluginLV2UriTable;
+class PluginLV2Client_OptName;
+class PluginLV2Client_OptValue;
+class PluginLV2Client_Opt;
+class PluginLV2ClientConfig;
+
+#endif
--- /dev/null
+#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 */
--- /dev/null
+
+/*
+ * 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
--- /dev/null
+#ifndef __PLUGINLV2GUI_INC__
+#define __PLUGINLV2GUI_INC__
+
+class PluginLV2GUI;
+class PluginLV2ParentGUI;
+class PluginLV2ChildGUI;
+
+#endif
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])
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'
[ 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], [
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."
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], [
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)
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"
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)
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,...)
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))))
$(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: