From: Good Guy Date: Fri, 25 May 2018 23:10:42 +0000 (-0600) Subject: lv2 rework, sams ffmpeg icons, elision patch X-Git-Url: https://git.cinelerra-gg.org/git/?a=commitdiff_plain;h=803cf48f8f7ee246eb5473e55fc2125e8b398250;p=goodguy%2Fhistory.git lv2 rework, sams ffmpeg icons, elision patch --- 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 00000000..c1d5b4b9 Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity/ff_entropy.png differ 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 00000000..29584731 Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity/ff_fillborders.png differ 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 00000000..fade41fc Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity/ff_normalize.png differ 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 00000000..4794bc6b Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity/ff_setrange.png differ diff --git a/cinelerra-5.1/picon/cinfinity/ff_vfrdet.png b/cinelerra-5.1/picon/cinfinity/ff_vfrdet.png new file mode 100644 index 00000000..5f5e96f4 Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity/ff_vfrdet.png differ 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 00000000..b89d9d31 Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity2/ff_entropy.png differ diff --git a/cinelerra-5.1/picon/cinfinity2/ff_fillborders.png b/cinelerra-5.1/picon/cinfinity2/ff_fillborders.png new file mode 100644 index 00000000..6ee43f4a Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity2/ff_fillborders.png differ 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 00000000..e7f11335 Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity2/ff_normalize.png differ diff --git a/cinelerra-5.1/picon/cinfinity2/ff_setrange.png b/cinelerra-5.1/picon/cinfinity2/ff_setrange.png new file mode 100644 index 00000000..a922c42e Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity2/ff_setrange.png differ diff --git a/cinelerra-5.1/picon/cinfinity2/ff_vfrdet.png b/cinelerra-5.1/picon/cinfinity2/ff_vfrdet.png new file mode 100644 index 00000000..7e1b8171 Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity2/ff_vfrdet.png differ 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):