From 803cf48f8f7ee246eb5473e55fc2125e8b398250 Mon Sep 17 00:00:00 2001 From: Good Guy Date: Fri, 25 May 2018 17:10:42 -0600 Subject: [PATCH] lv2 rework, sams ffmpeg icons, elision patch --- cinelerra-5.1/cinelerra/Makefile | 9 +- cinelerra-5.1/cinelerra/bdcreate.C | 2 +- cinelerra-5.1/cinelerra/commercials.C | 6 +- cinelerra-5.1/cinelerra/devicempeginput.C | 14 +- cinelerra-5.1/cinelerra/filexml.C | 7 +- cinelerra-5.1/cinelerra/filexml.h | 7 +- cinelerra-5.1/cinelerra/forkbase.C | 77 +- cinelerra-5.1/cinelerra/forkbase.h | 13 +- cinelerra-5.1/cinelerra/lv2ui.C | 141 +--- cinelerra-5.1/cinelerra/pluginlv2.C | 393 +++++++++ cinelerra-5.1/cinelerra/pluginlv2.h | 92 +++ cinelerra-5.1/cinelerra/pluginlv2.inc | 6 + cinelerra-5.1/cinelerra/pluginlv2client.C | 778 +++++------------- cinelerra-5.1/cinelerra/pluginlv2client.h | 192 +---- cinelerra-5.1/cinelerra/pluginlv2client.inc | 13 +- cinelerra-5.1/cinelerra/pluginlv2config.C | 18 +- cinelerra-5.1/cinelerra/pluginlv2config.h | 3 +- cinelerra-5.1/cinelerra/pluginlv2gui.C | 503 ++++++----- cinelerra-5.1/cinelerra/pluginlv2gui.h | 179 ++-- cinelerra-5.1/cinelerra/pluginlv2gui.inc | 12 +- cinelerra-5.1/cinelerra/pluginlv2ui.C | 310 +++++++ cinelerra-5.1/cinelerra/pluginlv2ui.h | 95 +++ cinelerra-5.1/cinelerra/pluginlv2ui.inc | 7 + cinelerra-5.1/guicast/condition.C | 10 +- cinelerra-5.1/guicast/mutex.h | 9 - cinelerra-5.1/picon/cinfinity/ff_entropy.png | Bin 0 -> 12361 bytes .../picon/cinfinity/ff_fillborders.png | Bin 0 -> 10317 bytes .../picon/cinfinity/ff_normalize.png | Bin 0 -> 9135 bytes cinelerra-5.1/picon/cinfinity/ff_setrange.png | Bin 0 -> 12628 bytes cinelerra-5.1/picon/cinfinity/ff_vfrdet.png | Bin 0 -> 13189 bytes cinelerra-5.1/picon/cinfinity2/ff_entropy.png | Bin 0 -> 11045 bytes .../picon/cinfinity2/ff_fillborders.png | Bin 0 -> 9283 bytes .../picon/cinfinity2/ff_normalize.png | Bin 0 -> 6744 bytes .../picon/cinfinity2/ff_setrange.png | Bin 0 -> 11747 bytes cinelerra-5.1/picon/cinfinity2/ff_vfrdet.png | Bin 0 -> 12117 bytes cinelerra-5.1/plugins/Makefile | 2 +- 36 files changed, 1645 insertions(+), 1253 deletions(-) create mode 100644 cinelerra-5.1/cinelerra/pluginlv2.C create mode 100644 cinelerra-5.1/cinelerra/pluginlv2.h create mode 100644 cinelerra-5.1/cinelerra/pluginlv2.inc create mode 100644 cinelerra-5.1/cinelerra/pluginlv2ui.C create mode 100644 cinelerra-5.1/cinelerra/pluginlv2ui.h create mode 100644 cinelerra-5.1/cinelerra/pluginlv2ui.inc create mode 100644 cinelerra-5.1/picon/cinfinity/ff_entropy.png create mode 100644 cinelerra-5.1/picon/cinfinity/ff_fillborders.png create mode 100644 cinelerra-5.1/picon/cinfinity/ff_normalize.png create mode 100644 cinelerra-5.1/picon/cinfinity/ff_setrange.png create mode 100644 cinelerra-5.1/picon/cinfinity/ff_vfrdet.png create mode 100644 cinelerra-5.1/picon/cinfinity2/ff_entropy.png create mode 100644 cinelerra-5.1/picon/cinfinity2/ff_fillborders.png create mode 100644 cinelerra-5.1/picon/cinfinity2/ff_normalize.png create mode 100644 cinelerra-5.1/picon/cinfinity2/ff_setrange.png create mode 100644 cinelerra-5.1/picon/cinfinity2/ff_vfrdet.png diff --git a/cinelerra-5.1/cinelerra/Makefile b/cinelerra-5.1/cinelerra/Makefile index 4af6b1a1..a179559f 100644 --- a/cinelerra-5.1/cinelerra/Makefile +++ b/cinelerra-5.1/cinelerra/Makefile @@ -224,6 +224,7 @@ OBJS = \ $(OBJDIR)/pluginclient.o \ $(OBJDIR)/plugindialog.o \ $(OBJDIR)/pluginfclient.o \ + $(OBJDIR)/pluginlv2.o \ $(OBJDIR)/pluginlv2config.o \ $(OBJDIR)/pluginlv2client.o \ $(OBJDIR)/pluginlv2gui.o \ @@ -379,7 +380,8 @@ ifneq ($(WANT_LV2UI),no) LV2UI = $(OBJDIR)/lv2ui LV2OBJS = \ $(OBJDIR)/lv2ui.o \ - $(OBJDIR)/pluginlv2gui.o \ + $(OBJDIR)/pluginlv2.o \ + $(OBJDIR)/pluginlv2ui.o \ $(OBJDIR)/pluginlv2config.o \ $(OBJDIR)/forkbase.o endif @@ -415,7 +417,8 @@ CFLAGS += -DUSE_ALPHA else LDFLAGS1 = -export-dynamic -LDFLAGS2 = +# avoid the intel lock elision bug, if possible +LDFLAGS2 = $(lastword $(wildcard /usr/lib/noelision /lib/noelision /usr/lib64/noelision /lib/noelision)) LINKER = g++ -o $(OUTPUT) endif @@ -482,7 +485,9 @@ ifneq ($(WANT_LV2UI),no) GTK2_INCS := `pkg-config --cflags gtk+-2.0` GTK2_LIBS := `pkg-config --libs gtk+-2.0` +$(OBJDIR)/pluginlv2ui.o: pluginlv2ui.C $(OBJDIR)/lv2ui.o: lv2ui.C +$(OBJDIR)/pluginlv2ui.o $(OBJDIR)/lv2ui.o: $(CXX) `cat $(OBJDIR)/c_flags` $(GTK2_INCS) -DMSGQUAL=$* -c $< -o $@ $(OBJDIR)/lv2ui: $(LV2OBJS) diff --git a/cinelerra-5.1/cinelerra/bdcreate.C b/cinelerra-5.1/cinelerra/bdcreate.C index c7cbfbc5..27f728ad 100644 --- a/cinelerra-5.1/cinelerra/bdcreate.C +++ b/cinelerra-5.1/cinelerra/bdcreate.C @@ -229,7 +229,7 @@ int CreateBD_Thread::create_bd_jobs(ArrayList *jobs, const char fprintf(fp,"sz=`du -cb $1/bd.m2ts* | tail -1 | sed -e 's/[ \t].*//'`\n"); fprintf(fp,"blks=$((sz/2048 + 4096))\n"); fprintf(fp,"rm -f %s\n", udfs); - fprintf(fp,"mkudffs %s $blks\n", udfs); + fprintf(fp,"mkudffs -b 2048 %s $blks\n", udfs); fprintf(fp,"mount %s%s\n", mopts, mntpt); fprintf(fp,"bdwrite %s $1/bd.m2ts*\n",mntpt); fprintf(fp,"umount %s\n",mntpt); diff --git a/cinelerra-5.1/cinelerra/commercials.C b/cinelerra-5.1/cinelerra/commercials.C index a81aafe8..3a3de586 100644 --- a/cinelerra-5.1/cinelerra/commercials.C +++ b/cinelerra-5.1/cinelerra/commercials.C @@ -804,16 +804,18 @@ run() void SdbPacketQueue:: put_packet(SdbPacket *p) { - mLock holds(this); + lock("SdbPacketQueue::put_packet"); append(p); + unlock(); } SdbPacket *SdbPacketQueue:: get_packet() { - mLock holds(this); + lock("SdbPacketQueue::get_packet"); SdbPacket *p = first; remove_pointer(p); + unlock(); return p; } diff --git a/cinelerra-5.1/cinelerra/devicempeginput.C b/cinelerra-5.1/cinelerra/devicempeginput.C index b87bed33..056da30a 100644 --- a/cinelerra-5.1/cinelerra/devicempeginput.C +++ b/cinelerra-5.1/cinelerra/devicempeginput.C @@ -415,36 +415,40 @@ int DeviceMPEGInput::set_channel(Channel *channel) void DeviceMPEGInput::set_captioning(int strk) { - mLock holds(decoder_lock); + decoder_lock->lock("DeviceMPEGInput::set_captioning"); captioning = strk; if( src && video_stream >= 0 ) src->show_subtitle(video_stream, strk); + decoder_lock->unlock(); } int DeviceMPEGInput::drop_frames(int frames) { - mLock holds(decoder_lock); + decoder_lock->lock("DeviceMPEGInput::drop_frames"); double result = -1.; if( src && video_stream >= 0 ) result = src->drop_frames(frames,video_stream); + decoder_lock->unlock(); return result; } double DeviceMPEGInput::audio_timestamp() { - mLock holds(decoder_lock); + decoder_lock->lock("DeviceMPEGInput::audio_timestamp"); double result = -1.; if( src && audio_stream >= 0 ) result = src->get_audio_time(audio_stream); + decoder_lock->unlock(); return result; } double DeviceMPEGInput::video_timestamp() { - mLock holds(decoder_lock); + decoder_lock->lock("DeviceMPEGInput::video_timestamp"); double ret = -1.; if( src && video_stream >= 0 ) ret = src->get_video_time(video_stream); + decoder_lock->unlock(); return ret; } @@ -540,7 +544,7 @@ int DeviceMPEGInput::get_video_pid(int track) int DeviceMPEGInput::get_video_info(int track, int &pid, double &framerate, int &width, int &height, char *title) { - //mLock holds(decoder_lock); caller of callback holds lock + //caller of callback holds decoder_lock; if( !src ) return 1; pid = src->video_pid(track); framerate = src->frame_rate(track); diff --git a/cinelerra-5.1/cinelerra/filexml.C b/cinelerra-5.1/cinelerra/filexml.C index 065dce7d..5390617b 100644 --- a/cinelerra-5.1/cinelerra/filexml.C +++ b/cinelerra-5.1/cinelerra/filexml.C @@ -73,9 +73,10 @@ XMLBuffer::~XMLBuffer() if( destroy ) delete [] bfr; } -unsigned char *&XMLBuffer::demand(long len) +int XMLBuffer::demand(long len) { if( len > bsz ) { + if( !destroy ) return 0; long sz = inp-bfr; len += sz/2 + BCTEXTLEN; unsigned char *np = new unsigned char[len]; @@ -85,13 +86,13 @@ unsigned char *&XMLBuffer::demand(long len) lmt = np + len; bsz = len; delete [] bfr; bfr = np; } - return bfr; + return 1; } int XMLBuffer::write(const char *bp, int len) { - if( !destroy && lmt-inp < len ) len = lmt-inp; if( len <= 0 ) return 0; + if( !destroy && lmt-inp < len ) len = lmt-inp; demand(otell()+len); memmove(inp,bp,len); inp += len; diff --git a/cinelerra-5.1/cinelerra/filexml.h b/cinelerra-5.1/cinelerra/filexml.h index a701b649..af45e308 100644 --- a/cinelerra-5.1/cinelerra/filexml.h +++ b/cinelerra-5.1/cinelerra/filexml.h @@ -38,7 +38,7 @@ class XMLBuffer unsigned char *inp, *outp, *bfr, *lmt; int destroy; - unsigned char *&demand(long len); + int demand(long len); public: XMLBuffer(long buf_size=0x1000, long max_size=LONG_MAX, int del=1); XMLBuffer(long buf_size, char *buf, int del=0); // writing @@ -56,10 +56,7 @@ public: int cur() { return outp>=inp ? -1 : *outp; } int next() { return outp>=inp ? -1 : *outp++; } - int next(int ch) { - demand(otell()+1); - return *inp++ = ch; - } + int next(int ch) { return !demand(otell()+1) ? -1 : *inp++ = ch; } static char *decode_data(char *bp, const char *sp, int n=-1); static char *encode_data(char *bp, const char *sp, int n=-1); diff --git a/cinelerra-5.1/cinelerra/forkbase.C b/cinelerra-5.1/cinelerra/forkbase.C index 8e87cb3d..174019dd 100644 --- a/cinelerra-5.1/cinelerra/forkbase.C +++ b/cinelerra-5.1/cinelerra/forkbase.C @@ -32,8 +32,9 @@ #include ForkBase::ForkBase() + : Mutex("ForkBase::lock") { - pid = 0; + ppid = pid = 0; child = 0; child_fd = -1; @@ -47,7 +48,6 @@ ForkBase::ForkBase() parent_bytes = 0; parent_allocated = 0; parent_data = 0; - } ForkBase::~ForkBase() @@ -58,6 +58,12 @@ ForkBase::~ForkBase() if( parent_fd >= 0 ) close(parent_fd); } +// return 1 parent is running +int ForkChild::is_running() +{ + return !ppid || !kill(ppid, 0) ? 1 : 0; +} + int ForkChild::child_iteration() { int ret = read_child(100); @@ -67,22 +73,22 @@ int ForkChild::child_iteration() void ForkParent::start_child() { - lock->lock("ForkParent::new_child"); + 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]; + ppid = getpid(); 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->ppid = ppid; child->run(); + delete child; _exit(0); } - lock->unlock(); + unlock(); } // Return -1 if the parent is dead @@ -101,13 +107,14 @@ int ForkBase::read_timeout(int ms, int fd, void *data, int bytes) FD_ZERO(&rfds); FD_SET(fd, &rfds); int result = select(fd+1, &rfds, 0, 0, &timeout_struct); + if( result < 0 ) perror("read_timeout select"); 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 ) perror("read_timeout read"); if( fragment < 0 || !is_running() ) return -1; if( fragment > 0 ) bytes_read += fragment; } - return 1; } @@ -130,10 +137,14 @@ int ForkBase::read_parent(int ms) delete [] parent_data; parent_data = new uint8_t[parent_allocated = parent_bytes]; } - if( parent_bytes ) + if( parent_bytes ) { ret = read_timeout(1000, parent_fd, parent_data, parent_bytes); + if( !ret ) { + printf("read_parent timeout: %d\n", parent_fd); + ret = -1; + } + } } -//if( ret < 0 ) printf("read_parent timeout\n"); return ret; } @@ -148,28 +159,47 @@ int ForkBase::read_child(int ms) delete [] child_data; child_data = new uint8_t[child_allocated = child_bytes]; } - if( child_bytes ) + if( child_bytes ) { ret = read_timeout(1000, child_fd, child_data, child_bytes); + if( !ret ) { + printf("read_child timeout: %d\n", child_fd); + ret = -1; + } + } } -//if( ret < 0 ) printf("read_child timeout\n"); return ret; } +void ForkBase::send_bfr(int fd, const void *bfr, int len) +{ + int ret = 0; + for( int retries=10; --retries>=0 && (ret=write(fd, bfr, len)) < 0; ) { + printf("send_bfr socket(%d) write error: %d/%d bytes\n%m\n", fd,ret,len); + usleep(100000); + } + if( ret < len ) + printf("send_bfr socket(%d) write short: %d/%d bytes\n%m\n", fd,ret,len); +} + int ForkBase::send_parent(int64_t token, const void *data, int bytes) { + lock("ForkBase::send_parent"); 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); + send_bfr(child_fd, &bfr, sizeof(bfr)); + if( data && bytes ) send_bfr(child_fd, data, bytes); + unlock(); return 0; } int ForkBase::send_child(int64_t token, const void *data, int bytes) { + lock("ForkBase::send_child"); 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); + send_bfr(parent_fd, &bfr, sizeof(bfr)); + if( data && bytes ) send_bfr(parent_fd, data, bytes); + unlock(); return 0; } @@ -191,13 +221,19 @@ int ForkChild::handle_child() ForkParent::ForkParent() : Thread(1, 0, 0) { - lock = new Mutex("ForkParent::lock"); done = -1; } ForkParent::~ForkParent() { - delete lock; +} + +// return 1 child is running +int ForkParent::is_running() +{ + int status = 0; + if( waitpid(pid, &status, WNOHANG) < 0 ) return 0; + return !kill(pid, 0) ? 1 : 0; } // Return -1,0,1 if dead,timeout,success @@ -225,8 +261,9 @@ void ForkParent::stop() { if( is_running() ) { send_child(EXIT_CODE, 0, 0); - int status = 0; - waitpid(pid, &status, 0); + int retry = 10; + while( --retry>=0 && is_running() ) usleep(100000); + if( retry < 0 ) kill(pid, SIGKILL); } join(); } diff --git a/cinelerra-5.1/cinelerra/forkbase.h b/cinelerra-5.1/cinelerra/forkbase.h index 5502413d..2ca84b71 100644 --- a/cinelerra-5.1/cinelerra/forkbase.h +++ b/cinelerra-5.1/cinelerra/forkbase.h @@ -30,7 +30,7 @@ #include -class ForkBase +class ForkBase : public Mutex { public: enum { EXIT_CODE=0x7fff }; @@ -39,14 +39,15 @@ public: ForkBase(); virtual ~ForkBase(); - int is_running(); + virtual int is_running() = 0; + void send_bfr(int fd, const void *bfr, int len); 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; + int done, ppid, pid; ForkChild *child; int child_fd; @@ -67,9 +68,10 @@ class ForkChild : public ForkBase public: ForkChild(); virtual ~ForkChild(); - virtual void run() = 0; virtual int handle_child(); int child_iteration(); + int is_running(); + virtual void run() {} }; class ForkParent : public Thread, public ForkBase @@ -79,14 +81,13 @@ public: virtual ~ForkParent(); virtual int handle_parent(); virtual ForkChild *new_fork() = 0; + int is_running(); void start_child(); void start(); void stop(); void run(); int parent_iteration(); - - Mutex *lock; }; #endif diff --git a/cinelerra-5.1/cinelerra/lv2ui.C b/cinelerra-5.1/cinelerra/lv2ui.C index 21acda44..3a06102a 100644 --- a/cinelerra-5.1/cinelerra/lv2ui.C +++ b/cinelerra-5.1/cinelerra/lv2ui.C @@ -1,143 +1,50 @@ #include +#include #include #include #include "bcsignals.h" #include "pluginlv2client.h" -#include "pluginlv2gui.h" +#include "pluginlv2ui.h" -static void lilv_destroy(GtkWidget* widget, gpointer data) +int PluginLV2UI::run(int ac, char **av) { - 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 sample_rate = 48000; + if( ac > 2 ) sample_rate = atoi(av[2]); + if( init_ui(av[1], sample_rate) ) { + fprintf(stderr," init_ui failed\n"); + return 1; } + start_gui(); + return run_ui(); } -int PluginLV2ChildGUI::handle_child() +int PluginLV2ChildUI::run(int ac, char **av) { - 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; + signal(SIGINT, SIG_IGN); + ForkBase::child_fd = atoi(av[1]); + ForkBase::parent_fd = atoi(av[2]); + ForkBase::ppid = atoi(av[3]); + return run_ui(this); } -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) { +// to grab this task in the debugger +const char *cp = getenv("BUG"); +static int zbug = !cp ? 0 : atoi(cp); volatile int bug = zbug; +while( bug ) usleep(10000); BC_Signals signals; if( getenv("BC_TRAP_LV2_SEGV") ) { signals.initialize("/tmp/lv2ui_%d.dmp"); - BC_Signals::set_catch_segv(1); + 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); + return ac < 3 ? + PluginLV2UI().run(ac, av) : + PluginLV2ChildUI().run(ac, av); } diff --git a/cinelerra-5.1/cinelerra/pluginlv2.C b/cinelerra-5.1/cinelerra/pluginlv2.C new file mode 100644 index 00000000..698be88e --- /dev/null +++ b/cinelerra-5.1/cinelerra/pluginlv2.C @@ -0,0 +1,393 @@ +#ifdef HAVE_LV2 + +#include "bctrace.h" +#include "bcwindowbase.h" +#include "pluginlv2.h" +#include "samples.h" + +#include +#include + +PluginLV2::PluginLV2() +{ + shm_bfr = 0; + use_shm = 1; + shmid = -1; + in_buffers = 0; iport = 0; + out_buffers = 0; oport = 0; + nb_inputs = 0; + nb_outputs = 0; + max_bufsz = 0; + ui_features = 0; + + world = 0; + lilv = 0; + lilv_uis = 0; + inst = 0; + sinst = 0; + ui_host = 0; + + lv2_InputPort = 0; + lv2_OutputPort = 0; + lv2_AudioPort = 0; + lv2_ControlPort = 0; + lv2_CVPort = 0; + lv2_Optional = 0; + atom_AtomPort = 0; + atom_Sequence = 0; + powerOf2BlockLength = 0; + fixedBlockLength = 0; + boundedBlockLength = 0; + seq_out = 0; +} + +PluginLV2::~PluginLV2() +{ + reset_lv2(); + if( world ) lilv_world_free(world); +} + +void PluginLV2::reset_lv2() +{ + if( inst ) lilv_instance_deactivate(inst); + lilv_instance_free(inst); inst = 0; + lilv_uis_free(lilv_uis); lilv_uis = 0; + + lilv_node_free(lv2_InputPort); lv2_InputPort = 0; + lilv_node_free(lv2_OutputPort); lv2_OutputPort = 0; + lilv_node_free(lv2_AudioPort); lv2_AudioPort = 0; + lilv_node_free(lv2_ControlPort); lv2_ControlPort = 0; + lilv_node_free(lv2_CVPort); lv2_CVPort = 0; + + lilv_node_free(lv2_Optional); lv2_Optional = 0; + lilv_node_free(atom_AtomPort); atom_AtomPort = 0; + lilv_node_free(atom_Sequence); atom_Sequence = 0; + lilv_node_free(boundedBlockLength); boundedBlockLength = 0; + lilv_node_free(fixedBlockLength); fixedBlockLength = 0; + lilv_node_free(powerOf2BlockLength); powerOf2BlockLength = 0; + + delete [] (char *)seq_out; seq_out = 0; + uri_table.remove_all_objects(); + features.remove_all_objects(); ui_features = 0; + del_buffer(); +} + + +int PluginLV2::load_lv2(const char *path, char *title) +{ + if( !world ) { + world = lilv_world_new(); + if( !world ) { + printf("lv2: lilv_world_new failed\n"); + return 1; + } + lilv_world_load_all(world); + } + + LilvNode *uri = lilv_new_uri(world, path); + if( !uri ) { + printf("lv2: lilv_new_uri(%s) failed\n", 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: lilv_plugins_get_by_uriPlugin(%s) failed\n", path); + return 1; + } + + if( title ) { + LilvNode *name = lilv_plugin_get_name(lilv); + const char *nm = lilv_node_as_string(name); + sprintf(title, "L2_%s", nm); + lilv_node_free(name); + } + return 0; +} + +int PluginLV2::init_lv2(PluginLV2ClientConfig &conf, int sample_rate) +{ + reset_lv2(); + + lv2_AudioPort = lilv_new_uri(world, LV2_CORE__AudioPort); + lv2_ControlPort = lilv_new_uri(world, LV2_CORE__ControlPort); + lv2_CVPort = lilv_new_uri(world, LV2_CORE__CVPort); + lv2_InputPort = lilv_new_uri(world, LV2_CORE__InputPort); + lv2_OutputPort = lilv_new_uri(world, LV2_CORE__OutputPort); + 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); + 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); + seq_out = (LV2_Atom_Sequence *) new char[sizeof(LV2_Atom_Sequence) + LV2_SEQ_SIZE]; + + conf.init_lv2(lilv); + nb_inputs = nb_outputs = 0; + + for( int i=0; imap(uri); +} + +const char *PluginLV2::uri_table_unmap(LV2_URID_Map_Handle handle, LV2_URID urid) +{ + return ((PluginLV2UriTable *)handle)->unmap(urid); +} + +void PluginLV2::connect_ports(PluginLV2ClientConfig &conf, int typ) +{ + int ich = 0, och = 0; + for( int i=0; iatom.size = LV2_SEQ_SIZE; + seq_out->atom.type = uri_table.map(LV2_ATOM__Chunk); +} + +void PluginLV2::del_buffer() +{ + if( shmid >= 0 ) + shm_buffer(-1); + + delete [] in_buffers; in_buffers = 0; + delete [] out_buffers; out_buffers = 0; +} + +void PluginLV2::new_buffer(int64_t sz) +{ + uint8_t *bp = 0; + if( use_shm ) { // currently, always uses shm + shmid = shmget(IPC_PRIVATE, sz, IPC_CREAT | 0777); + if( shmid >= 0 ) { + bp = (unsigned char*)shmat(shmid, NULL, 0); + if( bp == (void *) -1 ) { perror("shmat"); bp = 0; } + shmctl(shmid, IPC_RMID, 0); // delete when last ref gone + } + else { + perror("PluginLV2::allocate_buffer: shmget failed\n"); + BC_Trace::dump_shm_stats(stdout); + } + } + + shm_bfr = (shm_bfr_t *) bp; + if( shm_bfr ) shm_bfr->sz = sz; +} + +shm_bfr_t *PluginLV2::shm_buffer(int shmid) +{ + if( this->shmid != shmid ) { + if( this->shmid >= 0 ) { + shmdt(shm_bfr); this->shmid = -1; + shm_bfr = 0; + } + if( shmid >= 0 ) { + shm_bfr = (shm_bfr_t *)shmat(shmid, NULL, 0); + if( shm_bfr == (void *)-1 ) { perror("shmat"); shm_bfr = 0; } + this->shmid = shm_bfr ? shmid : -1; + } + } + return shm_bfr; +} + +void PluginLV2::init_buffer(int samples) +{ + int64_t sz = sizeof(shm_bfr_t) + + sizeof(iport[0])*nb_inputs + sizeof(oport[0])*nb_outputs + + sizeof(*in_buffers[0]) *samples * nb_inputs + + sizeof(*out_buffers[0])*samples * nb_outputs; + + if( shm_bfr ) { + if( shm_bfr->sz < sz || + shm_bfr->nb_inputs != nb_inputs || + shm_bfr->nb_outputs != nb_outputs ) + del_buffer(); + } + + if( !shm_bfr ) + new_buffer(sz); + + shm_bfr->samples = samples; + shm_bfr->done = 0; + shm_bfr->nb_inputs = nb_inputs; + shm_bfr->nb_outputs = nb_outputs; + + map_buffer(); +} + +// shm_bfr layout: +// struct shm_bfr { +// int64_t sz; +// int samples, done; +// int nb_inputs, nb_outputs; +// int iport[nb_inputs], +// float in_buffers[samples][nb_inputs]; +// int oport[nb_outputs]; +// float out_buffers[samples][nb_outputs]; +// }; + +void PluginLV2::map_buffer() +{ + uint8_t *bp = (uint8_t *)(shm_bfr + 1); + + nb_inputs = shm_bfr->nb_inputs; + iport = (int *)bp; + bp += sizeof(iport[0])*nb_inputs; + in_buffers = new float*[nb_inputs]; + int samples = shm_bfr->samples; + for(int i=0; inb_outputs; + oport = (int *)bp; + bp += sizeof(oport[0])*nb_outputs; + out_buffers = new float*[nb_outputs]; + for( int i=0; i 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)); + sprintf(arg, "%d", ppid); + 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); +} + + +PluginLV2UI::PluginLV2UI() + : PluginLV2() +{ + lilv_ui = 0; + lilv_type = 0; + uri_map = 0; + + done = 0; + running = 0; + redraw = 0; + host_updates = updates = 0; + host_hidden = hidden = 1; + title[0] = 0; + +// only gtk-2 + gtk_type = "http://lv2plug.in/ns/extensions/ui#GtkUI"; + top_level = 0; +} + +PluginLV2UI::~PluginLV2UI () +{ + reset_gui(); +} + +#endif diff --git a/cinelerra-5.1/cinelerra/pluginlv2.h b/cinelerra-5.1/cinelerra/pluginlv2.h new file mode 100644 index 00000000..9b449b48 --- /dev/null +++ b/cinelerra-5.1/cinelerra/pluginlv2.h @@ -0,0 +1,92 @@ +#ifndef __PLUGINLV2_H__ +#define __PLUGINLV2_H__ + +#define LV2_SEQ_SIZE 9624 +#include "forkbase.h" +#include "pluginlv2config.h" +#include "samples.inc" + +#include +#define NS_EXT "http://lv2plug.in/ns/ext/" + +typedef struct { + int64_t sz; + int samples, done; + int nb_inputs, nb_outputs; +} shm_bfr_t; + +#define TYP_AUDIO 1 +#define TYP_CONTROL 2 +#define TYP_ATOM 4 +#define TYP_ALL ~0 + +class PluginLV2 +{ +public: + PluginLV2(); + virtual ~PluginLV2(); + + shm_bfr_t *shm_bfr; + int use_shm, shmid; + float **in_buffers, **out_buffers; + int *iport, *oport; + int nb_inputs, nb_outputs; + int max_bufsz, ui_features; + + void reset_lv2(); + int load_lv2(const char *path,char *title=0); + int init_lv2(PluginLV2ClientConfig &conf, int sample_rate); + + 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 connect_ports(PluginLV2ClientConfig &conf, int typ=TYP_ALL); + void del_buffer(); + void new_buffer(int64_t sz); + shm_bfr_t *shm_buffer(int shmid); + void init_buffer(int samples); + void map_buffer(); + + LilvWorld *world; + const LilvPlugin *lilv; + LilvUIs *lilv_uis; + + PluginLV2UriTable uri_table; + LV2_URID_Map map; + LV2_Feature map_feature; + LV2_URID_Unmap unmap; + LV2_Feature unmap_feature; + Lv2Features features; + LV2_Atom_Sequence seq_in[2]; + LV2_Atom_Sequence *seq_out; + + LilvInstance *inst; + SuilInstance *sinst; + SuilHost *ui_host; + + LilvNode *atom_AtomPort; + LilvNode *atom_Sequence; + LilvNode *lv2_AudioPort; + LilvNode *lv2_CVPort; + LilvNode *lv2_ControlPort; + LilvNode *lv2_Optional; + LilvNode *lv2_InputPort; + LilvNode *lv2_OutputPort; + LilvNode *powerOf2BlockLength; + LilvNode *fixedBlockLength; + LilvNode *boundedBlockLength; +}; + +typedef struct { int sample_rate; char path[1]; } open_bfr_t; +typedef struct { int idx; float value; } control_bfr_t; + +enum { NO_COMMAND, + LV2_OPEN, + LV2_LOAD, + LV2_UPDATE, + LV2_SHOW, + LV2_HIDE, + LV2_SET, + LV2_SHMID, + NB_COMMANDS }; + +#endif diff --git a/cinelerra-5.1/cinelerra/pluginlv2.inc b/cinelerra-5.1/cinelerra/pluginlv2.inc new file mode 100644 index 00000000..a6506ada --- /dev/null +++ b/cinelerra-5.1/cinelerra/pluginlv2.inc @@ -0,0 +1,6 @@ +#ifndef __PLUGINLV2_INC__ +#define __PLUGINLV2_INC__ + +class PluginLV2; + +#endif diff --git a/cinelerra-5.1/cinelerra/pluginlv2client.C b/cinelerra-5.1/cinelerra/pluginlv2client.C index a2c0b51c..50df5ae6 100644 --- a/cinelerra-5.1/cinelerra/pluginlv2client.C +++ b/cinelerra-5.1/cinelerra/pluginlv2client.C @@ -20,481 +20,154 @@ * */ +#include "bchash.h" #include "clip.h" #include "cstrdup.h" -#include "bchash.h" +#include "file.h" #include "filexml.h" #include "language.h" +#include "mainerror.h" #include "mwindow.h" +#include "plugin.h" #include "pluginlv2client.h" #include "pluginlv2config.h" +#include "pluginlv2ui.inc" #include "pluginserver.h" +#include "pluginset.h" #include "samples.h" +#include "track.h" #include #include +PluginLV2UIs PluginLV2ParentUI::plugin_lv2; -PluginLV2ClientUI:: -PluginLV2ClientUI(PluginLV2ClientWindow *gui, int x, int y) - : BC_GenericButton(x, y, _("UI")) -{ - this->gui = gui; -} - -PluginLV2ClientUI:: -~PluginLV2ClientUI() -{ -} - -int PluginLV2ClientUI::handle_event() -{ - if( !gui->plugin->open_lv2_gui(gui) ) - flicker(8, 64); - return 1; -} - -PluginLV2ClientReset:: -PluginLV2ClientReset(PluginLV2ClientWindow *gui, int x, int y) - : BC_GenericButton(x, y, _("Reset")) -{ - this->gui = gui; -} - -PluginLV2ClientReset:: -~PluginLV2ClientReset() -{ -} - -int PluginLV2ClientReset::handle_event() +PluginLV2UIs::PluginLV2UIs() + : Mutex("PluginLV2UIs") { - PluginLV2Client *plugin = gui->plugin; - plugin->init_lv2(); - gui->selected = 0; - gui->update_selected(); - gui->panel->update(); - plugin->send_configure_change(); - return 1; } -PluginLV2ClientText:: -PluginLV2ClientText(PluginLV2ClientWindow *gui, int x, int y, int w) - : BC_TextBox(x, y, w, 1, (char *)"") +PluginLV2UIs::~PluginLV2UIs() { - this->gui = gui; + del_uis(); } -PluginLV2ClientText:: -~PluginLV2ClientText() +void PluginLV2UIs::del_uis() { + while( size() ) remove_object(); } -int PluginLV2ClientText::handle_event() -{ - return 0; -} - - -PluginLV2ClientApply:: -PluginLV2ClientApply(PluginLV2ClientWindow *gui, int x, int y) - : BC_GenericButton(x, y, _("Apply")) +PluginLV2ParentUI *PluginLV2UIs::del_ui(PluginLV2Client *client) { - this->gui = gui; -} - -PluginLV2ClientApply:: -~PluginLV2ClientApply() -{ -} - -int PluginLV2ClientApply::handle_event() -{ - const char *text = gui->text->get_text(); - if( text && gui->selected ) { - gui->selected->update(atof(text)); - gui->update_selected(); - gui->plugin->send_configure_change(); + lock("PluginLV2UIs::del_ui client"); + int i = size(); + while( --i >= 0 && get(i)->client != client ); + PluginLV2ParentUI *ui = 0; + if( i >= 0 ) { + if( (ui=get(i))->gui ) ui->client = 0; + else { remove_object_number(i); ui = 0; } } - return 1; -} - - - -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]) -{ - this->gui = gui; - update(); // init col/wid/columns -} - -PluginLV2Client_OptPanel:: -~PluginLV2Client_OptPanel() -{ -} - -int PluginLV2Client_OptPanel::selection_changed() -{ - PluginLV2Client_Opt *opt = 0; - BC_ListBoxItem *item = get_selection(0, 0); - if( item ) { - PluginLV2Client_OptName *opt_name = (PluginLV2Client_OptName *)item; - opt = opt_name->opt; - } - gui->update(opt); - return 1; -} - -void PluginLV2Client_OptPanel::update() -{ - opts.remove_all(); - vals.remove_all(); - PluginLV2ClientConfig &conf = gui->plugin->config; - for( int i=0; iitem_name); - vals.append(opt->item_value); + unlock(); + return ui; +} +PluginLV2ParentUI *PluginLV2UIs::del_ui(PluginLV2ClientWindow *gui) +{ + lock("PluginLV2UIs::del_ui gui"); + int i = size(); + while( --i >= 0 && get(i)->gui != gui ); + PluginLV2ParentUI *ui = 0; + if( i >= 0 ) { + if( (ui=get(i))->client ) ui->gui = 0; + else { remove_object_number(i); ui = 0; } } - const char *cols[] = { "option", "value", }; - const int col1_w = 150; - int wids[] = { col1_w, get_w()-col1_w }; - BC_ListBox::update(&items[0], &cols[0], &wids[0], sizeof(items)/sizeof(items[0])); + unlock(); + return ui; } -PluginLV2ClientWindow::PluginLV2ClientWindow(PluginLV2Client *plugin) - : PluginClientWindow(plugin, 500, 300, 500, 300, 1) +PluginLV2ParentUI *PluginLV2UIs::add_ui(PluginLV2ParentUI *ui, PluginLV2Client *client) { - this->plugin = plugin; - selected = 0; + ui->start_child(); + ui->start_parent(client); + append(ui); + return ui; } -PluginLV2ClientWindow::~PluginLV2ClientWindow() +PluginLV2ParentUI *PluginLV2UIs::search_ui(Plugin *plugin) { -} - + int64_t position = plugin->startproject; + PluginSet *plugin_set = plugin->plugin_set; + int set_no = plugin_set->get_number(); + int track_no = plugin_set->track->number_of(); -void PluginLV2ClientWindow::create_objects() -{ - BC_Title *title; - 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, "")); - 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; - add_subwindow(apply = new PluginLV2ClientApply(this, x1, y)); - add_subwindow(text = new PluginLV2ClientText(this, x, y, x1-x - 8)); - y += title->get_h() + 10; - add_subwindow(pot = new PluginLV2ClientPot(this, x, y)); - x1 = x + pot->get_w() + 10; - add_subwindow(slider = new PluginLV2ClientSlider(this, x1, y+10)); - 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 panel_h = get_h()-10 - panel_y; - panel = new PluginLV2Client_OptPanel(this, panel_x, panel_y, panel_w, panel_h); - add_subwindow(panel); - panel->update(); - show_window(1); -} - -int PluginLV2ClientWindow::resize_event(int w, int h) -{ - 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()); - text->reposition_window(text->get_x(), text->get_y(), x1-text->get_x() - 8); - x1 = pot->get_x() + pot->get_w() + 10; - int w1 = w - slider->get_x() - 20; - slider->set_pointer_motion_range(w1); - slider->reposition_window(x1, slider->get_y(), w1, slider->get_h()); - int panel_x = panel->get_x(), panel_y = panel->get_y(); - panel->reposition_window(panel_x, panel_y, w-10-panel_x, h-10-panel_y); - return 1; + PluginLV2ParentUI *ui = 0; + for( int i=size(); !ui && --i>=0; ) { + PluginLV2ParentUI *parent_ui = get(i); + if( parent_ui->position != position ) continue; + if( parent_ui->set_no != set_no ) continue; + if( parent_ui->track_no == track_no ) ui = parent_ui; + } + return ui; } -PluginLV2ClientPot::PluginLV2ClientPot(PluginLV2ClientWindow *gui, int x, int y) - : BC_FPot(x, y, 0.f, 0.f, 0.f) +PluginLV2ParentUI *PluginLV2UIs::find_ui(Plugin *plugin) { - this->gui = gui; + if( !plugin ) return 0; + lock("PluginLV2UIs::find_ui"); + PluginLV2ParentUI *ui = search_ui(plugin); + unlock(); + return ui; } - -int PluginLV2ClientPot::handle_event() +PluginLV2ParentUI *PluginLV2Client::find_ui() { - if( gui->selected ) { - gui->selected->update(get_value()); - gui->update_selected(); - gui->plugin->send_configure_change(); - } - return 1; + return PluginLV2ParentUI::plugin_lv2.find_ui(server->plugin); } - -PluginLV2ClientSlider::PluginLV2ClientSlider(PluginLV2ClientWindow *gui, int x, int y) - : BC_FSlider(x, y, 0, gui->get_w()-x-20, gui->get_w()-x-20, 0.f, 0.f, 0.f) +PluginLV2ParentUI *PluginLV2ClientWindow::find_ui() { - this->gui = gui; + return PluginLV2ParentUI::plugin_lv2.find_ui(client->server->plugin); } -int PluginLV2ClientSlider::handle_event() +PluginLV2ParentUI *PluginLV2UIs::get_ui(PluginLV2Client *client) { - if( gui->selected ) { - gui->selected->update(get_value()); - gui->update_selected(); - gui->plugin->send_configure_change(); - } - return 1; + lock("PluginLV2UIs::get_ui"); + Plugin *plugin = client->server->plugin; + PluginLV2ParentUI *ui = search_ui(plugin); + if( !ui ) ui = add_ui(new PluginLV2ParentUI(plugin), client); + unlock(); + return ui; } - -void PluginLV2ClientWindow::update_selected() +PluginLV2ParentUI *PluginLV2Client::get_ui() { - 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)); - } + PluginLV2ParentUI *ui = PluginLV2ParentUI::plugin_lv2.get_ui(this); + ui->client = this; + return ui; } - -int PluginLV2ClientWindow::scalar(float f, char *rp) +PluginLV2ParentUI *PluginLV2ClientWindow::get_ui() { - const char *cp = 0; - if( f == FLT_MAX ) cp = "FLT_MAX"; - else if( f == FLT_MIN ) cp = "FLT_MIN"; - else if( f == -FLT_MAX ) cp = "-FLT_MAX"; - else if( f == -FLT_MIN ) cp = "-FLT_MIN"; - else if( f == 0 ) cp = signbit(f) ? "-0" : "0"; - else if( isnan(f) ) cp = signbit(f) ? "-NAN" : "NAN"; - else if( isinf(f) ) cp = signbit(f) ? "-INF" : "INF"; - else return sprintf(rp, "%g", f); - return sprintf(rp, "%s", cp); -} - -void PluginLV2ClientWindow::update(PluginLV2Client_Opt *opt) -{ - if( selected != opt ) { - if( selected ) selected->item_name->set_selected(0); - selected = opt; - if( selected ) selected->item_name->set_selected(1); - } - char var[BCSTRLEN]; var[0] = 0; - char val[BCSTRLEN]; val[0] = 0; - char rng[BCTEXTLEN]; rng[0] = 0; - if( opt ) { - sprintf(var,"%s:", opt->conf->names[opt->idx]); - char *cp = rng; - cp += sprintf(cp,"( "); - float min = opt->conf->mins[opt->idx]; - cp += scalar(min, cp); - cp += sprintf(cp, " .. "); - float max = opt->conf->maxs[opt->idx]; - cp += scalar(max, cp); - cp += sprintf(cp, " )"); - float v = opt->get_value(); - sprintf(val, "%f", v); - slider->update(slider->get_w(), v, min, max); - pot->update(v, min, max); - } - else { - slider->update(slider->get_w(), 0.f, 0.f, 0.f); - pot->update(0.f, 0.f, 0.f); - } - varbl->update(var); - range->update(rng); - text->update(val); - panel->update(); + PluginLV2ParentUI *ui = PluginLV2ParentUI::plugin_lv2.get_ui(client); + ui->gui = this; + return ui; } PluginLV2Client::PluginLV2Client(PluginServer *server) - : PluginAClient(server) -{ - in_buffers = 0; - out_buffers = 0; - nb_in_bfrs = 0; - nb_out_bfrs = 0; - bfrsz = 0; - nb_inputs = 0; - nb_outputs = 0; - max_bufsz = 0; - - world = 0; - instance = 0; - lv2_InputPort = 0; - lv2_OutputPort = 0; - lv2_AudioPort = 0; - lv2_CVPort = 0; - lv2_ControlPort = 0; - lv2_Optional = 0; - atom_AtomPort = 0; - atom_Sequence = 0; - powerOf2BlockLength = 0; - fixedBlockLength = 0; - boundedBlockLength = 0; - seq_out = 0; - parent_gui = 0; + : PluginAClient(server), PluginLV2() +{ + title[0] = 0; } PluginLV2Client::~PluginLV2Client() { - reset_lv2(); - lilv_world_free(world); + PluginLV2ParentUI::plugin_lv2.del_ui(this); } -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(atom_Sequence); atom_Sequence = 0; - lilv_node_free(atom_AtomPort); atom_AtomPort = 0; - lilv_node_free(lv2_Optional); lv2_Optional = 0; - lilv_node_free(lv2_ControlPort); lv2_ControlPort = 0; - lilv_node_free(lv2_AudioPort); lv2_AudioPort = 0; - lilv_node_free(lv2_CVPort); lv2_CVPort = 0; - lilv_node_free(lv2_OutputPort); lv2_OutputPort = 0; - lilv_node_free(lv2_InputPort); lv2_InputPort = 0; - delete [] (char *)seq_out; seq_out = 0; - uri_table.remove_all_objects(); - delete_buffers(); - nb_inputs = 0; - nb_outputs = 0; - max_bufsz = 0; - config.reset(); - config.remove_all_objects(); -} - -int PluginLV2Client::load_lv2(const char *path) -{ - if( !world ) { - world = lilv_world_new(); - if( !world ) { - printf("lv2: lilv_world_new failed"); - return 1; - } - lilv_world_load_all(world); - } - - LilvNode *uri = lilv_new_uri(world, path); - if( !uri ) { - printf("lv2: 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: 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); - return 0; -} +NEW_WINDOW_MACRO(PluginLV2Client, PluginLV2ClientWindow) int PluginLV2Client::init_lv2() { - reset_lv2(); - - lv2_InputPort = lilv_new_uri(world, LV2_CORE__InputPort); - lv2_OutputPort = lilv_new_uri(world, LV2_CORE__OutputPort); - lv2_AudioPort = lilv_new_uri(world, LV2_CORE__AudioPort); - lv2_ControlPort = lilv_new_uri(world, LV2_CORE__ControlPort); - lv2_CVPort = lilv_new_uri(world, LV2_CORE__CVPort); - 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); - 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); - seq_out = (LV2_Atom_Sequence *) new char[sizeof(LV2_Atom_Sequence) + LV2_SEQ_SIZE]; - - config.init_lv2(lilv); - nb_inputs = nb_outputs = 0; - - for( int i=0; ititle); - return 1; - } - lilv_instance_activate(instance); -// not sure what to do with these - max_bufsz = nb_inputs && - (lilv_plugin_has_feature(lilv, powerOf2BlockLength) || - lilv_plugin_has_feature(lilv, fixedBlockLength) || - lilv_plugin_has_feature(lilv, boundedBlockLength)) ? 4096 : 0; - return 0; -} - -LV2_URID PluginLV2Client::uri_table_map(LV2_URID_Map_Handle handle, const char *uri) -{ - return ((PluginLV2UriTable *)handle)->map(uri); + int sample_rate = get_project_samplerate(); + return PluginLV2::init_lv2(config, sample_rate); } -const char *PluginLV2Client::uri_table_unmap(LV2_URID_Map_Handle handle, LV2_URID urid) -{ - return ((PluginLV2UriTable *)handle)->unmap(urid); -} - -NEW_WINDOW_MACRO(PluginLV2Client, PluginLV2ClientWindow) - int PluginLV2Client::load_configuration() { int64_t src_position = get_source_position(); @@ -522,34 +195,9 @@ void PluginLV2Client::update_gui() 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(); + PluginLV2ParentUI *ui = find_ui(); + if( !ui ) return; + ui->send_child(LV2_UPDATE, config.ctls, sizeof(float)*config.nb_ports); } @@ -598,141 +246,65 @@ void PluginLV2Client::read_data(KeyFrame *keyframe) } } -void PluginLV2Client::connect_ports() +void PluginLV2Client::load_buffer(int samples, Samples **input, int ich) { - int ich = 0, och = 0; - for( int i=0; iget_data(); + float *ip = in_buffers[i]; + for( int j=samples; --j>=0; *ip++=*inp++ ); } - - seq_in[0].atom.size = sizeof(LV2_Atom_Sequence_Body); - seq_in[0].atom.type = uri_table.map(LV2_ATOM__Sequence); - seq_in[1].atom.size = 0; - seq_in[1].atom.type = 0; - seq_out->atom.size = LV2_SEQ_SIZE; - seq_out->atom.type = uri_table.map(LV2_ATOM__Chunk); + for( int i=0; iget_data(); + float *op = out_buffers[i]; + for( int j=samples; --j>=0; *outp++=*op++ ); } + return samples; } -void PluginLV2Client::delete_buffers() +void PluginLV2Client::process_buffer(int size) { - if( in_buffers ) { - for( int i=0; idone ) return 0; - delete parent_gui; - } - parent_gui = new PluginLV2ParentGUI(gui); - parent_gui->start_child(); - parent_gui->start_parent(); - return 1; -#else - return 0; -#endif + PluginLV2ParentUI *ui = get_ui(); + if( !ui ) return; + shm_bfr->done = 0; + ui->send_child(LV2_SHMID, &shmid, sizeof(shmid)); +// timeout 10*duration, min 2sec, max 10sec + double sample_rate = get_project_samplerate(); + double t = !sample_rate ? 2. : 10. * size / sample_rate; + bclamp(t, 2., 10.); + ui->output_bfr->timed_lock(t*1e6, "PluginLV2Client::process_buffer"); + if( !shm_bfr->done ) + eprintf("timeout: %s",server->title); } int PluginLV2Client::process_realtime(int64_t size, Samples *input_ptr, Samples *output_ptr) { - init_plugin(size); - - for( int i=0; iget_data(); - float *ip = in_buffers[i]; - for( int j=size; --j>=0; *ip++=*inp++ ); - } - for( int i=0; iget_data(); - float *op = out_buffers[0]; - for( int i=size; --i>=0; *outp++=*op++ ); - return size; + load_configuration(); + init_buffer(size); + load_buffer(size, &input_ptr, 1); + process_buffer(size); + return unload_buffer(size, &output_ptr, 1); } int PluginLV2Client::process_realtime(int64_t size, Samples **input_ptr, Samples **output_ptr) { - init_plugin(size); - - for( int i=0; iget_data(); - float *ip = in_buffers[i]; - for( int j=size; --j>=0; *ip++=*inp++ ); - } - for( int i=0; iget_data(); - float *op = out_buffers[i]; - for( int j=size; --j>=0; *outp++=*op++ ); - } - return size; + load_configuration(); + init_buffer(size); + load_buffer(size, input_ptr, PluginClient::total_in_buffers); + process_buffer(size); + return unload_buffer(size, output_ptr, PluginClient::total_out_buffers); } + PluginServer* MWindow::new_lv2_server(MWindow *mwindow, const char *name) { return new PluginServer(mwindow, name, PLUGIN_TYPE_LV2); @@ -741,11 +313,8 @@ PluginServer* MWindow::new_lv2_server(MWindow *mwindow, const char *name) PluginClient *PluginServer::new_lv2_plugin() { PluginLV2Client *client = new PluginLV2Client(this); -//for some lv2 clients - if( client->sample_rate < 64 ) client->sample_rate = 64; - if( client->project_sample_rate < 64 ) client->project_sample_rate = 64; - if( client->load_lv2(path) ) { delete client; client = 0; } - else client->init_lv2(); + if( client->load_lv2(path, client->title) ) { delete client; return client = 0; } + client->init_lv2(); return client; } @@ -771,48 +340,68 @@ int MWindow::init_lv2_index(MWindow *mwindow, Preferences *preferences, FILE *fp return 0; } -ForkChild *PluginLV2ParentGUI::new_fork() +PluginLV2ParentUI::PluginLV2ParentUI(Plugin *plugin) { -#ifdef HAVE_LV2UI - return new PluginLV2ChildGUI(); -#else - return 0; -#endif -} + this->position = plugin->startproject; + PluginSet *plugin_set = plugin->plugin_set; + if( plugin_set ) { + this->set_no = plugin_set->get_number(); + this->track_no = plugin_set->track->number_of(); + } + else + this->track_no = this->set_no = -1; -PluginLV2ParentGUI::PluginLV2ParentGUI(PluginLV2ClientWindow *gui) -{ - this->gui = gui; + output_bfr = new Condition(0, "PluginLV2ParentUI::output_bfr", 1); + client = 0; + gui = 0; + hidden = 1; } -PluginLV2ParentGUI::~PluginLV2ParentGUI() +PluginLV2ParentUI::~PluginLV2ParentUI() { stop(); + delete output_bfr; } -void PluginLV2ParentGUI::start_parent() +void PluginLV2ParentUI::start_parent(PluginLV2Client *client) { 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); + const char *path = client->server->path; + int len = sizeof(open_bfr_t) + strlen(path); + char bfr[len]; memset(bfr, 0, len); + open_bfr_t *open_bfr = (open_bfr_t *)bfr; + open_bfr->sample_rate = client->get_project_samplerate(); + strcpy(open_bfr->path, path); + send_child(LV2_OPEN, open_bfr, len); + PluginLV2ClientConfig &conf = client->config; send_child(LV2_LOAD, conf.ctls, conf.nb_ports*sizeof(float)); } -int PluginLV2ParentGUI::handle_parent() +int PluginLV2ParentUI::handle_parent() { int result = 1; switch( parent_token ) { - case LV2_UPDATE: - gui->plugin->lv2_update((float *)parent_data); - break; + case LV2_UPDATE: { + if( !gui ) break; + gui->lv2_update((float *)parent_data); + break; } + case LV2_HIDE: { + hidden = 1; + break; } + case LV2_SHOW: { + hidden = 0; + break; } case LV2_SET: { - control_t *ctl = (control_t *)parent_data; - gui->plugin->lv2_set(ctl->idx, ctl->value); + if( !gui ) break; + control_bfr_t *ctl = (control_bfr_t *)parent_data; + gui->lv2_set(ctl->idx, ctl->value); + break; } + case LV2_SHMID: { + output_bfr->unlock(); break; } case EXIT_CODE: { + output_bfr->unlock(); result = -1; break; } default: @@ -823,12 +412,35 @@ int PluginLV2ParentGUI::handle_parent() return result; } +int PluginLV2ParentUI::show() +{ + if( !hidden ) return 1; + send_child(LV2_SHOW, 0, 0); + return 0; +} + +int PluginLV2ParentUI::hide() +{ + if( hidden ) return 1; + send_child(LV2_HIDE, 0, 0); + return 0; +} + + // stub in parent -int PluginLV2ChildGUI::handle_child() +int PluginLV2ChildUI::handle_child() { return 0; } +void PluginLV2UI::reset_gui() {} + +ForkChild *PluginLV2ParentUI::new_fork() { +#ifdef HAVE_LV2UI + return new PluginLV2ChildUI(); +#else return 0; +#endif } + #else #include "mwindow.h" #include "pluginserver.h" diff --git a/cinelerra-5.1/cinelerra/pluginlv2client.h b/cinelerra-5.1/cinelerra/pluginlv2client.h index 5100a712..da703e8e 100644 --- a/cinelerra-5.1/cinelerra/pluginlv2client.h +++ b/cinelerra-5.1/cinelerra/pluginlv2client.h @@ -1,130 +1,59 @@ +#ifndef __PLUGINLV2CLIENT_H__ +#define __PLUGINLV2CLIENT_H__ -/* - * CINELERRA - * Copyright (C) 2008 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 PLUGINLV2CLIENT_H -#define PLUGINLV2CLIENT_H - +#include "condition.inc" +#include "mutex.h" #include "pluginaclient.h" +#include "plugin.inc" +#include "pluginlv2.h" #include "pluginlv2config.h" #include "pluginlv2client.inc" #include "pluginlv2gui.h" +#include "pluginlv2ui.inc" #include "samples.inc" -#define LV2_SEQ_SIZE 9624 - -class PluginLV2Client_OptPanel : public BC_ListBox +class PluginLV2UIs : public ArrayList, public Mutex { public: - PluginLV2Client_OptPanel(PluginLV2ClientWindow *gui, int x, int y, int w, int h); - ~PluginLV2Client_OptPanel(); + PluginLV2UIs(); + ~PluginLV2UIs(); - PluginLV2ClientWindow *gui; - ArrayList items[2]; - ArrayList &opts; - ArrayList &vals; + void del_uis(); + PluginLV2ParentUI *del_ui(PluginLV2Client *client); + PluginLV2ParentUI *del_ui(PluginLV2ClientWindow *gui); + PluginLV2ParentUI *add_ui(PluginLV2ParentUI *ui, PluginLV2Client *client); + PluginLV2ParentUI *search_ui(Plugin *plugin); + PluginLV2ParentUI *find_ui(Plugin *plugin); + PluginLV2ParentUI *get_ui(PluginLV2Client *client); - int selection_changed(); - void update(); }; -class PluginLV2ClientText : public BC_TextBox { -public: - PluginLV2ClientWindow *gui; - - PluginLV2ClientText(PluginLV2ClientWindow *gui, int x, int y, int w); - ~PluginLV2ClientText(); - int handle_event(); -}; - -class PluginLV2ClientReset : public BC_GenericButton +class PluginLV2ParentUI : public ForkParent { public: + PluginLV2ParentUI(Plugin *plugin); + ~PluginLV2ParentUI(); + ForkChild* new_fork(); + void start_parent(PluginLV2Client *client); + int handle_parent(); + + Condition *output_bfr; + PluginLV2Client *client; PluginLV2ClientWindow *gui; - PluginLV2ClientReset(PluginLV2ClientWindow *gui, int x, int y); - ~PluginLV2ClientReset(); - int handle_event(); -}; + int hidden; + int show(); + int hide(); -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; +//from Plugin::identitical_location + int64_t position; + int set_no; + int track_no; - PluginLV2ClientApply(PluginLV2ClientWindow *gui, int x, int y); - ~PluginLV2ClientApply(); - int handle_event(); + static PluginLV2UIs plugin_lv2; }; -class PluginLV2ClientPot : public BC_FPot -{ -public: - PluginLV2ClientPot(PluginLV2ClientWindow *gui, int x, int y); - int handle_event(); - PluginLV2ClientWindow *gui; -}; - -class PluginLV2ClientSlider : public BC_FSlider -{ -public: - PluginLV2ClientSlider(PluginLV2ClientWindow *gui, int x, int y); - int handle_event(); - PluginLV2ClientWindow *gui; -}; - -class PluginLV2ClientWindow : public PluginClientWindow -{ -public: - PluginLV2ClientWindow(PluginLV2Client *plugin); - ~PluginLV2ClientWindow(); - - void create_objects(); - int resize_event(int w, int h); - void update_selected(); - void update_selected(float v); - int scalar(float f, char *rp); - void update(PluginLV2Client_Opt *opt); - - PluginLV2Client *plugin; - PluginLV2ClientUI *ui; - PluginLV2ClientReset *reset; - PluginLV2ClientApply *apply; - PluginLV2ClientPot *pot; - PluginLV2ClientSlider *slider; - PluginLV2ClientText *text; - BC_Title *varbl, *range; - PluginLV2Client_OptPanel *panel; - PluginLV2Client_Opt *selected; -}; - - -class PluginLV2Client : public PluginAClient +class PluginLV2Client : public PluginAClient, public PluginLV2 { public: PluginLV2Client(PluginServer *server); @@ -144,56 +73,17 @@ public: char* to_string(char *string, const char *input); void save_data(KeyFrame *keyframe); void read_data(KeyFrame *keyframe); - void reset_lv2(); - int load_lv2(const char *path); - int init_lv2(); - int open_lv2_gui(PluginLV2ClientWindow *gui); + void load_buffer(int samples, Samples **input, int ich); + int unload_buffer(int samples, Samples **output, int och); + void process_buffer(int size); void update_gui(); void update_lv2(); - void lv2_update(); - void lv2_update(float *vals); - void lv2_set(int idx, float val); + int init_lv2(); + PluginLV2ParentUI *find_ui(); + PluginLV2ParentUI *get_ui(); PLUGIN_CLASS_MEMBERS(PluginLV2ClientConfig) char title[BCSTRLEN]; - int bfrsz, nb_in_bfrs, nb_out_bfrs; - float **in_buffers, **out_buffers; - - void delete_buffers(); - void init_plugin(int size); - void connect_ports(); - 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); - -// lv2 - LilvWorld *world; - const LilvPlugin *lilv; - int nb_inputs, nb_outputs; - int max_bufsz; - - PluginLV2UriTable uri_table; - LV2_URID_Map map; - LV2_Feature map_feature; - LV2_URID_Unmap unmap; - LV2_Feature unmap_feature; - Lv2Features features; - LV2_Atom_Sequence seq_in[2]; - LV2_Atom_Sequence *seq_out; - - LilvInstance *instance; - LilvNode *atom_AtomPort; - LilvNode *atom_Sequence; - LilvNode *lv2_AudioPort; - LilvNode *lv2_CVPort; - LilvNode *lv2_ControlPort; - LilvNode *lv2_Optional; - LilvNode *lv2_InputPort; - LilvNode *lv2_OutputPort; - 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 4950519c..5b85e82a 100644 --- a/cinelerra-5.1/cinelerra/pluginlv2client.inc +++ b/cinelerra-5.1/cinelerra/pluginlv2client.inc @@ -19,16 +19,11 @@ * */ -#ifndef PLUGINLV2CLIENT_INC -#define PLUGINLV2CLIENT_INC +#ifndef __PLUGINLV2CLIENT_INC__ +#define __PLUGINLV2CLIENT_INC__ -class PluginLV2Client_OptPanel; -class PluginLV2ClientText; -class PluginLV2ClientReset; -class PluginLV2ClientApply; -class PluginLV2ClientPot; -class PluginLV2ClientSlider; -class PluginLV2ClientWindow; +class PluginLV2UIs; +class PluginLV2ParentUI; class PluginLV2Client; #endif diff --git a/cinelerra-5.1/cinelerra/pluginlv2config.C b/cinelerra-5.1/cinelerra/pluginlv2config.C index 776f9d67..66c9a498 100644 --- a/cinelerra-5.1/cinelerra/pluginlv2config.C +++ b/cinelerra-5.1/cinelerra/pluginlv2config.C @@ -29,6 +29,7 @@ #include PluginLV2UriTable::PluginLV2UriTable() + : Mutex("PluginLV2UriTable::PluginLV2UriTable") { set_array_delete(); } @@ -40,18 +41,21 @@ PluginLV2UriTable::~PluginLV2UriTable() LV2_URID PluginLV2UriTable::map(const char *uri) { - mLock locker(uri_table_lock); - for( int i=0; i= n ) append(cstrdup(uri)); + unlock(); + return i+1; } const char *PluginLV2UriTable::unmap(LV2_URID urid) { - mLock locker(uri_table_lock); + lock("PluginLV2UriTable::unmap"); int idx = urid - 1; - return idx>=0 && idx=0 && idx +class PluginLV2UriTable : public ArrayList, public Mutex { - Mutex uri_table_lock; public: PluginLV2UriTable(); ~PluginLV2UriTable(); diff --git a/cinelerra-5.1/cinelerra/pluginlv2gui.C b/cinelerra-5.1/cinelerra/pluginlv2gui.C index baa03f19..9e17f9cd 100644 --- a/cinelerra-5.1/cinelerra/pluginlv2gui.C +++ b/cinelerra-5.1/cinelerra/pluginlv2gui.C @@ -1,306 +1,355 @@ -#ifdef HAVE_LV2UI -#include "file.h" +/* + * 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 "clip.h" +#include "cstrdup.h" +#include "bchash.h" +#include "filexml.h" #include "language.h" +#include "mwindow.h" +#include "pluginlv2client.h" +#include "pluginlv2config.h" #include "pluginlv2gui.h" +#include "pluginserver.h" +#include "samples.h" #include #include -PluginLV2ChildGUI::PluginLV2ChildGUI() +PluginLV2ClientUI::PluginLV2ClientUI(PluginLV2ClientWindow *gui, int x, int y) + : BC_GenericButton(x, y, _("UI")) { - lv2_gui = 0; + this->gui = gui; } -PluginLV2ChildGUI::~PluginLV2ChildGUI() +PluginLV2ClientUI::~PluginLV2ClientUI() { - delete lv2_gui; } -void PluginLV2ChildGUI::run() +int PluginLV2ClientUI::handle_event() { - 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); + PluginLV2ParentUI *ui = gui->get_ui(); + if( ui->show() ) + flicker(8, 64); + return 1; } +PluginLV2ClientReset:: +PluginLV2ClientReset(PluginLV2ClientWindow *gui, int x, int y) + : BC_GenericButton(x, y, _("Reset")) +{ + this->gui = gui; +} -#define NS_EXT "http://lv2plug.in/ns/ext/" - -PluginLV2GUI::PluginLV2GUI() +PluginLV2ClientReset:: +~PluginLV2ClientReset() { - 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 () +int PluginLV2ClientReset::handle_event() { - reset_gui(); - if( world ) lilv_world_free(world); + PluginLV2Client *client = gui->client; + client->config.init_lv2(client->lilv); + client->config.update(); + client->update_lv2(); + gui->update(0); + client->send_configure_change(); + return 1; } -void PluginLV2GUI::reset_gui() +PluginLV2ClientText::PluginLV2ClientText(PluginLV2ClientWindow *gui, int x, int y, int w) + : BC_TextBox(x, y, w, 1, (char *)"") { - 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(); + this->gui = gui; } -int PluginLV2GUI::init_gui(const char *path) +PluginLV2ClientText::~PluginLV2ClientText() { - 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; - } +int PluginLV2ClientText::handle_event() +{ + return 0; +} - 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); +PluginLV2ClientApply::PluginLV2ClientApply(PluginLV2ClientWindow *gui, int x, int y) + : BC_GenericButton(x, y, _("Apply")) +{ + this->gui = gui; +} - lv2_InputPort = lilv_new_uri(world, LV2_CORE__InputPort); - lv2_ControlPort = lilv_new_uri(world, LV2_CORE__ControlPort); +PluginLV2ClientApply::~PluginLV2ClientApply() +{ +} - for( int i=0; itext->get_text(); + if( text && gui->selected ) { + gui->selected->update(atof(text)); + gui->update_selected(); + gui->client->send_configure_change(); } + return 1; +} - 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); +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]) +{ + this->gui = gui; + update(); // init col/wid/columns +} + +PluginLV2Client_OptPanel::~PluginLV2Client_OptPanel() +{ +} + +int PluginLV2Client_OptPanel::selection_changed() +{ + PluginLV2Client_Opt *opt = 0; + BC_ListBoxItem *item = get_selection(0, 0); + if( item ) { + PluginLV2Client_OptName *opt_name = (PluginLV2Client_OptName *)item; + opt = opt_name->opt; } - if( !ui ) - ui = lilv_uis_get(uis, lilv_uis_begin(uis)); - if( !ui ) { - printf("lv2_gui: init_ui failed: %s\n", title); - return 1; + gui->update(opt); + return 1; +} + +void PluginLV2Client_OptPanel::update() +{ + opts.remove_all(); + vals.remove_all(); + PluginLV2ClientConfig &conf = gui->client->config; + for( int i=0; iitem_name); + vals.append(opt->item_value); } + const char *cols[] = { "option", "value", }; + const int col1_w = 150; + int wids[] = { col1_w, get_w()-col1_w }; + BC_ListBox::update(&items[0], &cols[0], &wids[0], sizeof(items)/sizeof(items[0])); +} - lilv_instance_activate(inst); - return 0; +PluginLV2ClientPot::PluginLV2ClientPot(PluginLV2ClientWindow *gui, int x, int y) + : BC_FPot(x, y, 0.f, 0.f, 0.f) +{ + this->gui = gui; } -void PluginLV2GUI::update_value(int idx, uint32_t bfrsz, uint32_t typ, const void *bfr) +int PluginLV2ClientPot::handle_event() { - 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; - } + if( gui->selected ) { + gui->selected->update(get_value()); + gui->update_selected(); + gui->client->send_configure_change(); } + return 1; } -void PluginLV2GUI::write_from_ui(void *the, uint32_t idx, - uint32_t bfrsz, uint32_t typ, const void *bfr) + +PluginLV2ClientSlider::PluginLV2ClientSlider(PluginLV2ClientWindow *gui, int x, int y) + : BC_FSlider(x, y, 0, gui->get_w()-x-20, gui->get_w()-x-20, 0.f, 0.f, 0.f) { - ((PluginLV2GUI*)the)->update_value(idx, bfrsz, typ, bfr); + this->gui = gui; } - -uint32_t PluginLV2GUI::port_index(void* obj, const char* sym) +int PluginLV2ClientSlider::handle_event() { - PluginLV2GUI *the = (PluginLV2GUI*)obj; - for( int i=0, sz=the->config.size(); iconfig[i]; - if( !strcmp(sym, opt->sym) ) return opt->idx; + if( gui->selected ) { + gui->selected->update(get_value()); + gui->update_selected(); + gui->client->send_configure_change(); } - return UINT32_MAX; + return 1; } -void PluginLV2GUI::update_control(int idx, uint32_t bfrsz, uint32_t typ, const void *bfr) +PluginLV2ClientWindow::PluginLV2ClientWindow(PluginLV2Client *client) + : PluginClientWindow(client, 500, 300, 500, 300, 1) { - if( !sinst || idx >= config.nb_ports ) return; - suil_instance_port_event(sinst, idx, bfrsz, typ, bfr); + this->client = client; + selected = 0; } +void PluginLV2ClientWindow::done_event(int result) +{ + PluginLV2ParentUI *ui = PluginLV2ParentUI::plugin_lv2.del_ui(this); + if( ui ) ui->hide(); +} -#if 0 -void PluginLV2GUI::touch(void *obj, uint32_t pidx, bool grabbed) +PluginLV2ClientWindow::~PluginLV2ClientWindow() { - 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); + done_event(0); } + + +void PluginLV2ClientWindow::create_objects() +{ + BC_Title *title; + int x = 10, y = 10, x1; + add_subwindow(title = new BC_Title(x, y, client->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, "")); + 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; + add_subwindow(apply = new PluginLV2ClientApply(this, x1, y)); + add_subwindow(text = new PluginLV2ClientText(this, x, y, x1-x - 8)); + y += title->get_h() + 10; + add_subwindow(pot = new PluginLV2ClientPot(this, x, y)); + x1 = x + pot->get_w() + 10; + add_subwindow(slider = new PluginLV2ClientSlider(this, x1, y+10)); + y += pot->get_h() + 10; + + client->init_lv2(); + client->load_configuration(); + client->config.update(); + + int panel_x = x, panel_y = y; + int panel_w = get_w()-10 - panel_x; + int panel_h = get_h()-10 - panel_y; + panel = new PluginLV2Client_OptPanel(this, panel_x, panel_y, panel_w, panel_h); + add_subwindow(panel); + panel->update(); + show_window(1); +} -uint32_t PluginLV2GUI::uri_to_id(LV2_URID_Map_Handle handle, const char *map, const char *uri) +int PluginLV2ClientWindow::resize_event(int w, int h) { - return ((PluginLV2UriTable *)handle)->map(uri); + 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()); + text->reposition_window(text->get_x(), text->get_y(), x1-text->get_x() - 8); + x1 = pot->get_x() + pot->get_w() + 10; + int w1 = w - slider->get_x() - 20; + slider->set_pointer_motion_range(w1); + slider->reposition_window(x1, slider->get_y(), w1, slider->get_h()); + int panel_x = panel->get_x(), panel_y = panel->get_y(); + panel->reposition_window(panel_x, panel_y, w-10-panel_x, h-10-panel_y); + return 1; } -LV2_URID PluginLV2GUI::uri_table_map(LV2_URID_Map_Handle handle, const char *uri) +void PluginLV2ClientWindow::update_selected() { - return ((PluginLV2UriTable *)handle)->map(uri); + update(selected); + if( !selected ) return; + PluginLV2ParentUI *ui = find_ui(); + if( !ui ) return; + control_bfr_t ctl_bfr; + ctl_bfr.idx = selected->idx; + ctl_bfr.value = selected->get_value(); + ui->send_child(LV2_SET, &ctl_bfr, sizeof(ctl_bfr)); } -const char *PluginLV2GUI::uri_table_unmap(LV2_URID_Map_Handle handle, LV2_URID urid) +int PluginLV2ClientWindow::scalar(float f, char *rp) { - return ((PluginLV2UriTable *)handle)->unmap(urid); + const char *cp = 0; + if( f == FLT_MAX ) cp = "FLT_MAX"; + else if( f == FLT_MIN ) cp = "FLT_MIN"; + else if( f == -FLT_MAX ) cp = "-FLT_MAX"; + else if( f == -FLT_MIN ) cp = "-FLT_MIN"; + else if( f == 0 ) cp = signbit(f) ? "-0" : "0"; + else if( isnan(f) ) cp = signbit(f) ? "-NAN" : "NAN"; + else if( isinf(f) ) cp = signbit(f) ? "-INF" : "INF"; + else return sprintf(rp, "%g", f); + return sprintf(rp, "%s", cp); } -void PluginLV2GUI::lv2ui_instantiate(void *parent) +void PluginLV2ClientWindow::update(PluginLV2Client_Opt *opt) { - 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); + if( selected != opt ) { + if( selected ) selected->item_name->set_selected(0); + selected = opt; + if( selected ) selected->item_name->set_selected(1); + } + char var[BCSTRLEN]; var[0] = 0; + char val[BCSTRLEN]; val[0] = 0; + char rng[BCTEXTLEN]; rng[0] = 0; + if( opt ) { + sprintf(var,"%s:", opt->conf->names[opt->idx]); + char *cp = rng; + cp += sprintf(cp,"( "); + float min = opt->conf->mins[opt->idx]; + cp += scalar(min, cp); + cp += sprintf(cp, " .. "); + float max = opt->conf->maxs[opt->idx]; + cp += scalar(max, cp); + cp += sprintf(cp, " )"); + float v = opt->get_value(); + sprintf(val, "%f", v); + slider->update(slider->get_w(), v, min, max); + pot->update(v, min, max); + } + else { + slider->update(slider->get_w(), 0.f, 0.f, 0.f); + pot->update(0.f, 0.f, 0.f); } + varbl->update(var); + range->update(rng); + text->update(val); + panel->update(); +} - 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); +void PluginLV2ClientWindow::lv2_update() +{ + lock_window("PluginLV2ClientWindow::lv2_update"); + PluginLV2ClientConfig &conf = client->config; + int ret = conf.update(); + if( ret > 0 ) update(0); + unlock_window(); + if( ret > 0 ) + client->send_configure_change(); } -bool PluginLV2GUI::lv2ui_resizable() +void PluginLV2ClientWindow::lv2_update(float *vals) { - 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; + PluginLV2ClientConfig &conf = client->config; + int nb_ports = conf.nb_ports; + float *ctls = conf.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; iconfig; + conf[idx]->set_value(val); + lv2_update(); } -#endif /* HAVE_LV2UI */ diff --git a/cinelerra-5.1/cinelerra/pluginlv2gui.h b/cinelerra-5.1/cinelerra/pluginlv2gui.h index eed7143a..a3e6624d 100644 --- a/cinelerra-5.1/cinelerra/pluginlv2gui.h +++ b/cinelerra-5.1/cinelerra/pluginlv2gui.h @@ -1,121 +1,110 @@ +#ifndef __PLUGINLV2GUI_H__ +#define __PLUGINLV2GUI_H__ -/* - * CINELERRA - * Copyright (C) 2008 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 __PLUGINLV2UI_H__ -#define __PLUGINLV2UI_H__ - +#include "guicast.h" #include "forkbase.h" #include "pluginlv2gui.inc" -#include "pluginlv2client.h" +#include "pluginlv2ui.h" +#include "pluginaclient.h" + +class PluginLV2ClientUI : public BC_GenericButton { +public: + PluginLV2ClientWindow *gui; + + PluginLV2ClientUI(PluginLV2ClientWindow *gui, int x, int y); + ~PluginLV2ClientUI(); + int handle_event(); +}; -class PluginLV2GUI +class PluginLV2ClientReset : public BC_GenericButton { 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 + PluginLV2ClientWindow *gui; - char title[BCSTRLEN]; - const char *gtk_type; - uint32_t last, updates; - int done, running; + PluginLV2ClientReset(PluginLV2ClientWindow *gui, int x, int y); + ~PluginLV2ClientReset(); + int handle_event(); +}; - void start(); - void stop(); - int update_lv2(float *vals, int force); - int redraw; +class PluginLV2ClientText : public BC_TextBox { +public: + PluginLV2ClientWindow *gui; - void run_gui(PluginLV2ChildGUI *child=0); + PluginLV2ClientText(PluginLV2ClientWindow *gui, int x, int y, int w); + ~PluginLV2ClientText(); + int handle_event(); }; -enum { NO_COMMAND, - LV2_OPEN, - LV2_LOAD, - LV2_UPDATE, - LV2_START, - LV2_SET, - NB_COMMANDS }; +class PluginLV2ClientApply : public BC_GenericButton { +public: + PluginLV2ClientWindow *gui; -typedef struct { int idx; float value; } control_t; + PluginLV2ClientApply(PluginLV2ClientWindow *gui, int x, int y); + ~PluginLV2ClientApply(); + int handle_event(); +}; -class PluginLV2ParentGUI : public ForkParent +class PluginLV2Client_OptPanel : public BC_ListBox { public: - PluginLV2ParentGUI(PluginLV2ClientWindow *gui); - ~PluginLV2ParentGUI(); - ForkChild* new_fork(); - void start_parent(); + PluginLV2Client_OptPanel(PluginLV2ClientWindow *gui, int x, int y, int w, int h); + ~PluginLV2Client_OptPanel(); + + PluginLV2ClientWindow *gui; + ArrayList items[2]; + ArrayList &opts; + ArrayList &vals; + + int selection_changed(); + void update(); +}; - int handle_parent(); +class PluginLV2ClientPot : public BC_FPot +{ +public: + PluginLV2ClientPot(PluginLV2ClientWindow *gui, int x, int y); + int handle_event(); PluginLV2ClientWindow *gui; }; -class PluginLV2ChildGUI : public ForkChild +class PluginLV2ClientSlider : public BC_FSlider { public: - PluginLV2ChildGUI(); - ~PluginLV2ChildGUI(); + PluginLV2ClientSlider(PluginLV2ClientWindow *gui, int x, int y); + int handle_event(); + PluginLV2ClientWindow *gui; +}; - int handle_child(); - void run(); - int run(int ac, char **av); +class PluginLV2ClientWindow : public PluginClientWindow +{ +public: + PluginLV2ClientWindow(PluginLV2Client *client); + ~PluginLV2ClientWindow(); + void done_event(int result); + + void create_objects(); + int resize_event(int w, int h); + void update_selected(); + void update_selected(float v); + int scalar(float f, char *rp); + void update(PluginLV2Client_Opt *opt); + void lv2_update(); + void lv2_update(float *vals); + void lv2_set(int idx, float val); + PluginLV2ParentUI *find_ui(); + PluginLV2ParentUI *get_ui(); + + PluginLV2Client *client; + PluginLV2ClientUI *ui; + PluginLV2ClientReset *reset; + PluginLV2ClientApply *apply; + PluginLV2ClientPot *pot; + PluginLV2ClientSlider *slider; + PluginLV2ClientText *text; + BC_Title *varbl, *range; + PluginLV2Client_OptPanel *panel; + PluginLV2Client_Opt *selected; - PluginLV2GUI *lv2_gui; -// Command tokens }; #endif diff --git a/cinelerra-5.1/cinelerra/pluginlv2gui.inc b/cinelerra-5.1/cinelerra/pluginlv2gui.inc index 033986c3..f282cc59 100644 --- a/cinelerra-5.1/cinelerra/pluginlv2gui.inc +++ b/cinelerra-5.1/cinelerra/pluginlv2gui.inc @@ -1,8 +1,14 @@ #ifndef __PLUGINLV2GUI_INC__ #define __PLUGINLV2GUI_INC__ -class PluginLV2GUI; -class PluginLV2ParentGUI; -class PluginLV2ChildGUI; +class PluginLV2ClientUI; +class PluginLV2ClientReset; +class PluginLV2ClientText; +class PluginLV2ClientApply; +class PluginLV2Client_OptPanel; +class PluginLV2ClientPot; +class PluginLV2ClientSlider; +class PluginLV2ClientWindow; +class PluginLV2ParentUI; #endif diff --git a/cinelerra-5.1/cinelerra/pluginlv2ui.C b/cinelerra-5.1/cinelerra/pluginlv2ui.C new file mode 100644 index 00000000..904f9549 --- /dev/null +++ b/cinelerra-5.1/cinelerra/pluginlv2ui.C @@ -0,0 +1,310 @@ +#ifdef HAVE_LV2UI + +// shared between parent/child fork +#include "language.h" +#include "pluginlv2ui.h" + +#include +#include + +#include +#include + +int PluginLV2UI::init_ui(const char *path, int sample_rate) +{ + if( load_lv2(path, title) ) return 1; + if( init_lv2(config, sample_rate) ) return 1; + + lilv_uis = lilv_plugin_get_uis(lilv); + if( !lilv_uis ) { + printf("lv2: lilv_plugin_get_uis(%s) failed\n", path); + return 1; + } + + if( gtk_type ) { + LilvNode *gui_type = lilv_new_uri(world, gtk_type); + LILV_FOREACH(uis, i, lilv_uis) { + const LilvUI *ui = lilv_uis_get(lilv_uis, i); + if( lilv_ui_is_supported(ui, suil_ui_supported, gui_type, &lilv_type)) { + lilv_ui = ui; + break; + } + } + lilv_node_free(gui_type); + } + if( !lilv_ui ) + lilv_ui = lilv_uis_get(lilv_uis, lilv_uis_begin(lilv_uis)); + if( !lilv_ui ) { + printf("lv2_gui: init_ui failed: %s\n", title); + return 1; + } + + lilv_instance_activate(inst); + return 0; +} + +void PluginLV2UI::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 PluginLV2UI::write_from_ui(void *the, uint32_t idx, + uint32_t bfrsz, uint32_t typ, const void *bfr) +{ + ((PluginLV2UI*)the)->update_value(idx, bfrsz, typ, bfr); +} + +uint32_t PluginLV2UI::port_index(void* obj, const char* sym) +{ + PluginLV2UI *the = (PluginLV2UI*)obj; + for( int i=0, sz=the->config.size(); iconfig[i]; + if( !strcmp(sym, opt->sym) ) return opt->idx; + } + return UINT32_MAX; +} + +void PluginLV2UI::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 PluginLV2UI::touch(void *obj, uint32_t pidx, bool grabbed) +{ + PluginLV2UI* 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 PluginLV2UI::uri_to_id(LV2_URID_Map_Handle handle, const char *map, const char *uri) +{ + return ((PluginLV2UriTable *)handle)->map(uri); +} + +LV2_URID PluginLV2UI::uri_table_map(LV2_URID_Map_Handle handle, const char *uri) +{ + return ((PluginLV2UriTable *)handle)->map(uri); +} + +const char *PluginLV2UI::uri_table_unmap(LV2_URID_Map_Handle handle, LV2_URID urid) +{ + return ((PluginLV2UriTable *)handle)->unmap(urid); +} + +void PluginLV2UI::lv2ui_instantiate(void *parent) +{ + if ( !ui_host ) { + ui_host = suil_host_new( + PluginLV2UI::write_from_ui, + PluginLV2UI::port_index, + 0, 0); +// suil_host_set_touch_func(ui_host, +// PluginLV2GUI::touch); + } + + features.remove(); // remove terminating zero + ui_features = features.size(); + LV2_Handle lilv_handle = lilv_instance_get_handle(inst); + 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; + features.append(new Lv2Feature(LV2_DATA_ACCESS_URI, ext_data)); + features.append(new Lv2Feature(LV2_UI__parent, parent)); + features.append(new Lv2Feature(LV2_UI__idleInterface, 0)); + features.append(0); // add new terminating zero + + const char* bundle_uri = lilv_node_as_uri(lilv_ui_get_bundle_uri(lilv_ui)); + char* bundle_path = lilv_file_uri_parse(bundle_uri, NULL); + const char* binary_uri = lilv_node_as_uri(lilv_ui_get_binary_uri(lilv_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(lilv_ui)), + lilv_node_as_uri(lilv_type), + bundle_path, binary_path, features); + + lilv_free(binary_path); + lilv_free(bundle_path); +} + +bool PluginLV2UI::lv2ui_resizable() +{ + if( !lilv_ui ) return false; + const LilvNode* s = lilv_ui_get_uri(lilv_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 PluginLV2UI::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; ihidden = 1; + the->top_level = 0; + ++the->updates; +} + +void PluginLV2UI::start_gui() +{ + top_level = gtk_window_new(GTK_WINDOW_TOPLEVEL); + g_signal_connect(top_level, "destroy", G_CALLBACK(lilv_destroy), this); + gtk_window_set_title(GTK_WINDOW(top_level), title); + + GtkWidget *vbox = gtk_vbox_new(FALSE, 0); + gtk_window_set_role(GTK_WINDOW(top_level), "plugin_ui"); + gtk_container_add(GTK_CONTAINER(top_level), 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(top_level), lv2ui_resizable()); + gtk_widget_show_all(vbox); + gtk_widget_grab_focus(widget); + float *ctls = (float *)config.ctls; + update_lv2(ctls, 1); + connect_ports(config, TYP_CONTROL); + lilv_instance_run(inst, 0); + gtk_window_present(GTK_WINDOW(top_level)); +} + + +void PluginLV2UI::host_update(PluginLV2ChildUI *child) +{ +//printf("update\n"); + host_updates = updates; + if( !child ) return; + if( host_hidden != hidden ) { + host_hidden = hidden; + if( hidden ) reset_gui(); + child->send_parent(hidden ? LV2_HIDE : LV2_SHOW, 0, 0); + } + if( running < 0 ) { running = 1; return; } + child->send_parent(LV2_UPDATE, config.ctls, sizeof(float)*config.nb_ports); +} + +void PluginLV2UI::reset_gui() +{ + if( sinst ) { suil_instance_free(sinst); sinst = 0; } + if( ui_host ) { suil_host_free(ui_host); ui_host = 0; } + if( top_level ) { gtk_widget_destroy(top_level); top_level = 0; } + + while( features.size() > ui_features ) features.remove_object(); + features.append(0); + hidden = 1; +} + + +// child main +int PluginLV2UI::run_ui(PluginLV2ChildUI *child) +{ + running = 1; + while( !done ) { + if( gtk_events_pending() ) { + gtk_main_iteration(); + continue; + } + if( running && host_updates != updates ) + host_update(child); + if( redraw ) { + redraw = 0; + update_lv2(config.ctls, 1); + } + if( !child ) usleep(10000); + else if( child->child_iteration() < 0 ) + done = 1; + } + running = 0; + return 0; +} + +void PluginLV2UI::run_buffer(int shmid) +{ + if( !shm_buffer(shmid) ) return; + map_buffer(); + int samples = shm_bfr->samples; + connect_ports(config); + lilv_instance_run(inst, samples); + shm_bfr->done = 1; +} + +int PluginLV2ChildUI::handle_child() +{ + switch( child_token ) { + case LV2_OPEN: { + open_bfr_t *open_bfr = (open_bfr_t *)child_data; + if( init_ui(open_bfr->path, open_bfr->sample_rate) ) exit(1); + break; } + case LV2_LOAD: { + float *ctls = (float *)child_data; + update_lv2(ctls, 1); + break; } + case LV2_UPDATE: { + float *ctls = (float *)child_data; + if( update_lv2(ctls, 0) > 0 ) + ++updates; + break; } + case LV2_SHOW: { + start_gui(); + hidden = 0; ++updates; + break; } + case LV2_HIDE: { + hidden = 1; ++updates; + break; } + case LV2_SET: { + control_bfr_t *ctl_bfr = (control_bfr_t *)child_data; + config.ctls[ctl_bfr->idx] = ctl_bfr->value; + redraw = 1; + break; } + case LV2_SHMID: { + int shmid = *(int *)child_data; + run_buffer(shmid); + send_parent(LV2_SHMID, 0, 0); + break; } + case EXIT_CODE: + return -1; + } + return 1; +} + +#endif /* HAVE_LV2UI */ diff --git a/cinelerra-5.1/cinelerra/pluginlv2ui.h b/cinelerra-5.1/cinelerra/pluginlv2ui.h new file mode 100644 index 00000000..75fe8262 --- /dev/null +++ b/cinelerra-5.1/cinelerra/pluginlv2ui.h @@ -0,0 +1,95 @@ + +/* + * CINELERRA + * Copyright (C) 2008 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 __PLUGINLV2UI_H__ +#define __PLUGINLV2UI_H__ + +#ifdef HAVE_LV2UI + +#include "forkbase.h" +#include "pluginlv2.h" +#include "pluginlv2client.h" +#include "pluginlv2gui.inc" +#include "pluginlv2ui.inc" + +typedef struct _GtkWidget GtkWidget; + +class PluginLV2UI : public PluginLV2 +{ +public: + PluginLV2UI(); + ~PluginLV2UI(); + + const LilvUI *lilv_ui; + const LilvNode *lilv_type; + + LV2_Extension_Data_Feature *ext_data; + PluginLV2UriTable uri_table; + LV2_URI_Map_Feature *uri_map; + LV2_URID_Map map; + LV2_URID_Unmap unmap; + + char title[BCSTRLEN]; + PluginLV2ClientConfig config; + uint32_t host_updates, updates; + int host_hidden, hidden; + int done, running; + const char *gtk_type; + GtkWidget *top_level; + + void reset_gui(); + int init_ui(const char *path, int sample_rate); + void start(); + void stop(); + int update_lv2(float *vals, int force); + int redraw; + + void update_value(int 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 void write_from_ui(void *the, uint32_t 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 start_gui(); + int run_ui(PluginLV2ChildUI *child=0); + void run_buffer(int shmid); + void host_update(PluginLV2ChildUI *child); + int run(int ac, char **av); +}; + +class PluginLV2ChildUI : public ForkChild, public PluginLV2UI +{ +public: + PluginLV2ChildUI(); + ~PluginLV2ChildUI(); + void run(); + + int handle_child(); + int run(int ac, char **av); +}; +#endif +#endif diff --git a/cinelerra-5.1/cinelerra/pluginlv2ui.inc b/cinelerra-5.1/cinelerra/pluginlv2ui.inc new file mode 100644 index 00000000..5b8309bd --- /dev/null +++ b/cinelerra-5.1/cinelerra/pluginlv2ui.inc @@ -0,0 +1,7 @@ +#ifndef __PLUGINLV2UI_INC__ +#define __PLUGINLV2UI_INC__ + +class PluginLV2UI; +class PluginLV2ChildUI; + +#endif diff --git a/cinelerra-5.1/guicast/condition.C b/cinelerra-5.1/guicast/condition.C index 6bd8169e..e57110ca 100644 --- a/cinelerra-5.1/guicast/condition.C +++ b/cinelerra-5.1/guicast/condition.C @@ -92,11 +92,11 @@ int Condition::timed_lock(int microseconds, const char *location) struct timeval now; gettimeofday(&now, 0); #if 1 - struct timespec timeout; - timeout.tv_sec = now.tv_sec + microseconds / 1000000; - timeout.tv_nsec = now.tv_usec * 1000 + (microseconds % 1000000) * 1000; - while(value <= 0 && result != ETIMEDOUT) - { + int64_t nsec = now.tv_usec * 1000 + (microseconds % 1000000) * 1000; + int64_t sec = nsec / 1000000000; nsec %= 1000000000; + sec += now.tv_sec + microseconds / 1000000; + struct timespec timeout; timeout.tv_sec = sec; timeout.tv_nsec = nsec; + while( value <= 0 && result != ETIMEDOUT ) { result = pthread_cond_timedwait(&cond, &mutex, &timeout); } diff --git a/cinelerra-5.1/guicast/mutex.h b/cinelerra-5.1/guicast/mutex.h index ab153add..c61317ee 100644 --- a/cinelerra-5.1/guicast/mutex.h +++ b/cinelerra-5.1/guicast/mutex.h @@ -53,13 +53,4 @@ public: const char *title; }; -class mLock -{ - Mutex &mutex; -public: - mLock(Mutex &m) : mutex(m) { mutex.lock(); } - mLock(Mutex *m) : mutex(*m) { mutex.lock(); } - ~mLock() { mutex.unlock(); } -}; - #endif diff --git a/cinelerra-5.1/picon/cinfinity/ff_entropy.png b/cinelerra-5.1/picon/cinfinity/ff_entropy.png new file mode 100644 index 0000000000000000000000000000000000000000..c1d5b4b9addb7eb09df5d8be65c682ae16dde4e4 GIT binary patch literal 12361 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%0ApJDRr6nT+q!4=KOr1LTQv@XcN5QjuG%~2I)d7;< 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 literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/picon/cinfinity/ff_fillborders.png b/cinelerra-5.1/picon/cinfinity/ff_fillborders.png new file mode 100644 index 0000000000000000000000000000000000000000..2958473142ce0e4a9b680729fd289d1df41f5436 GIT binary patch literal 10317 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 literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/picon/cinfinity/ff_normalize.png b/cinelerra-5.1/picon/cinfinity/ff_normalize.png new file mode 100644 index 0000000000000000000000000000000000000000..fade41fc9e624078c37e79a4066a2b2e94051dbb GIT binary patch literal 9135 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 literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/picon/cinfinity/ff_setrange.png b/cinelerra-5.1/picon/cinfinity/ff_setrange.png new file mode 100644 index 0000000000000000000000000000000000000000..4794bc6b2ce4469e391cde706d2ae649231f23d7 GIT binary patch literal 12628 zcmV-aF{{prP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3;uk{maZh5zFea|G;fY0O0O#aUh)i&wpR{U;ODcc9%=*b=2zllSdwL@=f=jKcBC`=lAdXliK%p z;n&yQ&tF7dN_yw#$7+9FoUEAO5^zVhfzxZ*%q&r7m{$8Mezoz)> z>u!9fG54RQ^ZmaSzrG*(jOH&t=f+~3!u3*g(NajBe|S^+| zynjdhygE}#nSV=4pPRbBF6Phg!f#&x%UXu`dEN2CuWM6(e*MSSL;2^mbZ^Q2bm!22 z-uai;M~VKIKYv=wdrx=w+Gln%SC+1RC-q}0?>pYeBInO)RQ@*pFMQwL-@)JR{Pdd; z9>0mm;`Ru# zsKlRR3Gcq+-EK4e<4@q7F>tZKC!*6o|B1i9z0keN&=7q8xmJuTYQ-6bBBy_O7Xb

vM@!!Z){+N9hGR@y5c}Pwj+uz87GLxOZVNArS#z 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 O0rJwyQgsq0A^!sz?F`!h literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/picon/cinfinity2/ff_entropy.png b/cinelerra-5.1/picon/cinfinity2/ff_entropy.png new file mode 100644 index 0000000000000000000000000000000000000000..b89d9d316b0c9a456b241e7b1cf022e674ce6d47 GIT binary patch literal 11045 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 fu^$}r_5A++P) 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 literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/picon/cinfinity2/ff_normalize.png b/cinelerra-5.1/picon/cinfinity2/ff_normalize.png new file mode 100644 index 0000000000000000000000000000000000000000..e7f1133558a3aab13f3b81100bf78da8adf54023 GIT binary patch literal 6744 zcmV-e8mHxnP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3*db{sjfME|jhUIOM}IT+7*J9x|QYltL8Qe>67 zt4T?jiV@*%Zf*vI+5i84$NY<*)M_*_m6}`5mY>*S^PMl%K0nW=v+@3We?ocfbDy`H z_Z^;1K}SCS&HHtHXM6f}LW!^K-4P5PV=np@z<9y8mXcE#-c< z{Of{yZfd>;^ZlFqVf&X@I{$1pZ1^0T{Qmjvc9*`7rMV&daA#NF@BC?d^e)?vKObUw z&Z_2|{XAWdnb76eL%lu9{lKnBwd zbL9cM9nU33axZKNN8u(qaG*-yfxj#3bpb-ey%U20#nIX9LUP&J;(c+BI9Br0xlr{X z`aud@N`5g))k!8f)$87zQ`|k)C;x1QYDh#1nNq1FsFN%45%?*wf}x&5iYcX>N~)=) zonrIuED4K>zOb1k)++G=mU1vo7=YPHqYTJPMnbLGz2odbFw zeuNQ68hMmaM;mLP;v&~Z#$ur8N`D)}71X;0sXtRbjt>J=e=LToR!w{ECyQD}G`NMVsy?TaUU4-Z3SPhD( zC2vP`eC>1Y8394((Ev;6_SgyP$0{&mIDHi$%$AzNA#sCVwD|T!H}&f*F)s8-)({U z&hyB+HDjIhaW0oP#! z{>-fd$VcD7c+gV)V1sL?#zhrG#9&x7&NfmS%@ylfokVZOlJnx8VHO8lR0cO(XbEtb zT_QJJqqkj`o5fS-^Ar-(U>*wpZ2B&xO6L9C$NS>}W0-lzHMx$0w4-B0UHzjEBGo!~ zEZsH=Uc(%DkpUGv#Sm9Sh&9y#(tvGtjYba2$OY6GFhuAZRXlijTPUiOSM-O=Y<_GG zy`Dr8^4e?-tIw1vUXJTFu2p9)RJ@_Qk$W6DM`PGvZ&!GPdf930mB}R!=t}LYQGop4 zi^vFZQyl=826if9)W<%B@eA<>lmgH5`9QvW19>9z5%h;HGD6bMHrC|WQy05pAr%J_ zg1Jyb53+sODA;>T``f4S58CaDa}g&HqdS4b)5>NWpajYJ9!}iC_~BBF2n5d5ww)_L zBJk}2Jf8Y=#S`!aW6=#(YccM?cpL281J4RRkQ%4g)ytyR;vC#*@w}wY6V_3<_MoxR zpz2o5PpUH^0&juWm``HIJgVE=*0Hq}Q+R|C9Ja=h$aqfSJdMsSIzobLG*I9QD^Y=~ zfTcZP@Yz&=fPwFF1lRp$KKHOuQSbOB){me{6vR& z15XbpAR*zFlM{^MDQ}HvxK6L*NH-fDV)Q~dY1I=-nqUfLAv_K#`qMG1FLH;XK0wlZ z#3lTp4OZC02JK+OYln7O``Q@_4bxQmvE)~!9~KM)-#b$0xi(MN>=Ru3 z`{ymH?w-J!vcj!zx7Fh(at4W9YZgPe1UyUr`BJ*qC5gGse#&uH($n%+8u^e<6bY(s z_nrMH6{!%BOBI<$r)b$5q+(I4CfhYTCnC$RcAde)J&SOK#fiO8p}C<-QlsCX$sndk z2P6?r{oCZO;-gq-H0T)d?LNtF+60}5uRNS?P4lv9Fu<&V57?FS5DKszRS(rJFN;$y z`0Jt>4m23ZTcoji!np=GKoQgAW`^}wDR9?Vo+grX7J($HCUHa6K255jfapnU#1kV* z5?-b$(WD4Sq94-PAwFmi`4td91<6M@w1K!Z19>CZ7&^UEiV+#yLLE<(f#0ui7YyfY zs1G_L!-BD*YcmBuq$SL(12!Z+v}@m~hA5UtmEu}q3+QYov>VNpni<2@*4>75ENnI4 z_A^xTA(|~MMgyhY?L0+{nMcONi5aCQ&!Xeg!ZK3*(AhSg1WGw{3mWba7DOm!sQc>d zopr)VNe&qWPV$p_P;1ck9JDHi)d7E52qGTS(<$M1d3W@kp(w2*s#!g(xk~LMk$T6C zBn$$bCA?MXPY?$@#XRC_N1m2;{$nv@p;-+N>T{5zxR8=|6)6sJtZiI=c#v*#Q6U-) zNb&4p?67^LDRj;vR!)s`p(*GiQMMKF#1nX-ej5+0Nn|OlV^c0Uh}LN~hexBbM#acr zD(c)+%E@T%5IiOX%*-Zv;Re0R0Anb8bJdBGYWO;jouD$yN`M@FjuLXJ8=QnL+slY%&#b@YOlhL;Yj()Tiy|Zs+|62|1bo(B8ij4Jwf!7kpP84lcI-0Q=1+v zpM$5Tw?}DfLj7C@X@do$!OUXD5IE_#DDin*kc5%vB_|yeK=Zepxz`@@8u0dZj?k$; zIa(OG!(tpXq?E||viWXBZ$*_%4cM7iJDc%`4r(O!UbKq(M-9!NWj}BcTHdhI?^th~ zVm2OixBdcd$ts2wem&LU9|;1rh9=Ck4+t3NnrVAj2ox0t$xB!A+(mgu^Q7ET@j&KK zC02pLJu(VF9WW^1$qm z^d|XSU|PJ8CGUy=G95gFULpk#;Y=_TSQFeUK^R!A>BJpkZvf&mSs&B16VO^}jwOdo zbzo4$g-~#zaPn;O=A}5zOZd>ZSSE^r=;QLyd030t_b@q31jTmpSqv)-7as}BrnxQZ z@7Sf5Ubb{I`s&DI;C?^vG4H!1gpcN4!$zkPN%UtuxMctjX9O`biN#C@PDa^alJ)Sg zsIEa@Q};oxR-O&&fId9xoz^7imCI4MH-V0j&&gNrCH!+kO6&Fr{4COsTE0>RL$nT7 z9(mEZ@HgAfz)?+n3TA1%@o#+>>|d4q3F8rWcr%n$sz12~Khl`~5{eH7XEUD0dn8nW zN}mcC_K0yamachLzTU^{!R4+QTo1#ga;)cknf7foEtBA8tJCa58U!Ofltn%8`{jUV z_fstM>HjuEY#Z0W_+afr69t_sAWa|=$`M){;^<1tqn$yK@T?~}&2kK^Ll1@3HZ2=k zM!X{pMs3KH1&(B_HZ3h>Zxcy|8%K|uXJ~VR#GEuIlZL~Fp;0K!M*0y&m|Y}B7)W(m z3tgL5->O_CRdo{5=thxSkI^n|EPO^lZA`4up(o>o3`&^xizGnZxJim}x{Q*_&XSk- zc*?j$SQuFZE_n*-D-DhNZ_dxH@WUV!L6XRVyL@NmPXNGx9HlW90Mj{mWkSaW^=- z1wgUQae?sX(+5Sz@ znfI#uhec;@)%oz0+ynO?OOB#>itd||GrK<3yMHgb4>k3B!F{R7WuB_b?6$Z9yD5QFs_PpKsf;B*JAF1biZ|dq zk-uHGj+hND*E?q^GTBT`d4Lb}d~;lFq5NhP!_euR3={F#binAr$c2cf8W34{2pj2M z9VK3pLEUG~OXFM8adB7n!4T9`(k$-WswoTB)sm#WDPfL1BT=f=k)8)VOalL2}M%%wF9rF|iDbu54VOvI6Ya(z?BI|;q#8+*a#P0bo z#GgUW*c!Vg`g=ktQMvHnBtb=UB|z=ZI-B`WYJb$(`sdE(-#VN5zJvYeoz48?B71c< z^Hyg6w6mG-itNAXZ019meOqMj^G9iHH&^kiqYx*$i53v3BTdCYrKb3oQwDRIili;# ze{jE=T1$Ch0;=EMw}g}%5nqA}$;C!pwctX4H4gO7L*k&u-jc64WX5$8t-*;?6ArHO z6kz{k&3ItGD4YB6%R&VBxX?TbGnwowYAzrO!5IVT4;yz-goy17;yQ94yj#!&l6q}r zvH&4;BubGURDCom!jWo0H_H?=u-)ozZL)t8k4Ob-K|&2IIIL<)P7@_)+OxUa8{o~4 zS`NUcJvp>yM^nfDX|^)UOvgtPU6XVz65M0>;_(H5H;;tk&eG%eK#7by`IPXOr!7sr zrJwd30|_k{4Ut`5sSfV1-1JXo+We<(`X@7O{=!WsB+85z>5b=cYFANHXBKMX_igvx zX&yMnTW$A_4uBN7WJERy4b*kAj~jh^q94YP`@B2Zg>JIHoU;}kZz%5EuD$p( z9|5RIqgx<|ON=1)k70zDSos?sHJ^x-uOiZR8smMfO!%Ls6fsX9<{r&oPCm*>&Co%z z*Nok&2ihRg(ZmZePNk*U|Jiy37rXo~a_$mt%jlqs4Xki1Fzb#Jq zQTUNy7YaPZrzy<=mgDcONXtQsmI88Cuoa(IfmC z3HF&&>s~M(S&OIyA0)0iLM3ah6A8yH@nM=@WLwGsX1XfC{OtrIl-ceA!kZFEZ|fnh zemLBGI#09o=`O#WXU*lVzVT@J!w!Vj+j7iK8NR@fZD-Pa6cA#fw5E%$i6Jc9Q$!O=9|w~1g0T+{wTw-U^;sc+kwoq!*pR5P4EDV>8k2W zOUmocVlJ64^d8&NqXRV)jM#VE8IrShsP1p;4N8Cdx zpk)oonuDSVch0b2j=&PRUzvgEt%snwWIOCa*W5=+>b? z9;0BwrxZJ5o?HS0vIoL_JS*J0tIIUfagbLb+GoKlKlDWLWZ%_eA-&rrsc10q!r<*e@51Bk_S z!FS`%BSwTSH6W%H0{*+u85*DfB%E!v(1`pT!>{cP5cHez0Sdi|K`fV!a$-5F#asu= zQB)SEi*SFjoF<|J&SKE+Wd4?ek7Cu_*6y^>yYf7=mOtXen{Tb&Q4*=A;q-C`Dfd)c zqkpzHIOdCU^BL&>JqUGM@l9(uJMgTX!&}VvAxJY z(ueC+EhkS9fZjz}Z7rVmVUe!n1;1I)a||2Zl_y4^qU@_GqG*kw2NQWJq(6mshSO_H z=e`K1*Onk%t+5aba;!;FN7-7neyf#Fy|r`&UClhEDfi8#`^wMJ3kT-ke8|5Cb~_tE z00006VoOIv09pWA09s*nf0+OP010qNS#tmY7U=*07U=; zIq}WP7loPzMnU&!k?aaJrVg$a>#f_?tGa$Y?&7Ie+J zZ^Jg4Hfn^H55N6+ZqJH2#REo0>I<{SSkOfqi7zzUYuYH1%Gdj51uZx^r#g)VUA)oQ z0tc8jiiDP(OW@*uS!Kl5--?cd`=>=~uEwh@IAdP7ZF;oPPQgQ9v;oLij&Wo?s_596 zTT(rFu;yCqi1b8NwJoBI!%TasrGRpKTEST+5akk0kt-{QE|zb5R(${4((v1slcNO1 z?ge*VTY|@yD80S>_=#jB7N+yB&JBfV2sDtFo`=lYOMeW8r6` zxS&u$A4$Zuh|f1X2UE=eN5HPHAO* zKCtru=k}g+51d9bG&S_E&U{!&ZFa3Y;0$5V6lvng>=Wy|`n-CMrX6+1%*Aw!mT(I* z@tIcwBfYc~wvcP&xrZSconAOJK5mSzP$^f;->d@kkHB!XRGhegEMA9w#4jF?`Vy zm`rab#aYGffCK26>)}S^hI<6%zjo#M75bm`yAuxJROA$qnTR{#0M3NZFdd(^J+3`} z?cKl6P@ZJox3TSziR1*Wqph6SbpmhVVDMn9$V%CCoDZgdAS?2n zv)a5OwW>gBnsB2_*Dcy+F&}R#rTIkj1p428ab zb^g-IN$n7IW~vz3{-*)88L&|;RNb*e>JijRMN;ZcAZ~D!KSosL?yOVop0I zlTWozlx(&|x4bQd8PY<1`Ab8_(^cOJQl`}$aB{t8ob9WdT2BiPYs}#58C&x!k2k8i uf$ld?r)&7kh-v?}RZf^u5F=|no&GoCbBsdFN#hUz0000 zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3;ua$L8Ph5us}y#&m|asVU{(L3nn_jgdFY{_!i z5${R1iY(r`Lk?$1fbRU?|6cb${As;JmrLt))av<@M;>wVMfaaSpV#2?`}h4x?dxaZ z=l9)@A4J|tI`Z>vJzvL9-YAdw`TD;VzrH^7xtm|U&y8SM;e08&cv487e|@wPb4npvZFT4oQcT=Y>S^*? z-oGP$-kmA&s(13|qVCsV{`e~V&HKN^GQ`jOjyHaeP5tru+xJ8HeJtGz*`KZ)`j0FB z^nO3V{Gb2)DVFzIclVyp)6HB7UHy8f??-uGaUem?>3yv7xAA}B>-PQ*{&wf5-=xs| zCL@clM~FoKh8!%+aKm}8J8W(-#}gZ`G47b&dp)%{;!YG~NLhcwjV+C2O}V>7W0`-@iT4y{ga z$_w!K-(UYIuZawn7v|0bPQN~!JFn+b^w_!?3P zHTV`|3xPOx@-sP6k15AR3PLH-xJ&g(B{@Cn+I*&kcWf;2^EOaJB1)>Mk(!Yvxys-X z_0w{vhGt16mr`nJrI%4=O*Pk2E4?Sonk}{5N~^84-bR}}_1sIZz4h+;=ySx8z_c>x z)zQZob8^winJ1r~95CmKE3LfBs;jNO#+sY**?E^;ciY|Vv8P2#1|C?oX5EI(6Aq)hF7I15W35bm2Pq^a+)KrpDC<0F(Vb zzP5EOj$QfQa*fj+E>HMcEo%^FA~9yNU8kLT2LKoED1F~SD9##}t?i%@T49eBSz)aRAuEw`6r5tF@HXYc@{jDsbM(Sqq0OBT(k5gmtgL>2smNP!ZW$ zpsE`69meE_=h~=?7|zH%R`aBP#I<|nhr4zPHmq|7wL{F-tSilN$>*d&toG?|nH=BR z8uN7x-LZ1Ng4*Vd8!VKA^$^zBV^#}NO^4vxHlbtIhjxkF-Oe>_Q|E|uxG(CCw01Yg zrp|J-h#(18Z_aC21~g*rH=faN@d|afHo3KGp8g=AZiape<&x+ppzgF%&TTu~W^(=|IV8UdrVh%88o1llT!X zs+NexdHEC(D3-WIKImxS-pCbg0WJ;H2;@Fc9(|H-nywOvvnu@y4h*A2TUj%mLFKPS z@n0w&7%3!c`P^-(5Y*T6w43+x_ZV4(A~wff-wPN*C2nd!2hqYO(mXa}Z>>5S$xwda zpL#kjx`X$9I2Q9+R=RPs;ZhU?xBICG(jlu7*KCnH_MlCTj#lC%b5ML#V_iOVVwDO+ zI@;d*as?9J=vUHb{Zjul)L5CwQH`(sYb(x|M3Y$GnGfW{LvgD#5*4@40b)w^o2voG zor<4?VGK%mw@R;9QgHI*dah6rRB1Ov6Q`I10!S@f>83pgAJ`M`8C*esRpE_dW>iNEb8RN3{JBdFcGHjRU1o4_A^#e=>p-$-I+bt@b)-3qF%oyw_& z7W6_`F~Blk2PY&N-oOvyo#-9#YSuEEtq2-XgUM9@m3mZWAp!2-5JvthCXkywmpwXV zG;6+XoXVrMVYgO30vYbw(y?R3ftbim^B`$DspDlhJeIcFqqmKSZCtWmNU7ohkhomi zW&-=kD)&-Bk(wOYz3Zx>iTa#gNKv>Z07t*-UTACLZXiQFgPuG`_yYq`s08zRo}n*y zJ7o@L&Z$3JLVla6?YuwlM1kenWuBiuz3tC~vlJx(r zAR!zBrDb(Mf+@V4jZ5;#K*t4%>E%TwqgYl2fw6cra2vaaeX3dnsoyu+z&FBIcAqdf zya)Hk-Rvw?#HJl}OQ|6cLY{upoHOUAW1?UBhT4j<&%P~gzR(J{ z=jQV6k_S|hNj@P8Kyn&=V9J(xmC;?GH~gJp1gIDO+lTYb-Z6(D;>iQbzP=sU0TGg> z+2v7|H*lTI(ln8fbC2*^@uNWX;9({4VeW|wEp^ZYW!x}`5lsTp7m#&;2MVnRlaY)F zW!<=k@FI#f^vHYgxgFFL+2KM1W`@P+GMCk(i3$b_J5hveLC>8akPFiu8Vk9I-R&y~ zb(XB-+gosROiXy3<(5>AhA%6f-*!co8ejU0pK`YuF<~z?$A~%Kp&AgoKbHCSY1xhjInB7M@h3L|+i)3(SBm==K$@?nHgA zb?FLW2U>lBU_3mfP2NXv*0CHzXKQfHRN@Z!kl`8B?k-RG0sfNPSegPra(9U)n^bJe zTc1LXxrKZ+DHos-5zt_t4M|=ZWt0*o0&hl#p&;=k04OL|QCm8k!hpz#1jd;d;Z0hm z{e_V!P}$fVzVBNpplkqG@S@NaP+5djR;nTu&bV~|7lr3sr0Q+J#E29?ziNmEs#trX zSH8j{Ng=*!)e|IulcxzV#cEfBfQb2|BpebC9-9H3(D*s@+Z11vvm-cv$JWN<6`1srjZi;12{=;*1AI@Pm@`Xf7l@`5yAC1;NTaUQcr& zMLML2c14V0mpR3N+fY_$ax*BiQ2A6hmB2%Ecmhj?$sUE51IQ^f8CyG%c8K1w9RRdc zh5_B#i33*nC}^#NwRG0;nWlckB-jU?&;s~UpM`}>6oZCBm~l341kEZ%nsLF~ zUT@~w$!Z$#1t8#Xu57#vd| zXDst;I&@o2d}1Lp`SB!*QDA@v$R;+6wGK#gauhY#3rXJCtOaUxQYJUZg>aryK>^&r z-6Ho3Weh5>o@@>fi{uZfz1UU7n>mmiQ z!o}-YgqG}LQZh_@8}*c!1PxnxA9V$6JbjhMs+C7-w@DwB4{;$p7VJMASCxR~JAf1H zKgjczKQ6!{CF>HWAYF&~-6CfixS8-Q;;GP8w-E2#&W;`k01N11g%_`ZcAJ4>gHoYW ziqng;AhcymGIZc3X^pgP=+M6p^gT4IZk>t$j#z}pTQ_K|iBFK%@Wa#FTM%35J3*%0)^OM~OcBI8Ntj&8f?TBR@@lpF`B6wD6X+Lcn94^b zUMB3}!}TbCNZMt38Fa)~P;|9sh!vxPf}>{X1hQX1iRKMHrzg5m+w?2wk62dE1uBh( zcKCT+3@MERm{8x~n|KZJi}a-}2ef0-;F?5hn2`p(MyeZEsaZC?fJZ*ht%AQ^n>mA8qBi*HB!TyR<`GCq{o_^O-_%;4(KysXAmdm z9yCrwpzr}I^Emq&2=1*x4yc1(xSE8><07j{NHb+=5l#UFG+Ewz5j8`e6nlmnj3L9c zRpJXdJvD;~4UTTG1Z-S2l939<(2>$js%RasmE%E|DFUApdH`IP1IAE{5#`t+{IKOa zxK|#(@w9mplRU120k8HSy5b9y=Mj0k$C)umA=E9tA)69Bcrrs;D)@?h+hhAUrwK zeG>mvhwiQ1#yyA=SS0VKeKjoBa05{~`Q(s}!)6#nN?Z{C^iA&I3`HHo z0lk3A5$_)3Q6xl*M^0{ESOSAXjFwBY(*q>{$CQSO3*H9^qk`6x*EA}i5y5zTe-kMl z3LE_+hy+>!PBC6jjDY^y(9MZ7!0$YP(1M1-^rBUcA9@Bu_d`Jl-cjLF%n4MrVT!t&q1JV!Lp*8Uw!1)&S8X^P-z3>#0w({k&0GKF4N+V$}b_D=|0B3@S+{PCmi(wu# zLe-2FN0R~jf~ROO-W3v@{|JsY7N2>1ZjUY-#?dY@mVut#Q6zFDUw% zDpHToe$gDn33>Dd3i){B=x=~}LmY}??nKT>mK-wl5Kv;|OfEa{jBi*5XgYbfY~-f# z9*w8v?qOwxC0~{L7==+kt;8{A z>5E0*j?*IG2TTgT3{a%dUzs*NH3xj(-7qRa_ke{&B_0VyivrcGR!a#+DxiNy<3hh{ zptHs16_ao@l?NKC=0-3HBA%Zv9)iYvX~!Il`-WdH=ap(f`k@+dfc0Rhk{S{s>WCbW zJ*T^fS)}IfQakpZ;~_Fw0f^fUPqEWQL#^fxpQR>|I4}By@X?D!1p%!IFzwzVjx9-4 z;Y8^|tzQT1rYZF>H{j|TRHL@X?QkFk=C#B)q)hruv zyp3ALuTidj(y|Ecw+#f*2`FmH^G6UquTbxPUy5caN&8_CIM_kda+2C@qvm+8ax)0G z(t-Tcs5abh0{tP$Xm2=2L~)Ut-2sw>tK(@;wv-yB&|cs4^O-;pIeOykG_;h(k+i-H zDLPWyVp-;kF59rhm@7{3rx-}!6F)vs`z-Yp#{*2xXh)@taX5)d8yV_E zqIEoQkys=iUrjV zc)@|D<6ywnqL%nhqtmq{y8Hi7mHF-O-#91|oPw%)nF3B+^{VySQVr0mmmzLyiW8bW7AW2{bO`euqn? z=?jdnY48w(2Ht220H|Ion8A2P4PR@K1nJ7!QrJGxx0-C#N%dF9M@i+4SNmLsEL<`l zbPIQKO|6oyp6w%1^vtDSK!v^!(52>|G!j6r_5O|t^!eEh^k>^|xdJXgCLNv;?@`A> zgFR;-#l0XNO`fHzH8Q=yLy!rPNUDfD@-}RV)Q+IzeCJ5=EhHxrYD=qm1BFtXyr`ow zzT2oKe!782-0 zpcU7MneWatanK?j1YBq#4w|EPt=VVIG~uy@cZUfz%QlUM0Ff>a9-jar$efVM_sc8T;`pEhk_Y8B=o zI3gjO%PJ5(8dd~_l1H>&!jJEOMBW%eyIqjA*=e`~wZSVI!%`TrisGt6FS`Z_UBBK49lqUN156ImC&Bnh+4Lfp0xD?U z;C7@gw7pkzr-bgE*d_zNp$VisRv!t7Rnz`y3PJOixAg*rie}uhqd_}+T*N*TrjUp5 zH$rx4TST~_;vp^1F$mdoU^=bvkoJ~=Bjg_~q#YtlKaClLgmC=8PZ+TQM#^qUN{G;P znK>Ly*M>lvm4YI>cteQOo?F=PBMpwsaM13$8GuLFLzGqs3tcN02J+Y9vw=F)e=bR` z#F}RF>YY_rm>z{bDbVB4idpk^R1nyME9c;&_3kaF^@bABG%8(DVlH1$|IpYoXVa}p4ownF5RUZ6~;6B>IhQz=?B9hSQ3x5u6twybMj5vwaio@Gk_catE z4-og-CY}MXwIxpb4;$W+Tf)g>C}vYW5z(ekFU`V zGYS|<@tq=op2yTm7q}e;aoz*vgmS4~iT*MyWY0GOFU)a%|e(m`uEuTzfgx_xeC!#9(uK>AbB^urmi$50n)ZfM3ayJ z=>rkIogN+Cv;1beUIH*{GvR{m`B?Mp@3ua<{Vi9nDm+8asvF3^2wqbcTj z#J48>meaL-g0(~Gq4Eg}Pz%IjU!b0?VKTCM^2n}C3Q`LuZ6Xh~V_~9&dzWm~9A>{o z-AE`fMVbmX_@f|4C|AuU^3g1oUZcl?#x!qZW}L*k@-Woc6T*{l(-)?_$YaNPhh#(a zf_CjS&}PW^Hek4)GCDBvGiw($Fi^C8SO&adh;dk^9Y|DqCZADT3EuK4n9@JL3ez%X zkebSPVF=Ez&uOLn{upxn^Q-&%f~I^1`ot*S3W2PY^>%R3%|fG$(}hT3=`Nexh1j)* zEtvyEp=veDx*9DE`Bc7dLw-Neikyv9M5G|)rFG5n<`i^%S=5eUpCxrP%XJ7T#MyfL zUBLJ;-T*dfdqE5u8PY%GtIokLq#d@`wRb!u|Eluc^7`--jEkzVB{T2)n zTz6y*11Os)(-C3*Bh^2}NSMIjH3}s`PHVzpEdm4FCK$=M=b@1cMX;qIaBBx6q7BVh z6w2#pkr<&0E>qkb5s8BXoJAy6d!(zbZum?bSSueHb2+0%7#QBI^~b0=1a=9+KlMJ5 zii__DS+jJfsN;^#G1vt|63~5jn#>@*!R^ZiRgg~OLG6>&1`F*>(EdMg0cGjXB^QiS zqYZ(DT%dpRqgs*fL4=^&0z9BvZJXpCcrN{p!dtE=+5j`A!+H~~{+2!GFJq=PJ;NPVQB&C3E~8y3jp*n%O}GY8x%!2h z4)SZq7m>WR!SgQL>u0UjZYfxa>k%~C(KaBQL`m4Pi)z0-np_UHuA$*+3_Ozdk+hlu zOpEd4yl-7`uUM$|IG>$KN1IjXt6j(Y-2@GfwXMEu1dzl~51nZ?u++g|huTB;8s>_k zNf7ktL37v79?Z}l_xr6~%tA<7Hb?<9Ex_zciVel~HeBHlHNQpzP%dD+Ctb89TBuje z&yjUVrTV6Tt7{L&)KW>4AlHt30_mu})3piVWg6b2Uo{y3&Q5`HhlY1r^)1xT)DEa- zlo!&k*cp_f_I96+tT|P`f24hjv~_DkzZKfF|LvYNX4Z0k9YQy4n*_MK=E?f4%!74& zJ9sC+RJ3tGo22mMX~-gLpEP1-jQ9H^S}|;!nokthHS8>+LAy7w`}=$Ae%C63``bCr zKfW#vts+7-Ys(y-7LSF7&@YP0$_=fO8_0o2rO-9d=DDE4CZDd~kD4KA`kJ+8wrGzT z%4H>oYrPspYX$p0=eWqbe#Itf`C(~GEow(4AOqQC)Uk?`*p3>mVCSWXs3QvXP{p4W zRg_27tYd5SHe_5(!ED4PPr3c>MH^QR@)=ADkfFBF3tDb=kO5=xBbJPv4#qPycG6Jex^bqH)NRK3qnVD0GikwbA5mIL zl4+6_n#8V?x^Yvtm^c~FwAh}6$vDpVSukJ>n1_%Npv4jop~q@hd++)64=vJawRiO> zrpoUhjqW|K&pF@o`~A+jD@SbvkI}I za4(~E!0W)LgSz=Zg&x-iube5LGMsh#g2BZHj>!Z~JiyH*ucmk1HLoCCD;nDaJBMKT zM1whQ1#1c~q4CPGu9*^?cs;>zrW;5Whr2$knZNqT3Z3QtBK7OFu|g~NR3F^54;X@? z;v29+A^=WQfGJAToDZPRAbPBL-6bJ1f72{>Zq#6886rO#1J^q2JRSf@g4qW$G{Jb< zeIXM7sLt%kOVUkaykvk}I}z&#S8fVvW^*&PE@!(L`Tf+d*M1^*<+kM3NoM_8T7nnQ zSD`&A}vGd{u1|VAiOe=a@zE>Op6i7vaokzk7 zy#-cJ{0M5I;|CNjG!qvCMt?G}U$0j9`Ko!O=SBE}-2c>(HjWW53IEVd_78N*&* z7>IfSd4q7)DI~Y?`_81@yuF!5Y$}h|g0>X~t2Yd7X{PD!dLI1DJYIXXho^sf3eVR< z>B(vrSUS=l(B5zks#y>pS`ahW5%fTdZ(V&EpZU1NGb+kJwvyJ*~SvF zW94O4u#Qrh11AWWendw-p$(nGrSPdmVf6pd zd5qtm^ZqEJIUtfiv}l zs;wXa$+2&ReF8TLl;%nO=s35V7ZP&X^uvQVL+PAVOCvTfV9$cg_gk<5V3+N_kIiKu z>9OM{35>wqt7}K$Mx2KV2R)%&pfO}A%b0)|Hyj7^0eh|RLC7*EThDkUST}<4(%Jt_ zPAu%rYxVSau*W9`18^MSGwbW|JZ1Zi1mUpZu2t0(9Q`GQw=;%AMo9$(az7jB^W$8b zFL*i6)Tzoz%}mZp_2f8~0mPmfeHVqHCt9#eCI%akpd!JjQ?bvR?%{vd>?|_!-nF=pjVAhr!~) znXj&(=A(0&j-`hzjw85^Fmd{>!b#uoCPE_Qlb^3x74~NwE>vVjo}IEnGP~kJIr(#9 z-6Y1pT>jE1SQuWqV-BtVb&k#tQqzKqgbl7Eg%7JimQgs8aoBB?3(iBOW9%;vRS`|A@xKHD>f`892UN@t&K$Y^Z-Xx)w|TktI~1Y4CG`c>Iv_rUAjt#GntE4=+5pv(aO9eBpaknH=+Zm1L?<`F-t3`sSLC6;YI+y zxvh<^^XX~BIf)y-*4j}k^wuk0twrL31DL_$=fji=ohoD;OB`?!P@&rwq9IGnH(WAG z9U$T&+6i1lr3d5)LK^fP1WV@0X1IQIbxUI|H?An-mDet?=bcO3dQ%0nBF@y|SlHSM zFldAeVMC%+=$Iq)*IWE*khtO~m{eidJ{1xIVw5;wtk7)@QBh`DgM^gXegu^S!Z~cH z6XT!8I%hEUJl>PHVs99KL@JHBEMHd2FMfHB!zcRq$cl2pVKY6raq=_5`H0Y2CUndd zlJgW>Z6PK&KA3b)CW3HLg%1QGt`ZeEXN9OJz7=W(9Fs)!6v7FR(-`|MnSZ_&yP`61 za1~`Cnij{{`C=DG-XGwWmF0v(=Kl^i?rOmi&doA(mJ1!%2&s8Kwo)LjxE{!m;3ITf z;UdG*?DGvJ&Tyts3y2;?or8$okN5Zz?8=F+BdROIG-d(YP9?c@WjUcq-qB1NZroAF zF?5#*o#n#GIw5n7#a1a21%D9E4jBfFC9Q%Jw#=0<5wjo6F1)QV^ycbG_f=aJVbP)} zJ74I+iNLbOrIWjOVvQ<*2wfpYTUK+2B zQ8H_C&c!WCZY&rd5l|J>cMwsyoRX=acDzI^!s&>^=?G9I>~65URckpmc$Vw>GJJBH zlXk;(Wm76&6i%%HYsTF3smkP9E>Wl%J{Z_0_}e9K();s&<)=S8kLwEeWHa{<)7&ek zMMY{9oh?X(qO%Od6`Ejs2!sVCZ*$iv(x7O_ z@E^_|);oV$;Am1$YS8D&r#gs59ab(a`%vH}^p;X?p$4>EAP%FK6!|HI!gWCD@cU=X z+uZMdC9vJWl+U)O+IjEL0AJqFFlA>kEjS5Vv<9S7(J}*}2^@&4uo###3jU1Q%l+=7 z6UWM=$3Om{owj31Hh!s*WsUJG4=0rttrnzA(YP?dMc8QNdW$ZQF%vLZuo1ukkMBHr zg43r`{KcO&v7oNx3huezQZ$>+=p>;iAC{oT#>Tj3%)Tjs0mNf2U;KOn|NgTxR8@qo z@XEDLAwvmgC0ILt67D&%hkvWzNLk!vrr0D?Y(=iM&{7!e?~{9}e&UmC`~3znPMKKzA+96Zp^kBWU>`u~8F z>R~8dXoi1u5@0_t2lxYb6H?&Q`7O)K`P_r`yzyF*&r4Uy+>s2v3AA$JE%<~v$YLen7MrzW<`6AUTcm_25g%-!spzL7&4RY;Ny4Ja_{fX;eYn@(AR%;LxjK~ z7x)!$N3nvNlJD_Q#U>0xQ|@Hl+Bw{LTNP!cS2wsTykdaoixs*v@g5zUKh5EzUDLbu zHNx!j&{f}WR`hwp8hMN1U%!pBEvB6vHD6)zfJ5pqK}Qnxi#_<@a!m92amWLaT)&l8IQU= z^7#hp=12JU_fBx;Y-%QhJr`TG>xKLv{t$3rvpLNp?k3#4AAOd_h5@57hj0GVaS~mr znFw}RMgKU*V~*O~m%VEaM;_W$qKWH+8aUgX=IdLJ4{Q06#muRW%m^@F^l;kof4j2f zmuCv5UuW0230E$(_~Jen)X3bL2#;=PL{<6L_uIJ8lbI1xRMF;KFpAwL^uDp~6Rvt& zjQTegdVl)tAbpV>`|$qtMfvW{_~E_j>rd)Tb2c@T|LBt| z#BJc$)qlTo_j=)Ed2zvebs=i_!>7||K9@Yamua@guk7W*X{DFQ^mjhd$%Q|?pI`SG zTb9sAZtVDK=tb%2K7iD#=e!yK z>u2jN_UJcrI;meAAJPXe*W>%l4iWOvv&-3b%BSneY|qYX`hmsXOaAvKd;0VB@wGsH zIet5<+v7!HkHExxEPCc)&h`eK;mCLB&XuoQPu9cW57D+yGP2~IUlCJZh&-3f1BfS| zdd4h61d8l_BW)($qdJYN2Qn09(%Oc5lClDJCKwB3QIW-W?^*+$4*spW{9jLejur@d z47YKo|E`4Y9@DWqG;#5Q9Cl8koFq!g29*x~Ic%Hm<>JeJ5J1_$hyyrq3(u@ksu741h0^eO*k$P2Q&gf;HN0^- zmh@z67W0^GwHkj8S7mZsaO&8!r)p%k9P2m~kLL9?&sQ#Od*7HkF7&5D-w@?6kHoP3 z<)8e$V3F+`C-L^XYocmW!=<{e;XnbOf7NZnzVpUufHYM>@MzJrJlAi8a>>5qHBGl} z%l(~jrxJe~u`yL%)FH*FLyYBUdulPZMtX+_2>mUEm! zq3V=RyqZL0Od}09AB~APb3V!>;*RMvxpVK(-=mN3DBTY%p7PmGYO)iIj^2pP{DY_L z3cI`A`|)m=N(7EdL1n)jN4!B6C=|<$02GhP&a!Ni7Pq#I`z0gL3+sNgmRFd1Ck1JG zyC$a^Lnd{2vqaDe?`iqc7PpK=$S6Y@)0vH^niQ`AWvm%~#r)blM91YZS-z9&nQhZQ zrk|UB`vj2-;OOYjJuOqBkk=bef*~{+OYBvlx)E8(wwd;*tm) zo@?q1WcM@ei7e08M0|UE-_O20cX!^s8fB|f&?gRI#|t?Xwu^oF$}=oHqY&v!hML-6N^g zJkEXPQXq7VR@3C~$~e{^hbr*0y<^``Dh33z^pqcG7?UBZ6-V>>Rcwh)wxYJxRQt}j zwrVD^R)>y+7*{003uJp@r{m}Aoj;D4TRXe7MqK%iatohi&!++BY*lSP73496=doR6 z;uf(BNF|;&@~6L}(Z9}Sh_QJ?dGjVhn5DKCgS4dpSZIxoMlr*#BmF42mo>)u<32Op zWY#QOYc4pI{L|`k&f9xA66+rMsULQ_@vR&N?Us--+<%=d%jixbNmWdIo&Q9)Q&HWz z9veTuJFG;#Uu;V43=xe5>uDlcbEPyoSegY|@|}Ve%+J)PicG%B&i4N_29-X&=pJ?u zzD{rvL20rFbM5>A9@E1(-Eklq2FHfBki1Sr-wE4`x~KKn<2vN-@q{3QrNX2DLM&1BF#@_n0-axV)q5@7;m?F8;U`hH9t= zp6YlCD~N}H%XD3<8@Jd=AAHF3B9~;Z5e_`A5?6LesPs}N{rD`vh_&$1YmU^&UE@k* zPNRshQW+$5KADS#G=1l*c?^F9vfLr}R+ecR%|(g{U?`e{iYE3Jvdtt^ndQ_wKocf2 z|N7k8+j-;v6UGC|x#Y$`hPv89sC|bkgpw89&?YR5l-OVH0IKMmqEl49_Qef#if@pV zZ<-+TD$qw4-igc~oSkdLE|Xx~5%v^2!A96At-RY}qFM>MV|H?Nsk)NTYhu9M zrn@e}4aVZs&ls^Ixi8zsaTej|DbQr+J-u0eKLtuvny7XvWu9P|gjEn+H$8SPXmI#N z53^)SNsJN*_fyd%ZF2sE%01W^Imxt;GH_7g%oHP<&B3l2nX&Y6L?yA?JFpLIo2w16cW>6A|D7nWnU2898p=P@L=t6UmY>qi zaRcFoLahO8=TR6;G_Ev*AsnL0s1n?+x~aR7h#?d=o_a|}=q)*tr2oM3ar@&#{jQQC zvB`2H`WB5=7vVtY4-h2W{IsDC5$M3IK<(DR za*d(jP*eu-7-N)yFrY9y#Pe~4^GP>&b7Fq}BN9Q2=xVav6>KeVE|f6%L-{62q(73Q zOFAg^SJ`@CYdtr;6jB(}_EET@%unKia6MBR-0j69TRH6#HN`2st zf;t%0$e+`jx*-Y*ALNJSz(mI4!h?`V*-O$X(Dw667D3s5BOI3n(Z6v0T_Q8beT4W0 zXb63Y1nn+i>4^G3$Z)u(@Q-|}bHPqZIULFsU=u7ADAf9f8CQ%iOhsLMHzXB~37*?lS7KI50hj;rR2>K}chVJ0aHV~qAw z3Urp6m9=!v5Q;LlKZ9Uxw$Q9y1@qP@D#1=9Pl9cuTr_#9FgaK2VOD!d0XbOC=%vaJ zftKl;a<ODOB|~PLP&I|57T94Iv&|5!1osSQm^)z2oknUFeeVss}Y_AcEj~Yh{wW z%)ZoChjiMn9r-Dc8OALhy<9)ez=F!3zF14i zG*475;iY+xG2CTFB>$%sQFnPmO@JyRjjxX}<=0^c$@~RTf~AOsdvGm>Oo37GZS@Pj z8P%%1ae~P+TQwMW_$;*r20W%e*qTgHjFuxw0pBu>g+II&R<=*PrNZ{Rpg8RyA^@G= zN9aq%*`-j8*0yJoI&~Y@o4&68p!%X-4kS3$Y*)OZ_=tTHa$@X6sagM2RE6*#Iv$4H z`NN?^p`qSV5gMxrPA&svlcOWRQ3`ACQo228LdK7`?_$5qjKzRY%06qTunbDvFi>*| zCcTNC0Td@oHtgQ)Jf1 z-l%~f$DF?e!*lP}&WgT_wdJzG@W{kne01}yd1*q6~GYu`{#j7Uk>B& zhyd-3_9ABSyu1#=VqjDxd8%fkIOX#YvZpiTCbVN=&EVm0%0cCLs$a=*vq3}%d*&xH z+foI#6o!gGd?$Han*!%^K zT~TyMu`_2xx|1njJWho<>nG|cSOH}T;CU&@LuB3~F>OarWJ%(n@Ij0$MztxidNvsR;~6_JYo7Y3}kdCV|M_ibID8o2alXU#{_C1%I^ zi6ueE%#E@Yw%&s^OT(Cnsyh_Rl3wt=;cR;Z!0*lp?t-d8>;03s$~@UYXGI=>yCcQiJ=<+8%zVwPZo1Bu_y~b$|89md zA|xz2hEx8CvnSw(tIco(&9r0sdfBH}DIrNp!)H!!d=-M3TN3m(wn)|{5vA>znD61d zYGdIH7Kd^$ep>cM?2FT{-e))yXv7LxY~61& z^HPOabB%S6*kuI)4O2-79|N&?!%8d)ONCz!jeRI1lhkBdJ?XV!?R(n(HUi+P6=TxqE9%+Y)*>ypGYz-}{8Bt+}`!aY)mX_3N} z&?NGqO;A=%vOhW?`nIbWrh zT9<++O411WXDnm{@aRWdzo& z@c?+`Ha!DbY91DgznofukeO_WB@snW72)uNFk3eNbi`rmI>9$gNKtZVH2O}Hddb}y z7#eISliQ`npm3{$=~7Sh(+kWXW_QCsHOzE8qY$Knd{h{CMw5=;@2Ym_R7=kg$Wu1^0} zEqZJ&*JC-Z7+$v7KF2a~tan%clmU&uQD}*X=Bn3A?5aW~ZJRBs81%YkiwnRU#S{H2B4r86eIcRM39iB2L&t|#lOysdQQ=sifR|}VbykH<;^F(+nWlHH$%g@ zndnw9N7R!xm>b?{qEo};w&1$K*V3cC}FOiHoVz#{5z*Ei=&#Pp7FYlCz0TQ9qD^Bb0hS7RGI!AhHp;MdGWg ztF9J{yzu);bp#_wjmsherVOuR!ld<4m?Ng?9U%R6#y?qcUB6<|cd#1jH0M2$q$aLh zb)f9szgY6yz{U=1Wo|nI{?Hz6&t^daHKt(jygV@wqA;lf2kxBxok4F)uQ_#C-3^Pp zs!%n2tTiqh zIQhqR5%b-N^v>Ype2OC_>93gD!LWAY@JY|VXpR5i>It=UQU+YfkByjO(5&bNp4J%x9l-<<{R7w}on4t`{#k~b zuNNsOMR7rn4>j&DM4py`_+c}WD}r+LA*&CfV(k1>RFCO4Iq?6vjO@6tJ%=Oqot#gF z@P=Xcwmbh3RC_;}AEHvNg9OdjY|j%;9gNl1pJMbqR;qsYnRHbn{IHH7KBvSxHt75@ z;8Ix=P@ib*77^6S&ts10AazVCDpB~bpoV)`PJF9=diChFL_j(mP*Rb{I@8PdwRGkF z%Xa;uKmbwu;#p-$e^rI~?DS5y^eB#tvXcJcic1np46RxFpwL)vGI0s>B~uSUUC!Gy z?w^@a;vKOm%{gXq?S4pKAjwrUK&S95znpyNPtZFZ&h47aS&FmtDzQ*SZ%~)nVqVZe zVo6!TOpSEIge&n?{5*K3S((@n`DFPNDO)USf_bM6t=eyF|5~-y5BPa(sL23fDeRqx z)!HDC^O?&6c+y5C$HOcu&~Yg1=a3&{EF~lxu^@uWfl_mv+@63u7v%GHm#?$@Cu4ux zY%vSOAEOI{i$=KV2gZk&VKI>1pmET}N(~^$hlyv%6Q-B*qehh-nw` zIcAc@f6m6~oW+Zqb^p zl91vd0PVu44$gScb&)MYXn8VUqki~2(H!-KAr7IfeLi6f3%t;%C``{}Uv;~!%2Gn< zEPhC3A2)TMGl>-^3f#BC(7mhxcr?g{<(1%kZZfoc2#)IJ4f1`VcIbhi`Fe!KB6bgP z0+HXiP8mU15(dw`SJ4bs`<&M*mz8ay88v8~>!t;}URT?9levocpF0`W<7C%7=S8oWs84$leW8Lo`HV_N{l9iUd|S<6;P$ zONhKj7~R6d-{$hbEXN+ka?SV~zxNL>TF2#atHauIlT?qE*#p{cvcw8qD-TIb0gPk7 z^y%rOD{#5IGjKNSO*?t?7@?VrdmN^}7OP1LmJ&`@$3#E8@=#f{9S+}dFe8!`+fWRi z=A?P$=A`gkwFA|`mbUkpgapQfg~h1gU>pAFqwL;M*M_Xm41+wcLdwX3g0b92AJsro z35DU+V<-QhZ-1=5ZW5K6Wx-Mvj%aV0 zZw(AofKJ26#Xk$Agh;E`s17w%S@@-O+cICACgyfNt4}3Hy&9eXGMNDk(A+9>@qfQz zXYn@`->xbkKXY4bYvj-DY7B;E{H`QrtmxP0AkyzpsdXBjXL)wln%`~`IVi-Yo*$nP zBp{{~0tooSf*L5*GwCoDL1E>`Z{N$tW%r60%66?q*JNd4WESG2goUO@RY5gtV)eoQ zmX#7lxM3WbA@~>wJjN53=A=$^y)c%h^M14kNcj zv&gOiiw&Gj+I7n$zEF>-?1z7+zafVFo`c@8y)Wba!5$oSyA0r=*LA=HVB?Z(*RhDu zY?Syyn(sx%Z4L@tp{lLD+E{u=2_g1PS7->cIEoOI+u*4tX?cM64OSh zAvW@CiPb!lF}GPkTw4lo9XUZ-PHrms9l;=Z-vX!j`I~b<=v)`#*tIHk3pKQ)^{KHi z#6|+p((1UAt4wO;Bu;N>SA*N7zPU0BIeKjTg<>&OYHOViXq{PBl8mWcT%K(`nuELo zH~9*f{L_LXFGI`z++{-Qn29t4r33`S zRr1X?+DN0*QgPr%(|gX`1R~@y%n!=0mfQCY|c7Igtc*%j7763n~}0ndwzctO+!Gk?Su zs`eo1Td}%{z>@W25_p|vPUc`3_qtI+c{h7 z%S{qdM9KRGRN9Qjr!^T`CJ(&nlDq=K3JpXk?1ayT)z!hCrVi+if)-1@meman@sBP? ziST_z%dG0&J*36*BE0k#{K^iim*bfKtZNmPa>JTcpuD|bMjA9!~IB$FS7!3)#vP6*SEt-D!? z)i|qfnj*_5OH0ZlJ)pcnj!7-stX?@O4S0Gn&d-zz;2maWy$-hc#Dq_xIo87_1#6lN z8H((S!7mm(`0Dy0wQ(gB&YxBFLO?>f*;W*v8_mRIjJhtB#pW`0g+i(n5{y;Ufem#< ziG5MpC7StA3vEEFSl2_0mK{XS&Jl)H=i>$1QV6jXPKd;1#YW)!I?zc}#eJ zy8@mMvTl+x;D^e^X=~$Q|E`}`<_Xq!QRY50wbI;T(*7gJ>UC(!kUh_fDCSg@Pg&MQ zChOd>m?Nl!+aFFX4_a>=nOf#K(QmQ=*rNNvri=QRqW%XCEhgv8(z_lQ< zxny-AiPL=ep(Luir7^Fb&)ZL>?VMVr$51Iul^q& zaLJLzg>Nh;(B?t>I{TrOOAq=o%YZS>FbQ@d4N!u^!7_yAfCY6onDIA3)V;44)JPuw zMs0dc*jjeqpWuz755E{|p%|S?%2Db#@r~a(@!GI&VG?s6N$Xni*ov0dvCITpK8byc zn?r_9)aj9{tN(~8?=VlUlY~-I8B^-7?&`D6y{na8*9ZQn zTEN+L!DcXmsF6rMZ)sy-qVRrrqzf_;0WDcas6A{cY-Do-HWB?!{3x#GzFrpDFYq=N zClE3vmS$9WQjP2nc@@1wBAiskYmNYi+gT((MY*p%%O5cMi{R7-KxayAZ6V@ z0OB`!*=|r%H*Cq#j4nt`F#p8Yee1wZVbbR?B;@Q@Wn7N@BNR+i#xBa`b%$c4nVJEb zv_F-_ZPK6!zOv?PvNwp zR*EFkxlWdN1*aH%ZG-)k?)y(MNYYmQa^#|2m}j#ob^F~?pYXNhw1D@G6+gq4MQF`m z&8kT|hvv&i_9^kK)8ofP>Jk0C@@MeMnd|5{SBYDRK8xp6roHE8jy}~mO{bkIJ19iba-&wwDtA? zC(FWPtF~FX-m<-F@!$FE{9bmxO>sY8to-cD4>T1mlrOvo9B2rL5!g#*jJ1No$Cc|_}L$L7xGp2Gv}8H|5x<4(3Pj6qGJBX;qe1@ zcL&3ybW+IRoyRyA0{8;E-Ih(5ao6dJKhi&*yqAW2gP|y*cgslV`Nf0@fzNp!nE5kO5)zR1t@y1Qv6DxlNfe+1?DGAD z(YHPz9kt1mM`IREryUBsxm39dLO;fy%?fNg6=jpe?d%u>g+YMVS-HRr!4K;MYbD=kj59+(pO&89WV^!j;V0zROT557ZqYO~HFbNtCnge6>VU<3 z0j_nRVQ64r;pK(fyQ9cWK!t;_55)KW>B&#jW$*);h#%!CF60&TZ1i8+VS~XzpA?0>v2gF=q1p~rae~@1q%nq zqZ~mBqrj?+Dn{t?vIeN!irdKOXl7m>meGBk#w4_b_H--=7y|=Cf;5Gdt?l5+11el- zf;q1KN-*DH@$cU;^YbbQgS*#Tom11(`;Oc{`{4SuK^XHb{x%%fKr;gY zTr4y4^6>#(P}9&L1E7tYC6$(zG6uTnXk1$R-fVZ%Lc(TcYbjJ3l$7pO~min zcY1mnwmj3pn>&s8i}cn9J84H#Q?uRool~JaS(rqa1f`(8eeDUA6GF3X)%!D+YrF5} z`M|vs7=(Y%&kk@u1yJxoH>JfNc7y~3{w^+J0GAmtO9O*|0>htrU5=OH$Sp^ML52cj zlto2OPF}KLt)r_;%gBgHy7c+}%p$))Wq~z!ai&%%(%_0(P*@mves06!VPzGO&E){s ztD~YK%8qxm-eNmrsg#wSedpaRoiucQP8S>;ES)4SCI;@%^IDeSakDMZ^Lm`^_E?9K za|FJ!&>swq?7Tk&%km6NIK6If%mwy#j~k-8-Y?!j;Q&YO7z#i|Rflh|ilLz*000Z} ze6xc+=Vxe0JZ`4K(ERJ!eqgU2L|OV};onS_$H$8keqeWZcTie?zX$;mv_Tzq-O6OG ze&?S$mrjqHkt_FuJ5Of$WJCW?b%@c9+J&7R2lB(yxnfQxJ4n4RDQ?$O6m@lVlkV47 zFTamFDUr+jd)DaaXkhsOv+(ipaicYD&rz%72QbWLth7ab+G*{ccVu^-dMFFCv%(Z; zYYD%SDAsC2K^}$)cHeJ$f3Pw=JUj#e%UwMiFGapzT}^G*xn2C@#JT;}lfO-m3Dphg zvzyrU(P+BH40Iau$L-!AFq5L(EG#Y0Zf-`|T0M!L8TvyYosmn$tqRV!yPW)l8oRgE zcrgd40bvrIFo1xp{anVP)^TB%KbS9-mDp@*w1qb#g?^BD0%Ax>Pmews9UaBR!$ZRj zee7bG95P|SAJu1CdE!oY7~zmdk2K@Vrc9qKtfI>*b9%iu$HK;jbaHcZ!?6EZh9A8b>OS`^R(St3cM zT#`b$vO1=^db|4-9&p3IvuT%?=NA_#Mjm)_k#G9~!8y0iudXDLDENtxiQ=Uq8dAI7 zd<1nXTD4=^E44-roRni#Fhb2(t-&o(f1-YFdF-r39zkI9@$%Bp)1yB~ z0gE^zLs(s1r4j>3ru(K=S(2RDn0`tN?5MbQ(Jt}CLRfAIqK;TA3??q^1YGu;M$XPE zD7vbuVzRQ)6+g8*Y--y5zx{L}FF#%%ijbNb8$}tg&>vJQF@V7v(66YH0kS++v|YRl zFz9BixCnygt*TP6HV`a%Ny+vKJBshEh~roi!7o%zA!#naaREQbusET`x|z z)t-fulPaRNw$|eN>(gYj3ixkvYcvlqtk;`7+3z&X&6#pxa#VvrYeSzeFE3BzDXFQL z|5MWXI$oIZ?D{&LftByvBS;>P%g9Lg^|d`|+S<>w+FB+VS=r&2+goOMc=$gaC+OB& z9&T=X&h0~d4%=O?KI7+OV=$F!aQZ8-p`w>-P35QX)m1hNmHGZ(nTd(0B0e-2Mb*`^ z5MaP`Fkwiabb7kf*0t_NDKM|uSYHoW%FE3)x3I8y&slKGrPr)Qi5~?}CF6vNczAdu zcGmyWNaLGu~H}0GDWhqy!=(leDvctwSt`7?B*tr!^Rrr+}t>T`%pCW$6#xa zUB0Zm-0S_SRYJS2tZYO>u+8U{b){DSmrcmOIVs{o8n~(|AP$~iPYlS!f@W+T@(bcs zm6flP3sl;)ia;_2D!g{uTDuFis;cVH!ClcONVSmnzlgLntbsk|fWOA&DzrT>`|$H; zu8A2ZhC&~=V!-h*W0dG&93rA)V7*^lKVt?~*VY1s1{h2;?XsdGQSk#HNm{tOr)e>0 zK+K|5j*kPjeV_Fy0CaG1b$ab4F7&S?pxgf6zIgcfpb?`7K!QJ8CNBY=J-_qJT^7z<7ghH4B>!4{ykUV*Om7(~t zv#ToyS@0#Gqk}h5HmeN4j%N;3%^W_D>)~KF`Q(NM7STc!`&Qi&!bIs1;H2Y|6F{ko z1OWjdA*OjhFiocOg=TX3JfeaO2ATioZ-?$jET9Af8zu%Uu?6#d%8U^rd&iON=f#A?q*4C&; z-uf#*AAu?iL;|#&l9HmNq7t-oQ{LK|{-gK9d7)TM#mnneD6_2nLA%W|(uy?`Lt_d| zNkc=@#f42?US3U8^WgbCkpkc-yy6C|iAZrW@nU6OUS4kJLl_`sl2t2Eppn)7^W?v{ z<^Y~ympAqF^d!e~nCz(iw(Ha#^|;Z?L49lj4Sk#F3GaA~;u4Y&U&u z-CTPOd6wuQnxV*evQC+>^m_AljNxiUR+#^AS{jbR#(UTzin%6 zef|f0_=8A$y>E5*nkCPF?h22mi8v=P9F{@(qFK{{z*RXwE=Sj{+?c z<~c!g^K*UA@uR)F+t*9hGAAD=GyOWo1=tF$HkhU*;xW+DzP6%ME9iNafp2<|7dF>8J&M;{pLlD2UgJ8U_6a&_q&v literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/Makefile b/cinelerra-5.1/plugins/Makefile index bd7d8591..6ed357c7 100644 --- a/cinelerra-5.1/plugins/Makefile +++ b/cinelerra-5.1/plugins/Makefile @@ -171,7 +171,7 @@ all: $(PLUGIN_DIR) $(DIRS) $(DATA) $(LADSPA_DIR) $(PLUGIN_DIR): mkdir -p $@ -$(DATA): +$(DATA): $(PLUGIN_DIR) cp -a $(notdir $@) $(PLUGIN_DIR)/. $(LADSPA_DIR): -- 2.26.2