[SCM] zynjacku packaging branch, master, updated. upstream/4-4-gb252f84
mira-guest at users.alioth.debian.org
mira-guest at users.alioth.debian.org
Mon Jul 20 14:08:01 UTC 2009
The following commit has been merged in the master branch:
commit 344fac04fe0f5ececd2245d7b89103e24f94f8ec
Author: miramikes <mira at 64studio.64studio>
Date: Mon Jul 20 15:45:05 2009 +0200
Imported Upstream version 5
diff --git a/Makefile.am b/Makefile.am
index 9018e33..19bb10b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,19 +32,18 @@ endif
zynjacku_c_CFLAGS += @GTK_CFLAGS@
zynjacku_c_CFLAGS += @PYGTK_CFLAGS@
-zynjacku_c_CFLAGS += @SLV2_CFLAGS@
zynjacku_c_CFLAGS += @JACK_CFLAGS@
zynjacku_c_CFLAGS += @LV2DYNPARAMHOST1_CFLAGS@
INCLUDES = $(PYTHON_INCLUDES) $(zynjacku_c_CFLAGS)
-pkgpyexecdir = $(pythondir)
+pkgpyexecdir = $(pythondir)/zynworld/
-pkgpyexec_LTLIBRARIES = zynjacku_c.la
+pkgpyexec_LTLIBRARIES = zynjacku_c.la zynjacku_ttl.la
+pkgpyexec_SCRIPTS = zynworld/lv2.py zynworld/__init__.py
ZYNJACKU_LDFLAGS = @GTK_LIBS@
ZYNJACKU_LDFLAGS += @PYGTK_LIBS@
-ZYNJACKU_LDFLAGS += @SLV2_LIBS@
ZYNJACKU_LDFLAGS += @JACK_LIBS@
ZYNJACKU_LDFLAGS += @LV2DYNPARAMHOST1_LIBS@
@@ -60,12 +59,8 @@ zynjacku_c_la_SOURCES += jack_compat.c
zynjacku_c_la_SOURCES += plugin.c
zynjacku_c_la_SOURCES += plugin.h
zynjacku_c_la_SOURCES += plugin_internal.h
-zynjacku_c_la_SOURCES += synth.h
-zynjacku_c_la_SOURCES += effect.h
zynjacku_c_la_SOURCES += lv2.c
zynjacku_c_la_SOURCES += lv2.h
-zynjacku_c_la_SOURCES += plugin_repo.c
-zynjacku_c_la_SOURCES += plugin_repo.h
zynjacku_c_la_SOURCES += log.c
zynjacku_c_la_SOURCES += log.h
zynjacku_c_la_SOURCES += zynjacku_wrap.c
@@ -77,6 +72,7 @@ zynjacku_c_la_SOURCES += gtk2gui.h
zynjacku_c_la_SOURCES += hints.c
zynjacku_c_la_SOURCES += hints.h
zynjacku_c_la_SOURCES += list.h
+zynjacku_c_la_SOURCES += lv2_ui.h
zynjacku_c_la_SOURCES += lv2-miditype.h
zynjacku_c_la_SOURCES += lv2_contexts.h
zynjacku_c_la_SOURCES += lv2_data_access.h
@@ -100,10 +96,14 @@ zynjacku_c_la_SOURCES += midi_cc_map_internal.h
PYGTK_DEFS=`pkg-config --variable=defsdir pygtk-2.0`
PYGTK_CODEGEN=`pkg-config --variable=codegendir pygtk-2.0`
-zynjacku.defs: engine.h rack.h plugin.h enum.h hints.h midi_cc_map.h
+zynjacku.defs: engine.h rack.h plugin.h enum.h hints.h midi_cc_map.h lv2.h
python $(PYGTK_CODEGEN)/h2def.py $^ | \
sed -e '/define-method set_parameter/,/^$$/ { s/\("midi_cc_map_obj_ptr"\)/\1 (null-ok) (default "NULL")/g; }' \
-e '/define-method set_midi_cc_map/,/^$$/ { s/\("midi_cc_map_obj_ptr"\)/\1 (null-ok)/g; }' \
+ -e '/define-method ui_on/,/^$$/ { s/\("ui_uri"\)/\1 (null-ok) (default "NULL")/g; }' \
+ -e '/define-method ui_on/,/^$$/ { s/\("ui_type_uri"\)/\1 (null-ok) (default "NULL")/g; }' \
+ -e '/define-method ui_on/,/^$$/ { s/\("ui_binary_path"\)/\1 (null-ok) (default "NULL")/g; }' \
+ -e '/define-method ui_on/,/^$$/ { s/\("ui_bundle_path"\)/\1 (null-ok) (default "NULL")/g; }' \
> $@
# Generate the C wrapper from the defs and our override file
@@ -114,17 +114,28 @@ zynjacku_wrap.c: zynjacku.defs zynjacku.override
--override zynjacku.override \
zynjacku.defs > $@
+zynjacku_ttl_la_LDFLAGS = -module -avoid-version
+
+zynjacku_ttl_la_SOURCES = zynjacku_ttl.c
+zynjacku_ttl_la_SOURCES += ttl_lexer.h
+zynjacku_ttl_la_SOURCES += flex_ttl.c
+zynjacku_ttl_la_SOURCES += flex_ttl.h
+
CLEANFILES = zynjacku_wrap.c *.pyc zynjacku.defs
-EXTRA_DIST = zynjacku.override zynjacku.defs zynjacku.py lv2rack.py
+EXTRA_DIST = zynjacku.override zynjacku.defs zynjacku.py lv2rack.py zynspect.py zynworld/__init__.py zynworld/lv2.py
-bin_SCRIPTS = zynjacku.py lv2rack.py
+bin_SCRIPTS = zynjacku.py lv2rack.py zynspect.py
zynjackudir = $(pkgdatadir)
-dist_zynjacku_DATA = gpl.txt zynjacku.glade logo.png
+dist_zynjacku_DATA = gpl.txt zynjacku.glade art/logo/logo.png
install-exec-hook:
ln -vfs zynjacku.py $(DESTDIR)$(bindir)/zynjacku
ln -vfs lv2rack.py $(DESTDIR)$(bindir)/lv2rack
+ ln -vfs zynspect.py $(DESTDIR)$(bindir)/zynspect
uninstall-hook:
rm -vf $(DESTDIR)$(bindir)/zynjacku
+
+ttl_flex_regenerate:
+ flex --batch --nodefault -o flex_ttl.c --header-file=flex_ttl.h ttl.l
diff --git a/Makefile.in b/Makefile.in
index 69f28d2..ddbc542 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -81,30 +81,35 @@ am__vpath_adj = case $$p in \
esac;
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
am__installdirs = "$(DESTDIR)$(pkgpyexecdir)" "$(DESTDIR)$(bindir)" \
- "$(DESTDIR)$(zynjackudir)"
+ "$(DESTDIR)$(pkgpyexecdir)" "$(DESTDIR)$(zynjackudir)"
pkgpyexecLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(pkgpyexec_LTLIBRARIES)
zynjacku_c_la_DEPENDENCIES =
am__zynjacku_c_la_SOURCES_DIST = zynjacku.h engine.c engine.h rack.c \
- rack.h jack_compat.c plugin.c plugin.h plugin_internal.h \
- synth.h effect.h lv2.c lv2.h plugin_repo.c plugin_repo.h log.c \
- log.h zynjacku_wrap.c zynjackumodule.c enum.c enum.h gtk2gui.c \
- gtk2gui.h hints.c hints.h list.h lv2-miditype.h lv2_contexts.h \
- lv2_data_access.h lv2_event.h lv2_event_helpers.h \
- lv2_uri_map.h lv2_string_port.h lv2_progress.h \
- lv2_external_ui.h rtmempool.c rtmempool.h midi_cc_map.c \
- midi_cc_map.h midi_cc_map_internal.h
+ rack.h jack_compat.c plugin.c plugin.h plugin_internal.h lv2.c \
+ lv2.h log.c log.h zynjacku_wrap.c zynjackumodule.c enum.c \
+ enum.h gtk2gui.c gtk2gui.h hints.c hints.h list.h lv2_ui.h \
+ lv2-miditype.h lv2_contexts.h lv2_data_access.h lv2_event.h \
+ lv2_event_helpers.h lv2_uri_map.h lv2_string_port.h \
+ lv2_progress.h lv2_external_ui.h rtmempool.c rtmempool.h \
+ midi_cc_map.c midi_cc_map.h midi_cc_map_internal.h
@HAVE_DYNPARAMS_TRUE at am__objects_1 = rtmempool.lo
am_zynjacku_c_la_OBJECTS = engine.lo rack.lo jack_compat.lo plugin.lo \
- lv2.lo plugin_repo.lo log.lo zynjacku_wrap.lo \
- zynjackumodule.lo enum.lo gtk2gui.lo hints.lo $(am__objects_1) \
- midi_cc_map.lo
+ lv2.lo log.lo zynjacku_wrap.lo zynjackumodule.lo enum.lo \
+ gtk2gui.lo hints.lo $(am__objects_1) midi_cc_map.lo
zynjacku_c_la_OBJECTS = $(am_zynjacku_c_la_OBJECTS)
zynjacku_c_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(zynjacku_c_la_LDFLAGS) $(LDFLAGS) -o $@
+zynjacku_ttl_la_LIBADD =
+am_zynjacku_ttl_la_OBJECTS = zynjacku_ttl.lo flex_ttl.lo
+zynjacku_ttl_la_OBJECTS = $(am_zynjacku_ttl_la_OBJECTS)
+zynjacku_ttl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(zynjacku_ttl_la_LDFLAGS) $(LDFLAGS) -o $@
binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
-SCRIPTS = $(bin_SCRIPTS)
+pkgpyexecSCRIPT_INSTALL = $(INSTALL_SCRIPT)
+SCRIPTS = $(bin_SCRIPTS) $(pkgpyexec_SCRIPTS)
depcomp = $(SHELL) $(top_srcdir)/config/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
@@ -116,8 +121,9 @@ CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
-SOURCES = $(zynjacku_c_la_SOURCES)
-DIST_SOURCES = $(am__zynjacku_c_la_SOURCES_DIST)
+SOURCES = $(zynjacku_c_la_SOURCES) $(zynjacku_ttl_la_SOURCES)
+DIST_SOURCES = $(am__zynjacku_c_la_SOURCES_DIST) \
+ $(zynjacku_ttl_la_SOURCES)
dist_zynjackuDATA_INSTALL = $(INSTALL_DATA)
DATA = $(dist_zynjacku_DATA)
ETAGS = etags
@@ -198,6 +204,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PYGTK_CFLAGS = @PYGTK_CFLAGS@
PYGTK_LIBS = @PYGTK_LIBS@
+PYLIBDIR = @PYLIBDIR@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_INCLUDES = @PYTHON_INCLUDES@
@@ -208,8 +215,6 @@ RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
-SLV2_CFLAGS = @SLV2_CFLAGS@
-SLV2_LIBS = @SLV2_LIBS@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
@@ -253,7 +258,7 @@ mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
-pkgpyexecdir = $(pythondir)
+pkgpyexecdir = $(pythondir)/zynworld/
pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -269,34 +274,37 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
DEFAULT_INCLUDES =
zynjacku_c_CFLAGS = -DDATA_DIR='"$(pkgdatadir)"' -Wall -g \
- $(am__append_2) @GTK_CFLAGS@ @PYGTK_CFLAGS@ @SLV2_CFLAGS@ \
- @JACK_CFLAGS@ @LV2DYNPARAMHOST1_CFLAGS@ $(am__empty)
+ $(am__append_2) @GTK_CFLAGS@ @PYGTK_CFLAGS@ @JACK_CFLAGS@ \
+ @LV2DYNPARAMHOST1_CFLAGS@ $(am__empty)
INCLUDES = $(PYTHON_INCLUDES) $(zynjacku_c_CFLAGS)
-pkgpyexec_LTLIBRARIES = zynjacku_c.la
-ZYNJACKU_LDFLAGS = @GTK_LIBS@ @PYGTK_LIBS@ @SLV2_LIBS@ @JACK_LIBS@ \
+pkgpyexec_LTLIBRARIES = zynjacku_c.la zynjacku_ttl.la
+pkgpyexec_SCRIPTS = zynworld/lv2.py zynworld/__init__.py
+ZYNJACKU_LDFLAGS = @GTK_LIBS@ @PYGTK_LIBS@ @JACK_LIBS@ \
@LV2DYNPARAMHOST1_LIBS@ $(am__empty)
zynjacku_c_la_LDFLAGS = -module -avoid-version $(ZYNJACKU_LDFLAGS)
zynjacku_c_la_LIBADD = $(ZYNJACKU_LIBS)
zynjacku_c_la_SOURCES = zynjacku.h engine.c engine.h rack.c rack.h \
- jack_compat.c plugin.c plugin.h plugin_internal.h synth.h \
- effect.h lv2.c lv2.h plugin_repo.c plugin_repo.h log.c log.h \
- zynjacku_wrap.c zynjackumodule.c enum.c enum.h gtk2gui.c \
- gtk2gui.h hints.c hints.h list.h lv2-miditype.h lv2_contexts.h \
- lv2_data_access.h lv2_event.h lv2_event_helpers.h \
- lv2_uri_map.h lv2_string_port.h lv2_progress.h \
- lv2_external_ui.h $(am__append_3) midi_cc_map.c midi_cc_map.h \
- midi_cc_map_internal.h
+ jack_compat.c plugin.c plugin.h plugin_internal.h lv2.c lv2.h \
+ log.c log.h zynjacku_wrap.c zynjackumodule.c enum.c enum.h \
+ gtk2gui.c gtk2gui.h hints.c hints.h list.h lv2_ui.h \
+ lv2-miditype.h lv2_contexts.h lv2_data_access.h lv2_event.h \
+ lv2_event_helpers.h lv2_uri_map.h lv2_string_port.h \
+ lv2_progress.h lv2_external_ui.h $(am__append_3) midi_cc_map.c \
+ midi_cc_map.h midi_cc_map_internal.h
#nodist_zynjacku_la_SOURCES =
# The path to the GTK+ python types (FIXME: use configure result)
PYGTK_DEFS = `pkg-config --variable=defsdir pygtk-2.0`
PYGTK_CODEGEN = `pkg-config --variable=codegendir pygtk-2.0`
+zynjacku_ttl_la_LDFLAGS = -module -avoid-version
+zynjacku_ttl_la_SOURCES = zynjacku_ttl.c ttl_lexer.h flex_ttl.c \
+ flex_ttl.h
CLEANFILES = zynjacku_wrap.c *.pyc zynjacku.defs
-EXTRA_DIST = zynjacku.override zynjacku.defs zynjacku.py lv2rack.py
-bin_SCRIPTS = zynjacku.py lv2rack.py
+EXTRA_DIST = zynjacku.override zynjacku.defs zynjacku.py lv2rack.py zynspect.py zynworld/__init__.py zynworld/lv2.py
+bin_SCRIPTS = zynjacku.py lv2rack.py zynspect.py
zynjackudir = $(pkgdatadir)
-dist_zynjacku_DATA = gpl.txt zynjacku.glade logo.png
+dist_zynjacku_DATA = gpl.txt zynjacku.glade art/logo/logo.png
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
@@ -381,6 +389,8 @@ clean-pkgpyexecLTLIBRARIES:
done
zynjacku_c.la: $(zynjacku_c_la_OBJECTS) $(zynjacku_c_la_DEPENDENCIES)
$(zynjacku_c_la_LINK) -rpath $(pkgpyexecdir) $(zynjacku_c_la_OBJECTS) $(zynjacku_c_la_LIBADD) $(LIBS)
+zynjacku_ttl.la: $(zynjacku_ttl_la_OBJECTS) $(zynjacku_ttl_la_DEPENDENCIES)
+ $(zynjacku_ttl_la_LINK) -rpath $(pkgpyexecdir) $(zynjacku_ttl_la_OBJECTS) $(zynjacku_ttl_la_LIBADD) $(LIBS)
install-binSCRIPTS: $(bin_SCRIPTS)
@$(NORMAL_INSTALL)
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@@ -400,6 +410,25 @@ uninstall-binSCRIPTS:
echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
rm -f "$(DESTDIR)$(bindir)/$$f"; \
done
+install-pkgpyexecSCRIPTS: $(pkgpyexec_SCRIPTS)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkgpyexecdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgpyexecdir)"
+ @list='$(pkgpyexec_SCRIPTS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ if test -f $$d$$p; then \
+ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
+ echo " $(pkgpyexecSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgpyexecdir)/$$f'"; \
+ $(pkgpyexecSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgpyexecdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-pkgpyexecSCRIPTS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgpyexec_SCRIPTS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
+ echo " rm -f '$(DESTDIR)$(pkgpyexecdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(pkgpyexecdir)/$$f"; \
+ done
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -409,6 +438,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/engine.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/enum.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/flex_ttl.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gtk2gui.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/hints.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/jack_compat.Plo at am__quote@
@@ -416,9 +446,9 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/lv2.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/midi_cc_map.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/plugin.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/plugin_repo.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/rack.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/rtmempool.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/zynjacku_ttl.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/zynjacku_wrap.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/zynjackumodule.Plo at am__quote@
@@ -646,7 +676,7 @@ check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(SCRIPTS) $(DATA) config.h
installdirs:
- for dir in "$(DESTDIR)$(pkgpyexecdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(zynjackudir)"; do \
+ for dir in "$(DESTDIR)$(pkgpyexecdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgpyexecdir)" "$(DESTDIR)$(zynjackudir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
@@ -700,7 +730,8 @@ install-data-am: install-dist_zynjackuDATA
install-dvi: install-dvi-am
-install-exec-am: install-binSCRIPTS install-pkgpyexecLTLIBRARIES
+install-exec-am: install-binSCRIPTS install-pkgpyexecLTLIBRARIES \
+ install-pkgpyexecSCRIPTS
@$(NORMAL_INSTALL)
$(MAKE) $(AM_MAKEFLAGS) install-exec-hook
@@ -737,7 +768,7 @@ ps: ps-am
ps-am:
uninstall-am: uninstall-binSCRIPTS uninstall-dist_zynjackuDATA \
- uninstall-pkgpyexecLTLIBRARIES
+ uninstall-pkgpyexecLTLIBRARIES uninstall-pkgpyexecSCRIPTS
@$(NORMAL_INSTALL)
$(MAKE) $(AM_MAKEFLAGS) uninstall-hook
@@ -755,19 +786,24 @@ uninstall-am: uninstall-binSCRIPTS uninstall-dist_zynjackuDATA \
install-exec install-exec-am install-exec-hook install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-pkgpyexecLTLIBRARIES \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-binSCRIPTS \
- uninstall-dist_zynjackuDATA uninstall-hook \
- uninstall-pkgpyexecLTLIBRARIES
+ install-pkgpyexecSCRIPTS install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-binSCRIPTS uninstall-dist_zynjackuDATA \
+ uninstall-hook uninstall-pkgpyexecLTLIBRARIES \
+ uninstall-pkgpyexecSCRIPTS
-zynjacku.defs: engine.h rack.h plugin.h enum.h hints.h midi_cc_map.h
+zynjacku.defs: engine.h rack.h plugin.h enum.h hints.h midi_cc_map.h lv2.h
python $(PYGTK_CODEGEN)/h2def.py $^ | \
sed -e '/define-method set_parameter/,/^$$/ { s/\("midi_cc_map_obj_ptr"\)/\1 (null-ok) (default "NULL")/g; }' \
-e '/define-method set_midi_cc_map/,/^$$/ { s/\("midi_cc_map_obj_ptr"\)/\1 (null-ok)/g; }' \
+ -e '/define-method ui_on/,/^$$/ { s/\("ui_uri"\)/\1 (null-ok) (default "NULL")/g; }' \
+ -e '/define-method ui_on/,/^$$/ { s/\("ui_type_uri"\)/\1 (null-ok) (default "NULL")/g; }' \
+ -e '/define-method ui_on/,/^$$/ { s/\("ui_binary_path"\)/\1 (null-ok) (default "NULL")/g; }' \
+ -e '/define-method ui_on/,/^$$/ { s/\("ui_bundle_path"\)/\1 (null-ok) (default "NULL")/g; }' \
> $@
# Generate the C wrapper from the defs and our override file
@@ -781,9 +817,13 @@ zynjacku_wrap.c: zynjacku.defs zynjacku.override
install-exec-hook:
ln -vfs zynjacku.py $(DESTDIR)$(bindir)/zynjacku
ln -vfs lv2rack.py $(DESTDIR)$(bindir)/lv2rack
+ ln -vfs zynspect.py $(DESTDIR)$(bindir)/zynspect
uninstall-hook:
rm -vf $(DESTDIR)$(bindir)/zynjacku
+
+ttl_flex_regenerate:
+ flex --batch --nodefault -o flex_ttl.c --header-file=flex_ttl.h ttl.l
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/NEWS b/NEWS
index 31433ef..c135346 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,17 @@
+= Version 5 on 2009-06-13 =
+ * slv2 is no longer required
+ * cache list of suitable plugins
+ * speedup plugin list window
+ * new tool, zynspect, that can be used to list and inspect available
+ lv2 plguins.
+ * Fix assert when restoring rack presets
+ * By default, sort plugins by name
+ * Experimental support for dynmanifest extension. Combined with
+ NASPRO allows loading ladspa plugins in lv2rack.
+ * Set plugin GUI window's role to "plugin_ui" (for WM kludges etc)
+ * single plugin mode for lv2rack
+ * Hide external UIs when zynjacku/lv2rack quits
+
= Version 4 on 2009-01-28 =
* lv2rack does no longer require PHAT (it was not really using it even
in zynjacku-3 release)
diff --git a/art/logo/logo.png b/art/logo/logo.png
new file mode 100644
index 0000000..338df3b
Binary files /dev/null and b/art/logo/logo.png differ
diff --git a/configure b/configure
index 9a4aef4..b3c58d5 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for zynjacku 4.
+# Generated by GNU Autoconf 2.61 for zynjacku 5.
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='zynjacku'
PACKAGE_TARNAME='zynjacku'
-PACKAGE_VERSION='4'
-PACKAGE_STRING='zynjacku 4'
+PACKAGE_VERSION='5'
+PACKAGE_STRING='zynjacku 5'
PACKAGE_BUGREPORT=''
# Factoring default headers for most tests.
@@ -886,8 +886,6 @@ LV2DYNPARAMHOST1_CFLAGS
LV2DYNPARAMHOST1_LIBS
HAVE_DYNPARAMS_TRUE
HAVE_DYNPARAMS_FALSE
-SLV2_CFLAGS
-SLV2_LIBS
JACK_MIDI_CFLAGS
JACK_MIDI_LIBS
OLD_JACK_MIDI_CFLAGS
@@ -904,6 +902,7 @@ pkgpythondir
pyexecdir
pkgpyexecdir
PYTHON_INCLUDES
+PYLIBDIR
LIBOBJS
LTLIBOBJS'
ac_subst_files=''
@@ -933,12 +932,11 @@ JACK_CFLAGS
JACK_LIBS
LV2DYNPARAMHOST1_CFLAGS
LV2DYNPARAMHOST1_LIBS
-SLV2_CFLAGS
-SLV2_LIBS
JACK_MIDI_CFLAGS
JACK_MIDI_LIBS
OLD_JACK_MIDI_CFLAGS
-OLD_JACK_MIDI_LIBS'
+OLD_JACK_MIDI_LIBS
+PYLIBDIR'
# Initialize some variables set by options.
@@ -1441,7 +1439,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures zynjacku 4 to adapt to many kinds of systems.
+\`configure' configures zynjacku 5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1511,7 +1509,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of zynjacku 4:";;
+ short | recursive ) echo "Configuration of zynjacku 5:";;
esac
cat <<\_ACEOF
@@ -1563,8 +1561,6 @@ Some influential environment variables:
C compiler flags for LV2DYNPARAMHOST1, overriding pkg-config
LV2DYNPARAMHOST1_LIBS
linker flags for LV2DYNPARAMHOST1, overriding pkg-config
- SLV2_CFLAGS C compiler flags for SLV2, overriding pkg-config
- SLV2_LIBS linker flags for SLV2, overriding pkg-config
JACK_MIDI_CFLAGS
C compiler flags for JACK_MIDI, overriding pkg-config
JACK_MIDI_LIBS
@@ -1573,6 +1569,7 @@ Some influential environment variables:
C compiler flags for OLD_JACK_MIDI, overriding pkg-config
OLD_JACK_MIDI_LIBS
linker flags for OLD_JACK_MIDI, overriding pkg-config
+ PYLIBDIR Override default Python site-packages dir
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
@@ -1637,7 +1634,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-zynjacku configure 4
+zynjacku configure 5
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1651,7 +1648,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by zynjacku $as_me 4, which was
+It was created by zynjacku $as_me 5, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -2341,7 +2338,7 @@ fi
# Define the identity of the package.
PACKAGE='zynjacku'
- VERSION='4'
+ VERSION='5'
cat >>confdefs.h <<_ACEOF
@@ -4411,7 +4408,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 4414 "configure"' > conftest.$ac_ext
+ echo '#line 4411 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -7148,11 +7145,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7151: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7148: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7155: \$? = $ac_status" >&5
+ echo "$as_me:7152: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7438,11 +7435,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7441: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7438: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7445: \$? = $ac_status" >&5
+ echo "$as_me:7442: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7542,11 +7539,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7545: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7542: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7549: \$? = $ac_status" >&5
+ echo "$as_me:7546: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -9891,7 +9888,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 9894 "configure"
+#line 9891 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9991,7 +9988,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 9994 "configure"
+#line 9991 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12411,11 +12408,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:12414: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:12411: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:12418: \$? = $ac_status" >&5
+ echo "$as_me:12415: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -12515,11 +12512,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:12518: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:12515: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:12522: \$? = $ac_status" >&5
+ echo "$as_me:12519: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -14077,11 +14074,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:14080: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14077: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:14084: \$? = $ac_status" >&5
+ echo "$as_me:14081: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -14181,11 +14178,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:14184: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14181: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:14188: \$? = $ac_status" >&5
+ echo "$as_me:14185: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -16368,11 +16365,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:16371: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:16368: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:16375: \$? = $ac_status" >&5
+ echo "$as_me:16372: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -16658,11 +16655,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:16661: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:16658: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:16665: \$? = $ac_status" >&5
+ echo "$as_me:16662: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -16762,11 +16759,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:16765: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:16762: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:16769: \$? = $ac_status" >&5
+ echo "$as_me:16766: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -20071,117 +20068,6 @@ else
fi
-pkg_failed=no
-{ echo "$as_me:$LINENO: checking for SLV2" >&5
-echo $ECHO_N "checking for SLV2... $ECHO_C" >&6; }
-
-if test -n "$PKG_CONFIG"; then
- if test -n "$SLV2_CFLAGS"; then
- pkg_cv_SLV2_CFLAGS="$SLV2_CFLAGS"
- else
- if test -n "$PKG_CONFIG" && \
- { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"slv2 >= 0.6.1\"") >&5
- ($PKG_CONFIG --exists --print-errors "slv2 >= 0.6.1") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- pkg_cv_SLV2_CFLAGS=`$PKG_CONFIG --cflags "slv2 >= 0.6.1" 2>/dev/null`
-else
- pkg_failed=yes
-fi
- fi
-else
- pkg_failed=untried
-fi
-if test -n "$PKG_CONFIG"; then
- if test -n "$SLV2_LIBS"; then
- pkg_cv_SLV2_LIBS="$SLV2_LIBS"
- else
- if test -n "$PKG_CONFIG" && \
- { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"slv2 >= 0.6.1\"") >&5
- ($PKG_CONFIG --exists --print-errors "slv2 >= 0.6.1") 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; then
- pkg_cv_SLV2_LIBS=`$PKG_CONFIG --libs "slv2 >= 0.6.1" 2>/dev/null`
-else
- pkg_failed=yes
-fi
- fi
-else
- pkg_failed=untried
-fi
-
-
-
-if test $pkg_failed = yes; then
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
- _pkg_short_errors_supported=yes
-else
- _pkg_short_errors_supported=no
-fi
- if test $_pkg_short_errors_supported = yes; then
- SLV2_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "slv2 >= 0.6.1"`
- else
- SLV2_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "slv2 >= 0.6.1"`
- fi
- # Put the nasty error message in config.log where it belongs
- echo "$SLV2_PKG_ERRORS" >&5
-
- { { echo "$as_me:$LINENO: error: Package requirements (slv2 >= 0.6.1) were not met:
-
-$SLV2_PKG_ERRORS
-
-Consider adjusting the PKG_CONFIG_PATH environment variable if you
-installed software in a non-standard prefix.
-
-Alternatively, you may set the environment variables SLV2_CFLAGS
-and SLV2_LIBS to avoid the need to call pkg-config.
-See the pkg-config man page for more details.
-" >&5
-echo "$as_me: error: Package requirements (slv2 >= 0.6.1) were not met:
-
-$SLV2_PKG_ERRORS
-
-Consider adjusting the PKG_CONFIG_PATH environment variable if you
-installed software in a non-standard prefix.
-
-Alternatively, you may set the environment variables SLV2_CFLAGS
-and SLV2_LIBS to avoid the need to call pkg-config.
-See the pkg-config man page for more details.
-" >&2;}
- { (exit 1); exit 1; }; }
-elif test $pkg_failed = untried; then
- { { echo "$as_me:$LINENO: error: The pkg-config script could not be found or is too old. Make sure it
-is in your PATH or set the PKG_CONFIG environment variable to the full
-path to pkg-config.
-
-Alternatively, you may set the environment variables SLV2_CFLAGS
-and SLV2_LIBS to avoid the need to call pkg-config.
-See the pkg-config man page for more details.
-
-To get pkg-config, see <http://pkg-config.freedesktop.org/>.
-See \`config.log' for more details." >&5
-echo "$as_me: error: The pkg-config script could not be found or is too old. Make sure it
-is in your PATH or set the PKG_CONFIG environment variable to the full
-path to pkg-config.
-
-Alternatively, you may set the environment variables SLV2_CFLAGS
-and SLV2_LIBS to avoid the need to call pkg-config.
-See the pkg-config man page for more details.
-
-To get pkg-config, see <http://pkg-config.freedesktop.org/>.
-See \`config.log' for more details." >&2;}
- { (exit 1); exit 1; }; }
-else
- SLV2_CFLAGS=$pkg_cv_SLV2_CFLAGS
- SLV2_LIBS=$pkg_cv_SLV2_LIBS
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
- :
-fi
-
# JACK MIDI
have_jackmidi="unknown"
# Check whether --enable-jackmidi was given.
@@ -20718,6 +20604,41 @@ CPPFLAGS="$save_CPPFLAGS"
#AS_AC_EXPAND(PYTHONDIR, $pythondir)
#AC_SUBST(PYTHONDIR)
+# Allow the user to override AM_PATH_PYTHON choice of PYTHON_PREFIX
+# and PYTHON_EXEC_PREFIX by setting PYLIBDIR
+
+if test "$PYLIBDIR" ; then
+ pylibdir=$PYLIBDIR
+ { echo "$as_me:$LINENO: User set PYLIBDIR... $pylibdir" >&5
+echo "$as_me: User set PYLIBDIR... $pylibdir" >&6;}
+ pythondir=$pylibdir
+
+ pyexecdir=$pylibdir
+
+fi
+
+# Warn if python does not search in the installed places
+#AC_MSG_NOTICE([Checking to see whether Python will find installed files...])
+
+# Figure out the script directory
+if test "$prefix" == 'NONE'; then
+ #AC_MSG_NOTICE([prefix not set, falling back to ac_default_prefix...])
+ pyprefix=$ac_default_prefix
+else
+ pyprefix=$prefix
+fi
+abs_pythondir=`echo $pythondir | $SED s='${prefix}'=$pyprefix=`
+#AC_MSG_NOTICE([Python script dir will be: $abs_pythondir])
+match_pythondir=no
+for p in `$PYTHON -c "import sys
+for p in sys.path:
+ print p"`
+do
+ #AC_MSG_NOTICE([Checking Python sys.path entry $p ...])
+ if test $p == $abs_pythondir ; then
+ match_pythondir=
+ fi
+done
ac_config_files="$ac_config_files Makefile"
cat >confcache <<\_ACEOF
@@ -21165,7 +21086,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by zynjacku $as_me 4, which was
+This file was extended by zynjacku $as_me 5, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -21218,7 +21139,7 @@ Report bugs to <bug-autoconf at gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-zynjacku config.status 4
+zynjacku config.status 5
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
@@ -21558,8 +21479,6 @@ LV2DYNPARAMHOST1_CFLAGS!$LV2DYNPARAMHOST1_CFLAGS$ac_delim
LV2DYNPARAMHOST1_LIBS!$LV2DYNPARAMHOST1_LIBS$ac_delim
HAVE_DYNPARAMS_TRUE!$HAVE_DYNPARAMS_TRUE$ac_delim
HAVE_DYNPARAMS_FALSE!$HAVE_DYNPARAMS_FALSE$ac_delim
-SLV2_CFLAGS!$SLV2_CFLAGS$ac_delim
-SLV2_LIBS!$SLV2_LIBS$ac_delim
JACK_MIDI_CFLAGS!$JACK_MIDI_CFLAGS$ac_delim
JACK_MIDI_LIBS!$JACK_MIDI_LIBS$ac_delim
OLD_JACK_MIDI_CFLAGS!$OLD_JACK_MIDI_CFLAGS$ac_delim
@@ -21576,11 +21495,12 @@ pkgpythondir!$pkgpythondir$ac_delim
pyexecdir!$pyexecdir$ac_delim
pkgpyexecdir!$pkgpyexecdir$ac_delim
PYTHON_INCLUDES!$PYTHON_INCLUDES$ac_delim
+PYLIBDIR!$PYLIBDIR$ac_delim
LIBOBJS!$LIBOBJS$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 43; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 42; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
@@ -22187,9 +22107,40 @@ echo "${ECHO_T}========================" >&6; }
echo "${ECHO_T}Prefix : $prefix" >&6; }
{ echo "$as_me:$LINENO: result: Dynparam1 plugins support : $HAVE_DYNPARAMS" >&5
echo "${ECHO_T}Dynparam1 plugins support : $HAVE_DYNPARAMS" >&6; }
-{ echo "$as_me:$LINENO: result: Python dir : $PYTHON_INCLUDES" >&5
-echo "${ECHO_T}Python dir : $PYTHON_INCLUDES" >&6; }
+{ echo "$as_me:$LINENO: result: Python include dir : $PYTHON_INCLUDES" >&5
+echo "${ECHO_T}Python include dir : $PYTHON_INCLUDES" >&6; }
+{ echo "$as_me:$LINENO: result: Python script dir : $abs_pythondir" >&5
+echo "${ECHO_T}Python script dir : $abs_pythondir" >&6; }
{ echo "$as_me:$LINENO: result: Dev version : $dev_version" >&5
echo "${ECHO_T}Dev version : $dev_version" >&6; }
{ echo "$as_me:$LINENO: result: " >&5
echo "${ECHO_T}" >&6; }
+
+if test "$match_pythondir"; then
+ { echo "$as_me:$LINENO: WARNING: ==================================================" >&5
+echo "$as_me: WARNING: ==================================================" >&2;}
+ { echo "$as_me:$LINENO: WARNING: == ==" >&5
+echo "$as_me: WARNING: == ==" >&2;}
+ { echo "$as_me:$LINENO: WARNING: == pythondir is NOT in your Python's sys.path ==" >&5
+echo "$as_me: WARNING: == pythondir is NOT in your Python's sys.path ==" >&2;}
+ { echo "$as_me:$LINENO: WARNING: == which means you should add it to PYTHONPATH ==" >&5
+echo "$as_me: WARNING: == which means you should add it to PYTHONPATH ==" >&2;}
+ { echo "$as_me:$LINENO: WARNING: == at runtime, or add a .pth file to one of ==" >&5
+echo "$as_me: WARNING: == at runtime, or add a .pth file to one of ==" >&2;}
+ { echo "$as_me:$LINENO: WARNING: == your Python's existing sys.path directories. ==" >&5
+echo "$as_me: WARNING: == your Python's existing sys.path directories. ==" >&2;}
+ { echo "$as_me:$LINENO: WARNING: == ==" >&5
+echo "$as_me: WARNING: == ==" >&2;}
+ { echo "$as_me:$LINENO: WARNING: == Alternatively, re-run ./configure with ==" >&5
+echo "$as_me: WARNING: == Alternatively, re-run ./configure with ==" >&2;}
+ { echo "$as_me:$LINENO: WARNING: == PYLIBDIR set to override the default ==" >&5
+echo "$as_me: WARNING: == PYLIBDIR set to override the default ==" >&2;}
+ { echo "$as_me:$LINENO: WARNING: == pythondir, or adjust prefix to match the ==" >&5
+echo "$as_me: WARNING: == pythondir, or adjust prefix to match the ==" >&2;}
+ { echo "$as_me:$LINENO: WARNING: == prefix used to build your Python. ==" >&5
+echo "$as_me: WARNING: == prefix used to build your Python. ==" >&2;}
+ { echo "$as_me:$LINENO: WARNING: == ==" >&5
+echo "$as_me: WARNING: == ==" >&2;}
+ { echo "$as_me:$LINENO: WARNING: ==================================================" >&5
+echo "$as_me: WARNING: ==================================================" >&2;}
+fi
diff --git a/configure.ac b/configure.ac
index 95259c0..e3ae26b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,7 +20,7 @@
#
AC_PREREQ(2.61)
-AC_INIT(zynjacku, 4)
+AC_INIT(zynjacku, 5)
AC_CONFIG_AUX_DIR(config)
AM_INIT_AUTOMAKE
AC_CONFIG_HEADER([config.h])
@@ -50,7 +50,6 @@ then
AC_DEFINE([HAVE_DYNPARAMS], 1, [Defined if dynparam1 is present.])
fi
AM_CONDITIONAL(HAVE_DYNPARAMS, test "$HAVE_DYNPARAMS" = "yes")
-PKG_CHECK_MODULES(SLV2, slv2 >= 0.6.1)
# JACK MIDI
have_jackmidi="unknown"
@@ -83,6 +82,38 @@ AM_CHECK_PYTHON_HEADERS(,[AC_MSG_ERROR(Could not find Python headers)])
#AS_AC_EXPAND(PYTHONDIR, $pythondir)
#AC_SUBST(PYTHONDIR)
+# Allow the user to override AM_PATH_PYTHON choice of PYTHON_PREFIX
+# and PYTHON_EXEC_PREFIX by setting PYLIBDIR
+AC_ARG_VAR(PYLIBDIR, [Override default Python site-packages dir])
+if test "$PYLIBDIR" ; then
+ pylibdir=$PYLIBDIR
+ AC_MSG_NOTICE([User set PYLIBDIR... $pylibdir])
+ AC_SUBST([pythondir],$pylibdir)
+ AC_SUBST([pyexecdir],$pylibdir)
+fi
+
+# Warn if python does not search in the installed places
+#AC_MSG_NOTICE([Checking to see whether Python will find installed files...])
+
+# Figure out the script directory
+if test "$prefix" == 'NONE'; then
+ #AC_MSG_NOTICE([prefix not set, falling back to ac_default_prefix...])
+ pyprefix=$ac_default_prefix
+else
+ pyprefix=$prefix
+fi
+abs_pythondir=`echo $pythondir | $SED s='${prefix}'=$pyprefix=`
+#AC_MSG_NOTICE([Python script dir will be: $abs_pythondir])
+match_pythondir=no
+for p in `$PYTHON -c "import sys
+for p in sys.path:
+ print p"`
+do
+ #AC_MSG_NOTICE([Checking Python sys.path entry $p ...])
+ if test $p == $abs_pythondir ; then
+ match_pythondir=
+ fi
+done
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
@@ -90,6 +121,23 @@ AC_MSG_RESULT([])
AC_MSG_RESULT([========================])
AC_MSG_RESULT([Prefix : $prefix])
AC_MSG_RESULT([Dynparam1 plugins support : $HAVE_DYNPARAMS])
-AC_MSG_RESULT([Python dir : $PYTHON_INCLUDES])
+AC_MSG_RESULT([Python include dir : $PYTHON_INCLUDES])
+AC_MSG_RESULT([Python script dir : $abs_pythondir])
AC_MSG_RESULT([Dev version : $dev_version])
AC_MSG_RESULT([])
+
+if test "$match_pythondir"; then
+ AC_MSG_WARN([==================================================])
+ AC_MSG_WARN([== ==])
+ AC_MSG_WARN([== pythondir is NOT in your Python's sys.path ==])
+ AC_MSG_WARN([== which means you should add it to PYTHONPATH ==])
+ AC_MSG_WARN([== at runtime, or add a .pth file to one of ==])
+ AC_MSG_WARN([== your Python's existing sys.path directories. ==])
+ AC_MSG_WARN([== ==])
+ AC_MSG_WARN([== Alternatively, re-run ./configure with ==])
+ AC_MSG_WARN([== PYLIBDIR set to override the default ==])
+ AC_MSG_WARN([== pythondir, or adjust prefix to match the ==])
+ AC_MSG_WARN([== prefix used to build your Python. ==])
+ AC_MSG_WARN([== ==])
+ AC_MSG_WARN([==================================================])
+fi
diff --git a/effect.h b/effect.h
deleted file mode 100644
index 8cbfd50..0000000
--- a/effect.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -*- Mode: C ; c-basic-offset: 2 -*- */
-/*****************************************************************************
- *
- * This file is part of zynjacku
- *
- * Copyright (C) 2008,2009 Nedko Arnaudov <nedko at arnaudov.name>
- *
- * 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; version 2 of the License
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *****************************************************************************/
-
-#ifndef EFFECT_H__6B544DDB_CFAC_4182_B10B_6183A3AB0933__INCLUDED
-#define EFFECT_H__6B544DDB_CFAC_4182_B10B_6183A3AB0933__INCLUDED
-
-bool
-zynjacku_plugin_construct_effect(
- struct zynjacku_plugin * plugin_ptr,
- ZynjackuPlugin * plugin_obj_ptr,
- GObject * engine_object_ptr);
-
-#endif /* #ifndef EFFECT_H__6B544DDB_CFAC_4182_B10B_6183A3AB0933__INCLUDED */
diff --git a/engine.c b/engine.c
index 17f9a20..b1b205e 100644
--- a/engine.c
+++ b/engine.c
@@ -37,7 +37,6 @@
#include <lv2dynparam/lv2_rtmempool.h>
#include <lv2dynparam/host.h>
#endif
-#include <slv2/lv2_ui.h>
#include "lv2_contexts.h"
#include "lv2-miditype.h"
@@ -45,6 +44,7 @@
#include "lv2_uri_map.h"
#include "lv2_string_port.h"
#include "lv2_progress.h"
+#include "lv2_ui.h"
#include "list.h"
#define LOG_LEVEL LOG_LEVEL_ERROR
@@ -63,15 +63,12 @@
#if HAVE_DYNPARAMS
#include "rtmempool.h"
#endif
-#include "plugin_repo.h"
#include "lv2_event_helpers.h"
#include "midi_cc_map.h"
#include "midi_cc_map_internal.h"
-#define ZYNJACKU_ENGINE_SIGNAL_TICK 0 /* plugin iterated */
-#define ZYNJACKU_ENGINE_SIGNAL_TACK 1 /* "good" plugin found */
-#define ZYNJACKU_ENGINE_SIGNAL_PROGRESS 2 /* plugin instantiation progress */
-#define ZYNJACKU_ENGINE_SIGNALS_COUNT 3
+#define ZYNJACKU_ENGINE_SIGNAL_PROGRESS 0 /* plugin instantiation progress */
+#define ZYNJACKU_ENGINE_SIGNALS_COUNT 1
/* URI map value for event MIDI type */
#define ZYNJACKU_MIDI_EVENT_ID 1
@@ -112,8 +109,6 @@ struct zynjacku_engine
pthread_mutex_t rt_lock;
struct list_head plugins_pending_activation; /* protected using rt_lock */
- struct list_head midi_ports; /* PORT_TYPE_MIDI "struct zynjacku_port"s linked by port_type_siblings */
- struct list_head audio_ports; /* PORT_TYPE_AUDIO "struct zynjacku_port"s linked by port_type_siblings */
jack_port_t * jack_midi_in;
LV2_MIDI lv2_midi_buffer;
LV2_Event_Buffer lv2_midi_event_buffer;
@@ -192,7 +187,6 @@ zynjacku_engine_dispose(GObject * obj)
if (engine_ptr->jack_client)
{
zynjacku_engine_stop_jack(ZYNJACKU_ENGINE(obj));
- zynjacku_plugin_repo_uninit();
}
pthread_mutex_destroy(&engine_ptr->rt_lock);
@@ -230,38 +224,6 @@ zynjacku_engine_class_init(
g_type_class_add_private(G_OBJECT_CLASS(class_ptr), sizeof(struct zynjacku_engine));
- g_zynjacku_engine_signals[ZYNJACKU_ENGINE_SIGNAL_TICK] =
- g_signal_new(
- "tick", /* signal_name */
- ZYNJACKU_ENGINE_TYPE, /* itype */
- G_SIGNAL_RUN_LAST |
- G_SIGNAL_ACTION, /* signal_flags */
- 0, /* class_offset */
- NULL, /* accumulator */
- NULL, /* accu_data */
- NULL, /* c_marshaller */
- G_TYPE_NONE, /* return type */
- 2, /* n_params */
- G_TYPE_FLOAT, /* progress 0 .. 1 */
- G_TYPE_STRING); /* uri of plugin being scanned */
-
- g_zynjacku_engine_signals[ZYNJACKU_ENGINE_SIGNAL_TACK] =
- g_signal_new(
- "tack", /* signal_name */
- ZYNJACKU_ENGINE_TYPE, /* itype */
- G_SIGNAL_RUN_LAST |
- G_SIGNAL_ACTION, /* signal_flags */
- 0, /* class_offset */
- NULL, /* accumulator */
- NULL, /* accu_data */
- NULL, /* c_marshaller */
- G_TYPE_NONE, /* return type */
- 4, /* n_params */
- G_TYPE_STRING, /* plugin name */
- G_TYPE_STRING, /* plugin uri */
- G_TYPE_STRING, /* plugin license */
- G_TYPE_STRING); /* plugin author */
-
g_zynjacku_engine_signals[ZYNJACKU_ENGINE_SIGNAL_PROGRESS] =
g_signal_new(
"progress", /* signal_name */
@@ -449,8 +411,6 @@ zynjacku_engine_init(
assert(ZYNJACKU_ENGINE_FEATURES == count);
engine_ptr->host_features[count] = NULL;
/* keep in mind to update the constant when adding things here */
-
- zynjacku_plugin_repo_init();
}
GType zynjacku_engine_get_type()
@@ -494,8 +454,6 @@ zynjacku_engine_start_jack(
INIT_LIST_HEAD(&engine_ptr->plugins_all);
INIT_LIST_HEAD(&engine_ptr->plugins_active);
INIT_LIST_HEAD(&engine_ptr->plugins_pending_activation);
- INIT_LIST_HEAD(&engine_ptr->midi_ports);
- INIT_LIST_HEAD(&engine_ptr->audio_ports);
INIT_LIST_HEAD(&engine_ptr->midicc_ui);
INIT_LIST_HEAD(&engine_ptr->midicc_pending_activation);
@@ -574,9 +532,6 @@ fail_close_jack_client:
engine_ptr->jack_client = NULL;
fail:
- assert(list_empty(&engine_ptr->audio_ports));
- assert(list_empty(&engine_ptr->midi_ports));
-
return FALSE;
}
@@ -615,9 +570,6 @@ zynjacku_engine_stop_jack(
jack_client_close(engine_ptr->jack_client);
engine_ptr->jack_client = NULL;
-
- assert(list_empty(&engine_ptr->audio_ports));
- assert(list_empty(&engine_ptr->midi_ports));
}
/* Translate from a JACK MIDI buffer to an LV2 MIDI buffers (both old midi port and new midi event port). */
@@ -976,21 +928,21 @@ jack_process_cb(
#endif
/* Connect plugin LV2 output audio ports directly to JACK buffers */
- if (synth_ptr->subtype.synth.audio_out_left_port.type == PORT_TYPE_AUDIO)
+ if (synth_ptr->subtype.synth.audio_out_left_port_ptr != NULL)
{
zynjacku_lv2_connect_port(
synth_ptr->lv2plugin,
- &synth_ptr->subtype.synth.audio_out_left_port,
- jack_port_get_buffer(synth_ptr->subtype.synth.audio_out_left_port.data.audio, nframes));
+ synth_ptr->subtype.synth.audio_out_left_port_ptr,
+ jack_port_get_buffer(synth_ptr->subtype.synth.audio_out_left_port_ptr->data.audio, nframes));
}
/* Connect plugin LV2 output audio ports directly to JACK buffers */
- if (synth_ptr->subtype.synth.audio_out_right_port.type == PORT_TYPE_AUDIO)
+ if (synth_ptr->subtype.synth.audio_out_right_port_ptr != NULL)
{
zynjacku_lv2_connect_port(
synth_ptr->lv2plugin,
- &synth_ptr->subtype.synth.audio_out_right_port,
- jack_port_get_buffer(synth_ptr->subtype.synth.audio_out_right_port.data.audio, nframes));
+ synth_ptr->subtype.synth.audio_out_right_port_ptr,
+ jack_port_get_buffer(synth_ptr->subtype.synth.audio_out_right_port_ptr->data.audio, nframes));
}
/* Run plugin for this cycle */
@@ -1004,6 +956,7 @@ jack_process_cb(
#undef engine_ptr
+static
void
zynjacku_engine_deactivate_synth(
GObject * synth_obj_ptr)
@@ -1026,6 +979,36 @@ zynjacku_engine_deactivate_synth(
}
void
+zynjacku_engine_get_required_features(
+ GObject * engine_obj_ptr,
+ const LV2_Feature * const ** host_features,
+ unsigned int * host_feature_count)
+{
+ struct zynjacku_engine * engine_ptr;
+
+ engine_ptr = ZYNJACKU_ENGINE_GET_PRIVATE(engine_obj_ptr);
+
+ *host_features = engine_ptr->host_features;
+ *host_feature_count = ZYNJACKU_ENGINE_FEATURES;
+}
+
+static
+void
+zynjacku_engine_unregister_port(
+ GObject * engine_obj_ptr,
+ struct zynjacku_port * port_ptr)
+{
+ struct zynjacku_engine * engine_ptr;
+
+ engine_ptr = ZYNJACKU_ENGINE_GET_PRIVATE(engine_obj_ptr);
+
+ if (port_ptr->data.audio != NULL)
+ {
+ jack_port_unregister(engine_ptr->jack_client, port_ptr->data.audio);
+ }
+}
+
+void
zynjacku_engine_ui_run(
ZynjackuEngine * engine_obj_ptr)
{
@@ -1096,197 +1079,23 @@ zynjacku_get_version()
return VERSION;
}
-#define engine_obj_ptr ((ZynjackuEngine *)context)
-
-bool
-zynjacku_check_plugin(
- void * context,
- const char * plugin_uri,
- const char * plugin_name,
- uint32_t audio_in_ports_count,
- uint32_t audio_out_ports_count,
- uint32_t midi_in_ports_count,
- uint32_t control_ports_count,
- uint32_t string_ports_count,
- uint32_t event_ports_count,
- uint32_t midi_event_in_ports_count,
- uint32_t ports_count)
-{
- if (midi_in_ports_count + control_ports_count + string_ports_count + event_ports_count + audio_out_ports_count != ports_count ||
- midi_in_ports_count + midi_event_in_ports_count != 1 ||
- audio_out_ports_count == 0)
- {
- LOG_DEBUG("Skipping 's' %s, [synth] plugin with unsupported port configuration", plugin_name, plugin_uri);
- LOG_DEBUG(" midi input ports: %d", (unsigned int)midi_in_ports_count);
- LOG_DEBUG(" control ports: %d", (unsigned int)control_ports_count);
- LOG_DEBUG(" string ports: %d", (unsigned int)string_ports_count);
- LOG_DEBUG(" event ports: %d", (unsigned int)event_ports_count);
- LOG_DEBUG(" event midi input ports: %d", (unsigned int)midi_event_in_ports_count);
- LOG_DEBUG(" audio input ports: %d", (unsigned int)audio_in_ports_count);
- LOG_DEBUG(" audio output ports: %d", (unsigned int)audio_out_ports_count);
- LOG_DEBUG(" total ports %d", (unsigned int)ports_count);
- return false;
- }
-
- LOG_DEBUG("Found \"simple\" synth plugin '%s' %s", plugin_name, plugin_uri);
- LOG_DEBUG(" midi input ports: %d", (unsigned int)midi_in_ports_count);
- LOG_DEBUG(" control ports: %d", (unsigned int)control_ports_count);
- LOG_DEBUG(" event ports: %d", (unsigned int)event_ports_count);
- LOG_DEBUG(" event midi input ports: %d", (unsigned int)midi_event_in_ports_count);
- LOG_DEBUG(" audio input ports: %d", (unsigned int)audio_in_ports_count);
- LOG_DEBUG(" audio output ports: %d", (unsigned int)audio_out_ports_count);
- LOG_DEBUG(" total ports %d", (unsigned int)ports_count);
- return true;
-}
-
-void
-zynjacku_engine_tick(
- void *context,
- float progress, /* 0..1 */
- const char *message)
-{
- g_signal_emit(
- engine_obj_ptr,
- g_zynjacku_engine_signals[ZYNJACKU_ENGINE_SIGNAL_TICK],
- 0,
- progress,
- message);
-}
-
-void
-zynjacku_engine_tack(
- void *context,
- const char *uri)
-{
- const char * name;
- const char * license;
- const char * author;
-
- name = zynjacku_plugin_repo_get_name(uri);
- license = zynjacku_plugin_repo_get_license(uri);
- author = zynjacku_plugin_repo_get_author(uri);
-
- g_signal_emit(
- engine_obj_ptr,
- g_zynjacku_engine_signals[ZYNJACKU_ENGINE_SIGNAL_TACK],
- 0,
- name,
- uri,
- license,
- author);
-}
-
-#undef engine_obj_ptr
-
-void
-zynjacku_engine_iterate_plugins(
+const gchar *
+zynjacku_engine_get_supported_feature(
ZynjackuEngine * engine_obj_ptr,
- gboolean force)
-{
- struct zynjacku_engine * engine_ptr;
-
- engine_ptr = ZYNJACKU_ENGINE_GET_PRIVATE(engine_obj_ptr);
-
- zynjacku_plugin_repo_iterate(
- force,
- engine_ptr->host_features,
- engine_obj_ptr,
- zynjacku_check_plugin,
- zynjacku_engine_tick,
- zynjacku_engine_tack);
-}
-
-void
-zynjacku_free_synth_ports(
- GObject * plugin_object_ptr)
+ guint index)
{
struct zynjacku_engine * engine_ptr;
- struct zynjacku_plugin * plugin_ptr;
- plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_object_ptr);
- engine_ptr = ZYNJACKU_ENGINE_GET_PRIVATE(plugin_ptr->engine_object_ptr);
-
- zynjacku_free_plugin_ports(plugin_ptr);
-
- if (plugin_ptr->type == PLUGIN_TYPE_SYNTH)
+ if (index >= ZYNJACKU_ENGINE_FEATURES)
{
- if (plugin_ptr->subtype.synth.audio_out_left_port.type == PORT_TYPE_AUDIO)
- {
- jack_port_unregister(engine_ptr->jack_client, plugin_ptr->subtype.synth.audio_out_left_port.data.audio);
- list_del(&plugin_ptr->subtype.synth.audio_out_left_port.port_type_siblings);
- }
-
- if (plugin_ptr->subtype.synth.audio_out_right_port.type == PORT_TYPE_AUDIO) /* stereo? */
- {
- assert(plugin_ptr->subtype.synth.audio_out_left_port.type == PORT_TYPE_AUDIO);
- jack_port_unregister(engine_ptr->jack_client, plugin_ptr->subtype.synth.audio_out_right_port.data.audio);
- list_del(&plugin_ptr->subtype.synth.audio_out_right_port.port_type_siblings);
- }
-
- if (plugin_ptr->subtype.synth.midi_in_port.type == PORT_TYPE_MIDI ||
- plugin_ptr->subtype.synth.midi_in_port.type == PORT_TYPE_EVENT_MIDI)
- {
- list_del(&plugin_ptr->subtype.synth.midi_in_port.port_type_siblings);
- }
+ return NULL;
}
-}
-
-#define synth_ptr (&((struct zynjacku_plugin *)context)->subtype.synth)
-
-bool
-zynjacku_synth_create_port(
- void * context,
- unsigned int port_type,
- bool output,
- uint32_t port_index)
-{
- struct zynjacku_port * port_ptr;
-
- LOG_NOTICE("creating synth %s port of type %u, index %u", output ? "output" : "input", (unsigned int)port_type, (unsigned int)port_index);
-
- switch (port_type)
- {
- case PORT_TYPE_AUDIO:
- if (output)
- {
- if (synth_ptr->audio_out_left_port.type == PORT_TYPE_INVALID)
- {
- port_ptr = &synth_ptr->audio_out_left_port;
- }
- else if (synth_ptr->audio_out_right_port.type == PORT_TYPE_INVALID)
- {
- port_ptr = &synth_ptr->audio_out_right_port;
- }
- else
- {
- /* ignore, we dont support more than two audio ports yet */
- return true;
- }
- port_ptr->type = PORT_TYPE_AUDIO;
- port_ptr->flags = 0;
- port_ptr->index = port_index;
-
- return true;
- }
- break;
- case PORT_TYPE_MIDI:
- case PORT_TYPE_EVENT_MIDI:
- if (!output)
- {
- port_ptr = &synth_ptr->midi_in_port;
- port_ptr->type = port_type;
- port_ptr->index = port_index;
- return true;
- }
- break;
- }
+ engine_ptr = ZYNJACKU_ENGINE_GET_PRIVATE(engine_obj_ptr);
- return false;
+ return engine_ptr->host_features[index]->URI;
}
-#undef synth_ptr
-
static
bool
zynjacku_set_midi_cc_map(
@@ -1424,28 +1233,93 @@ zynjacku_midi_cc_map_cc_no_assign(
#define synth_ptr (&plugin_ptr->subtype.synth)
-bool
-zynjacku_plugin_construct_synth(
- struct zynjacku_plugin * plugin_ptr,
- ZynjackuPlugin * plugin_obj_ptr,
- GObject * engine_object_ptr)
+gboolean
+zynjacku_engine_construct_plugin(
+ ZynjackuEngine * engine_object_ptr,
+ ZynjackuPlugin * plugin_object_ptr)
{
static unsigned int id;
char * port_name;
size_t size_name;
size_t size_id;
struct zynjacku_engine * engine_ptr;
+ struct list_head * node_ptr;
+ struct zynjacku_port * port_ptr;
+ struct zynjacku_port * midi_port_ptr;
+ struct zynjacku_port * audio_left_port_ptr;
+ struct zynjacku_port * audio_right_port_ptr;
+ struct zynjacku_plugin * plugin_ptr;
engine_ptr = ZYNJACKU_ENGINE_GET_PRIVATE(engine_object_ptr);
+ plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_object_ptr);
- plugin_ptr->type = PLUGIN_TYPE_SYNTH;
- synth_ptr->midi_in_port.type = PORT_TYPE_INVALID;
- synth_ptr->audio_out_left_port.type = PORT_TYPE_INVALID;
- synth_ptr->audio_out_right_port.type = PORT_TYPE_INVALID;
+ if (plugin_ptr->uri == NULL)
+ {
+ LOG_ERROR("\"uri\" property needs to be set before constructing plugin");
+ goto fail;
+ }
+
+ if (plugin_ptr->name == NULL)
+ {
+ LOG_ERROR("\"name\" property needs to be set before constructing plugin");
+ goto fail;
+ }
+
+ if (plugin_ptr->dlpath == NULL)
+ {
+ LOG_ERROR("Plugin %s has no dlpath set", plugin_ptr->uri);
+ goto fail;
+ }
+
+ if (plugin_ptr->bundle_path == NULL)
+ {
+ LOG_ERROR("Plugin %s has no bundle path set", plugin_ptr->uri);
+ goto fail;
+ }
+
+ if (list_empty(&plugin_ptr->midi_ports))
+ {
+ LOG_ERROR("Cannot construct synth plugin without MIDI port. %s", plugin_ptr->uri);
+ goto fail;
+ }
+
+ midi_port_ptr = list_entry(plugin_ptr->midi_ports.next, struct zynjacku_port, plugin_siblings);
+ if (!PORT_IS_INPUT(midi_port_ptr))
+ {
+ LOG_ERROR("Cannot construct synth plugin without MIDI inpu port. %s", plugin_ptr->uri);
+ goto fail;
+ }
- if (!zynjacku_plugin_repo_load_plugin(plugin_ptr, plugin_ptr, zynjacku_synth_create_port, zynjacku_check_plugin, engine_ptr->host_features))
+ if (plugin_ptr->midi_ports.next != plugin_ptr->midi_ports.prev)
{
- LOG_ERROR("Failed to load LV2 info for plugin %s", plugin_ptr->uri);
+ LOG_ERROR("Cannot construct synth plugin with more than one MIDI input port. %s", plugin_ptr->uri);
+ goto fail;
+ }
+
+ audio_left_port_ptr = NULL;
+ audio_right_port_ptr = NULL;
+
+ list_for_each(node_ptr, &plugin_ptr->audio_ports)
+ {
+ port_ptr = list_entry(node_ptr, struct zynjacku_port, plugin_siblings);
+ assert(port_ptr->type == PORT_TYPE_AUDIO);
+ if (PORT_IS_OUTPUT(port_ptr))
+ {
+ if (audio_left_port_ptr == NULL)
+ {
+ audio_left_port_ptr = port_ptr;
+ continue;
+ }
+
+ assert(audio_right_port_ptr == NULL);
+ audio_right_port_ptr = port_ptr;
+ break;
+ }
+ }
+
+ if (audio_left_port_ptr == NULL)
+ {
+ LOG_ERROR("Cannot construct synth plugin without audio output port(s). %s", plugin_ptr->uri);
goto fail;
}
@@ -1455,6 +1329,8 @@ zynjacku_plugin_construct_synth(
plugin_ptr->lv2plugin = zynjacku_lv2_load(
plugin_ptr->uri,
+ plugin_ptr->dlpath,
+ plugin_ptr->bundle_path,
zynjacku_engine_get_sample_rate(ZYNJACKU_ENGINE(engine_object_ptr)),
engine_ptr->host_features);
@@ -1475,8 +1351,8 @@ zynjacku_plugin_construct_synth(
/* connect parameter/measure ports */
if (!zynjacku_connect_plugin_ports(
plugin_ptr,
- plugin_obj_ptr,
- engine_object_ptr
+ plugin_object_ptr,
+ G_OBJECT(engine_object_ptr)
#if HAVE_DYNPARAMS
, &engine_ptr->mempool_allocator
#endif
@@ -1485,52 +1361,61 @@ zynjacku_plugin_construct_synth(
goto fail_unload;
}
+ synth_ptr->midi_in_port_ptr = midi_port_ptr;
+
/* connect midi port */
- switch (synth_ptr->midi_in_port.type)
+ switch (midi_port_ptr->type)
{
case PORT_TYPE_MIDI:
- zynjacku_lv2_connect_port(plugin_ptr->lv2plugin, &synth_ptr->midi_in_port, &engine_ptr->lv2_midi_buffer);
+ zynjacku_lv2_connect_port(plugin_ptr->lv2plugin, midi_port_ptr, &engine_ptr->lv2_midi_buffer);
break;
case PORT_TYPE_EVENT_MIDI:
- zynjacku_lv2_connect_port(plugin_ptr->lv2plugin, &synth_ptr->midi_in_port, &engine_ptr->lv2_midi_event_buffer);
+ zynjacku_lv2_connect_port(plugin_ptr->lv2plugin, midi_port_ptr, &engine_ptr->lv2_midi_event_buffer);
break;
default:
- LOG_ERROR("don't know how to connect midi port of type %u", synth_ptr->midi_in_port.type);
+ LOG_ERROR("don't know how to connect midi port of type %u", midi_port_ptr->type);
goto fail_detach_dynparams;
}
- list_add_tail(&synth_ptr->midi_in_port.port_type_siblings, &engine_ptr->midi_ports);
-
/* setup audio ports (they are connected in jack process callback */
+ synth_ptr->audio_out_left_port_ptr = audio_left_port_ptr;
+ synth_ptr->audio_out_right_port_ptr = audio_right_port_ptr;
+
size_name = strlen(plugin_ptr->name);
port_name = malloc(size_name + 1024);
if (port_name == NULL)
{
LOG_ERROR("Failed to allocate memory for port name");
- goto fail_free_ports;
+ goto fail_detach_dynparams;
}
size_id = sprintf(port_name, "%u:", id);
memcpy(port_name + size_id, plugin_ptr->name, size_name);
- if (synth_ptr->audio_out_left_port.type == PORT_TYPE_AUDIO &&
- synth_ptr->audio_out_right_port.type == PORT_TYPE_AUDIO)
+ if (audio_left_port_ptr != NULL &&
+ audio_right_port_ptr != NULL)
{
+ assert(audio_left_port_ptr->type == PORT_TYPE_AUDIO);
+ assert(PORT_IS_OUTPUT(audio_left_port_ptr));
+
strcpy(port_name + size_id + size_name, " L");
- synth_ptr->audio_out_left_port.data.audio = jack_port_register(engine_ptr->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
- list_add_tail(&synth_ptr->audio_out_left_port.port_type_siblings, &engine_ptr->audio_ports);
+ audio_left_port_ptr->data.audio = jack_port_register(engine_ptr->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+
+ assert(audio_right_port_ptr->type == PORT_TYPE_AUDIO);
+ assert(PORT_IS_OUTPUT(audio_right_port_ptr));
strcpy(port_name + size_id + size_name, " R");
- synth_ptr->audio_out_right_port.data.audio = jack_port_register(engine_ptr->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
- list_add_tail(&synth_ptr->audio_out_right_port.port_type_siblings, &engine_ptr->audio_ports);
+ audio_right_port_ptr->data.audio = jack_port_register(engine_ptr->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
}
- else if (synth_ptr->audio_out_left_port.type == PORT_TYPE_AUDIO &&
- synth_ptr->audio_out_right_port.type == PORT_TYPE_INVALID)
+ else if (audio_left_port_ptr != NULL &&
+ audio_right_port_ptr == NULL)
{
+ assert(audio_left_port_ptr->type == PORT_TYPE_AUDIO);
+ assert(PORT_IS_OUTPUT(audio_left_port_ptr));
+
port_name[size_id + size_name] = 0;
- synth_ptr->audio_out_left_port.data.audio = jack_port_register(engine_ptr->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
- list_add_tail(&synth_ptr->audio_out_left_port.port_type_siblings, &engine_ptr->audio_ports);
+ audio_left_port_ptr->data.audio = jack_port_register(engine_ptr->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
}
port_name[size_id + size_name] = 0;
@@ -1551,12 +1436,9 @@ zynjacku_plugin_construct_synth(
g_object_ref(plugin_ptr->engine_object_ptr);
- /* no plugins to test gtk2gui */
- plugin_ptr->gtk2gui = zynjacku_gtk2gui_create(engine_ptr->host_features, ZYNJACKU_ENGINE_FEATURES, plugin_ptr->lv2plugin,
- plugin_ptr, plugin_obj_ptr, plugin_ptr->uri, plugin_ptr->id, &plugin_ptr->parameter_ports);
-
plugin_ptr->deactivate = zynjacku_engine_deactivate_synth;
- plugin_ptr->free_ports = zynjacku_free_synth_ports;
+ plugin_ptr->get_required_features = zynjacku_engine_get_required_features;
+ plugin_ptr->unregister_port = zynjacku_engine_unregister_port;
plugin_ptr->set_midi_cc_map = zynjacku_set_midi_cc_map;
plugin_ptr->midi_cc_map_cc_no_assign = zynjacku_midi_cc_map_cc_no_assign;
@@ -1564,10 +1446,6 @@ zynjacku_plugin_construct_synth(
return true;
-fail_free_ports:
- zynjacku_free_synth_ports(G_OBJECT(plugin_obj_ptr));
- plugin_ptr->engine_object_ptr = NULL;
-
fail_detach_dynparams:
#if HAVE_DYNPARAMS
if (plugin_ptr->dynparams != NULL)
diff --git a/engine.h b/engine.h
index ec06045..fb4e1da 100644
--- a/engine.h
+++ b/engine.h
@@ -74,10 +74,15 @@ zynjacku_engine_get_midi_activity(
const gchar *
zynjacku_get_version();
-void
-zynjacku_engine_iterate_plugins(
+const gchar *
+zynjacku_engine_get_supported_feature(
+ ZynjackuEngine * engine_obj_ptr,
+ guint index);
+
+gboolean
+zynjacku_engine_construct_plugin(
ZynjackuEngine * engine_obj_ptr,
- gboolean force);
+ ZynjackuPlugin * plugin_obj_ptr);
G_END_DECLS
diff --git a/flex_ttl.c b/flex_ttl.c
new file mode 100644
index 0000000..afa56b3
--- /dev/null
+++ b/flex_ttl.c
@@ -0,0 +1,2054 @@
+#line 2 "flex_ttl.c"
+
+#line 4 "flex_ttl.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+ are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = yyg->yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void yypop_buffer_state (yyscan_t yyscanner );
+
+static void yyensure_buffer_stack (yyscan_t yyscanner );
+static void yy_load_buffer_state (yyscan_t yyscanner );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void yyfree (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yyg->yytext_ptr = yy_bp; \
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ yyg->yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 21
+#define YY_END_OF_BUFFER 22
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[61] =
+ { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 22, 12,
+ 11, 11, 4, 2, 10, 12, 9, 10, 7, 8,
+ 12, 12, 9, 20, 19, 14, 15, 18, 21, 16,
+ 21, 0, 0, 7, 9, 7, 8, 6, 6, 8,
+ 0, 5, 0, 14, 0, 18, 17, 3, 0, 6,
+ 8, 0, 13, 0, 6, 0, 0, 0, 1, 0
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 4, 5, 1, 1, 1, 1, 6,
+ 6, 1, 7, 6, 8, 9, 1, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 11, 6, 12,
+ 1, 13, 1, 14, 15, 15, 15, 15, 16, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 6, 17, 6, 1, 15, 1, 15, 15, 15, 15,
+
+ 18, 19, 15, 15, 20, 15, 15, 15, 15, 15,
+ 15, 21, 15, 22, 15, 15, 15, 15, 15, 23,
+ 15, 15, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[24] =
+ { 0,
+ 1, 1, 2, 3, 1, 1, 1, 4, 5, 6,
+ 5, 1, 1, 1, 4, 4, 2, 4, 4, 4,
+ 4, 4, 4
+ } ;
+
+static yyconst flex_int16_t yy_base[70] =
+ { 0,
+ 0, 0, 115, 114, 112, 111, 21, 23, 114, 119,
+ 119, 119, 109, 119, 119, 19, 21, 102, 24, 0,
+ 98, 89, 26, 119, 119, 0, 105, 0, 119, 119,
+ 103, 98, 91, 32, 34, 37, 0, 34, 39, 0,
+ 83, 119, 43, 0, 59, 0, 119, 119, 46, 48,
+ 0, 44, 119, 51, 50, 40, 31, 16, 119, 119,
+ 66, 72, 78, 81, 32, 87, 93, 99, 102
+ } ;
+
+static yyconst flex_int16_t yy_def[70] =
+ { 0,
+ 60, 1, 61, 61, 62, 62, 63, 63, 60, 60,
+ 60, 60, 60, 60, 60, 60, 64, 60, 60, 65,
+ 66, 60, 64, 60, 60, 67, 60, 68, 60, 60,
+ 60, 60, 60, 60, 64, 64, 65, 60, 60, 69,
+ 66, 60, 60, 67, 60, 68, 60, 60, 60, 60,
+ 69, 60, 60, 60, 60, 60, 60, 60, 60, 0,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60
+ } ;
+
+static yyconst flex_int16_t yy_nxt[143] =
+ { 0,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 10, 22, 23, 23, 10, 23, 23, 23,
+ 23, 23, 23, 29, 30, 29, 30, 33, 34, 33,
+ 36, 37, 39, 34, 60, 40, 37, 31, 59, 31,
+ 39, 34, 60, 38, 37, 39, 36, 37, 50, 49,
+ 58, 49, 54, 54, 49, 55, 49, 50, 57, 55,
+ 55, 56, 53, 49, 52, 49, 24, 24, 24, 24,
+ 24, 24, 26, 26, 26, 26, 26, 26, 28, 28,
+ 28, 28, 28, 28, 35, 35, 35, 41, 41, 41,
+ 41, 41, 41, 44, 44, 42, 44, 44, 44, 46,
+
+ 38, 48, 46, 46, 46, 51, 47, 51, 45, 43,
+ 42, 38, 32, 60, 27, 27, 25, 25, 9, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60
+ } ;
+
+static yyconst flex_int16_t yy_chk[143] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 7, 7, 8, 8, 16, 16, 17,
+ 17, 17, 19, 19, 23, 65, 23, 7, 58, 8,
+ 34, 34, 35, 38, 35, 36, 36, 36, 39, 38,
+ 57, 38, 49, 49, 39, 49, 39, 50, 56, 55,
+ 54, 52, 45, 50, 43, 50, 61, 61, 61, 61,
+ 61, 61, 62, 62, 62, 62, 62, 62, 63, 63,
+ 63, 63, 63, 63, 64, 64, 64, 66, 66, 66,
+ 66, 66, 66, 67, 67, 41, 67, 67, 67, 68,
+
+ 33, 32, 68, 68, 68, 69, 31, 69, 27, 22,
+ 21, 18, 13, 9, 6, 5, 4, 3, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60
+ } ;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "ttl.l"
+#line 2 "ttl.l"
+#include <Python.h>
+#include "ttl_lexer.h"
+
+
+PyObject *ttl_list = NULL;
+static PyObject *tmp_string = NULL;
+
+void yyerror(const char *str)
+{
+ PyErr_SetString(PyExc_SyntaxError, str);
+}
+
+void add_to(const char *str)
+{
+ PyString_ConcatAndDel(&tmp_string, PyString_FromString(str));
+}
+
+void add_token_str(const char *name, const char *value)
+{
+ PyList_Append(ttl_list, Py_BuildValue("(ss)", name, value));
+}
+
+void add_token(const char *name, PyObject *value)
+{
+ PyList_Append(ttl_list, Py_BuildValue("(sO)", name, value));
+}
+
+
+#line 507 "flex_ttl.c"
+
+#define INITIAL 0
+#define C_COMMENT 1
+#define C_LONGSTRING 2
+#define C_STRING 3
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+ {
+
+ /* User-defined. Not touched by flex. */
+ YY_EXTRA_TYPE yyextra_r;
+
+ /* The rest are the same as the globals declared in the non-reentrant scanner. */
+ FILE *yyin_r, *yyout_r;
+ size_t yy_buffer_stack_top; /**< index of top of stack. */
+ size_t yy_buffer_stack_max; /**< capacity of stack. */
+ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+ char yy_hold_char;
+ int yy_n_chars;
+ int yyleng_r;
+ char *yy_c_buf_p;
+ int yy_init;
+ int yy_start;
+ int yy_did_buffer_switch_on_eof;
+ int yy_start_stack_ptr;
+ int yy_start_stack_depth;
+ int *yy_start_stack;
+ yy_state_type yy_last_accepting_state;
+ char* yy_last_accepting_cpos;
+
+ int yylineno_r;
+ int yy_flex_debug_r;
+
+ char *yytext_r;
+ int yy_more_flag;
+ int yy_more_len;
+
+ }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+int yylex_init (yyscan_t* scanner);
+
+int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (yyscan_t yyscanner );
+
+int yyget_debug (yyscan_t yyscanner );
+
+void yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *yyget_in (yyscan_t yyscanner );
+
+void yyset_in (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *yyget_out (yyscan_t yyscanner );
+
+void yyset_out (FILE * out_str ,yyscan_t yyscanner );
+
+int yyget_leng (yyscan_t yyscanner );
+
+char *yyget_text (yyscan_t yyscanner );
+
+int yyget_lineno (yyscan_t yyscanner );
+
+void yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (yyscan_t yyscanner );
+#else
+extern int yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ int n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (yyscan_t yyscanner);
+
+#define YY_DECL int yylex (yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+#line 37 "ttl.l"
+
+
+#line 732 "flex_ttl.c"
+
+ if ( !yyg->yy_init )
+ {
+ yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yyg->yy_start )
+ yyg->yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ yy_load_buffer_state(yyscanner );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yyg->yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yyg->yy_start;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 61 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_current_state != 60 );
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yyg->yy_hold_char;
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 39 "ttl.l"
+{ add_token_str("prefix", "@prefix"); }
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 40 "ttl.l"
+BEGIN(C_COMMENT);
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 41 "ttl.l"
+{ tmp_string = PyString_FromString(""); BEGIN(C_LONGSTRING); }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 42 "ttl.l"
+{ tmp_string = PyString_FromString(""); BEGIN(C_STRING); }
+ YY_BREAK
+case 5:
+/* rule 5 can match eol */
+YY_RULE_SETUP
+#line 43 "ttl.l"
+{ add_token_str("URI_", yytext); }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 44 "ttl.l"
+{ add_token_str("float", yytext); }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 45 "ttl.l"
+{ add_token("number", PyInt_FromLong(atol(yytext))); }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 46 "ttl.l"
+{ add_token_str("prnot", yytext); }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 47 "ttl.l"
+{ add_token_str("symbol", yytext); }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 48 "ttl.l"
+{ add_token_str(yytext, yytext); }
+ YY_BREAK
+case 11:
+/* rule 11 can match eol */
+YY_RULE_SETUP
+#line 49 "ttl.l"
+;
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 51 "ttl.l"
+{
+ // TODO concat with yytext
+ //printf("yytext = '%u''%u'\n", yytext[0], yytext[1]);
+ PyErr_SetString(PyExc_ValueError, "Unexpected characters");
+ yyerror("Syntax error");
+}
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 58 "ttl.l"
+{ add_token("string", tmp_string); BEGIN(INITIAL); }
+ YY_BREAK
+case 14:
+/* rule 14 can match eol */
+YY_RULE_SETUP
+#line 59 "ttl.l"
+add_to(yytext);
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 60 "ttl.l"
+add_to("\"");
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 62 "ttl.l"
+{ add_token("string", tmp_string); BEGIN(INITIAL); }
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 63 "ttl.l"
+add_to("\"");
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 64 "ttl.l"
+add_to(yytext);
+ YY_BREAK
+case 19:
+/* rule 19 can match eol */
+YY_RULE_SETUP
+#line 66 "ttl.l"
+{ BEGIN(INITIAL); }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 67 "ttl.l"
+;
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 69 "ttl.l"
+YY_FATAL_ERROR( "flex scanner jammed" );
+ YY_BREAK
+#line 925 "flex_ttl.c"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(C_COMMENT):
+case YY_STATE_EOF(C_LONGSTRING):
+case YY_STATE_EOF(C_STRING):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yyg->yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yyg->yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yyg->yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap(yyscanner ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p =
+ yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yyg->yy_c_buf_p =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = yyg->yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ yyg->yy_n_chars, (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ if ( yyg->yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart(yyin ,yyscanner);
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ yyg->yy_n_chars += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_current_state = yyg->yy_start;
+
+ for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 61 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+ register int yy_is_jam;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+ register char *yy_cp = yyg->yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 61 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 60);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (yyscan_t yyscanner)
+#else
+ static int input (yyscan_t yyscanner)
+#endif
+
+{
+ int c;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+ if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ /* This was really a NUL. */
+ *yyg->yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ ++yyg->yy_c_buf_p;
+
+ switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart(yyin ,yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap(yyscanner ) )
+ return EOF;
+
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput(yyscanner);
+#else
+ return input(yyscanner);
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
+ *yyg->yy_c_buf_p = '\0'; /* preserve yytext */
+ yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void yyrestart (FILE * input_file , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+ yy_load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack (yyscanner);
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ yy_load_buffer_state(yyscanner );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void yy_load_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ,yyscanner );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer(b,file ,yyscanner);
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+ void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+ yyfree((void *) b ,yyscanner );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+
+{
+ int oerrno = errno;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_flush_buffer(b ,yyscanner);
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+ void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ yy_load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ * @param yyscanner The scanner object.
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack(yyscanner);
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ yyg->yy_buffer_stack_top++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ * @param yyscanner The scanner object.
+ */
+void yypop_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if (yyg->yy_buffer_stack_top > 0)
+ --yyg->yy_buffer_stack_top;
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (yyscan_t yyscanner)
+{
+ int num_to_alloc;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (!yyg->yy_buffer_stack) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ yyg->yy_buffer_stack_top = 0;
+ return;
+ }
+
+ if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
+ (yyg->yy_buffer_stack,
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer(b ,yyscanner );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+
+ return yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) yyalloc(n ,yyscanner );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer(buf,n ,yyscanner);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = yyg->yy_hold_char; \
+ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+ yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+ *yyg->yy_c_buf_p = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_lineno (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_column (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_in (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_out (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int yyget_leng (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *yyget_text (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_lineno (int line_number , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* lineno is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "yyset_lineno called with no buffer" , yyscanner);
+
+ yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_column (int column_no , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* column is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "yyset_column called with no buffer" , yyscanner);
+
+ yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE * in_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyin = in_str ;
+}
+
+void yyset_out (FILE * out_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyout = out_str ;
+}
+
+int yyget_debug (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yy_flex_debug;
+}
+
+void yyset_debug (int bdebug , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+/* User-visible API */
+
+/* yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int yylex_init(yyscan_t* ptr_yy_globals)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to yyalloc in
+ * the yyextra field.
+ */
+
+int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+ struct yyguts_t dummy_yyguts;
+
+ yyset_extra (yy_user_defined, &dummy_yyguts);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in
+ yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ yyset_extra (yy_user_defined, *ptr_yy_globals);
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from yylex_destroy(), so don't allocate here.
+ */
+
+ yyg->yy_buffer_stack = 0;
+ yyg->yy_buffer_stack_top = 0;
+ yyg->yy_buffer_stack_max = 0;
+ yyg->yy_c_buf_p = (char *) 0;
+ yyg->yy_init = 0;
+ yyg->yy_start = 0;
+
+ yyg->yy_start_stack_ptr = 0;
+ yyg->yy_start_stack_depth = 0;
+ yyg->yy_start_stack = NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * yylex_init()
+ */
+ return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ yypop_buffer_state(yyscanner);
+ }
+
+ /* Destroy the stack itself. */
+ yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyg->yy_buffer_stack = NULL;
+
+ /* Destroy the start condition stack. */
+ yyfree(yyg->yy_start_stack ,yyscanner );
+ yyg->yy_start_stack = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * yylex() is called, initialization will occur. */
+ yy_init_globals( yyscanner);
+
+ /* Destroy the main struct (reentrant only). */
+ yyfree ( yyscanner , yyscanner );
+ yyscanner = NULL;
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *yyalloc (yy_size_t size , yyscan_t yyscanner)
+{
+ return (void *) malloc( size );
+}
+
+void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr , yyscan_t yyscanner)
+{
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 69 "ttl.l"
+
+
+
+int yywrap(yyscan_t scanner)
+{
+ return 1;
+}
+
+
diff --git a/flex_ttl.h b/flex_ttl.h
new file mode 100644
index 0000000..766e23f
--- /dev/null
+++ b/flex_ttl.h
@@ -0,0 +1,335 @@
+#ifndef yyHEADER_H
+#define yyHEADER_H 1
+#define yyIN_HEADER 1
+
+#line 6 "flex_ttl.h"
+
+#line 8 "flex_ttl.h"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+ are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+void yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void yypop_buffer_state (yyscan_t yyscanner );
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void yyfree (void * ,yyscan_t yyscanner );
+
+/* Begin user sect3 */
+
+#define yytext_ptr yytext_r
+
+#ifdef YY_HEADER_EXPORT_START_CONDITIONS
+#define INITIAL 0
+#define C_COMMENT 1
+#define C_LONGSTRING 2
+#define C_STRING 3
+
+#endif
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+int yylex_init (yyscan_t* scanner);
+
+int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (yyscan_t yyscanner );
+
+int yyget_debug (yyscan_t yyscanner );
+
+void yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *yyget_in (yyscan_t yyscanner );
+
+void yyset_in (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *yyget_out (yyscan_t yyscanner );
+
+void yyset_out (FILE * out_str ,yyscan_t yyscanner );
+
+int yyget_leng (yyscan_t yyscanner );
+
+char *yyget_text (yyscan_t yyscanner );
+
+int yyget_lineno (yyscan_t yyscanner );
+
+void yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (yyscan_t yyscanner );
+#else
+extern int yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (yyscan_t yyscanner);
+
+#define YY_DECL int yylex (yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+#undef YY_NEW_FILE
+#undef YY_FLUSH_BUFFER
+#undef yy_set_bol
+#undef yy_new_buffer
+#undef yy_set_interactive
+#undef YY_DO_BEFORE_ACTION
+
+#ifdef YY_DECL_IS_OURS
+#undef YY_DECL_IS_OURS
+#undef YY_DECL
+#endif
+
+#line 69 "ttl.l"
+
+
+#line 334 "flex_ttl.h"
+#undef yyIN_HEADER
+#endif /* yyHEADER_H */
diff --git a/gtk2gui.c b/gtk2gui.c
index 1bfd05b..def5697 100644
--- a/gtk2gui.c
+++ b/gtk2gui.c
@@ -34,7 +34,6 @@
#include <lv2dynparam/lv2_rtmempool.h>
#include <lv2dynparam/host.h>
#endif
-#include <slv2/lv2_ui.h>
#include <gtk/gtk.h>
#include <jack/jack.h>
@@ -43,6 +42,7 @@
#include "lv2_uri_map.h"
#include "lv2_data_access.h"
#include "lv2_string_port.h"
+#include "lv2_ui.h"
#include "lv2_external_ui.h"
#include "list.h"
@@ -51,7 +51,6 @@
#include "zynjacku.h"
#include "plugin.h"
#include "plugin_internal.h"
-#include "plugin_repo.h"
#define LOG_LEVEL LOG_LEVEL_ERROR
#include "log.h"
@@ -65,15 +64,15 @@
struct zynjacku_gtk2gui
{
const LV2_Feature ** host_features;
- const char *plugin_uri;
- char *bundle_path;
+ char * plugin_uri;
+ char * bundle_path;
unsigned int ports_count;
struct zynjacku_port ** ports;
- struct zynjacku_plugin * plugin;
+ struct zynjacku_plugin * plugin_ptr;
void * context_ptr;
- const char * synth_id;
+ const char * instance_name;
bool resizable;
- void *dlhandle;
+ void * dlhandle;
const LV2UI_Descriptor * lv2ui;
LV2UI_Handle ui_handle;
GtkWidget * widget_ptr;
@@ -106,36 +105,37 @@ zynjacku_gtk2gui_create(
const LV2_Feature * const * host_features,
unsigned int host_feature_count,
zynjacku_lv2_handle plugin_handle,
- struct zynjacku_plugin *plugin,
- void *context_ptr,
- const char *uri,
- const char *synth_id,
- const struct list_head *parameter_ports_ptr)
+ struct zynjacku_plugin * plugin_ptr,
+ void * context_ptr,
+ const char * ui_type_uri,
+ const char * plugin_uri,
+ const char * ui_uri,
+ const char * ui_binary_path,
+ const char * ui_bundle_path,
+ const char * plugin_instance_name,
+ const struct list_head * parameter_ports_ptr)
{
struct zynjacku_gtk2gui * ui_ptr;
unsigned int ports_count;
- struct list_head *node_ptr;
+ struct list_head * node_ptr;
struct zynjacku_port * port_ptr;
LV2UI_DescriptorFunction lookup;
uint32_t index;
- char * ui_uri;
- char * ui_binary_path;
- char * ui_bundle_path;
unsigned int type;
- if (zynjacku_plugin_repo_get_ui_info(uri, LV2_UI_GTK_URI, &ui_uri, &ui_binary_path, &ui_bundle_path))
+ if (strcmp(ui_type_uri, LV2_UI_GTK_URI) == 0)
{
- LOG_NOTICE("GtkUI for '%s'", uri);
+ LOG_NOTICE("GtkUI for '%s'", plugin_uri);
type = UI_TYPE_GTK;
}
- else if (zynjacku_plugin_repo_get_ui_info(uri, LV2_EXTERNAL_UI_URI, &ui_uri, &ui_binary_path, &ui_bundle_path))
+ else if (strcmp(ui_type_uri, LV2_EXTERNAL_UI_URI) == 0)
{
- LOG_NOTICE("External UI for '%s'", uri);
+ LOG_NOTICE("External UI for '%s'", plugin_uri);
type = UI_TYPE_EXTERNAL;
}
else
{
- LOG_DEBUG("zynjacku_plugin_repo_get_ui_info() failed for '%s'", uri);
+ LOG_DEBUG("Ignoring UI '%s' of plugin '%s', unknown type '%s'", ui_uri, plugin_uri, ui_type_uri);
goto fail;
}
@@ -143,20 +143,26 @@ zynjacku_gtk2gui_create(
if (ui_ptr == NULL)
{
LOG_ERROR("malloc() failed.");
- goto fail_free_ui_strings;
+ goto fail;
}
ui_ptr->type = type;
- ui_ptr->plugin_uri = uri;
- ui_ptr->plugin = plugin;
+ ui_ptr->plugin_uri = strdup(plugin_uri);
+ if (ui_ptr->plugin_uri == NULL)
+ {
+ LOG_ERROR("strdup(\"%s\") failed", plugin_uri);
+ goto fail_free;
+ }
+
+ ui_ptr->plugin_ptr = plugin_ptr;
ui_ptr->context_ptr = context_ptr;
- ui_ptr->synth_id = synth_id;
+ ui_ptr->instance_name = plugin_instance_name;
ui_ptr->resizable = true;
ui_ptr->lv2plugin = plugin_handle;
ui_ptr->data_access.data_access = zynjacku_lv2_get_descriptor(plugin_handle)->extension_data;
ui_ptr->external_ui.ui_closed = zynjacku_plugin_ui_closed;
- ui_ptr->external_ui.plugin_human_id = synth_id;
+ ui_ptr->external_ui.plugin_human_id = plugin_instance_name;
ui_ptr->gui_feature_instance_access.URI = "http://lv2plug.in/ns/ext/instance-access";
ui_ptr->gui_feature_instance_access.data = zynjacku_lv2_get_handle(ui_ptr->lv2plugin);
@@ -180,7 +186,7 @@ zynjacku_gtk2gui_create(
if (ui_ptr->ports == NULL)
{
LOG_ERROR("malloc() failed.");
- goto fail_free;
+ goto fail_free_plugin_uri;
}
memset(ui_ptr->ports, 0, ports_count * sizeof(struct zynjacku_port *));
@@ -207,13 +213,18 @@ zynjacku_gtk2gui_create(
ui_ptr->host_features[host_feature_count++] = &ui_ptr->gui_feature_external_ui;
ui_ptr->host_features[host_feature_count++] = NULL;
- ui_ptr->bundle_path = ui_bundle_path;
+ ui_ptr->bundle_path = strdup(ui_bundle_path);
+ if (ui_ptr->bundle_path == NULL)
+ {
+ LOG_ERROR("strdup(\"%s\") failed", ui_bundle_path);
+ goto fail_free_features;
+ }
ui_ptr->dlhandle = dlopen(ui_binary_path, RTLD_NOW);
if (ui_ptr->dlhandle == NULL)
{
LOG_WARNING("Cannot load \"%s\": %s", ui_binary_path, dlerror());
- goto fail_free_features;
+ goto fail_free_bundle_path;
}
lookup = (LV2UI_DescriptorFunction)dlsym(ui_ptr->dlhandle, "lv2ui_descriptor");
@@ -230,7 +241,7 @@ zynjacku_gtk2gui_create(
ui_ptr->lv2ui = lookup(index);
if (ui_ptr->lv2ui == NULL)
{
- LOG_ERROR("Did not find UI %s in %s", uri, ui_binary_path);
+ LOG_ERROR("Did not find UI %s in %s", ui_uri, ui_binary_path);
goto fail_dlclose;
}
@@ -243,27 +254,26 @@ zynjacku_gtk2gui_create(
ui_ptr->window_ptr = NULL;
ui_ptr->external_ui_control = NULL;
- free(ui_uri);
-
return ui_ptr;
fail_dlclose:
dlclose(ui_ptr->dlhandle);
+fail_free_bundle_path:
+ free(ui_ptr->bundle_path);
+
fail_free_features:
free(ui_ptr->host_features);
fail_free_ports:
free(ui_ptr->ports);
+fail_free_plugin_uri:
+ free(ui_ptr->plugin_uri);
+
fail_free:
free(ui_ptr);
-fail_free_ui_strings:
- free(ui_uri);
- free(ui_bundle_path);
- free(ui_binary_path);
-
fail:
return NULL;
}
@@ -329,9 +339,17 @@ zynjacku_gtk2gui_destroy(
zynjacku_gtk2gui_handle ui_handle)
{
LOG_DEBUG("zynjacku_on_gtk2gui_destroy() called");
+
+ if (ui_ptr->ui_handle != NULL &&
+ ui_ptr->type == UI_TYPE_EXTERNAL)
+ {
+ LV2_EXTERNAL_UI_HIDE(ui_ptr->external_ui_control);
+ }
+
dlclose(ui_ptr->dlhandle);
free(ui_ptr->ports);
free(ui_ptr->bundle_path);
+ free(ui_ptr->plugin_uri);
free(ui_ptr);
}
@@ -353,6 +371,7 @@ zynjacku_gtk2gui_callback_write(
}
zynjacku_plugin_ui_set_port_value(ui_ptr->ports[port_index]->plugin_ptr, ui_ptr->ports[port_index], buffer, buffer_size);
+ zynjacku_gtk2gui_port_event(ui_ptr, ui_ptr->ports[port_index]);
}
bool
@@ -424,7 +443,9 @@ zynjacku_gtk2gui_ui_on(
{
ui_ptr->window_ptr = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title(GTK_WINDOW(ui_ptr->window_ptr), ui_ptr->synth_id);
+ gtk_window_set_title(GTK_WINDOW(ui_ptr->window_ptr), ui_ptr->instance_name);
+
+ gtk_window_set_role(GTK_WINDOW(ui_ptr->window_ptr), "plugin_ui");
gtk_window_set_resizable(GTK_WINDOW(ui_ptr->window_ptr), ui_ptr->resizable);
diff --git a/gtk2gui.h b/gtk2gui.h
index cc56bf4..7d602a0 100644
--- a/gtk2gui.h
+++ b/gtk2gui.h
@@ -35,8 +35,12 @@ zynjacku_gtk2gui_create(
zynjacku_lv2_handle plugin_handle,
struct zynjacku_plugin * plugin,
void * context_ptr,
- const char * uri,
- const char * synth_id,
+ const char * ui_type_uri,
+ const char * plugin_uri,
+ const char * ui_uri,
+ const char * ui_binary_path,
+ const char * ui_bundle_path,
+ const char * plugin_instance_name,
const struct list_head * parameter_ports_ptr);
void
diff --git a/logo.png b/logo.png
deleted file mode 100644
index 1ae3f23..0000000
Binary files a/logo.png and /dev/null differ
diff --git a/lv2.c b/lv2.c
index b504424..92cce83 100644
--- a/lv2.c
+++ b/lv2.c
@@ -22,12 +22,14 @@
#include "config.h"
+#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <assert.h>
#include <dlfcn.h>
#include <string.h>
#include <stdlib.h>
+#include <errno.h>
#include <jack/jack.h>
#include <glib-object.h>
#include <lv2.h>
@@ -49,7 +51,7 @@
#include "zynjacku.h"
//#define LOG_LEVEL LOG_LEVEL_DEBUG
#include "log.h"
-#include "plugin_repo.h"
+#include "plugin.h"
struct zynjacku_lv2_plugin
{
@@ -59,34 +61,110 @@ struct zynjacku_lv2_plugin
LV2_Handle lv2handle;
};
+/* TODO: cleanup allocation dman_dlhandles */
+static void **dman_dlhandles = NULL;
+static size_t dman_dlhandles_count = 0;
+
+char *
+zynjacku_lv2_dman_get(
+ const char * dlpath)
+{
+ void *dlhandle;
+ FILE * (*lv2_dyn_manifest)();
+ void (*lv2_dyn_manifest_done)(FILE *fp);
+ void *tmp;
+ FILE *fp;
+ long size;
+ char *ret;
+
+ dlhandle = dlopen(dlpath, RTLD_NOW);
+ if (dlhandle == NULL)
+ {
+ LOG_ERROR("Unable to open library %s (%s)", dlpath, dlerror());
+ return NULL;
+ }
+
+ dlerror();
+ lv2_dyn_manifest = dlsym(dlhandle, "lv2_dyn_manifest");
+ if (lv2_dyn_manifest == NULL)
+ {
+ LOG_ERROR("Cannot retrieve dynamic manifest generator function of LV2 plugin %s (%s)", dlpath, dlerror());
+ dlclose(dlhandle);
+ return NULL;
+ }
+
+ dlerror();
+ lv2_dyn_manifest_done = dlsym(dlhandle, "lv2_dyn_manifest_done");
+ if (lv2_dyn_manifest_done == NULL)
+ {
+ LOG_ERROR("Cannot retrieve dynamic manifest destructor function of LV2 plugin %s (%s)", dlpath, dlerror());
+ dlclose(dlhandle);
+ return NULL;
+ }
+
+ fp = lv2_dyn_manifest();
+ if (fp == NULL)
+ {
+ LOG_ERROR("LV2 plugin %s's lv2_dynamic_manifest() returned NULL", dlpath);
+ dlclose(dlhandle);
+ return NULL;
+ }
+
+ if (fseek(fp, 0, SEEK_END) < 0)
+ {
+ LOG_ERROR("Cannot determine the size of dynamic manifest file (%s)", strerror(errno));
+ dlclose(dlhandle);
+ return NULL;
+ }
+ size = ftell(fp);
+ if (size < 0)
+ {
+ LOG_ERROR("Cannot determine the size of dynamic manifest file (%s)", strerror(errno));
+ dlclose(dlhandle);
+ return NULL;
+ }
+ rewind(fp);
+
+ ret = malloc(size + 1);
+ if (ret == NULL)
+ {
+ LOG_ERROR("Failed to allocate memory to store the dynamically generated manifest file");
+ dlclose(dlhandle);
+ return NULL;
+ }
+
+ tmp = realloc(dman_dlhandles, (dman_dlhandles_count + 1) * sizeof(void *));
+ if (tmp == NULL)
+ {
+ LOG_ERROR("Failed to allocate memory for dman_dlhandles");
+ free(ret);
+ dlclose(dlhandle);
+ return NULL;
+ }
+ dman_dlhandles = tmp;
+ dman_dlhandles[dman_dlhandles_count] = dlhandle;
+ dman_dlhandles_count++;
+
+ size = fread(ret, 1, size, fp);
+ ret[size] = '\0';
+ lv2_dyn_manifest_done(fp);
+
+ return ret;
+}
+
zynjacku_lv2_handle
zynjacku_lv2_load(
const char * uri,
+ const char * dlpath,
+ const char * bundle_path,
double sample_rate,
const LV2_Feature * const * features)
{
- const char *dlpath;
- const char *bundle_path;
-
struct zynjacku_lv2_plugin *plugin_ptr;
LV2_Descriptor_Function lv2lookup;
char *error;
uint32_t plugin_index;
- dlpath = zynjacku_plugin_repo_get_dlpath(uri);
- if (dlpath == NULL)
- {
- LOG_ERROR("Failed to get path of library implementeding plugin %s", uri);
- goto fail;
- }
-
- bundle_path = zynjacku_plugin_repo_get_bundle_path(uri);
- if (bundle_path == NULL)
- {
- LOG_ERROR("Failed to get bundle path of plugin %s", uri);
- goto fail;
- }
-
plugin_ptr = malloc(sizeof(struct zynjacku_lv2_plugin));
if (plugin_ptr == NULL)
{
@@ -167,8 +245,17 @@ void
zynjacku_lv2_unload(
zynjacku_lv2_handle lv2handle)
{
+ size_t i;
+
plugin_ptr->lv2->cleanup(plugin_ptr->lv2handle);
dlclose(plugin_ptr->dlhandle);
+ for (i = 0; i < dman_dlhandles_count; i++)
+ if (dman_dlhandles[i] == plugin_ptr->dlhandle)
+ {
+ dlclose(plugin_ptr->dlhandle);
+ dman_dlhandles[i] = NULL;
+ break;
+ }
free(plugin_ptr);
}
diff --git a/lv2.h b/lv2.h
index 187694f..5b1eb33 100644
--- a/lv2.h
+++ b/lv2.h
@@ -27,9 +27,15 @@ typedef struct { int _unused; } * zynjacku_lv2_handle;
struct zynjacku_port;
+char *
+zynjacku_lv2_dman_get(
+ const char * dlpath);
+
zynjacku_lv2_handle
zynjacku_lv2_load(
const char * uri,
+ const char * dlpath,
+ const char * bundle_path,
double sample_rate,
const LV2_Feature * const * host_features);
diff --git a/lv2_ui.h b/lv2_ui.h
new file mode 100644
index 0000000..d5b813d
--- /dev/null
+++ b/lv2_ui.h
@@ -0,0 +1,372 @@
+/************************************************************************
+ *
+ * In-process UI extension for LV2
+ *
+ * Copyright (C) 2006-2008 Lars Luthman <lars.luthman at gmail.com>
+ *
+ * Based on lv2.h, which was
+ *
+ * Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis,
+ * Stefan Westerfeld
+ * Copyright (C) 2006 Steve Harris, Dave Robillard.
+ *
+ * This header is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License,
+ * or (at your option) any later version.
+ *
+ * This header 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ * USA.
+ *
+ ***********************************************************************/
+
+/** @file
+ This extension defines an interface that can be used in LV2 plugins and
+ hosts to create UIs for plugins. The UIs are plugins that reside in
+ shared object files in an LV2 bundle and are referenced in the RDF data
+ using the triples (Turtle shown)
+<pre>
+ @@prefix uiext: <http://lv2plug.in/ns/extensions/ui#> .
+ <http://my.plugin> uiext:ui <http://my.pluginui> .
+ <http://my.plugin> a uiext:GtkUI .
+ <http://my.pluginui> uiext:binary <myui.so> .
+</pre>
+ where <http://my.plugin> is the URI of the plugin, <http://my.pluginui> is
+ the URI of the plugin UI and <myui.so> is the relative URI to the shared
+ object file. While it is possible to have the plugin UI and the plugin in
+ the same shared object file it is probably a good idea to keep them
+ separate so that hosts that don't want UIs don't have to load the UI code.
+ A UI MUST specify its class in the RDF data, in this case uiext:GtkUI. The
+ class defines what type the UI is, e.g. what graphics toolkit it uses.
+ There are no UI classes defined in this extension, those are specified
+ separately (and anyone can define their own).
+
+ (Note: the prefix above is used throughout this file for the same URI)
+
+ It's entirely possible to have multiple UIs for the same plugin, or to have
+ the UI for a plugin in a different bundle from the actual plugin - this
+ way people other than the plugin author can write plugin UIs independently
+ without editing the original plugin bundle.
+
+ Note that the process that loads the shared object file containing the UI
+ code and the process that loads the shared object file containing the
+ actual plugin implementation does not have to be the same. There are many
+ valid reasons for having the plugin and the UI in different processes, or
+ even on different machines. This means that you can _not_ use singletons
+ and global variables and expect them to refer to the same objects in the
+ UI and the actual plugin. The function callback interface defined in this
+ header is all you can expect to work.
+
+ Since the LV2 specification itself allows for extensions that may add
+ new types of data and configuration parameters that plugin authors may
+ want to control with a UI, this extension allows for meta-extensions that
+ can extend the interface between the UI and the host. These extensions
+ mirror the extensions used for plugins - there are required and optional
+ "features" that you declare in the RDF data for the UI as
+<pre>
+ <http://my.pluginui> uiext:requiredFeature <http://my.feature> .
+ <http://my.pluginui> uiext:optionalFeature <http://my.feature> .
+</pre>
+ These predicates have the same semantics as lv2:requiredFeature and
+ lv2:optionalFeature - if a UI is declaring a feature as required, the
+ host is NOT allowed to load it unless it supports that feature, and if it
+ does support a feature (required or optional) it MUST pass that feature's
+ URI and any additional data (specified by the meta-extension that defines
+ the feature) in a LV2_Feature struct (as defined in lv2.h) to the UI's
+ instantiate() function.
+
+ These features may be used to specify how to pass data between the UI
+ and the plugin port buffers - see LV2UI_Write_Function for details.
+
+ There are four features defined in this extension that hosts may want to
+ implement:
+
+<pre>
+ uiext:makeResident
+</pre>
+ If this feature is required by a UI the host MUST NEVER unload the shared
+ library containing the UI implementation during the lifetime of the host
+ process (e.g. never calling dlclose() on Linux). This feature may be
+ needed by e.g. a Gtk UI that registers its own Glib types using
+ g_type_register_static() - if it gets unloaded and then loaded again the
+ type registration will break, since there is no way to unregister the
+ types when the library is unloaded. The data pointer in the LV2_Feature
+ for this feature should always be set to NULL.
+
+<pre>
+ uiext:makeSONameResident
+</pre>
+ This feature is ELF specific - it should only be used by UIs that
+ use the ELF file format for the UI shared object files (e.g. on Linux).
+ If it is required by an UI the UI should also list a number of SO names
+ (shared object names) for libraries that the UI shared object
+ depends on and that may not be unloaded during the lifetime of the host
+ process, using the predicate @c uiext:residentSONames, like this:
+<pre>
+ <http://my.pluginui> uiext:residentSONames "libgtkmm-2.4.so.1", "libfoo.so.0"
+</pre>
+ The host MUST then make sure that the shared libraries with the given ELF
+ SO names are not unloaded when the plugin UI is, but stay loaded during
+ the entire lifetime of the host process. On Linux this can be accomplished
+ by calling dlopen() on the shared library file with that SO name and never
+ calling a matching dlclose(). However, if a plugin UI requires the
+ @c uiext:makeSONameResident feature, it MUST ALWAYS be safe for the host to
+ just never unload the shared object containing the UI implementation, i.e.
+ act as if the UI required the @c uiext:makeResident feature instead. Thus
+ the host only needs to find the shared library files corresponding to the
+ given SO names if it wants to save RAM by unloading the UI shared object
+ file when it is no longer needed. The data pointer for the LV2_Feature for
+ this feature should always be set to NULL.
+
+<pre>
+ uiext:noUserResize
+</pre>
+ If an UI requires this feature it indicates that it does not make sense
+ to let the user resize the main widget, and the host should prevent that.
+ This feature may not make sense for all UI types. The data pointer for the
+ LV2_Feature for this feature should always be set to NULL.
+
+<pre>
+ uiext:fixedSize
+</pre>
+ If an UI requires this feature it indicates the same thing as
+ uiext:noUserResize, and additionally it means that the UI will not resize
+ the main widget on its own - it will always remain the same size (e.g. a
+ pixmap based GUI). This feature may not make sense for all UI types.
+ The data pointer for the LV2_Feature for this feature should always be set
+ to NULL.
+
+
+ UIs written to this specification do not need to be threadsafe - the
+ functions defined below may only be called in the same thread as the UI
+ main loop is running in.
+
+ Note that this UI extension is NOT a lv2:Feature. There is no way for a
+ plugin to know whether the host that loads it supports UIs or not, and
+ the plugin must ALWAYS work without the UI (although it may be rather
+ useless unless it has been configured using the UI in a previous session).
+
+ A UI does not have to be a graphical widget, it could just as well be a
+ server listening for OSC input or an interface to some sort of hardware
+ device, depending on the RDF class of the UI.
+*/
+
+#ifndef LV2_UI_H
+#define LV2_UI_H
+
+#include "lv2.h"
+
+#define LV2_UI_URI "http://lv2plug.in/ns/extensions/ui"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** A pointer to some widget or other type of UI handle.
+ The actual type is defined by the type URI of the UI.
+ All the functionality provided by this extension is toolkit
+ independent, the host only needs to pass the necessary callbacks and
+ display the widget, if possible. Plugins may have several UIs, in various
+ toolkits. */
+typedef void* LV2UI_Widget;
+
+
+/** This handle indicates a particular instance of a UI.
+ It is valid to compare this to NULL (0 for C++) but otherwise the
+ host MUST not attempt to interpret it. The UI plugin may use it to
+ reference internal instance data. */
+typedef void* LV2UI_Handle;
+
+
+/** This handle indicates a particular plugin instance, provided by the host.
+ It is valid to compare this to NULL (0 for C++) but otherwise the
+ UI plugin MUST not attempt to interpret it. The host may use it to
+ reference internal plugin instance data. */
+typedef void* LV2UI_Controller;
+
+
+/** This is the type of the host-provided function that the UI can use to
+ send data to a plugin's input ports. The @c buffer parameter must point
+ to a block of data, @c buffer_size bytes large. The contents of this buffer
+ and what the host should do with it depends on the value of the @c format
+ parameter.
+
+ The @c format parameter should either be 0 or a numeric ID for a "Transfer
+ mechanism". Transfer mechanisms are Features and may be defined in
+ meta-extensions. They specify how to translate the data buffers passed
+ to this function to input data for the plugin ports. If a UI wishes to
+ write data to an input port, it must list a transfer mechanism Feature
+ for that port's class as an optional or required feature (depending on
+ whether the UI will work without being able to write to that port or not).
+ The only exception is when the UI wants to write single float values to
+ input ports of the class lv2:ControlPort, in which case @c buffer_size
+ should always be 4, the buffer should always contain a single IEEE-754
+ float, and @c format should be 0.
+
+ The numeric IDs for the transfer mechanisms are provided by a
+ URI-to-integer mapping function provided by the host, using the URI Map
+ feature <http://lv2plug.in/ns/ext/uri-map> with the map URI
+ "http://lv2plug.in/ns/extensions/ui". Thus a UI that requires transfer
+ mechanism features also requires the URI Map feature, but this is
+ implicit - the UI does not have to list the URI map feature as a required
+ or optional feature in it's RDF data.
+
+ An UI MUST NOT pass a @c format parameter value (except 0) that has not
+ been returned by the host-provided URI mapping function for a
+ host-supported transfer mechanism feature URI.
+
+ The UI MUST NOT try to write to a port for which there is no specified
+ transfer mechanism, or to an output port. The UI is responsible for
+ allocating the buffer and deallocating it after the call.
+*/
+typedef void (*LV2UI_Write_Function)(LV2UI_Controller controller,
+ uint32_t port_index,
+ uint32_t buffer_size,
+ uint32_t format,
+ const void* buffer);
+
+
+/** This struct contains the implementation of an UI. A pointer to an
+ object of this type is returned by the lv2ui_descriptor() function.
+*/
+typedef struct _LV2UI_Descriptor {
+
+ /** The URI for this UI (not for the plugin it controls). */
+ const char* URI;
+
+ /** Create a new UI object and return a handle to it. This function works
+ similarly to the instantiate() member in LV2_Descriptor.
+
+ @param descriptor The descriptor for the UI that you want to instantiate.
+ @param plugin_uri The URI of the plugin that this UI will control.
+ @param bundle_path The path to the bundle containing the RDF data file
+ that references this shared object file, including the
+ trailing '/'.
+ @param write_function A function provided by the host that the UI can
+ use to send data to the plugin's input ports.
+ @param controller A handle for the plugin instance that should be passed
+ as the first parameter of @c write_function.
+ @param widget A pointer to an LV2UI_Widget. The UI will write a
+ widget pointer to this location (what type of widget
+ depends on the RDF class of the UI) that will be the
+ main UI widget.
+ @param features An array of LV2_Feature pointers. The host must pass
+ all feature URIs that it and the UI supports and any
+ additional data, just like in the LV2 plugin
+ instantiate() function. Note that UI features and plugin
+ features are NOT necessarily the same, they just share
+ the same data structure - this will probably not be the
+ same array as the one the plugin host passes to a
+ plugin.
+ */
+ LV2UI_Handle (*instantiate)(const struct _LV2UI_Descriptor* descriptor,
+ const char* plugin_uri,
+ const char* bundle_path,
+ LV2UI_Write_Function write_function,
+ LV2UI_Controller controller,
+ LV2UI_Widget* widget,
+ const LV2_Feature* const* features);
+
+
+ /** Destroy the UI object and the associated widget. The host must not try
+ to access the widget after calling this function.
+ */
+ void (*cleanup)(LV2UI_Handle ui);
+
+ /** Tell the UI that something interesting has happened at a plugin port.
+ What is interesting and how it is written to the buffer passed to this
+ function is defined by the @c format parameter, which has the same
+ meaning as in LV2UI_Write_Function. The only exception is ports of the
+ class lv2:ControlPort, for which this function should be called
+ when the port value changes (it does not have to be called for every
+ single change if the host's UI thread has problems keeping up with
+ the thread the plugin is running in), @c buffer_size should be 4 and the
+ buffer should contain a single IEEE-754 float. In this case the @c format
+ parameter should be 0.
+
+ By default, the host should only call this function for input ports of
+ the lv2:ControlPort class. However, the default setting can be modified
+ by using the following URIs in the UI's RDF data:
+ <pre>
+ uiext:portNotification
+ uiext:noPortNotification
+ uiext:plugin
+ uiext:portIndex
+ </pre>
+ For example, if you want the UI with uri
+ <code><http://my.pluginui></code> for the plugin with URI
+ <code><http://my.plugin></code> to get notified when the value of the
+ output control port with index 4 changes, you would use the following
+ in the RDF for your UI:
+ <pre>
+ <http://my.pluginui> uiext:portNotification [ uiext:plugin <http://my.plugin> ;
+ uiext:portIndex 4 ] .
+ </pre>
+ and similarly with <code>uiext:noPortNotification</code> if you wanted
+ to prevent notifications for a port for which it would be on by default
+ otherwise. The UI is not allowed to request notifications for ports of
+ types for which no transfer mechanism is specified, if it does it should
+ be considered broken and the host should not load it.
+
+ The @c buffer is only valid during the time of this function call, so if
+ the UI wants to keep it for later use it has to copy the contents to an
+ internal buffer.
+
+ This member may be set to NULL if the UI is not interested in any
+ port events.
+ */
+ void (*port_event)(LV2UI_Handle ui,
+ uint32_t port_index,
+ uint32_t buffer_size,
+ uint32_t format,
+ const void* buffer);
+
+ /** Returns a data structure associated with an extension URI, for example
+ a struct containing additional function pointers. Avoid returning
+ function pointers directly since standard C++ has no valid way of
+ casting a void* to a function pointer. This member may be set to NULL
+ if the UI is not interested in supporting any extensions. This is similar
+ to the extension_data() member in LV2_Descriptor.
+ */
+ const void* (*extension_data)(const char* uri);
+
+} LV2UI_Descriptor;
+
+
+
+/** A plugin UI programmer must include a function called "lv2ui_descriptor"
+ with the following function prototype within the shared object
+ file. This function will have C-style linkage (if you are using
+ C++ this is taken care of by the 'extern "C"' clause at the top of
+ the file). This function will be accessed by the UI host using the
+ @c dlsym() function and called to get a LV2UI_UIDescriptor for the
+ wanted plugin.
+
+ Just like lv2_descriptor(), this function takes an index parameter. The
+ index should only be used for enumeration and not as any sort of ID number -
+ the host should just iterate from 0 and upwards until the function returns
+ NULL or a descriptor with an URI matching the one the host is looking for.
+*/
+const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index);
+
+
+/** This is the type of the lv2ui_descriptor() function. */
+typedef const LV2UI_Descriptor* (*LV2UI_DescriptorFunction)(uint32_t index);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/lv2rack.py b/lv2rack.py
index f512dd1..3a4c792 100755
--- a/lv2rack.py
+++ b/lv2rack.py
@@ -24,10 +24,29 @@ import gtk.glade
import gobject
import re
import time
+from distutils import sysconfig
old_path = sys.path
-sys.path.insert(0, "%s/.libs" % os.path.dirname(sys.argv[0]))
-import zynjacku_c
+
+inplace_libs = os.path.join(os.path.dirname(sys.argv[0]), ".libs")
+if os.access(inplace_libs, os.R_OK):
+ sys.path.append(inplace_libs)
+else:
+ inplace_libs = None
+
+try:
+ if inplace_libs:
+ import zynjacku_c
+ else:
+ from zynworld import zynjacku_c
+except Exception, e:
+ print "Failed to import zynjacku internal python modules"
+ print repr(e)
+ print "These directories were searched"
+ for path in sys.path:
+ print " " + path
+ sys.exit(1)
+
sys.path = old_path
import zynjacku as zynjacku
@@ -39,14 +58,20 @@ except:
lash = None
class lv2rack(zynjacku.host):
- def __init__(self, data_dir, glade_xml, client_name, the_license, uris, lash_client):
+ def __init__(self, client_name, preset_extension=None, preset_name=None, lash_client=None):
#print "lv2rack constructor called."
- zynjacku.host.__init__(self, zynjacku_c.Rack(), client_name, "lv2rack", "effect stack", lash_client)
-
- self.data_dir = data_dir
- self.glade_xml = glade_xml
- self.main_window = glade_xml.get_widget("lv2rack")
+ zynjacku.host.__init__(self, zynjacku_c.Rack(), client_name, preset_extension, preset_name, lash_client)
+
+class lv2rack_multi(lv2rack):
+ def __init__(self, program_data, client_name, uris, lash_client):
+ #print "lv2rack_multi constructor called."
+ lv2rack.__init__(self, client_name, "lv2rack", "effect stack", lash_client)
+
+ self.program_data = program_data
+ self.glade_xml = program_data['glade_xml']
+
+ self.main_window = self.glade_xml.get_widget("lv2rack")
self.main_window.set_title(client_name)
self.statusbar = self.glade_xml.get_widget("lv2rack_statusbar")
@@ -62,15 +87,13 @@ class lv2rack(zynjacku.host):
self.signal_ids = []
for k, v in dic.items():
- w = glade_xml.get_widget(k)
+ w = self.glade_xml.get_widget(k)
if not w:
print "failed to get glade widget '%s'" % k
continue
self.signal_ids.append([w, w.connect("activate", v)])
- self.the_license = the_license
-
- self.effects_widget = glade_xml.get_widget("lv2rack_treeview_effects")
+ self.effects_widget = self.glade_xml.get_widget("lv2rack_treeview_effects")
self.store = gtk.ListStore(gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
text_renderer = gtk.CellRendererText()
@@ -113,16 +136,53 @@ class lv2rack(zynjacku.host):
self.store.clear()
- zynjacku.host.__del__(self)
+ lv2rack.__del__(self)
def new_plugin(self, uri, parameters=[], maps={}):
self.progress_window.show(uri)
- plugin = zynjacku.host.new_plugin(self, uri, parameters, maps)
+ plugin = lv2rack.new_plugin(self, uri, parameters, maps)
return plugin
def on_plugin_progress(self, engine, name, progress, message):
self.progress_window.progress(name, progress, message)
+ def check_plugin(self, plugin):
+ audio_in_ports_count = 0
+ audio_out_ports_count = 0
+
+ for port in plugin.ports:
+ if port.__dict__["isAudio"]:
+ if port.__dict__["isInput"]:
+ audio_in_ports_count += 1
+ continue
+ if port.__dict__["isOutput"]:
+ audio_out_ports_count += 1
+ continue
+ continue
+
+ if audio_in_ports_count == 0 or audio_out_ports_count == 0:
+# print "Skipping %s (%s), [effect] plugin with unsupported port configuration" % (plugin.name, plugin.uri)
+# #print " midi input ports: %d" % midi_in_ports_count
+# #print " control ports: %d" % control_ports_count
+# #print " string ports: %d" % string_ports_count
+# #print " event ports: %d" % event_ports_count
+# #print " event midi input ports: %d" % midi_event_in_ports_count
+# print " audio input ports: %d" % audio_in_ports_count
+# print " audio output ports: %d" % audio_out_ports_count
+# #print " total ports %d" % ports_count
+ return False;
+
+# print "Found effect plugin '%s' %s", (plugin.name, plugin.uri)
+# #print " midi input ports: %d" % midi_in_ports_count
+# #print " control ports: %d" % control_ports_count
+# #print " string ports: %d" % string_ports_count
+# #print " event ports: %d" % event_ports_count
+# #print " event midi input ports: %d" % midi_event_in_ports_count
+# print " audio input ports: %d" % audio_in_ports_count
+# print " audio output ports: %d" % audio_out_ports_count
+# #print " total ports %d" % ports_count
+ return True;
+
def load_plugin(self, uri, parameters=[], maps={}):
statusbar_context_id = self.statusbar.get_context_id("loading plugin")
statusbar_id = self.statusbar.push(statusbar_context_id, "Loading %s" % uri)
@@ -140,7 +200,7 @@ class lv2rack(zynjacku.host):
def run(self):
toggled_connect_id = self.toggle_renderer.connect('toggled', self.on_ui_visible_toggled, self.store)
- zynjacku.host.run(self)
+ lv2rack.run(self)
self.toggle_renderer.disconnect(toggled_connect_id)
@@ -166,21 +226,7 @@ class lv2rack(zynjacku.host):
self.statusbar.push(statusbar_context_id, "Failed to construct show effect UI")
def on_about(self, widget):
- about = gtk.AboutDialog()
- about.set_transient_for(self.main_window)
- about.set_name("lv2rack")
- if zynjacku_c.zynjacku_get_version() == "dev":
- about.set_comments("(development snapshot)")
- else:
- about.set_version(zynjacku_c.zynjacku_get_version())
- about.set_license(self.the_license)
- about.set_website("http://home.gna.org/zynjacku/")
- about.set_authors(["Nedko Arnaudov"])
- #about.set_artists(["Thorsten Wilms"])
- #about.set_logo(gtk.gdk.pixbuf_new_from_file("%s/logo.png" % self.data_dir))
- about.show()
- about.run()
- about.hide()
+ zynjacku.run_about_dialog(self.main_window, self.program_data)
def on_preset_load(self, widget):
self.preset_load_ask()
@@ -205,7 +251,7 @@ class lv2rack(zynjacku.host):
progressbar.show()
progressbar.set_fraction(progress)
- progressbar.set_text("Checking %s" % uri);
+ progressbar.set_text("Checking %s" % uri)
while gtk.events_pending():
gtk.main_iteration()
@@ -213,14 +259,57 @@ class lv2rack(zynjacku.host):
self.plugins_load("LV2 effect plugins")
def on_effect_clear(self, widget):
- self.store.clear();
+ self.store.clear()
self.clear_plugins()
+class lv2rack_single(lv2rack):
+ def __init__(self, program_data, client_name, uri):
+ #print "ZynjackuHostOne constructor called."
+ lv2rack.__init__(self, client_name, "lv2rack")
+
+ self.glade_xml = program_data['glade_xml']
+
+ self.plugin = self.new_plugin(uri)
+ if not self.plugin:
+ print"Failed to construct %s" % uri
+ return
+
+ if not lv2rack.create_plugin_ui(self, self.plugin):
+ print"Failed to create synth window"
+ return
+
+ def new_plugin(self, uri, parameters=[], maps={}):
+ self.progress_window.show(uri)
+ plugin = lv2rack.new_plugin(self, uri, parameters, maps)
+ self.progress_window.hide()
+ return plugin
+
+ def on_plugin_progress(self, engine, name, progress, message):
+ self.progress_window.progress(name, progress, message)
+
+ def on_plugin_ui_window_destroyed(self, window, synth, row):
+ gtk.main_quit()
+
+ def run(self):
+ if not self.plugin:
+ self.run_done()
+ return
+
+ self.plugin.ui_win.show()
+ lv2rack.run(self)
+
+ def __del__(self):
+ #print "lv2rack_single destructor called."
+
+ lv2rack.__del__(self)
+
def main():
- data_dir, glade_xml, the_license = zynjacku.file_setup()
+ program_data = zynjacku.get_program_data('lv2rack')
zynjacku.register_types()
+ client_name = "lv2rack"
+
if lash: # If LASH python bindings are available
# sys.argv is modified by this call
lash_client = lash.init(sys.argv, "lv2rack", lash.LASH_Config_File)
@@ -234,7 +323,12 @@ def main():
if lash_client:
print "Successfully connected to LASH server at " + lash.lash_get_server_name(lash_client)
- lv2rack(data_dir, glade_xml, "lv2rack", the_license, sys.argv[1:], lash_client).run()
+ if len(sys.argv) == 2 and sys.argv[1][-9:] != ".lv2rack":
+ host = lv2rack_single(program_data, client_name, sys.argv[1])
+ else:
+ host = lv2rack_multi(program_data, client_name, sys.argv[1:], lash_client)
+
+ host.run()
sys.stdout.flush()
sys.stderr.flush()
diff --git a/plugin.c b/plugin.c
index 34c61d1..2124798 100644
--- a/plugin.c
+++ b/plugin.c
@@ -23,16 +23,23 @@
#include "config.h"
+#include <stdbool.h>
#include <stdio.h>
#include <string.h>
+#include <assert.h>
#include <locale.h>
#include <unistd.h>
-#include <slv2/slv2.h>
-//#include <slv2/query.h>
#include <jack/jack.h>
#include <jack/midiport.h>
#include <glib-object.h>
+#include <lv2.h>
+#if HAVE_DYNPARAMS
+#include <lv2dynparam/lv2dynparam.h>
+#include <lv2dynparam/lv2_rtmempool.h>
+#include <lv2dynparam/host.h>
+#endif
+
#include "lv2-miditype.h"
#include "lv2_event.h"
#include "lv2_uri_map.h"
@@ -40,11 +47,6 @@
#include "list.h"
//#define LOG_LEVEL LOG_LEVEL_DEBUG
#include "log.h"
-#if HAVE_DYNPARAMS
-#include <lv2dynparam/lv2dynparam.h>
-#include <lv2dynparam/lv2_rtmempool.h>
-#include <lv2dynparam/host.h>
-#endif
#include "plugin.h"
#include "engine.h"
@@ -59,9 +61,6 @@
#include "zynjacku.h"
#include "plugin_internal.h"
-#include "plugin_repo.h"
-#include "synth.h"
-#include "effect.h"
#include "midi_cc_map.h"
#include "midi_cc_map_internal.h"
@@ -84,6 +83,9 @@
/* properties */
#define ZYNJACKU_PLUGIN_PROP_URI 1
+#define ZYNJACKU_PLUGIN_PROP_DLPATH 2
+#define ZYNJACKU_PLUGIN_PROP_BUNDLE_PATH 3
+#define ZYNJACKU_PLUGIN_PROP_NAME 4
static guint g_zynjacku_plugin_signals[ZYNJACKU_PLUGIN_SIGNALS_COUNT];
@@ -189,6 +191,24 @@ zynjacku_plugin_dispose(GObject * obj)
plugin_ptr->uri = NULL;
}
+ if (plugin_ptr->dlpath != NULL)
+ {
+ g_free(plugin_ptr->dlpath);
+ plugin_ptr->dlpath = NULL;
+ }
+
+ if (plugin_ptr->bundle_path != NULL)
+ {
+ g_free(plugin_ptr->bundle_path);
+ plugin_ptr->bundle_path = NULL;
+ }
+
+ if (plugin_ptr->name != NULL)
+ {
+ g_free(plugin_ptr->name);
+ plugin_ptr->name = NULL;
+ }
+
/* Chain up to the parent class */
G_OBJECT_CLASS(g_type_class_peek_parent(G_OBJECT_GET_CLASS(obj)))->dispose(obj);
}
@@ -233,6 +253,36 @@ zynjacku_plugin_set_property(
plugin_ptr->uri = g_value_dup_string(value_ptr);
LOG_DEBUG("plugin uri set to: \"%s\"", plugin_ptr->uri);
break;
+ case ZYNJACKU_PLUGIN_PROP_DLPATH:
+ //LOG_DEBUG("setting plugin dlpath to: \"%s\"", g_value_get_string(value_ptr));
+ //break;
+ if (plugin_ptr->dlpath != NULL)
+ {
+ g_free(plugin_ptr->dlpath);
+ }
+ plugin_ptr->dlpath = g_value_dup_string(value_ptr);
+ LOG_DEBUG("plugin dlpath set to: \"%s\"", plugin_ptr->dlpath);
+ break;
+ case ZYNJACKU_PLUGIN_PROP_BUNDLE_PATH:
+ //LOG_DEBUG("setting plugin bundle path to: \"%s\"", g_value_get_string(value_ptr));
+ //break;
+ if (plugin_ptr->bundle_path != NULL)
+ {
+ g_free(plugin_ptr->bundle_path);
+ }
+ plugin_ptr->bundle_path = g_value_dup_string(value_ptr);
+ LOG_DEBUG("plugin bundle path set to: \"%s\"", plugin_ptr->bundle_path);
+ break;
+ case ZYNJACKU_PLUGIN_PROP_NAME:
+ //LOG_DEBUG("setting plugin name to: \"%s\"", g_value_get_string(value_ptr));
+ //break;
+ if (plugin_ptr->name != NULL)
+ {
+ g_free(plugin_ptr->name);
+ }
+ plugin_ptr->name = g_value_dup_string(value_ptr);
+ LOG_DEBUG("plugin name set to: \"%s\"", plugin_ptr->name);
+ break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID(object_ptr, property_id, param_spec_ptr);
@@ -263,6 +313,36 @@ zynjacku_plugin_get_property(
g_value_set_string(value_ptr, "");
}
break;
+ case ZYNJACKU_PLUGIN_PROP_DLPATH:
+ if (plugin_ptr->dlpath != NULL)
+ {
+ g_value_set_string(value_ptr, plugin_ptr->dlpath);
+ }
+ else
+ {
+ g_value_set_string(value_ptr, "");
+ }
+ break;
+ case ZYNJACKU_PLUGIN_PROP_BUNDLE_PATH:
+ if (plugin_ptr->bundle_path != NULL)
+ {
+ g_value_set_string(value_ptr, plugin_ptr->bundle_path);
+ }
+ else
+ {
+ g_value_set_string(value_ptr, "");
+ }
+ break;
+ case ZYNJACKU_PLUGIN_PROP_NAME:
+ if (plugin_ptr->name != NULL)
+ {
+ g_value_set_string(value_ptr, plugin_ptr->name);
+ }
+ else
+ {
+ g_value_set_string(value_ptr, "");
+ }
+ break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID(object_ptr, property_id, param_spec_ptr);
@@ -275,7 +355,7 @@ zynjacku_plugin_class_init(
gpointer class_ptr,
gpointer class_data_ptr)
{
- GParamSpec * uri_param_spec;
+ GParamSpec * param_spec;
LOG_DEBUG("zynjacku_plugin_class_init() called.");
@@ -509,17 +589,53 @@ zynjacku_plugin_class_init(
G_OBJECT_CLASS(class_ptr)->get_property = zynjacku_plugin_get_property;
G_OBJECT_CLASS(class_ptr)->set_property = zynjacku_plugin_set_property;
- uri_param_spec = g_param_spec_string(
+ param_spec = g_param_spec_string(
"uri",
- "Plugin LV2 URI construct property",
- "Plugin LV2 URI construct property",
+ "Plugin URI",
+ "Plugin URI",
"" /* default value */,
G_PARAM_CONSTRUCT_ONLY |G_PARAM_READWRITE);
g_object_class_install_property(
G_OBJECT_CLASS(class_ptr),
ZYNJACKU_PLUGIN_PROP_URI,
- uri_param_spec);
+ param_spec);
+
+ param_spec = g_param_spec_string(
+ "dlpath",
+ "Path to plugin binary",
+ "Path to plugin binary",
+ "" /* default value */,
+ G_PARAM_CONSTRUCT_ONLY |G_PARAM_READWRITE);
+
+ g_object_class_install_property(
+ G_OBJECT_CLASS(class_ptr),
+ ZYNJACKU_PLUGIN_PROP_DLPATH,
+ param_spec);
+
+ param_spec = g_param_spec_string(
+ "bundle_path",
+ "Path to plugin bundle",
+ "Path to plugin bundle",
+ "" /* default value */,
+ G_PARAM_CONSTRUCT_ONLY |G_PARAM_READWRITE);
+
+ g_object_class_install_property(
+ G_OBJECT_CLASS(class_ptr),
+ ZYNJACKU_PLUGIN_PROP_BUNDLE_PATH,
+ param_spec);
+
+ param_spec = g_param_spec_string(
+ "name",
+ "Plugin name",
+ "Plugin name",
+ "" /* default value */,
+ G_PARAM_CONSTRUCT_ONLY |G_PARAM_READWRITE);
+
+ g_object_class_install_property(
+ G_OBJECT_CLASS(class_ptr),
+ ZYNJACKU_PLUGIN_PROP_NAME,
+ param_spec);
}
static void
@@ -534,16 +650,21 @@ zynjacku_plugin_init(
plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(instance);
plugin_ptr->dispose_has_run = FALSE;
+ INIT_LIST_HEAD(&plugin_ptr->midi_ports);
+ INIT_LIST_HEAD(&plugin_ptr->audio_ports);
INIT_LIST_HEAD(&plugin_ptr->parameter_ports);
INIT_LIST_HEAD(&plugin_ptr->measure_ports);
#if HAVE_DYNPARAMS
INIT_LIST_HEAD(&plugin_ptr->dynparam_ports);
#endif
- plugin_ptr->type = PLUGIN_TYPE_UNKNOWN;
-
plugin_ptr->uri = NULL;
+ plugin_ptr->name = NULL;
+ plugin_ptr->id = NULL;
+ plugin_ptr->dlpath = NULL;
+ plugin_ptr->bundle_path = NULL;
plugin_ptr->lv2plugin = NULL;
+ plugin_ptr->gtk2gui = ZYNJACKU_GTK2GUI_HANDLE_INVALID_VALUE;
plugin_ptr->root_group_ui_context = NULL;
}
@@ -708,41 +829,42 @@ zynjacku_plugin_generic_lv2_ui_off(
}
gboolean
-zynjacku_plugin_supports_generic_ui(
- ZynjackuPlugin * plugin_obj_ptr)
-{
-// struct zynjacku_plugin * plugin_ptr;
-
- LOG_DEBUG("zynjacku_plugin_supports_generic_ui() called.");
-
-// plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_obj_ptr);
-
- /* we can generate it always */
- return TRUE;
-}
-
-gboolean
-zynjacku_plugin_supports_custom_ui(
- ZynjackuPlugin * plugin_obj_ptr)
+zynjacku_plugin_ui_on(
+ ZynjackuPlugin * plugin_obj_ptr,
+ const char * ui_uri,
+ const char * ui_type_uri,
+ const char * ui_binary_path,
+ const char * ui_bundle_path)
{
struct zynjacku_plugin * plugin_ptr;
+ const LV2_Feature * const * host_features;
+ unsigned int host_feature_count;
- LOG_DEBUG("zynjacku_plugin_supports_custom_ui() called.");
+ LOG_DEBUG("zynjacku_plugin_ui_on(%s, %s, %s, %s) called.", ui_uri, ui_type_uri, ui_binary_path, ui_bundle_path);
plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_obj_ptr);
- return (plugin_ptr->gtk2gui != ZYNJACKU_GTK2GUI_HANDLE_INVALID_VALUE) ? TRUE : FALSE;
-}
-
-gboolean
-zynjacku_plugin_ui_on(
- ZynjackuPlugin * plugin_obj_ptr)
-{
- struct zynjacku_plugin * plugin_ptr;
-
- LOG_DEBUG("zynjacku_plugin_ui_on() called.");
+ if (ui_uri != NULL &&
+ ui_type_uri != NULL &&
+ ui_binary_path != NULL &&
+ ui_bundle_path != NULL)
+ {
+ plugin_ptr->get_required_features(plugin_ptr->engine_object_ptr, &host_features, &host_feature_count);
- plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_obj_ptr);
+ plugin_ptr->gtk2gui = zynjacku_gtk2gui_create(
+ host_features,
+ host_feature_count,
+ plugin_ptr->lv2plugin,
+ plugin_ptr,
+ plugin_obj_ptr,
+ ui_type_uri,
+ plugin_ptr->uri,
+ ui_uri,
+ ui_binary_path,
+ ui_bundle_path,
+ plugin_ptr->id,
+ &plugin_ptr->parameter_ports);
+ }
if (plugin_ptr->gtk2gui != ZYNJACKU_GTK2GUI_HANDLE_INVALID_VALUE)
{
@@ -750,6 +872,7 @@ zynjacku_plugin_ui_on(
}
#if HAVE_DYNPARAMS
+ LOG_DEBUG("dynparams is %s by plugin.", plugin_ptr->dynparams ? "supported" : "unsupported");
if (plugin_ptr->dynparams)
{
lv2dynparam_host_ui_on(plugin_ptr->dynparams);
@@ -872,8 +995,8 @@ zynjacku_connect_plugin_ports(
switch (port_ptr->type)
{
case PORT_TYPE_LV2_FLOAT:
- zynjacku_lv2_connect_port(plugin_ptr->lv2plugin, port_ptr, &port_ptr->data.lv2float);
- LOG_INFO("Set %s to %f", port_ptr->symbol, port_ptr->data.lv2float);
+ zynjacku_lv2_connect_port(plugin_ptr->lv2plugin, port_ptr, &port_ptr->data.lv2float.value);
+ LOG_INFO("Set %s to %f", port_ptr->symbol, port_ptr->data.lv2float.value);
break;
case PORT_TYPE_LV2_STRING:
zynjacku_lv2_connect_port(plugin_ptr->lv2plugin, port_ptr, &port_ptr->data.lv2string);
@@ -898,7 +1021,7 @@ zynjacku_connect_plugin_ports(
switch (port_ptr->type)
{
case PORT_TYPE_LV2_FLOAT:
- zynjacku_lv2_connect_port(plugin_ptr->lv2plugin, port_ptr, &port_ptr->data.lv2float);
+ zynjacku_lv2_connect_port(plugin_ptr->lv2plugin, port_ptr, &port_ptr->data.lv2float.value);
break;
case PORT_TYPE_LV2_STRING:
/* TODO measure string ports are broken for now */
@@ -917,7 +1040,7 @@ zynjacku_connect_plugin_ports(
switch (port_ptr->type)
{
case PORT_TYPE_LV2_FLOAT:
- send_message(plugin_ptr, port_ptr, &port_ptr->data.lv2float);
+ send_message(plugin_ptr, port_ptr, &port_ptr->data.lv2float.value);
break;
case PORT_TYPE_LV2_STRING:
send_message(plugin_ptr, port_ptr, &port_ptr->data.lv2string);
@@ -934,25 +1057,63 @@ void
zynjacku_free_port(
struct zynjacku_port * port_ptr)
{
- assert(port_ptr->type == PORT_TYPE_LV2_FLOAT || port_ptr->type == PORT_TYPE_LV2_STRING);
-
if (port_ptr->type == PORT_TYPE_LV2_STRING)
{
free(port_ptr->data.lv2string.data);
}
+ if (port_ptr->name != NULL)
+ {
+ free(port_ptr->name);
+ }
+
free(port_ptr->symbol);
- free(port_ptr->name);
free(port_ptr);
}
void
-zynjacku_free_plugin_ports(
- struct zynjacku_plugin * plugin_ptr)
+zynjacku_plugin_destruct(
+ ZynjackuPlugin * plugin_obj_ptr)
{
+ struct zynjacku_plugin * plugin_ptr;
struct list_head * node_ptr;
struct zynjacku_port * port_ptr;
+ plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_obj_ptr);
+
+ LOG_DEBUG("Destructing plugin <%s>", plugin_ptr->uri);
+
+ plugin_ptr->deactivate(G_OBJECT(plugin_obj_ptr));
+
+ if (plugin_ptr->gtk2gui != ZYNJACKU_GTK2GUI_HANDLE_INVALID_VALUE)
+ {
+ zynjacku_gtk2gui_destroy(plugin_ptr->gtk2gui);
+ }
+
+ while (!list_empty(&plugin_ptr->midi_ports))
+ {
+ node_ptr = plugin_ptr->midi_ports.next;
+ port_ptr = list_entry(node_ptr, struct zynjacku_port, plugin_siblings);
+
+ list_del(node_ptr);
+
+ zynjacku_free_port(port_ptr);
+ }
+
+ while (!list_empty(&plugin_ptr->audio_ports))
+ {
+ node_ptr = plugin_ptr->audio_ports.next;
+ port_ptr = list_entry(node_ptr, struct zynjacku_port, plugin_siblings);
+
+ assert(port_ptr->type == PORT_TYPE_AUDIO);
+
+ plugin_ptr->unregister_port(plugin_ptr->engine_object_ptr, port_ptr);
+
+ list_del(node_ptr);
+
+ zynjacku_free_port(port_ptr);
+ }
+
while (!list_empty(&plugin_ptr->parameter_ports))
{
node_ptr = plugin_ptr->parameter_ports.next;
@@ -990,62 +1151,6 @@ zynjacku_free_plugin_ports(
free(port_ptr);
}
#endif
-}
-
-gboolean
-zynjacku_plugin_construct(
- ZynjackuPlugin * plugin_obj_ptr,
- GObject * engine_object_ptr)
-{
- struct zynjacku_plugin * plugin_ptr;
-
- plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_obj_ptr);
-
- if (plugin_ptr->uri == NULL)
- {
- LOG_ERROR("\"uri\" property needs to be set before constructing plugin");
- return false;
- }
-
- if (ZYNJACKU_IS_ENGINE(engine_object_ptr))
- {
- return zynjacku_plugin_construct_synth(
- plugin_ptr,
- plugin_obj_ptr,
- engine_object_ptr);
- }
-
- if (ZYNJACKU_IS_RACK(engine_object_ptr))
- {
- return zynjacku_plugin_construct_effect(
- plugin_ptr,
- plugin_obj_ptr,
- engine_object_ptr);
- }
-
- LOG_ERROR("Cannot construct plugin for unknown engine type");
-
- return false;
-}
-
-void
-zynjacku_plugin_destruct(
- ZynjackuPlugin * plugin_obj_ptr)
-{
- struct zynjacku_plugin * plugin_ptr;
-
- plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_obj_ptr);
-
- LOG_DEBUG("Destructing plugin <%s>", plugin_ptr->uri);
-
- plugin_ptr->deactivate(G_OBJECT(plugin_obj_ptr));
-
- if (plugin_ptr->gtk2gui != ZYNJACKU_GTK2GUI_HANDLE_INVALID_VALUE)
- {
- zynjacku_gtk2gui_destroy(plugin_ptr->gtk2gui);
- }
-
- plugin_ptr->free_ports(G_OBJECT(plugin_obj_ptr));
#if HAVE_DYNPARAMS
if (plugin_ptr->dynparams != NULL)
@@ -1181,8 +1286,12 @@ zynjacku_plugin_set_midi_cc_map_internal(
if (plugin_ptr->set_midi_cc_map == NULL)
{
- LOG_ERROR("Cannot set midi cc map for plugin without engine");
- assert(0);
+ if (midi_cc_map_obj_ptr != NULL)
+ {
+ LOG_ERROR("Cannot set midi cc map for plugin without engine");
+ assert(0);
+ }
+
return false;
}
@@ -1749,6 +1858,341 @@ zynjacku_plugin_set_midi_cc_map(
return zynjacku_plugin_set_midi_cc_map_internal(port_ptr, midi_cc_map_obj_ptr);
}
+void
+zynjacku_plugin_add_supported_feature(
+ ZynjackuPlugin * plugin_obj_ptr,
+ const gchar * feature_uri)
+{
+ struct zynjacku_plugin * plugin_ptr;
+
+ LOG_DEBUG("Plugin supports feature '%s'", feature_uri);
+
+ plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_obj_ptr);
+
+#if HAVE_DYNPARAMS
+ if (strcmp(feature_uri, LV2DYNPARAM_URI) == 0)
+ {
+ plugin_ptr->dynparams_supported = true;
+ }
+#endif
+}
+
+static
+struct zynjacku_port *
+new_lv2parameter_port(
+ uint32_t index,
+ const char * symbol,
+ const char * name,
+ unsigned int type,
+ bool input,
+ bool msgcontext,
+ struct zynjacku_plugin * plugin_ptr)
+{
+ struct zynjacku_port * port_ptr;
+
+ port_ptr = malloc(sizeof(struct zynjacku_port));
+ if (port_ptr == NULL)
+ {
+ LOG_ERROR("malloc() failed to allocate memory for struct zynjacku_port.");
+ goto fail;
+ }
+
+ port_ptr->index = index;
+ port_ptr->type = type;
+ port_ptr->flags = 0;
+ port_ptr->ui_context = NULL;
+ port_ptr->plugin_ptr = plugin_ptr;
+ port_ptr->midi_cc_map_obj_ptr = NULL;
+
+ port_ptr->symbol = strdup(symbol);
+ if (port_ptr->symbol == NULL)
+ {
+ LOG_ERROR("strdup() failed.");
+ goto fail_free_port;
+ }
+
+ if (name != NULL)
+ {
+ port_ptr->name = strdup(name);
+ if (port_ptr->name == NULL)
+ {
+ LOG_ERROR("strdup() failed.");
+ goto fail_free_symbol;
+ }
+ }
+ else
+ {
+ port_ptr->name = NULL;
+ }
+
+ if (!input)
+ {
+ port_ptr->flags |= PORT_FLAGS_OUTPUT;
+ }
+
+ if (msgcontext)
+ {
+ port_ptr->flags |= PORT_FLAGS_MSGCONTEXT;
+ }
+
+ return port_ptr;
+
+fail_free_symbol:
+ free(port_ptr->symbol);
+
+fail_free_port:
+ free(port_ptr);
+
+fail:
+ return NULL;
+}
+
+gboolean
+zynjacku_plugin_create_oldmidi_input_port(
+ ZynjackuPlugin * plugin_obj_ptr,
+ guint port_index,
+ const gchar * symbol)
+{
+ struct zynjacku_plugin * plugin_ptr;
+ struct zynjacku_port * port_ptr;
+
+ LOG_DEBUG("zynjacku_plugin_create_oldmidi_input_port(%u, %s).", (unsigned int)port_index, symbol);
+
+ plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_obj_ptr);
+
+ port_ptr = new_lv2parameter_port(
+ port_index,
+ symbol,
+ NULL,
+ PORT_TYPE_MIDI,
+ true, /* input port */
+ false,
+ plugin_ptr);
+ if (port_ptr == NULL)
+ {
+ return false;
+ }
+
+ port_ptr->data.audio = NULL;
+
+ list_add_tail(&port_ptr->plugin_siblings, &plugin_ptr->midi_ports);
+
+ return true;
+}
+
+gboolean
+zynjacku_plugin_create_eventmidi_input_port(
+ ZynjackuPlugin * plugin_obj_ptr,
+ guint port_index,
+ const gchar * symbol)
+{
+ struct zynjacku_plugin * plugin_ptr;
+ struct zynjacku_port * port_ptr;
+
+ LOG_DEBUG("zynjacku_plugin_create_eventmidi_input_port(%u, %s).", (unsigned int)port_index, symbol);
+
+ plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_obj_ptr);
+
+ port_ptr = new_lv2parameter_port(
+ port_index,
+ symbol,
+ NULL,
+ PORT_TYPE_EVENT_MIDI,
+ true, /* input port */
+ false,
+ plugin_ptr);
+ if (port_ptr == NULL)
+ {
+ return false;
+ }
+
+ list_add_tail(&port_ptr->plugin_siblings, &plugin_ptr->midi_ports);
+
+ return true;
+}
+
+gboolean
+zynjacku_plugin_create_audio_port(
+ ZynjackuPlugin * plugin_obj_ptr,
+ guint port_index,
+ const gchar * symbol,
+ gboolean input)
+{
+ struct zynjacku_plugin * plugin_ptr;
+ struct zynjacku_port * port_ptr;
+
+ LOG_DEBUG("zynjacku_plugin_create_audio_port(%u, %s, %s).", (unsigned int)port_index, symbol, input ? "input" : "output");
+
+ plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_obj_ptr);
+
+ port_ptr = new_lv2parameter_port(
+ port_index,
+ symbol,
+ NULL,
+ PORT_TYPE_AUDIO,
+ input,
+ false,
+ plugin_ptr);
+ if (port_ptr == NULL)
+ {
+ return false;
+ }
+
+ port_ptr->data.audio = NULL;
+
+ list_add_tail(&port_ptr->plugin_siblings, &plugin_ptr->audio_ports);
+
+ return true;
+}
+
+gboolean
+zynjacku_plugin_create_float_parameter_port(
+ ZynjackuPlugin * plugin_obj_ptr,
+ guint port_index,
+ const gchar * symbol,
+ const gchar * name,
+ gboolean msgcontext,
+ gboolean default_provided,
+ gfloat default_value,
+ gboolean min_provided,
+ gfloat min_value,
+ gboolean max_provided,
+ gfloat max_value)
+{
+ struct zynjacku_plugin * plugin_ptr;
+ struct zynjacku_port * port_ptr;
+
+ LOG_DEBUG("zynjacku_plugin_create_float_parameter_port(%u, %s, %s).", (unsigned int)port_index, symbol, name);
+
+ plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_obj_ptr);
+
+ port_ptr = new_lv2parameter_port(
+ port_index,
+ symbol,
+ name,
+ PORT_TYPE_LV2_FLOAT,
+ true, /* input port */
+ msgcontext,
+ plugin_ptr);
+ if (port_ptr == NULL)
+ {
+ return false;
+ }
+
+ if (default_provided)
+ {
+ port_ptr->data.lv2float.value = default_value;
+ }
+ else if (min_provided)
+ {
+ port_ptr->data.lv2float.value = min_value;
+ }
+ else if (max_provided)
+ {
+ port_ptr->data.lv2float.value = min_value;
+ }
+ else
+ {
+ port_ptr->data.lv2float.value = 0.0;
+ }
+
+ port_ptr->data.lv2float.min_provided = min_provided;
+ port_ptr->data.lv2float.min = min_value;
+ port_ptr->data.lv2float.max_provided = max_provided;
+ port_ptr->data.lv2float.max = max_value;
+
+ list_add_tail(&port_ptr->plugin_siblings, &plugin_ptr->parameter_ports);
+
+ return true;
+}
+
+gboolean
+zynjacku_plugin_create_float_measure_port(
+ ZynjackuPlugin * plugin_obj_ptr,
+ guint port_index,
+ const gchar * symbol,
+ gboolean msgcontext)
+{
+ struct zynjacku_plugin * plugin_ptr;
+ struct zynjacku_port * port_ptr;
+
+ plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_obj_ptr);
+
+ port_ptr = new_lv2parameter_port(
+ port_index,
+ symbol,
+ NULL,
+ PORT_TYPE_LV2_FLOAT,
+ false, /* output port */
+ msgcontext,
+ plugin_ptr);
+ if (port_ptr == NULL)
+ {
+ return false;
+ }
+
+ list_add_tail(&port_ptr->plugin_siblings, &plugin_ptr->measure_ports);
+
+ return true;
+}
+
+gboolean
+zynjacku_plugin_create_string_parameter_port(
+ ZynjackuPlugin * plugin_obj_ptr,
+ guint port_index,
+ const gchar * symbol,
+ const gchar * name,
+ gboolean msgcontext,
+ const gchar * default_value,
+ gsize maxlen)
+{
+ struct zynjacku_plugin * plugin_ptr;
+ struct zynjacku_port * port_ptr;
+ size_t defval_len;
+
+ LOG_DEBUG("zynjacku_plugin_create_string_parameter_port(%u, %s, %s, %s, %s).", (unsigned int)port_index, symbol, name, msgcontext ? "true" : "false", default_value);
+
+ plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_obj_ptr);
+
+ port_ptr = new_lv2parameter_port(
+ port_index,
+ symbol,
+ name,
+ PORT_TYPE_LV2_STRING,
+ true, /* input port */
+ msgcontext,
+ plugin_ptr);
+ if (port_ptr == NULL)
+ {
+ return false;
+ }
+
+ port_ptr->data.lv2string.storage = maxlen;
+
+ if (default_value == NULL)
+ {
+ default_value = "";
+ }
+
+ defval_len = strlen(default_value) + 1;
+
+ if (defval_len > port_ptr->data.lv2string.storage)
+ {
+ port_ptr->data.lv2string.storage = defval_len;
+ }
+
+ port_ptr->data.lv2string.data = malloc(port_ptr->data.lv2string.storage);
+ memcpy(port_ptr->data.lv2string.data, default_value, defval_len);
+
+ port_ptr->data.lv2string.len = defval_len - 1;
+ port_ptr->data.lv2string.flags = LV2_STRING_DATA_CHANGED_FLAG;
+ port_ptr->data.lv2string.pad = 0;
+
+ list_add_tail(&port_ptr->plugin_siblings, &plugin_ptr->parameter_ports);
+
+ return true;
+}
+
gboolean
zynjacku_plugin_midi_cc_map_cc_no_assign(
GObject * plugin_obj_ptr,
diff --git a/plugin.h b/plugin.h
index ec276b3..91c943c 100644
--- a/plugin.h
+++ b/plugin.h
@@ -50,23 +50,10 @@ struct _ZynjackuPluginClass {
/* used by ZYNJACKU_TYPE_PLUGIN */
GType zynjacku_plugin_get_type();
-gboolean
-zynjacku_plugin_construct(
- ZynjackuPlugin * plugin_obj_ptr,
- GObject * engine_obj_ptr);
-
void
zynjacku_plugin_destruct(
ZynjackuPlugin * plugin_obj_ptr);
-gboolean
-zynjacku_plugin_supports_generic_ui(
- ZynjackuPlugin * plugin_obj_ptr);
-
-gboolean
-zynjacku_plugin_supports_custom_ui(
- ZynjackuPlugin * plugin_obj_ptr);
-
const char *
zynjacku_plugin_get_instance_name(
ZynjackuPlugin * obj_ptr);
@@ -81,7 +68,11 @@ zynjacku_plugin_get_uri(
gboolean
zynjacku_plugin_ui_on(
- ZynjackuPlugin * plugin_obj_ptr);
+ ZynjackuPlugin * plugin_obj_ptr,
+ const char * ui_uri,
+ const char * ui_type_uri,
+ const char * ui_binary_path,
+ const char * ui_bundle_path);
void
zynjacku_plugin_ui_off(
@@ -133,6 +124,61 @@ zynjacku_plugin_set_midi_cc_map(
gchar * string_context,
GObject * midi_cc_map_obj_ptr);
+void
+zynjacku_plugin_add_supported_feature(
+ ZynjackuPlugin * plugin_obj_ptr,
+ const gchar * feature_uri);
+
+gboolean
+zynjacku_plugin_create_oldmidi_input_port(
+ ZynjackuPlugin * plugin_obj_ptr,
+ guint port_index,
+ const gchar * symbol);
+
+gboolean
+zynjacku_plugin_create_eventmidi_input_port(
+ ZynjackuPlugin * plugin_obj_ptr,
+ guint port_index,
+ const gchar * symbol);
+
+gboolean
+zynjacku_plugin_create_audio_port(
+ ZynjackuPlugin * plugin_obj_ptr,
+ guint port_index,
+ const gchar * symbol,
+ gboolean input);
+
+gboolean
+zynjacku_plugin_create_float_parameter_port(
+ ZynjackuPlugin * plugin_obj_ptr,
+ guint port_index,
+ const gchar * symbol,
+ const gchar * name,
+ gboolean msgcontext,
+ gboolean default_provided,
+ gfloat default_value,
+ gboolean min_provided,
+ gfloat min_value,
+ gboolean max_provided,
+ gfloat max_value);
+
+gboolean
+zynjacku_plugin_create_float_measure_port(
+ ZynjackuPlugin * plugin_obj_ptr,
+ guint port_index,
+ const gchar * symbol,
+ gboolean msgcontext);
+
+gboolean
+zynjacku_plugin_create_string_parameter_port(
+ ZynjackuPlugin * plugin_obj_ptr,
+ guint port_index,
+ const gchar * symbol,
+ const gchar * name,
+ gboolean msgcontext,
+ const gchar * default_value,
+ gsize maxlen);
+
G_END_DECLS
#endif /* #ifndef PLUGIN_H__0C38A6AD_527B_4795_8711_3606AC3A16BD__INCLUDED */
diff --git a/plugin_internal.h b/plugin_internal.h
index e452cb6..33d3e79 100644
--- a/plugin_internal.h
+++ b/plugin_internal.h
@@ -25,10 +25,6 @@
#ifdef LV2_H_INCLUDED
-#define PLUGIN_TYPE_UNKNOWN 0
-#define PLUGIN_TYPE_SYNTH 1
-#define PLUGIN_TYPE_EFFECT 2
-
struct zynjacku_rt_plugin_command
{
struct zynjacku_port * port; /* port to set data for */
@@ -42,6 +38,8 @@ struct zynjacku_plugin
GObject * root_group_ui_context;
GObject * engine_object_ptr;
gchar * uri;
+ gchar * dlpath;
+ gchar * bundle_path;
struct list_head siblings_all;
struct list_head siblings_active;
@@ -49,6 +47,8 @@ struct zynjacku_plugin
#if HAVE_DYNPARAMS
bool dynparams_supported;
#endif
+ struct list_head midi_ports;
+ struct list_head audio_ports;
struct list_head parameter_ports;
struct list_head measure_ports;
#if HAVE_DYNPARAMS
@@ -61,22 +61,20 @@ struct zynjacku_plugin
bool recycle;
- unsigned int type;
-
union
{
struct
{
- struct zynjacku_port midi_in_port;
- struct zynjacku_port audio_out_left_port;
- struct zynjacku_port audio_out_right_port;
+ struct zynjacku_port * midi_in_port_ptr;
+ struct zynjacku_port * audio_out_left_port_ptr;
+ struct zynjacku_port * audio_out_right_port_ptr;
} synth;
struct
{
- struct zynjacku_port audio_in_left_port;
- struct zynjacku_port audio_in_right_port;
- struct zynjacku_port audio_out_left_port;
- struct zynjacku_port audio_out_right_port;
+ struct zynjacku_port * audio_in_left_port_ptr;
+ struct zynjacku_port * audio_in_right_port_ptr;
+ struct zynjacku_port * audio_out_left_port_ptr;
+ struct zynjacku_port * audio_out_right_port_ptr;
} effect;
} subtype;
@@ -84,7 +82,8 @@ struct zynjacku_plugin
struct zynjacku_rt_plugin_command * volatile command_result; /* command that has been executed */
void (* deactivate)(GObject * synth_obj_ptr);
- void (* free_ports)(GObject * synth_obj_ptr);
+ void (* get_required_features)(GObject * engine_obj_ptr, const LV2_Feature * const ** host_features, unsigned int * host_feature_count);
+ void (* unregister_port)(GObject * engine_obj_ptr, struct zynjacku_port * port_ptr);
bool (* set_midi_cc_map)(GObject * engine_obj_ptr, struct zynjacku_port * port_ptr, GObject * midi_cc_map_obj_ptr);
bool (* midi_cc_map_cc_no_assign)(GObject * engine_obj_ptr, GObject * midi_cc_map_obj_ptr, guint cc_no);
};
@@ -101,10 +100,6 @@ zynjacku_connect_plugin_ports(
#endif
);
-void
-zynjacku_free_plugin_ports(
- struct zynjacku_plugin * plugin_ptr);
-
void *
zynjacku_plugin_prerun_rt(
struct zynjacku_plugin * plugin_ptr);
diff --git a/plugin_repo.c b/plugin_repo.c
deleted file mode 100644
index bb425b7..0000000
--- a/plugin_repo.c
+++ /dev/null
@@ -1,1265 +0,0 @@
-/* -*- Mode: C ; c-basic-offset: 2 -*- */
-/*****************************************************************************
- *
- * This file is part of zynjacku
- *
- * Copyright (C) 2006,2007,2008,2009 Nedko Arnaudov <nedko at arnaudov.name>
- *
- * 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; version 2 of the License
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *****************************************************************************/
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <slv2/slv2.h>
-#include <glib-object.h>
-#if HAVE_DYNPARAMS
-#include <lv2dynparam/lv2dynparam.h>
-#include <lv2dynparam/lv2_rtmempool.h>
-#include <lv2dynparam/host.h>
-#endif
-#include <jack/jack.h>
-
-#include "lv2-miditype.h"
-#include "lv2_event.h"
-#include "lv2_string_port.h"
-#include "lv2_uri_map.h"
-
-#include "list.h"
-#include "lv2.h"
-#include "gtk2gui.h"
-#include "zynjacku.h"
-#include "plugin.h"
-#include "plugin_internal.h"
-#include "plugin_repo.h"
-//#define LOG_LEVEL LOG_LEVEL_DEBUG
-#include "log.h"
-
-#define LV2_RDF_LICENSE_URI "http://usefulinc.com/ns/doap#license"
-#define LV2_MIDI_PORT_URI "http://ll-plugins.nongnu.org/lv2/ext/MidiPort"
-#define LV2_EVENT_PORT_URI LV2_EVENT_URI "#EventPort"
-#define LV2_CONTEXT_URI "http://lv2plug.in/ns/dev/contexts"
-#define LV2_PORT_CONTEXT_URI LV2_CONTEXT_URI "#context"
-#define LV2_MESSAGE_CONTEXT_URI LV2_CONTEXT_URI "#MessageContext"
-#define LV2_STRING_PORT_ROOT_URI "http://lv2plug.in/ns/dev/string-port#"
-#define LV2_STRING_PORT_TYPE_URI LV2_STRING_PORT_ROOT_URI "StringPort"
-#define LV2_STRING_PORT_DEFAULT_URI LV2_STRING_PORT_ROOT_URI "default"
-
-struct zynjacku_plugin_info
-{
- struct list_head siblings;
- SLV2Plugin slv2info;
- char * name;
- char * license;
- char * author;
- char * uri;
-};
-
-struct zynjacku_iterate_context
-{
- float progress;
- float progress_step;
- const LV2_Feature * const * supported_features;
- void * context;
- zynjacku_plugin_repo_check_plugin check_plugin;
- zynjacku_plugin_repo_tick tick;
- zynjacku_plugin_repo_tack tack;
-};
-
-/* I would be useful if slv2_world_get_plugins_by_filter() had callback user context... */
-/* this should really be parameter of slv2 filter plugins callback */
-struct zynjacku_iterate_context g_iterate_context;
-
-static struct list_head g_available_plugins; /* "struct zynjacku_plugin_info's linked by siblings */
-static SLV2World g_world;
-static bool g_loaded;
-static bool g_fullscanned;
-static SLV2Value g_slv2uri_port_input;
-static SLV2Value g_slv2uri_port_output;
-static SLV2Value g_slv2uri_port_control;
-static SLV2Value g_slv2uri_port_audio;
-static SLV2Value g_slv2uri_port_midi;
-static SLV2Value g_slv2uri_port_event;
-static SLV2Value g_slv2uri_port_context;
-static SLV2Value g_slv2uri_message_context;
-static SLV2Value g_slv2uri_license;
-static SLV2Value g_slv2uri_event_midi;
-static SLV2Value g_slv2uri_port_string;
-static SLV2Value g_slv2uri_string_port_default;
-
-/* as slv2_value_as_string() but returns NULL if value is NULL or value type is not string
- such conditions are assumed to be error, thus this function should be
- used only when caller expects value to be string */
-const char *
-slv2_value_as_string_smart(SLV2Value value)
-{
- if (value == NULL)
- {
- LOG_ERROR("SLV2Value is NULL");
- return NULL;
- }
-
- if (!slv2_value_is_string(value))
- {
- LOG_ERROR("SLV2Value is not string");
- return NULL;
- }
-
- return slv2_value_as_string(value);
-}
-
-const char *
-slv2_value_as_uri_smart(SLV2Value value)
-{
- if (value == NULL)
- {
- LOG_ERROR("SLV2Value is NULL");
- return NULL;
- }
-
- if (!slv2_value_is_uri(value))
- {
- LOG_ERROR("SLV2Value is not string");
- return NULL;
- }
-
- return slv2_value_as_uri(value);
-}
-
-const char *
-slv2_plugin_get_uri_smart(SLV2Plugin plugin)
-{
- return slv2_value_as_uri(slv2_plugin_get_uri(plugin));
-}
-
-bool
-slv2_port_is_control(
- SLV2Plugin plugin,
- SLV2Port port)
-{
- return slv2_port_is_a(plugin, port, g_slv2uri_port_control);
-}
-
-bool
-slv2_port_is_string(
- SLV2Plugin plugin,
- SLV2Port port)
-{
- return slv2_port_is_a(plugin, port, g_slv2uri_port_string);
-}
-
-bool
-slv2_port_is_audio(
- SLV2Plugin plugin,
- SLV2Port port)
-{
- return slv2_port_is_a(plugin, port, g_slv2uri_port_audio);
-}
-
-bool
-slv2_port_is_midi(
- SLV2Plugin plugin,
- SLV2Port port)
-{
- return slv2_port_is_a(plugin, port, g_slv2uri_port_midi);
-}
-
-bool
-slv2_port_is_event(
- SLV2Plugin plugin,
- SLV2Port port)
-{
- return slv2_port_is_a(plugin, port, g_slv2uri_port_event);
-}
-
-bool
-slv2_port_is_input(
- SLV2Plugin plugin,
- SLV2Port port)
-{
- return slv2_port_is_a(plugin, port, g_slv2uri_port_input);
-}
-
-bool
-slv2_port_is_output(
- SLV2Plugin plugin,
- SLV2Port port)
-{
- return slv2_port_is_a(plugin, port, g_slv2uri_port_output);
-}
-
-bool
-slv2_port_is_midi_event(
- SLV2Plugin plugin,
- SLV2Port port)
-{
- return slv2_port_supports_event(plugin, port, g_slv2uri_event_midi);
-}
-
-struct uri_registration
-{
- const char *name;
- SLV2Value *value;
-};
-
-static struct uri_registration uri_regs[] = {
- {SLV2_PORT_CLASS_INPUT, &g_slv2uri_port_input},
- {SLV2_PORT_CLASS_OUTPUT, &g_slv2uri_port_output},
- {SLV2_PORT_CLASS_CONTROL, &g_slv2uri_port_control},
- {SLV2_PORT_CLASS_AUDIO, &g_slv2uri_port_audio},
- {LV2_MIDI_PORT_URI, &g_slv2uri_port_midi},
- {LV2_RDF_LICENSE_URI, &g_slv2uri_license},
- {LV2_PORT_CONTEXT_URI, &g_slv2uri_port_context},
- {LV2_MESSAGE_CONTEXT_URI, &g_slv2uri_message_context},
- {LV2_EVENT_PORT_URI, &g_slv2uri_port_event},
- {LV2_EVENT_URI_TYPE_MIDI, &g_slv2uri_event_midi},
- {LV2_STRING_PORT_TYPE_URI, &g_slv2uri_port_string},
- {LV2_STRING_PORT_DEFAULT_URI, &g_slv2uri_string_port_default},
-};
-
-bool
-zynjacku_plugin_repo_init()
-{
- int i;
- g_world = slv2_world_new();
- if (g_world == NULL)
- {
- LOG_ERROR("slv2_world_new() failed.");
- goto fail;
- }
-
- INIT_LIST_HEAD(&g_available_plugins);
- g_fullscanned = false;
- g_loaded = false;
-
- for (i = 0; i < sizeof(uri_regs) / sizeof(struct uri_registration); i++)
- {
- *uri_regs[i].value = slv2_value_new_uri(g_world, uri_regs[i].name);
- if (!*uri_regs[i].value)
- {
- LOG_ERROR("slv2_value_new_uri() failed.");
- for (i--; i >= 0; i--)
- slv2_value_free(*uri_regs[i].value);
- goto fail_free_world;
- }
- }
-
- return true;
-
-fail_free_world:
- slv2_world_free(g_world);
-
-fail:
- return false;
-}
-
-void
-zynjacku_plugin_repo_uninit()
-{
- struct list_head * node_ptr;
- struct zynjacku_plugin_info * plugin_info_ptr;
-
- while(!list_empty(&g_available_plugins))
- {
- node_ptr = g_available_plugins.next;
-
- list_del(node_ptr);
-
- plugin_info_ptr = list_entry(node_ptr, struct zynjacku_plugin_info, siblings);
-
- //LOG_DEBUG("Removing %s", plugin_info_ptr->name);
- free(plugin_info_ptr->author);
- free(plugin_info_ptr->license);
- free(plugin_info_ptr->name);
- free(plugin_info_ptr);
- }
-
- slv2_value_free(g_slv2uri_event_midi);
- slv2_value_free(g_slv2uri_port_event);
- slv2_value_free(g_slv2uri_license);
- slv2_value_free(g_slv2uri_port_midi);
- slv2_value_free(g_slv2uri_port_audio);
- slv2_value_free(g_slv2uri_port_control);
- slv2_value_free(g_slv2uri_port_output);
- slv2_value_free(g_slv2uri_port_input);
- slv2_world_free(g_world);
-}
-
-char *
-zynjacku_plugin_repo_get_plugin_license(
- SLV2Plugin plugin)
-{
- SLV2Values slv2_values;
- SLV2Value slv2_value;
- char * license;
- const char * license_uri;
-
- slv2_values = slv2_plugin_get_value(
- plugin,
- g_slv2uri_license);
-
- if (slv2_values_size(slv2_values) == 0)
- {
- LOG_WARNING("Plugin license query returned empty set");
- return strdup("none"); /* acutally, slv2 should reject those early */
- }
-
- slv2_value = slv2_values_get_at(slv2_values, 0);
- if (!slv2_value_is_uri(slv2_value))
- {
- LOG_WARNING("Plugin license is not uri");
- return strdup("none"); /* acutally, slv2 should reject those early */
- }
-
- license_uri = slv2_value_as_string(slv2_value);
-
- if (strcmp(license_uri, "http://usefulinc.com/doap/licenses/gpl") == 0)
- {
- license = strdup("GNU General Public License");
- }
- else if (strcmp(license_uri, "http://usefulinc.com/doap/licenses/lgpl") == 0)
- {
- license = strdup("GNU Lesser General Public License");
- }
- else
- {
- license = strdup(license_uri);
- }
-
- slv2_values_free(slv2_values);
-
- return license;
-}
-
-char *
-zynjacku_plugin_repo_get_plugin_author(
- SLV2Plugin plugin)
-{
- SLV2Value slv2_value;
- char * author;
- const char * author_const;
-
- slv2_value = slv2_plugin_get_author_name(plugin);
- if (slv2_value != NULL)
- {
- author_const = slv2_value_as_string_smart(slv2_value);
- }
- else
- {
- author_const = NULL;
- }
-
- if (author_const != NULL)
- {
- author = strdup(author_const);
- }
- else
- {
- author = strdup("unknown");
- }
-
- return author;
-}
-
-/* check whether plugin is a synth, if it is, save plugin info */
-static
-bool
-zynjacku_plugin_repo_check_and_maybe_init_plugin(
- SLV2Plugin plugin)
-{
- gboolean ret;
- uint32_t audio_in_ports_count;
- uint32_t audio_out_ports_count;
- uint32_t midi_in_ports_count;
- uint32_t control_ports_count;
- uint32_t string_ports_count;
- uint32_t event_ports_count;
- uint32_t midi_event_in_ports_count;
- uint32_t ports_count;
- uint32_t port_index;
- const char *plugin_uri;
- const char *feature_uri;
- const char *name;
- SLV2Value slv2name;
- SLV2Values slv2features;
- SLV2Value slv2feature;
- unsigned int features_count;
- unsigned int feature_index;
- struct zynjacku_plugin_info * plugin_info_ptr;
- SLV2Port port;
- const LV2_Feature * const * feature_ptr_ptr;
-
- plugin_uri = slv2_plugin_get_uri_smart(plugin);
-
- if (g_iterate_context.tick != NULL)
- {
- g_iterate_context.tick(g_iterate_context.context, g_iterate_context.progress, plugin_uri);
- }
-
- ret = FALSE;
-
- slv2name = slv2_plugin_get_name(plugin);
- if (slv2name == NULL)
- {
- LOG_ERROR("slv2_plugin_get_name() returned NULL.");
- goto exit;
- }
-
- name = slv2_value_as_string_smart(slv2name);
- if (name == NULL)
- {
- LOG_ERROR("slv2_value_as_string_smart() failed for plugin name value.");
- goto free_name;
- }
-
- /* check required features */
-
- slv2features = slv2_plugin_get_required_features(plugin);
- features_count = slv2_values_size(slv2features);
- //LOG_DEBUG("Plugin \"%s\" has %u required features", name, features_count);
-
- for (feature_index = 0 ; feature_index < features_count ; feature_index++)
- {
- slv2feature = slv2_values_get_at(slv2features, feature_index);
-
- feature_uri = slv2_value_as_uri_smart(slv2feature);
- if (feature_uri == NULL)
- {
- LOG_ERROR("slv2_value_as_uri_smart() failed for plugin name value.");
- goto free_features;
- }
-
- LOG_DEBUG("%s", feature_uri);
-
- feature_ptr_ptr = g_iterate_context.supported_features;
- while (*feature_ptr_ptr != NULL)
- {
- if (strcmp((*feature_ptr_ptr)->URI, feature_uri) == 0)
- {
- break;
- }
-
- feature_ptr_ptr++;
- }
-
- if (*feature_ptr_ptr == NULL)
- {
- LOG_DEBUG("Plugin \"%s\" requires unsupported feature \"%s\"", name, feature_uri);
- goto free_features;
- }
- }
-
- /* check port configuration */
-
- ports_count = slv2_plugin_get_num_ports(plugin);
- audio_in_ports_count = slv2_plugin_get_num_ports_of_class(plugin, g_slv2uri_port_audio, g_slv2uri_port_input, NULL);
- audio_out_ports_count = slv2_plugin_get_num_ports_of_class(plugin, g_slv2uri_port_audio, g_slv2uri_port_output, NULL);
- midi_in_ports_count = slv2_plugin_get_num_ports_of_class(plugin, g_slv2uri_port_midi, g_slv2uri_port_input, NULL);
- control_ports_count = slv2_plugin_get_num_ports_of_class(plugin, g_slv2uri_port_control, NULL);
- string_ports_count = slv2_plugin_get_num_ports_of_class(plugin, g_slv2uri_port_string, NULL);
- event_ports_count = slv2_plugin_get_num_ports_of_class(plugin, g_slv2uri_port_event, NULL);
-
- midi_event_in_ports_count = 0;
-
- if (event_ports_count != 0)
- {
- for (port_index = 0 ; port_index < ports_count ; port_index++)
- {
- port = slv2_plugin_get_port_by_index(plugin, port_index);
- if (slv2_port_is_midi_event(plugin, port) && slv2_port_is_input(plugin, port))
- {
- midi_event_in_ports_count++;
- }
- }
- }
-
- if (!g_iterate_context.check_plugin(
- g_iterate_context.context,
- plugin_uri,
- name,
- audio_in_ports_count,
- audio_out_ports_count,
- midi_in_ports_count,
- control_ports_count,
- string_ports_count,
- event_ports_count,
- midi_event_in_ports_count,
- ports_count))
- {
- goto free_features;
- }
-
- plugin_info_ptr = malloc(sizeof(struct zynjacku_plugin_info));
- if (plugin_info_ptr == NULL)
- {
- LOG_ERROR("Cannot allocate memory for zynjacku_plugin_info structure");
- goto free_features;
- }
-
- plugin_info_ptr->name = strdup(name);
- if (plugin_info_ptr->name == NULL)
- {
- goto free_info;
- }
-
- plugin_info_ptr->uri = strdup(plugin_uri);
- if (plugin_info_ptr->uri == NULL)
- {
- goto free_info_name;
- }
-
- plugin_info_ptr->license = zynjacku_plugin_repo_get_plugin_license(plugin);
- if (plugin_info_ptr->license == NULL)
- {
- goto free_info_uri;
- }
-
- plugin_info_ptr->author = zynjacku_plugin_repo_get_plugin_author(plugin);
- if (plugin_info_ptr->author == NULL)
- {
- goto free_info_license;
- }
-
- plugin_info_ptr->slv2info = plugin;
-
- list_add_tail(&plugin_info_ptr->siblings, &g_available_plugins);
-
- if (g_iterate_context.tack != NULL)
- {
- g_iterate_context.tack(g_iterate_context.context, plugin_uri);
- }
-
- ret = TRUE;
-
- goto free_features;
-
-free_info_license:
- free(plugin_info_ptr->license);
-
-free_info_uri:
- free(plugin_info_ptr->uri);
-
-free_info_name:
- free(plugin_info_ptr->name);
-
-free_info:
- free(plugin_info_ptr);
-
-free_features:
- slv2_values_free(slv2features);
-
-free_name:
- slv2_value_free(slv2name);
-
-exit:
- g_iterate_context.progress += g_iterate_context.progress_step;
- return ret;
-}
-
-void
-zynjacku_plugin_repo_iterate(
- bool force_scan,
- const LV2_Feature * const * supported_features,
- void * context,
- zynjacku_plugin_repo_check_plugin check_plugin,
- zynjacku_plugin_repo_tick tick,
- zynjacku_plugin_repo_tack tack)
-{
- struct list_head * node_ptr;
- SLV2Plugins slv2plugins;
- struct zynjacku_plugin_info * plugin_info_ptr;
-
- LOG_DEBUG("zynjacku_plugin_repo_iterate() called.");
-
- if (!force_scan && g_fullscanned)
- {
- if (tack != NULL)
- {
- LOG_DEBUG("Iterate existing plugins!");
-
- list_for_each(node_ptr, &g_available_plugins)
- {
- plugin_info_ptr = list_entry(node_ptr, struct zynjacku_plugin_info, siblings);
- tack(context, plugin_info_ptr->uri);
- }
- }
-
- if (tick != NULL)
- {
- tick(context, 1.0, "");
- }
-
- return;
- }
-
- /* scanned in past, clear world to scan again */
- zynjacku_plugin_repo_uninit();
- zynjacku_plugin_repo_init();
-
- LOG_DEBUG("Scanning plugins...");
-
- if (tick != NULL)
- {
- tick(context, 0.0, "Loading plugins (world) ...");
- }
-
- assert(!g_loaded);
-
- slv2_world_load_all(g_world);
- g_loaded = true;
-
- /* get plugins count */
- slv2plugins = slv2_world_get_all_plugins(g_world);
- g_iterate_context.progress_step = 1.0 / slv2_plugins_size(slv2plugins);
- slv2_plugins_free(g_world, slv2plugins);
-
- g_iterate_context.progress = 0.0;
- g_iterate_context.supported_features = supported_features;
- g_iterate_context.context = context;
- g_iterate_context.check_plugin = check_plugin;
- g_iterate_context.tick = tick;
- g_iterate_context.tack = tack;
-
- slv2plugins = slv2_world_get_plugins_by_filter(g_world, zynjacku_plugin_repo_check_and_maybe_init_plugin);
- slv2_plugins_free(g_world, slv2plugins);
-
- if (tick != NULL)
- {
- tick(context, 1.0, "");
- }
-
- g_fullscanned = true;
-}
-
-static
-struct zynjacku_plugin_info *
-zynjacku_plugin_repo_lookup_by_uri(
- const char * uri)
-{
- struct list_head * node_ptr;
- struct zynjacku_plugin_info * plugin_info_ptr;
-
- list_for_each(node_ptr, &g_available_plugins)
- {
- plugin_info_ptr = list_entry(node_ptr, struct zynjacku_plugin_info, siblings);
- if (strcmp(plugin_info_ptr->uri, uri) == 0)
- {
- return plugin_info_ptr;
- }
- }
-
- LOG_ERROR("Unknown plugin '%s'", uri);
- return NULL;
-}
-
-const char *
-zynjacku_plugin_repo_get_name(
- const char *uri)
-{
- struct zynjacku_plugin_info * plugin_info_ptr;
-
- plugin_info_ptr = zynjacku_plugin_repo_lookup_by_uri(uri);
- if (plugin_info_ptr == NULL)
- {
- return NULL;
- }
-
- return plugin_info_ptr->name;
-}
-
-const char *
-zynjacku_plugin_repo_get_license(
- const char *uri)
-{
- struct zynjacku_plugin_info * plugin_info_ptr;
-
- plugin_info_ptr = zynjacku_plugin_repo_lookup_by_uri(uri);
- if (plugin_info_ptr == NULL)
- {
- return NULL;
- }
-
- return plugin_info_ptr->license;
-}
-
-const char *
-zynjacku_plugin_repo_get_author(
- const char * uri)
-{
- struct zynjacku_plugin_info * plugin_info_ptr;
-
- plugin_info_ptr = zynjacku_plugin_repo_lookup_by_uri(uri);
- if (plugin_info_ptr == NULL)
- {
- return NULL;
- }
-
- return plugin_info_ptr->author;
-}
-
-const char *
-zynjacku_plugin_repo_get_dlpath(
- const char *uri)
-{
- struct zynjacku_plugin_info * info_ptr;
-
- info_ptr = zynjacku_plugin_repo_lookup_by_uri(uri);
- if (info_ptr == NULL)
- {
- return NULL;
- }
-
- return slv2_uri_to_path(slv2_value_as_uri(slv2_plugin_get_library_uri(info_ptr->slv2info)));
-}
-
-const char *
-zynjacku_plugin_repo_get_bundle_path(
- const char *uri)
-{
- struct zynjacku_plugin_info * info_ptr;
-
- info_ptr = zynjacku_plugin_repo_lookup_by_uri(uri);
- if (info_ptr == NULL)
- {
- return NULL;
- }
-
- return slv2_uri_to_path(slv2_value_as_uri(slv2_plugin_get_bundle_uri(info_ptr->slv2info)));
-}
-
-static
-struct zynjacku_port *
-new_lv2parameter_port(
- struct zynjacku_plugin_info * info_ptr,
- SLV2Port port,
- uint32_t index,
- const char * symbol_str,
- struct zynjacku_plugin * plugin_ptr)
-{
- struct zynjacku_port * port_ptr;
- SLV2Value name;
- const char * name_str;
- SLV2Values contexts;
- int i;
-
- port_ptr = malloc(sizeof(struct zynjacku_port));
- if (port_ptr == NULL)
- {
- LOG_ERROR("malloc() failed to allocate memory for struct zynjacku_port.");
- goto fail;
- }
-
- port_ptr->index = index;
- port_ptr->flags = 0;
- port_ptr->ui_context = NULL;
- port_ptr->plugin_ptr = plugin_ptr;
- port_ptr->midi_cc_map_obj_ptr = NULL;
-
- port_ptr->symbol = strdup(symbol_str);
- if (port_ptr->symbol == NULL)
- {
- LOG_ERROR("strdup() failed.");
- goto fail_free_port;
- }
-
- /* port name */
- name = slv2_port_get_name(info_ptr->slv2info, port);
- if (name == NULL)
- {
- LOG_ERROR("slv2_port_get_name() failed.");
- goto fail_free_symbol;
- }
-
- name_str = slv2_value_as_string_smart(name);
- if (name_str == NULL)
- {
- LOG_ERROR("port symbol is not string.");
- goto fail_free_symbol;
- }
-
- port_ptr->name = strdup(name_str);
-
- slv2_value_free(name);
-
- if (port_ptr->name == NULL)
- {
- LOG_ERROR("strdup() failed.");
- goto fail_free_symbol;
- }
-
- contexts = slv2_port_get_value(info_ptr->slv2info, port, g_slv2uri_port_context);
- for (i = 0; i < slv2_values_size(contexts); i++)
- {
- if (slv2_value_equals(slv2_values_get_at(contexts, i), g_slv2uri_message_context))
- {
- port_ptr->flags |= PORT_FLAGS_MSGCONTEXT;
- LOG_DEBUG("Port %d has message context", index);
- break;
- }
- }
-
- return port_ptr;
-
-fail_free_symbol:
- free(port_ptr->symbol);
-
-fail_free_port:
- free(port_ptr);
-
-fail:
- return NULL;
-}
-
-static
-bool
-zynjacku_plugin_repo_create_port_internal(
- struct zynjacku_plugin_info * info_ptr,
- uint32_t port_index,
- struct zynjacku_plugin * plugin_ptr,
- void * context,
- zynjacku_plugin_repo_create_port create_port)
-{
- struct zynjacku_port * port_ptr;
- SLV2Port port;
- SLV2Value symbol;
- const char * symbol_str;
- SLV2Value default_value;
- SLV2Value min_value;
- SLV2Value max_value;
- unsigned int port_type;
- bool output_port;
- SLV2Values defs;
- SLV2Value defval;
- const char * defval_str;
- size_t defval_len;
-
- port = slv2_plugin_get_port_by_index(info_ptr->slv2info, port_index);
-
- output_port = slv2_port_is_output(info_ptr->slv2info, port);
-
- /* port symbol */
- symbol = slv2_port_get_symbol(info_ptr->slv2info, port);
- if (symbol == NULL)
- {
- LOG_ERROR("slv2_port_get_symbol() failed.");
- return false;
- }
-
- symbol_str = slv2_value_as_string_smart(symbol);
- if (symbol_str == NULL)
- {
- LOG_ERROR("port symbol is not string.");
- return false;
- }
-
- if (slv2_port_is_control(info_ptr->slv2info, port))
- {
- port_ptr = new_lv2parameter_port(info_ptr, port, port_index, symbol_str, plugin_ptr);
-
- port_ptr->type = PORT_TYPE_LV2_FLOAT;
-
- if (output_port)
- {
- port_ptr->flags |= PORT_FLAGS_OUTPUT;
- list_add_tail(&port_ptr->plugin_siblings, &plugin_ptr->measure_ports);
- return true;
- }
-
- /* port range */
- slv2_port_get_range(
- info_ptr->slv2info,
- port,
- &default_value,
- &min_value,
- &max_value);
-
- if (default_value != NULL)
- {
- port_ptr->data.lv2float.value = slv2_value_as_float(default_value);
- slv2_value_free(default_value);
- }
-
- if (min_value != NULL)
- {
- port_ptr->data.lv2float.min = slv2_value_as_float(min_value);
- slv2_value_free(min_value);
- }
-
- if (max_value != NULL)
- {
- port_ptr->data.lv2float.max = slv2_value_as_float(max_value);
- slv2_value_free(max_value);
- }
-
- list_add_tail(&port_ptr->plugin_siblings, &plugin_ptr->parameter_ports);
-
- return true;
- }
-
- if (slv2_port_is_string(info_ptr->slv2info, port))
- {
- if (output_port)
- {
- /* TODO measure string ports are ignored for now */
- return true;
- }
-
- port_ptr = new_lv2parameter_port(info_ptr, port, port_index, symbol_str, plugin_ptr);
-
- port_ptr->type = PORT_TYPE_LV2_STRING;
-
- /* TODO: get from slv2 (requiredSpace) */
- port_ptr->data.lv2string.storage = 256;
-
- defval_str = "\0";
-
- /* get default */
- defs = slv2_port_get_value(info_ptr->slv2info, port, g_slv2uri_string_port_default);
- if (defs && slv2_values_size(defs) == 1)
- {
- defval = slv2_values_get_at(defs, 0);
- if (slv2_value_is_string(defval))
- {
- defval_str = slv2_value_as_string(defval);
- }
- }
-
- defval_len = strlen(defval_str) + 1;
-
- if (defval_len > port_ptr->data.lv2string.storage)
- {
- port_ptr->data.lv2string.storage = defval_len;
- }
-
- port_ptr->data.lv2string.data = malloc(port_ptr->data.lv2string.storage);
- memcpy(port_ptr->data.lv2string.data, defval_str, defval_len);
-
- port_ptr->data.lv2string.len = defval_len - 1;
- port_ptr->data.lv2string.flags = LV2_STRING_DATA_CHANGED_FLAG;
- port_ptr->data.lv2string.pad = 0;
-
- list_add_tail(&port_ptr->plugin_siblings, &plugin_ptr->parameter_ports);
-
- return true;
- }
-
- if (slv2_port_is_audio(info_ptr->slv2info, port))
- {
- port_type = PORT_TYPE_AUDIO;
- }
- else if (slv2_port_is_midi(info_ptr->slv2info, port))
- {
- port_type = PORT_TYPE_MIDI;
- }
- else if (slv2_port_is_event(info_ptr->slv2info, port) &&
- slv2_port_is_midi_event(info_ptr->slv2info, port))
- {
- port_type = PORT_TYPE_EVENT_MIDI;
- }
- else
- {
- LOG_ERROR("Unrecognized port '%s' type (index is %u)", slv2_value_as_string_smart(symbol), (unsigned int)port_index);
- return false;
- }
-
- if (create_port(
- context,
- port_type,
- output_port,
- port_index))
- {
- return true;
- }
-
- LOG_ERROR("Unmatched port '%s'. type is %u, index is %u", slv2_value_as_string_smart(symbol), (unsigned int)port_type, (unsigned int)port_index);
- return false;
-}
-
-bool
-zynjacku_plugin_repo_load_plugin(
- struct zynjacku_plugin * synth_ptr,
- void * context,
- zynjacku_plugin_repo_create_port create_port,
- zynjacku_plugin_repo_check_plugin check_plugin,
- const LV2_Feature * const * supported_features)
-{
- struct zynjacku_plugin_info * info_ptr;
- SLV2Values slv2features;
- SLV2Value slv2feature;
- unsigned int features_count;
- unsigned int feature_index;
- bool ret;
- const char *uri;
- uint32_t ports_count;
- uint32_t i;
- SLV2Plugins slv2plugins;
- SLV2Plugin slv2plugin;
- SLV2Value uri_value;
-
- ret = false;
-
- LOG_DEBUG("zynjacku_plugin_repo_load_plugin() called.");
-
-#if HAVE_DYNPARAMS
- synth_ptr->dynparams_supported = FALSE;
-#endif
-
- if (!g_fullscanned)
- {
- if (!g_loaded)
- {
- slv2_world_load_all(g_world);
- g_loaded = true;
- }
-
- g_iterate_context.supported_features = supported_features;
- g_iterate_context.context = context;
- g_iterate_context.check_plugin = check_plugin;
- g_iterate_context.progress_step = 0.0;
- g_iterate_context.progress = 0.0;
- g_iterate_context.tick = NULL;
- g_iterate_context.tack = NULL;
-
- slv2plugins = slv2_world_get_all_plugins(g_world);
-
- uri_value = slv2_value_new_uri(g_world, synth_ptr->uri);
-
- slv2plugin = slv2_plugins_get_by_uri(slv2plugins, uri_value);
- if (slv2plugin == NULL)
- {
- slv2_value_free(uri_value);
- slv2_plugins_free(g_world, slv2plugins);
- LOG_ERROR("Plugin '%s' not found", synth_ptr->uri);
- goto exit;
- }
-
- ret = zynjacku_plugin_repo_check_and_maybe_init_plugin(slv2plugin);
-
- slv2_value_free(uri_value);
-
- slv2_plugins_free(g_world, slv2plugins);
-
- if (!ret)
- {
- LOG_ERROR("plugin '%s' failed to match synth constraints", synth_ptr->uri);
- goto exit;
- }
-
- /* MAYBE: return info_ptr from zynjacku_plugin_repo_check_and_maybe_init_plugin()
- so we dont lookup it in next line, by calling zynjacku_plugin_repo_lookup_by_uri() */
- }
-
- info_ptr = zynjacku_plugin_repo_lookup_by_uri(synth_ptr->uri);
- if (info_ptr == NULL)
- {
- LOG_ERROR("Failed to find plugin %s", synth_ptr->uri);
- goto exit;
- }
-
- synth_ptr->name = strdup(info_ptr->name);
- if (synth_ptr->name == NULL)
- {
- LOG_ERROR("Failed to strdup('%s')", info_ptr->name);
- goto exit;
- }
-
- slv2features = slv2_plugin_get_optional_features(info_ptr->slv2info);
-
- features_count = slv2_values_size(slv2features);
- LOG_DEBUG("Plugin has %u optional features", features_count);
- for (feature_index = 0 ; feature_index < features_count ; feature_index++)
- {
- slv2feature = slv2_values_get_at(slv2features, feature_index);
-
- uri = slv2_value_as_uri_smart(slv2feature);
- if (uri == NULL)
- {
- LOG_ERROR("slv2_value_as_uri_smart() failed for plugin name value.");
- goto free_features;
- }
-
- LOG_DEBUG("%s", uri);
-
-#if HAVE_DYNPARAMS
- if (strcmp(LV2DYNPARAM_URI, uri) == 0)
- {
- synth_ptr->dynparams_supported = TRUE;
- }
-#endif
- }
-
- ports_count = slv2_plugin_get_num_ports(info_ptr->slv2info);
-
- for (i = 0 ; i < ports_count ; i++)
- {
- if (!zynjacku_plugin_repo_create_port_internal(info_ptr, i, synth_ptr, context, create_port))
- {
- LOG_ERROR("Failed to create plugin port");
- goto free_features;
- }
- }
-
- ret = true;
-
-free_features:
- slv2_values_free(slv2features);
-
-exit:
- return ret;
-}
-
-static
-const char *
-uri_to_fs_path(
- const char * uri)
-{
- if (uri == NULL)
- {
- return NULL;
- }
-
- if (strlen(uri) <= 8 || memcmp(uri, "file:///", 8) != 0)
- {
- return NULL;
- }
-
- return uri + 7;
-}
-
-bool
-zynjacku_plugin_repo_get_ui_info(
- const char * plugin_uri,
- const char * ui_type_uri,
- char ** ui_uri_ptr,
- char ** ui_binary_path_ptr,
- char ** ui_bundle_path_ptr)
-{
- struct zynjacku_plugin_info * plugin_info_ptr;
- SLV2UIs slv2uis;
- SLV2UI slv2ui;
- SLV2Value ui_type;
- SLV2Value ui_uri;
- SLV2Value ui_binary_uri;
- SLV2Value ui_bundle_uri;
- const char * ui_uri_str;
- const char * ui_binary_path;
- const char * ui_bundle_path;
- bool ret;
-
- LOG_DEBUG("zynjacku_plugin_repo_get_ui_info() called.");
-
- ret = false;
-
- ui_type = slv2_value_new_uri(g_world, ui_type_uri);
- if (ui_type == NULL)
- {
- LOG_ERROR("slv2_value_new_uri() failed.");
- goto fail;
- }
-
- plugin_info_ptr = zynjacku_plugin_repo_lookup_by_uri(plugin_uri);
- if (plugin_info_ptr == NULL)
- {
- LOG_ERROR("Unknown plugin '%s'", plugin_uri);
- goto fail_free_ui_type;
- }
-
- slv2uis = slv2_plugin_get_uis(plugin_info_ptr->slv2info);
-
- if (slv2_uis_size(slv2uis) == 0)
- {
- LOG_DEBUG("Plugin '%s' has no UIs", plugin_uri);
- goto fail_free_uis;
- }
-
- slv2ui = slv2_uis_get_at(slv2uis, 0);
- if (slv2ui == NULL)
- {
- LOG_ERROR("slv2_uis_get_at() failed with plugin '%s'", plugin_uri);
- goto fail_free_uis;
- }
-
- if (!slv2_ui_is_a(slv2ui, ui_type))
- {
- LOG_DEBUG("First UI of '%s' is not '%s'", plugin_uri, ui_type_uri);
- goto fail_free_uis;
- }
-
- ui_uri = slv2_ui_get_uri(slv2ui);
- ui_binary_uri = slv2_ui_get_binary_uri(slv2ui);
- ui_bundle_uri = slv2_ui_get_bundle_uri(slv2ui);
-
- ui_uri_str = slv2_value_as_uri_smart(ui_uri);
- ui_binary_path = uri_to_fs_path(slv2_value_as_uri_smart(ui_binary_uri));
- ui_bundle_path = uri_to_fs_path(slv2_value_as_uri_smart(ui_bundle_uri));
-
- if (ui_uri_str == NULL)
- {
- LOG_ERROR("Failed to retrieve UI URI of '%s'", plugin_uri);
- goto fail_free_uis;
- }
-
- if (ui_binary_uri == NULL)
- {
- LOG_ERROR("Failed to retrieve UI binary path of '%s'", plugin_uri);
- goto fail_free_uis;
- }
-
- if (ui_bundle_uri == NULL)
- {
- LOG_ERROR("Failed to retrieve UI bundle path of '%s'", plugin_uri);
- goto fail_free_uis;
- }
-
- LOG_DEBUG("UI URI is '%s'", ui_uri_str);
- LOG_DEBUG("UI binary URI is '%s'", ui_binary_path);
- LOG_DEBUG("UI bundle URI is '%s'", ui_bundle_path);
-
- *ui_uri_ptr = strdup(ui_uri_str);
- if (*ui_uri_ptr == NULL)
- {
- LOG_ERROR("strdup() failed");
- goto fail_free_uis;
- }
-
- *ui_binary_path_ptr = strdup(ui_binary_path);
- if (*ui_binary_path_ptr == NULL)
- {
- LOG_ERROR("strdup() failed");
- free(*ui_uri_ptr);
- goto fail_free_uis;
- }
-
- *ui_bundle_path_ptr = strdup(ui_bundle_path);
- if (*ui_bundle_path_ptr == NULL)
- {
- LOG_ERROR("strdup() failed");
- free(*ui_binary_path_ptr);
- goto fail_free_uis;
- }
-
- ret = true;
-
-fail_free_uis:
- slv2_uis_free(slv2uis);
-
-fail_free_ui_type:
- slv2_value_free(ui_type);
-
-fail:
- return ret;
-}
diff --git a/plugin_repo.h b/plugin_repo.h
deleted file mode 100644
index eb72acc..0000000
--- a/plugin_repo.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* -*- Mode: C ; c-basic-offset: 2 -*- */
-/*****************************************************************************
- *
- * This file is part of zynjacku
- *
- * Copyright (C) 2006,2007,2008,2009 Nedko Arnaudov <nedko at arnaudov.name>
- *
- * 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; version 2 of the License
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *****************************************************************************/
-
-#ifndef PLUGIN_REPO_H__27C1E0DC_DD5E_4A79_838B_DC6B90402229__INCLUDED
-#define PLUGIN_REPO_H__27C1E0DC_DD5E_4A79_838B_DC6B90402229__INCLUDED
-
-typedef
-void
-(* zynjacku_plugin_repo_tick)(
- void * context,
- float progress, /* 0..1 */
- const char * message);
-
-typedef
-void
-(* zynjacku_plugin_repo_tack)(
- void * context,
- const char * uri);
-
-typedef
-bool
-(* zynjacku_plugin_repo_check_plugin)(
- void * context,
- const char * plugin_uri,
- const char * plugin_name,
- uint32_t audio_in_ports_count,
- uint32_t audio_out_ports_count,
- uint32_t midi_in_ports_count,
- uint32_t control_ports_count,
- uint32_t string_ports_count,
- uint32_t event_ports_count,
- uint32_t midi_event_in_ports_count,
- uint32_t ports_count);
-
-typedef
-bool
-(* zynjacku_plugin_repo_create_port)(
- void * context,
- unsigned int port_type,
- bool output,
- uint32_t port_index);
-
-bool
-zynjacku_plugin_repo_init();
-
-void
-zynjacku_plugin_repo_iterate(
- bool force_scan,
- const LV2_Feature * const * supported_features,
- void * context,
- zynjacku_plugin_repo_check_plugin check_plugin,
- zynjacku_plugin_repo_tick tick,
- zynjacku_plugin_repo_tack tack);
-
-const char *
-zynjacku_plugin_repo_get_name(
- const char * uri);
-
-const char *
-zynjacku_plugin_repo_get_license(
- const char * uri);
-
-const char *
-zynjacku_plugin_repo_get_author(
- const char * uri);
-
-const char *
-zynjacku_plugin_repo_get_dlpath(
- const char * uri);
-
-const char *
-zynjacku_plugin_repo_get_bundle_path(
- const char * uri);
-
-bool
-zynjacku_plugin_repo_get_ui_info(
- const char * plugin_uri,
- const char * ui_type_uri,
- char ** ui_uri_ptr,
- char ** ui_binary_path_ptr,
- char ** ui_bundle_path_ptr);
-
-bool
-zynjacku_plugin_repo_load_plugin(
- struct zynjacku_plugin * synth_ptr,
- void * context,
- zynjacku_plugin_repo_create_port create_port,
- zynjacku_plugin_repo_check_plugin check_plugin,
- const LV2_Feature * const * supported_features);
-
-void
-zynjacku_plugin_repo_uninit();
-
-#endif /* #ifndef PLUGIN_REPO_H__27C1E0DC_DD5E_4A79_838B_DC6B90402229__INCLUDED */
diff --git a/rack.c b/rack.c
index bdbeea6..2e77171 100644
--- a/rack.c
+++ b/rack.c
@@ -61,7 +61,6 @@
#if HAVE_DYNPARAMS
#include "rtmempool.h"
#endif
-#include "plugin_repo.h"
#include "lv2_event_helpers.h"
#if HAVE_DYNPARAMS
@@ -107,10 +106,8 @@ struct lv2rack_engine
#define ZYNJACKU_RACK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), ZYNJACKU_RACK_TYPE, struct lv2rack_engine))
-#define ZYNJACKU_RACK_SIGNAL_TICK 0 /* plugin iterated */
-#define ZYNJACKU_RACK_SIGNAL_TACK 1 /* "good" plugin found */
-#define ZYNJACKU_RACK_SIGNAL_PROGRESS 2 /* plugin instantiation progress */
-#define ZYNJACKU_RACK_SIGNALS_COUNT 3
+#define ZYNJACKU_RACK_SIGNAL_PROGRESS 0 /* plugin instantiation progress */
+#define ZYNJACKU_RACK_SIGNALS_COUNT 1
/* URI map value for event MIDI type */
#define ZYNJACKU_MIDI_EVENT_ID 1
@@ -151,7 +148,6 @@ zynjacku_rack_dispose(GObject * obj)
if (rack_ptr->jack_client)
{
zynjacku_rack_stop_jack(ZYNJACKU_RACK(obj));
- zynjacku_plugin_repo_uninit();
}
/* Chain up to the parent class */
@@ -187,38 +183,6 @@ zynjacku_rack_class_init(
g_type_class_add_private(G_OBJECT_CLASS(class_ptr), sizeof(struct lv2rack_engine));
- g_zynjacku_rack_signals[ZYNJACKU_RACK_SIGNAL_TICK] =
- g_signal_new(
- "tick", /* signal_name */
- ZYNJACKU_RACK_TYPE, /* itype */
- G_SIGNAL_RUN_LAST |
- G_SIGNAL_ACTION, /* signal_flags */
- 0, /* class_offset */
- NULL, /* accumulator */
- NULL, /* accu_data */
- NULL, /* c_marshaller */
- G_TYPE_NONE, /* return type */
- 2, /* n_params */
- G_TYPE_FLOAT, /* progress 0 .. 1 */
- G_TYPE_STRING); /* uri of plugin being scanned */
-
- g_zynjacku_rack_signals[ZYNJACKU_RACK_SIGNAL_TACK] =
- g_signal_new(
- "tack", /* signal_name */
- ZYNJACKU_RACK_TYPE, /* itype */
- G_SIGNAL_RUN_LAST |
- G_SIGNAL_ACTION, /* signal_flags */
- 0, /* class_offset */
- NULL, /* accumulator */
- NULL, /* accu_data */
- NULL, /* c_marshaller */
- G_TYPE_NONE, /* return type */
- 4, /* n_params */
- G_TYPE_STRING, /* plugin name */
- G_TYPE_STRING, /* plugin uri */
- G_TYPE_STRING, /* plugin license */
- G_TYPE_STRING); /* plugin author */
-
g_zynjacku_rack_signals[ZYNJACKU_RACK_SIGNAL_PROGRESS] =
g_signal_new(
"progress", /* signal_name */
@@ -353,8 +317,6 @@ zynjacku_rack_init(
rack_ptr->host_features[count++] = &rack_ptr->host_feature_progress;
assert(ZYNJACKU_RACK_ENGINE_FEATURES == count);
rack_ptr->host_features[count] = NULL;
-
- zynjacku_plugin_repo_init();
}
GType zynjacku_rack_get_type()
@@ -531,31 +493,31 @@ jack_process_cb(
/* Connect plugin LV2 input audio ports */
zynjacku_lv2_connect_port(
effect_ptr->lv2plugin,
- &effect_ptr->subtype.effect.audio_in_left_port,
+ effect_ptr->subtype.effect.audio_in_left_port_ptr,
left);
- if (effect_ptr->subtype.effect.audio_in_right_port.type == PORT_TYPE_AUDIO)
+ if (effect_ptr->subtype.effect.audio_in_right_port_ptr != NULL)
{
zynjacku_lv2_connect_port(
effect_ptr->lv2plugin,
- &effect_ptr->subtype.effect.audio_in_right_port,
+ effect_ptr->subtype.effect.audio_in_right_port_ptr,
mono ? left : right);
}
/* Connect plugin LV2 output audio ports directly to JACK buffers */
- left = jack_port_get_buffer(effect_ptr->subtype.effect.audio_out_left_port.data.audio, nframes);
+ left = jack_port_get_buffer(effect_ptr->subtype.effect.audio_out_left_port_ptr->data.audio, nframes);
zynjacku_lv2_connect_port(
effect_ptr->lv2plugin,
- &effect_ptr->subtype.effect.audio_out_left_port,
+ effect_ptr->subtype.effect.audio_out_left_port_ptr,
left);
- mono = effect_ptr->subtype.effect.audio_out_right_port.type != PORT_TYPE_AUDIO;
+ mono = effect_ptr->subtype.effect.audio_out_right_port_ptr == NULL;
if (!mono)
{
- right = jack_port_get_buffer(effect_ptr->subtype.effect.audio_out_right_port.data.audio, nframes);
+ right = jack_port_get_buffer(effect_ptr->subtype.effect.audio_out_right_port_ptr->data.audio, nframes);
zynjacku_lv2_connect_port(
effect_ptr->lv2plugin,
- &effect_ptr->subtype.effect.audio_out_right_port,
+ effect_ptr->subtype.effect.audio_out_right_port_ptr,
right);
}
@@ -570,6 +532,7 @@ jack_process_cb(
#undef rack_ptr
+static
void
zynjacku_rack_deactivate_effect(
GObject * effect_obj_ptr)
@@ -592,6 +555,36 @@ zynjacku_rack_deactivate_effect(
}
void
+zynjacku_rack_get_required_features(
+ GObject * rack_obj_ptr,
+ const LV2_Feature * const ** host_features,
+ unsigned int * host_feature_count)
+{
+ struct lv2rack_engine * rack_ptr;
+
+ rack_ptr = ZYNJACKU_RACK_GET_PRIVATE(rack_obj_ptr);
+
+ *host_features = rack_ptr->host_features;
+ *host_feature_count = ZYNJACKU_RACK_ENGINE_FEATURES;
+}
+
+static
+void
+zynjacku_rack_unregister_port(
+ GObject * rack_obj_ptr,
+ struct zynjacku_port * port_ptr)
+{
+ struct lv2rack_engine * rack_ptr;
+
+ rack_ptr = ZYNJACKU_RACK_GET_PRIVATE(rack_obj_ptr);
+
+ if (port_ptr->data.audio != NULL)
+ {
+ jack_port_unregister(rack_ptr->jack_client, port_ptr->data.audio);
+ }
+}
+
+void
zynjacku_rack_ui_run(
ZynjackuRack * rack_obj_ptr)
{
@@ -634,218 +627,121 @@ zynjacku_rack_get_version()
return VERSION;
}
-#define rack_obj_ptr ((ZynjackuRack *)context)
-
-bool
-zynjacku_rack_check_plugin(
- void * context,
- const char * plugin_uri,
- const char * plugin_name,
- uint32_t audio_in_ports_count,
- uint32_t audio_out_ports_count,
- uint32_t midi_in_ports_count,
- uint32_t control_ports_count,
- uint32_t string_ports_count,
- uint32_t event_ports_count,
- uint32_t midi_event_in_ports_count,
- uint32_t ports_count)
-{
- if (audio_in_ports_count == 0 || audio_out_ports_count == 0)
- {
- LOG_DEBUG("Skipping 's' %s, [effect] plugin with unsupported port configuration", name, plugin_uri);
- LOG_DEBUG(" midi input ports: %d", (unsigned int)midi_in_ports_count);
- LOG_DEBUG(" control ports: %d", (unsigned int)control_ports_count);
- LOG_DEBUG(" string ports: %d", (unsigned int)string_ports_count);
- LOG_DEBUG(" event ports: %d", (unsigned int)event_ports_count);
- LOG_DEBUG(" event midi input ports: %d", (unsigned int)midi_event_in_ports_count);
- LOG_DEBUG(" audio input ports: %d", (unsigned int)audio_in_ports_count);
- LOG_DEBUG(" audio output ports: %d", (unsigned int)audio_out_ports_count);
- LOG_DEBUG(" total ports %d", (unsigned int)ports_count);
- return false;
- }
-
- LOG_DEBUG("Found effect plugin '%s' %s", name, plugin_uri);
- LOG_DEBUG(" midi input ports: %d", (unsigned int)midi_in_ports_count);
- LOG_DEBUG(" control ports: %d", (unsigned int)control_ports_count);
- LOG_DEBUG(" string ports: %d", (unsigned int)string_ports_count);
- LOG_DEBUG(" event ports: %d", (unsigned int)event_ports_count);
- LOG_DEBUG(" event midi input ports: %d", (unsigned int)midi_event_in_ports_count);
- LOG_DEBUG(" audio input ports: %d", (unsigned int)audio_in_ports_count);
- LOG_DEBUG(" audio output ports: %d", (unsigned int)audio_out_ports_count);
- LOG_DEBUG(" total ports %d", (unsigned int)ports_count);
- return true;
-}
-
-void
-zynjacku_rack_tick(
- void *context,
- float progress, /* 0..1 */
- const char *message)
-{
- g_signal_emit(
- rack_obj_ptr,
- g_zynjacku_rack_signals[ZYNJACKU_RACK_SIGNAL_TICK],
- 0,
- progress,
- message);
-}
-
-void
-zynjacku_rack_tack(
- void *context,
- const char *uri)
-{
- const char * name;
- const char * license;
- const char * author;
-
- name = zynjacku_plugin_repo_get_name(uri);
- license = zynjacku_plugin_repo_get_license(uri);
- author = zynjacku_plugin_repo_get_author(uri);
-
- g_signal_emit(
- rack_obj_ptr,
- g_zynjacku_rack_signals[ZYNJACKU_RACK_SIGNAL_TACK],
- 0,
- name,
- uri,
- license,
- author);
-}
-
-#undef rack_obj_ptr
-
-void
-zynjacku_rack_iterate_plugins(
+const gchar *
+zynjacku_rack_get_supported_feature(
ZynjackuRack * rack_obj_ptr,
- gboolean force)
+ guint index)
{
struct lv2rack_engine * rack_ptr;
+ if (index >= ZYNJACKU_RACK_ENGINE_FEATURES)
+ {
+ return NULL;
+ }
+
rack_ptr = ZYNJACKU_RACK_GET_PRIVATE(rack_obj_ptr);
- zynjacku_plugin_repo_iterate(
- force,
- rack_ptr->host_features,
- rack_obj_ptr,
- zynjacku_rack_check_plugin,
- zynjacku_rack_tick,
- zynjacku_rack_tack);
+ return rack_ptr->host_features[index]->URI;
}
-void
-zynjacku_free_effect_ports(
- GObject * plugin_object_ptr)
+#define effect_ptr (&plugin_ptr->subtype.effect)
+
+gboolean
+zynjacku_rack_construct_plugin(
+ ZynjackuRack * rack_object_ptr,
+ ZynjackuPlugin * plugin_object_ptr)
{
+ static unsigned int id;
+ char * port_name;
+ size_t size_name;
+ size_t size_id;
struct lv2rack_engine * rack_ptr;
+ struct list_head * node_ptr;
+ struct zynjacku_port * port_ptr;
+ struct zynjacku_port * audio_in_left_port_ptr;
+ struct zynjacku_port * audio_in_right_port_ptr;
+ struct zynjacku_port * audio_out_left_port_ptr;
+ struct zynjacku_port * audio_out_right_port_ptr;
struct zynjacku_plugin * plugin_ptr;
+ rack_ptr = ZYNJACKU_RACK_GET_PRIVATE(rack_object_ptr);
plugin_ptr = ZYNJACKU_PLUGIN_GET_PRIVATE(plugin_object_ptr);
- rack_ptr = ZYNJACKU_RACK_GET_PRIVATE(plugin_ptr->engine_object_ptr);
-
- LOG_DEBUG("zynjacku_free_effect_ports() called");
-
- zynjacku_free_plugin_ports(plugin_ptr);
- if (plugin_ptr->type == PLUGIN_TYPE_EFFECT)
+ if (plugin_ptr->uri == NULL)
{
- if (plugin_ptr->subtype.effect.audio_out_left_port.type == PORT_TYPE_AUDIO)
- {
- jack_port_unregister(rack_ptr->jack_client, plugin_ptr->subtype.effect.audio_out_left_port.data.audio);
- }
-
- if (plugin_ptr->subtype.effect.audio_out_right_port.type == PORT_TYPE_AUDIO) /* stereo? */
- {
- assert(plugin_ptr->subtype.effect.audio_out_left_port.type == PORT_TYPE_AUDIO);
- jack_port_unregister(rack_ptr->jack_client, plugin_ptr->subtype.effect.audio_out_right_port.data.audio);
- }
+ LOG_ERROR("\"uri\" property needs to be set before constructing plugin");
+ goto fail;
}
-}
-
-#define effect_ptr (&((struct zynjacku_plugin *)context)->subtype.effect)
-
-bool
-zynjacku_effect_create_port(
- void * context,
- unsigned int port_type,
- bool output,
- uint32_t port_index)
-{
- struct zynjacku_port * port_ptr;
- LOG_NOTICE("creating effect %s port of type %u, index %u", output ? "output" : "input", (unsigned int)port_type, (unsigned int)port_index);
+ if (plugin_ptr->name == NULL)
+ {
+ LOG_ERROR("\"name\" property needs to be set before constructing plugin");
+ goto fail;
+ }
- if (port_type != PORT_TYPE_AUDIO)
+ if (plugin_ptr->dlpath == NULL)
{
- /* ignore unknown ports */
- return true;
+ LOG_ERROR("Plugin %s has no dlpath set", plugin_ptr->uri);
+ goto fail;
}
- if (!output)
+ if (plugin_ptr->bundle_path == NULL)
{
- if (effect_ptr->audio_in_left_port.type == PORT_TYPE_INVALID)
- {
- port_ptr = &effect_ptr->audio_in_left_port;
- }
- else if (effect_ptr->audio_in_right_port.type == PORT_TYPE_INVALID)
- {
- port_ptr = &effect_ptr->audio_in_right_port;
- }
- else
- {
- /* ignore, we dont support more than two audio ports yet */
- return true;
- }
+ LOG_ERROR("Plugin %s has no bundle path set", plugin_ptr->uri);
+ goto fail;
}
- else
+
+ audio_in_left_port_ptr = NULL;
+ audio_in_right_port_ptr = NULL;
+
+ list_for_each(node_ptr, &plugin_ptr->audio_ports)
{
- if (effect_ptr->audio_out_left_port.type == PORT_TYPE_INVALID)
- {
- port_ptr = &effect_ptr->audio_out_left_port;
- }
- else if (effect_ptr->audio_out_right_port.type == PORT_TYPE_INVALID)
- {
- port_ptr = &effect_ptr->audio_out_right_port;
- }
- else
+ port_ptr = list_entry(node_ptr, struct zynjacku_port, plugin_siblings);
+ assert(port_ptr->type == PORT_TYPE_AUDIO);
+ if (PORT_IS_INPUT(port_ptr))
{
- /* ignore, we dont support more than two audio ports yet */
- return true;
+ if (audio_in_left_port_ptr == NULL)
+ {
+ audio_in_left_port_ptr = port_ptr;
+ continue;
+ }
+
+ assert(audio_in_right_port_ptr == NULL);
+ audio_in_right_port_ptr = port_ptr;
+ break;
}
}
- port_ptr->type = PORT_TYPE_AUDIO;
- port_ptr->index = port_index;
-
- return true;
-}
-
-#undef effect_ptr
-#define effect_ptr (&plugin_ptr->subtype.effect)
-
-bool
-zynjacku_plugin_construct_effect(
- struct zynjacku_plugin * plugin_ptr,
- ZynjackuPlugin * plugin_obj_ptr,
- GObject * rack_object_ptr)
-{
- static unsigned int id;
- char * port_name;
- size_t size_name;
- size_t size_id;
- struct lv2rack_engine * rack_ptr;
+ if (audio_in_left_port_ptr == NULL)
+ {
+ LOG_ERROR("Cannot construct effect plugin without audio input port(s). %s", plugin_ptr->uri);
+ goto fail;
+ }
- rack_ptr = ZYNJACKU_RACK_GET_PRIVATE(rack_object_ptr);
+ audio_out_left_port_ptr = NULL;
+ audio_out_right_port_ptr = NULL;
- plugin_ptr->type = PLUGIN_TYPE_EFFECT;
- effect_ptr->audio_in_left_port.type = PORT_TYPE_INVALID;
- effect_ptr->audio_in_right_port.type = PORT_TYPE_INVALID;
- effect_ptr->audio_out_left_port.type = PORT_TYPE_INVALID;
- effect_ptr->audio_out_right_port.type = PORT_TYPE_INVALID;
+ list_for_each(node_ptr, &plugin_ptr->audio_ports)
+ {
+ port_ptr = list_entry(node_ptr, struct zynjacku_port, plugin_siblings);
+ assert(port_ptr->type == PORT_TYPE_AUDIO);
+ if (PORT_IS_OUTPUT(port_ptr))
+ {
+ if (audio_out_left_port_ptr == NULL)
+ {
+ audio_out_left_port_ptr = port_ptr;
+ continue;
+ }
+
+ assert(audio_out_right_port_ptr == NULL);
+ audio_out_right_port_ptr = port_ptr;
+ break;
+ }
+ }
- if (!zynjacku_plugin_repo_load_plugin(plugin_ptr, plugin_ptr, zynjacku_effect_create_port, zynjacku_rack_check_plugin, rack_ptr->host_features))
+ if (audio_out_left_port_ptr == NULL)
{
- LOG_ERROR("Failed to load LV2 info for plugin %s", plugin_ptr->uri);
+ LOG_ERROR("Cannot construct effect plugin without audio output port(s). %s", plugin_ptr->uri);
goto fail;
}
@@ -855,6 +751,8 @@ zynjacku_plugin_construct_effect(
plugin_ptr->lv2plugin = zynjacku_lv2_load(
plugin_ptr->uri,
+ plugin_ptr->dlpath,
+ plugin_ptr->bundle_path,
zynjacku_rack_get_sample_rate(ZYNJACKU_RACK(rack_object_ptr)),
rack_ptr->host_features);
@@ -876,8 +774,8 @@ zynjacku_plugin_construct_effect(
if (!zynjacku_connect_plugin_ports(
plugin_ptr,
- plugin_obj_ptr,
- rack_object_ptr
+ plugin_object_ptr,
+ G_OBJECT(rack_object_ptr)
#if HAVE_DYNPARAMS
, &rack_ptr->mempool_allocator
#endif
@@ -888,31 +786,45 @@ zynjacku_plugin_construct_effect(
/* setup audio ports (they are connected in jack process callback */
+ effect_ptr->audio_in_left_port_ptr = audio_in_left_port_ptr;
+ effect_ptr->audio_in_right_port_ptr = audio_in_right_port_ptr;
+ effect_ptr->audio_out_left_port_ptr = audio_out_left_port_ptr;
+ effect_ptr->audio_out_right_port_ptr = audio_out_right_port_ptr;
+
size_name = strlen(plugin_ptr->name);
port_name = malloc(size_name + 1024);
if (port_name == NULL)
{
LOG_ERROR("Failed to allocate memory for port name");
- goto fail_free_ports;
+ goto fail_unload;
}
size_id = sprintf(port_name, "%u:", id);
memcpy(port_name + size_id, plugin_ptr->name, size_name);
- if (effect_ptr->audio_out_left_port.type == PORT_TYPE_AUDIO &&
- effect_ptr->audio_out_right_port.type == PORT_TYPE_AUDIO)
+ if (audio_out_left_port_ptr != NULL &&
+ audio_out_right_port_ptr != NULL)
{
+ assert(audio_out_left_port_ptr->type == PORT_TYPE_AUDIO);
+ assert(PORT_IS_OUTPUT(audio_out_left_port_ptr));
+
strcpy(port_name + size_id + size_name, " L");
- effect_ptr->audio_out_left_port.data.audio = jack_port_register(rack_ptr->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+ audio_out_left_port_ptr->data.audio = jack_port_register(rack_ptr->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+
+ assert(audio_out_right_port_ptr->type == PORT_TYPE_AUDIO);
+ assert(PORT_IS_OUTPUT(audio_out_right_port_ptr));
strcpy(port_name + size_id + size_name, " R");
- effect_ptr->audio_out_right_port.data.audio = jack_port_register(rack_ptr->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+ audio_out_right_port_ptr->data.audio = jack_port_register(rack_ptr->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
}
- else if (effect_ptr->audio_out_left_port.type == PORT_TYPE_AUDIO &&
- effect_ptr->audio_out_right_port.type == PORT_TYPE_INVALID)
+ else if (audio_out_left_port_ptr != NULL &&
+ audio_out_right_port_ptr == NULL)
{
+ assert(audio_out_left_port_ptr->type == PORT_TYPE_AUDIO);
+ assert(PORT_IS_OUTPUT(audio_out_left_port_ptr));
+
port_name[size_id + size_name] = 0;
- effect_ptr->audio_out_left_port.data.audio = jack_port_register(rack_ptr->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+ audio_out_left_port_ptr->data.audio = jack_port_register(rack_ptr->jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
}
port_name[size_id + size_name] = 0;
@@ -933,12 +845,9 @@ zynjacku_plugin_construct_effect(
g_object_ref(plugin_ptr->engine_object_ptr);
- /* no plugins to test gtk2gui */
- plugin_ptr->gtk2gui = zynjacku_gtk2gui_create(rack_ptr->host_features, ZYNJACKU_RACK_ENGINE_FEATURES, plugin_ptr->lv2plugin,
- plugin_ptr, plugin_obj_ptr, plugin_ptr->uri, plugin_ptr->id, &plugin_ptr->parameter_ports);
-
plugin_ptr->deactivate = zynjacku_rack_deactivate_effect;
- plugin_ptr->free_ports = zynjacku_free_effect_ports;
+ plugin_ptr->unregister_port = zynjacku_rack_unregister_port;
+ plugin_ptr->get_required_features = zynjacku_rack_get_required_features;
/* we dont support midi cc maps for lv2rack yet */
plugin_ptr->set_midi_cc_map = NULL;
@@ -948,18 +857,6 @@ zynjacku_plugin_construct_effect(
return true;
-fail_free_ports:
- zynjacku_free_effect_ports(G_OBJECT(plugin_obj_ptr));
- plugin_ptr->engine_object_ptr = NULL;
-
-#if HAVE_DYNPARAMS
- if (plugin_ptr->dynparams != NULL)
- {
- lv2dynparam_host_detach(plugin_ptr->dynparams);
- plugin_ptr->dynparams = NULL;
- }
-#endif
-
fail_unload:
zynjacku_lv2_unload(plugin_ptr->lv2plugin);
diff --git a/rack.h b/rack.h
index 13b02a9..fe96a6f 100644
--- a/rack.h
+++ b/rack.h
@@ -70,10 +70,15 @@ zynjacku_rack_ui_run(
const gchar *
zynjacku_rack_get_version();
-void
-zynjacku_rack_iterate_plugins(
+const gchar *
+zynjacku_rack_get_supported_feature(
+ ZynjackuRack * rack_obj_ptr,
+ guint index);
+
+gboolean
+zynjacku_rack_construct_plugin(
ZynjackuRack * rack_obj_ptr,
- gboolean force);
+ ZynjackuPlugin * plugin_obj_ptr);
G_END_DECLS
diff --git a/synth.h b/synth.h
deleted file mode 100644
index 3031433..0000000
--- a/synth.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -*- Mode: C ; c-basic-offset: 2 -*- */
-/*****************************************************************************
- *
- * This file is part of zynjacku
- *
- * Copyright (C) 2008,2009 Nedko Arnaudov <nedko at arnaudov.name>
- *
- * 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; version 2 of the License
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *****************************************************************************/
-
-#ifndef SYNTH_H__6B544DDB_CFAC_4182_B10B_6183A3AB0933__INCLUDED
-#define SYNTH_H__6B544DDB_CFAC_4182_B10B_6183A3AB0933__INCLUDED
-
-bool
-zynjacku_plugin_construct_synth(
- struct zynjacku_plugin * plugin_ptr,
- ZynjackuPlugin * plugin_obj_ptr,
- GObject * engine_object_ptr);
-
-#endif /* #ifndef SYNTH_H__6B544DDB_CFAC_4182_B10B_6183A3AB0933__INCLUDED */
diff --git a/ttl_lexer.h b/ttl_lexer.h
new file mode 100644
index 0000000..cad2ca5
--- /dev/null
+++ b/ttl_lexer.h
@@ -0,0 +1,10 @@
+#ifndef _TTLDATA_H
+#define _TTLDATA_H
+
+#include <Python.h>
+
+extern PyObject *ttl_list;
+
+#define YY_NO_INPUT
+
+#endif
diff --git a/zynjacku.defs b/zynjacku.defs
index b90ec24..cd115e8 100644
--- a/zynjacku.defs
+++ b/zynjacku.defs
@@ -94,12 +94,21 @@
)
)
-(define-method iterate_plugins
+(define-method get_supported_feature
(of-object "ZynjackuEngine")
- (c-name "zynjacku_engine_iterate_plugins")
- (return-type "none")
+ (c-name "zynjacku_engine_get_supported_feature")
+ (return-type "const-gchar*")
+ (parameters
+ '("guint" "index")
+ )
+)
+
+(define-method construct_plugin
+ (of-object "ZynjackuEngine")
+ (c-name "zynjacku_engine_construct_plugin")
+ (return-type "gboolean")
(parameters
- '("gboolean" "force")
+ '("ZynjackuPlugin*" "plugin_obj_ptr")
)
)
@@ -148,12 +157,21 @@
)
)
-(define-method iterate_plugins
+(define-method get_supported_feature
(of-object "ZynjackuRack")
- (c-name "zynjacku_rack_iterate_plugins")
- (return-type "none")
+ (c-name "zynjacku_rack_get_supported_feature")
+ (return-type "const-gchar*")
+ (parameters
+ '("guint" "index")
+ )
+)
+
+(define-method construct_plugin
+ (of-object "ZynjackuRack")
+ (c-name "zynjacku_rack_construct_plugin")
+ (return-type "gboolean")
(parameters
- '("gboolean" "force")
+ '("ZynjackuPlugin*" "plugin_obj_ptr")
)
)
@@ -168,33 +186,12 @@
)
)
-(define-method construct
- (of-object "ZynjackuPlugin")
- (c-name "zynjacku_plugin_construct")
- (return-type "gboolean")
- (parameters
- '("GObject*" "engine_obj_ptr")
- )
-)
-
(define-method destruct
(of-object "ZynjackuPlugin")
(c-name "zynjacku_plugin_destruct")
(return-type "none")
)
-(define-method supports_generic_ui
- (of-object "ZynjackuPlugin")
- (c-name "zynjacku_plugin_supports_generic_ui")
- (return-type "gboolean")
-)
-
-(define-method supports_custom_ui
- (of-object "ZynjackuPlugin")
- (c-name "zynjacku_plugin_supports_custom_ui")
- (return-type "gboolean")
-)
-
(define-method get_instance_name
(of-object "ZynjackuPlugin")
(c-name "zynjacku_plugin_get_instance_name")
@@ -217,6 +214,12 @@
(of-object "ZynjackuPlugin")
(c-name "zynjacku_plugin_ui_on")
(return-type "gboolean")
+ (parameters
+ '("const-char*" "ui_uri" (null-ok) (default "NULL"))
+ '("const-char*" "ui_type_uri" (null-ok) (default "NULL"))
+ '("const-char*" "ui_binary_path" (null-ok) (default "NULL"))
+ '("const-char*" "ui_bundle_path" (null-ok) (default "NULL"))
+ )
)
(define-method ui_off
@@ -301,6 +304,89 @@
)
)
+(define-method add_supported_feature
+ (of-object "ZynjackuPlugin")
+ (c-name "zynjacku_plugin_add_supported_feature")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "feature_uri")
+ )
+)
+
+(define-method create_oldmidi_input_port
+ (of-object "ZynjackuPlugin")
+ (c-name "zynjacku_plugin_create_oldmidi_input_port")
+ (return-type "gboolean")
+ (parameters
+ '("guint" "port_index")
+ '("const-gchar*" "symbol")
+ )
+)
+
+(define-method create_eventmidi_input_port
+ (of-object "ZynjackuPlugin")
+ (c-name "zynjacku_plugin_create_eventmidi_input_port")
+ (return-type "gboolean")
+ (parameters
+ '("guint" "port_index")
+ '("const-gchar*" "symbol")
+ )
+)
+
+(define-method create_audio_port
+ (of-object "ZynjackuPlugin")
+ (c-name "zynjacku_plugin_create_audio_port")
+ (return-type "gboolean")
+ (parameters
+ '("guint" "port_index")
+ '("const-gchar*" "symbol")
+ '("gboolean" "input")
+ )
+)
+
+(define-method create_float_parameter_port
+ (of-object "ZynjackuPlugin")
+ (c-name "zynjacku_plugin_create_float_parameter_port")
+ (return-type "gboolean")
+ (parameters
+ '("guint" "port_index")
+ '("const-gchar*" "symbol")
+ '("const-gchar*" "name")
+ '("gboolean" "msgcontext")
+ '("gboolean" "default_provided")
+ '("gfloat" "default_value")
+ '("gboolean" "min_provided")
+ '("gfloat" "min_value")
+ '("gboolean" "max_provided")
+ '("gfloat" "max_value")
+ )
+)
+
+(define-method create_float_measure_port
+ (of-object "ZynjackuPlugin")
+ (c-name "zynjacku_plugin_create_float_measure_port")
+ (return-type "gboolean")
+ (parameters
+ '("guint" "port_index")
+ '("const-gchar*" "symbol")
+ '("gboolean" "msgcontext")
+ )
+)
+
+(define-method create_string_parameter_port
+ (of-object "ZynjackuPlugin")
+ (c-name "zynjacku_plugin_create_string_parameter_port")
+ (return-type "gboolean")
+ (parameters
+ '("guint" "port_index")
+ '("const-gchar*" "symbol")
+ '("const-gchar*" "name")
+ '("gboolean" "msgcontext")
+ '("const-gchar*" "default_value")
+ '("gsize" "maxlen")
+ )
+)
+
;; From enum.h
@@ -455,3 +541,96 @@
)
+
+;; From lv2.h
+
+(define-function zynjacku_lv2_dman_get
+ (c-name "zynjacku_lv2_dman_get")
+ (return-type "char*")
+ (parameters
+ '("const-char*" "dlpath")
+ )
+)
+
+(define-function zynjacku_lv2_load
+ (c-name "zynjacku_lv2_load")
+ (return-type "zynjacku_lv2_handle")
+ (parameters
+ '("const-char*" "uri")
+ '("const-char*" "dlpath")
+ '("const-char*" "bundle_path")
+ '("double" "sample_rate")
+ '("const-LV2_Feature*-const*" "host_features")
+ )
+)
+
+(define-function zynjacku_lv2_unload
+ (c-name "zynjacku_lv2_unload")
+ (return-type "none")
+ (parameters
+ '("zynjacku_lv2_handle" "lv2handle")
+ )
+)
+
+(define-function zynjacku_lv2_connect_port
+ (c-name "zynjacku_lv2_connect_port")
+ (return-type "none")
+ (parameters
+ '("zynjacku_lv2_handle" "lv2handle")
+ '("struct-zynjacku_port*" "port")
+ '("void*" "data_location")
+ )
+)
+
+(define-function zynjacku_lv2_run
+ (c-name "zynjacku_lv2_run")
+ (return-type "none")
+ (parameters
+ '("zynjacku_lv2_handle" "lv2handle")
+ '("uint32_t" "sample_count")
+ )
+)
+
+(define-function zynjacku_lv2_activate
+ (c-name "zynjacku_lv2_activate")
+ (return-type "none")
+ (parameters
+ '("zynjacku_lv2_handle" "lv2handle")
+ )
+)
+
+(define-function zynjacku_lv2_deactivate
+ (c-name "zynjacku_lv2_deactivate")
+ (return-type "none")
+ (parameters
+ '("zynjacku_lv2_handle" "lv2handle")
+ )
+)
+
+(define-function zynjacku_lv2_get_descriptor
+ (c-name "zynjacku_lv2_get_descriptor")
+ (return-type "const-LV2_Descriptor*")
+ (parameters
+ '("zynjacku_lv2_handle" "lv2handle")
+ )
+)
+
+(define-function zynjacku_lv2_get_handle
+ (c-name "zynjacku_lv2_get_handle")
+ (return-type "LV2_Handle")
+ (parameters
+ '("zynjacku_lv2_handle" "lv2handle")
+ )
+)
+
+(define-function zynjacku_lv2_message
+ (c-name "zynjacku_lv2_message")
+ (return-type "none")
+ (parameters
+ '("zynjacku_lv2_handle" "lv2handle")
+ '("const-void*" "input_data")
+ '("void*" "output_data")
+ )
+)
+
+
diff --git a/zynjacku.h b/zynjacku.h
index ae2a525..bd65936 100644
--- a/zynjacku.h
+++ b/zynjacku.h
@@ -49,7 +49,6 @@
struct zynjacku_port
{
struct list_head plugin_siblings;
- struct list_head port_type_siblings;
unsigned int type; /* one of PORT_TYPE_XXX */
unsigned int flags; /* bitmask of PORT_FLAGS_XXX */
uint32_t index; /* LV2 port index within owning plugin, unused for dynparam ports */
@@ -60,7 +59,9 @@ struct zynjacku_port
struct
{
float value;
+ bool min_provided;
float min;
+ bool max_provided;
float max;
} lv2float; /* for PORT_TYPE_LV2_FLOAT */
struct _LV2_String_Data lv2string; /* for PORT_TYPE_LV2_STRING */
diff --git a/zynjacku.override b/zynjacku.override
index 001903c..b2f4ce2 100644
--- a/zynjacku.override
+++ b/zynjacku.override
@@ -11,6 +11,10 @@ headers
#include "enum.h"
#include "hints.h"
#include "midi_cc_map.h"
+
+char *
+zynjacku_lv2_dman_get(
+ const char * dlpath);
%%
modulename zynjacku_c
%%
diff --git a/zynjacku.py b/zynjacku.py
index 290b959..9472b71 100755
--- a/zynjacku.py
+++ b/zynjacku.py
@@ -29,10 +29,30 @@ import xml.dom.minidom
import cairo
from math import pi, sin, cos, atan2
from colorsys import hls_to_rgb, rgb_to_hls
+from distutils import sysconfig
old_path = sys.path
-sys.path.insert(0, "%s/.libs" % os.path.dirname(sys.argv[0]))
-import zynjacku_c as zynjacku
+
+inplace_libs = os.path.join(os.path.dirname(sys.argv[0]), ".libs")
+if os.access(inplace_libs, os.R_OK):
+ sys.path.append(inplace_libs)
+else:
+ inplace_libs = None
+
+try:
+ if inplace_libs:
+ import zynjacku_c as zynjacku
+ else:
+ from zynworld import zynjacku_c as zynjacku
+ from zynworld import lv2
+except Exception, e:
+ print "Failed to import zynjacku internal python modules"
+ print repr(e)
+ print "These directories were searched"
+ for path in sys.path:
+ print " " + path
+ sys.exit(1)
+
sys.path = old_path
try:
@@ -1396,13 +1416,18 @@ class PluginUI(gobject.GObject):
def show(self):
'''Show synth window'''
+ return False
def hide(self):
'''Hide synth window'''
class PluginUICustom(PluginUI):
- def __init__(self, plugin):
+ def __init__(self, plugin, ui_uri, ui_type_uri, ui_binary_path, ui_bundle_path):
PluginUI.__init__(self, plugin)
+ self.ui_uri = ui_uri
+ self.ui_type_uri = ui_type_uri
+ self.ui_binary_path = ui_binary_path
+ self.ui_bundle_path = ui_bundle_path
self.plugin.connect("custom-gui-off", self.on_window_destroy)
@@ -1412,7 +1437,7 @@ class PluginUICustom(PluginUI):
def show(self):
'''Show synth window'''
- return self.plugin.ui_on()
+ return self.plugin.ui_on(self.ui_uri, self.ui_type_uri, self.ui_binary_path, self.ui_bundle_path)
def hide(self):
'''Hide synth window'''
@@ -1536,6 +1561,7 @@ class PluginUIUniversal(PluginUI):
child.parent_group.child_param_add(child)
self.window.show_all()
+ return True
def hide(self):
'''Hide synth window'''
@@ -2168,6 +2194,37 @@ class host:
self.lash_client = lash_client
+ self.lv2features_supported = []
+ index = 0
+ while True:
+ feature = engine.get_supported_feature(index)
+ if not feature:
+ break
+ self.lv2features_supported.append(feature)
+ index += 1
+
+ self.available_plugins = []
+
+ lv2sources = []
+ cachedir = os.path.join(os.environ["HOME"], ".cache", preset_extension)
+ if not os.path.isdir(cachedir):
+ print 'Creating cache directory "%s"' % cachedir
+ os.makedirs(cachedir, 0755)
+
+ self.lv2_plugins_cache = os.path.join(cachedir, "plugins")
+ if os.path.isfile(self.lv2_plugins_cache):
+ print 'Loading LV2 plugin cache from "%s"' % self.lv2_plugins_cache
+ for line in file(self.lv2_plugins_cache):
+ source = line.strip()
+ if os.path.isfile(source) and os.access(source, os.R_OK):
+ lv2sources.append(source)
+ else:
+ print "Warning \"%s\" is not readble" % source
+ else:
+ file(self.lv2_plugins_cache, 'w')
+
+ self.lv2db = lv2.LV2DB(lv2sources)
+
def lash_check_events(self):
while lash.lash_get_pending_event_count(self.lash_client):
event = lash.lash_get_event(self.lash_client)
@@ -2199,11 +2256,30 @@ class host:
return True
def create_plugin_ui(self, plugin, data=None):
- if not self.plugin_ui_available(plugin):
- return False
+ info = self.lv2db.getPluginInfo(plugin.uri)
+
+ ui_binary_path = None
+
+ for ui_uri in info.ui:
+ ui = self.lv2db.get_ui_info(plugin.uri, ui_uri)
+ features_match = True
+ for required_feature in ui.requiredFeatures:
+ if required_feature == "http://lv2plug.in/ns/extensions/ui#makeResident":
+ continue
+ if not required_feature in self.lv2features_supported:
+ features_match = False
+
+ if not features_match:
+ print "Skipping UI %s because of missing required feature %s" % (ui_uri, required_feature)
+ break
- if plugin.supports_custom_ui():
- plugin.ui_win = PluginUICustom(plugin)
+ ui_type_uri = ui.type
+ ui_binary_path = ui.binary
+ break
+
+ if ui_binary_path:
+ ui_bundle_path = os.path.dirname(ui.binary) + '/'
+ plugin.ui_win = PluginUICustom(plugin, ui_uri, ui_type_uri, ui_binary_path, ui_bundle_path)
else:
plugin.ui_win = PluginUIUniversal(plugin, self.group_shadow_type, self.layout_type)
@@ -2213,12 +2289,98 @@ class host:
def on_plugin_ui_window_destroyed(self, window, plugin, data):
return
- def plugin_ui_available(self, plugin):
- return plugin.supports_custom_ui() or plugin.supports_generic_ui()
-
def new_plugin(self, uri, parameters=[], maps={}):
- plugin = zynjacku.Plugin(uri=uri)
- if not plugin.construct(self.engine):
+ info = self.lv2db.getPluginInfo(uri)
+ if not info:
+ print 'Cannot get info for plugin "%s"' % uri
+ return False
+
+ plugin = zynjacku.Plugin(
+ uri = uri,
+ name = info.name,
+ dlpath = info.binary,
+ bundle_path = os.path.dirname(info.binary) + '/')
+
+ for port in info.ports:
+ msgcontext = "http://lv2plug.in/ns/dev/contexts#MessageContext" in port.contexts
+
+ if port.isAudio and not msgcontext:
+ if not plugin.create_audio_port(port.index, port.symbol, not port.isOutput):
+ return False
+ elif port.isLarslMidi and port.isInput and not msgcontext:
+ if not plugin.create_oldmidi_input_port(port.index, port.symbol):
+ return False
+ elif port.isEvent and port.isInput and "http://lv2plug.in/ns/ext/midi#MidiEvent" in port.events and not msgcontext:
+ if not plugin.create_eventmidi_input_port(port.index, port.symbol):
+ return False
+ elif port.isControl:
+ if port.isInput:
+ default_provided = not port.defaultValue is None
+ if default_provided:
+ default_value = float(port.defaultValue)
+ else:
+ default_value = 0.0
+
+ min_provided = not port.minimum is None
+ if min_provided:
+ min_value = float(port.minimum);
+ else:
+ min_value = 0.0
+
+ max_provided = not port.maximum is None
+ if max_provided:
+ max_value = float(port.maximum)
+ else:
+ max_value = 1.0
+
+ if not plugin.create_float_parameter_port(
+ port.index,
+ port.symbol,
+ port.name,
+ msgcontext,
+ default_provided,
+ default_value,
+ min_provided,
+ min_value,
+ max_provided,
+ max_value):
+ return False
+ else:
+ if not plugin.create_float_measure_port(port.index, port.symbol, msgcontext):
+ return False
+ elif port.isString and port.isInput:
+ maxlen = 256 # TODO: get from lv2 (requiredSpace)
+
+ default_provided = port.__dict__.has_key('defaultValue')
+ if default_provided:
+ default_value = port.defaultValue
+ else:
+ default_value = ""
+
+ if not plugin.create_string_parameter_port(
+ port.index,
+ port.symbol,
+ port.name,
+ msgcontext,
+ default_value,
+ maxlen):
+ return False
+ else:
+ print "Port %s with not matched type" % port.symbol
+ if not "http://lv2plug.in/ns/lv2core#connectionOptional" in port.properties:
+ return False
+
+ # TODO: tell handle scale points somehow
+ #splist = port.scalePoints
+ #splist.sort(lambda x, y: cmp(x[1], y[1]))
+ #if len(splist):
+ # for sp in splist:
+ # print " Scale point %s: %s" % (sp[1], sp[0])
+
+ for feature in info.requiredFeatures + info.optionalFeatures:
+ plugin.add_supported_feature(feature)
+
+ if not self.engine.construct_plugin(plugin):
return False
for parameter in parameters:
@@ -2241,28 +2403,88 @@ class host:
def on_plugin_progress(self, engine, name, progress, message):
print "Loading plugin '%s', %5.1f%% complete. %s" % (name, progress, message)
- def on_plugin_repo_tick(self, repo, progress, uri, progressbar):
- if progress == 1.0:
- progressbar.hide()
- return
+ def check_plugin(self, plugin):
+ return False
+
+ def rescan_plugins(self, view, progressbar, force):
+ # detach from store to optimize speed
+ store = view.get_model()
+ view.set_model(None)
+ view.set_sensitive(False)
+
+ store.clear()
progressbar.show()
- progressbar.set_fraction(progress)
- progressbar.set_text("Checking %s" % uri);
- while gtk.events_pending():
- gtk.main_iteration()
- def on_plugin_repo_tack(self, repo, name, uri, plugin_license, author, store):
- #print "tack: %s %s %s" % (name, uri, plugin_license)
- store.append([name, uri, plugin_license, author])
+ if force:
+ self.lv2db = lv2.LV2DB()
+ self.available_plugins = []
- def rescan_plugins(self, store, progressbar, force):
- store.clear()
- tick = self.engine.connect("tick", self.on_plugin_repo_tick, progressbar)
- tack = self.engine.connect("tack", self.on_plugin_repo_tack, store)
- self.engine.iterate_plugins(force)
- self.engine.disconnect(tack)
- self.engine.disconnect(tick)
+ if self.available_plugins and not force:
+ for plugin in self.available_plugins:
+ store.append([plugin.name, plugin.uri, plugin.license_decoded, plugin.maintainers_string])
+ else:
+ lv2sources = set()
+ self.available_plugins = []
+
+ progressbar.set_text("Searching for LV2 plugins...");
+ progressbar.set_fraction(0.0)
+
+ plugins = self.lv2db.getPluginList()
+
+ step = 1.0 / len(plugins)
+ progress = 0.0
+
+ for uri in plugins:
+ progressbar.set_fraction(progress)
+ progressbar.set_text("Checking %s" % uri);
+ plugin = self.lv2db.getPluginInfo(uri)
+ if plugin == None:
+ continue
+
+ while gtk.events_pending():
+ gtk.main_iteration()
+
+ features_met = True
+ for feature in plugin.requiredFeatures:
+ if not feature in self.lv2features_supported:
+ features_met = False
+ break
+
+ if features_met and self.check_plugin(plugin):
+ plugin.maintainers_string = ""
+ for maintainer in plugin.maintainers:
+ if plugin.maintainers_string:
+ plugin.maintainers_string += "; "
+ plugin.maintainers_string += maintainer['name']
+ if not plugin.maintainers_string:
+ plugin.maintainers_string = "unknown"
+
+ license_map = {
+ "http://usefulinc.com/doap/licenses/gpl": "GNU General Public License",
+ "http://usefulinc.com/doap/licenses/lgpl":"GNU Lesser General Public License",
+ }
+ if license_map.has_key(plugin.license):
+ plugin.license_decoded = license_map[plugin.license]
+ else:
+ plugin.license_decoded = plugin.license
+
+ self.available_plugins.append(plugin)
+ store.append([plugin.name, plugin.uri, plugin.license_decoded, plugin.maintainers_string])
+ for source in plugin.sources:
+ lv2sources.add(source)
+
+ progress += step
+
+ if lv2sources and os.path.isfile(self.lv2_plugins_cache):
+ cachefile = file(self.lv2_plugins_cache, 'w')
+ for source in lv2sources:
+ cachefile.write(source + "\n")
+
+ progressbar.hide()
+
+ view.set_sensitive(True)
+ view.set_model(store)
def plugins_load(self, title="LV2 plugins"):
dialog = self.glade_xml.get_widget("zynjacku_plugin_repo")
@@ -2271,33 +2493,37 @@ class host:
dialog.set_title(title)
- plugin_repo_widget.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
+ store = plugin_repo_widget.get_model()
+ if not store:
+ plugin_repo_widget.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
- store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
- text_renderer = gtk.CellRendererText()
+ store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
+ text_renderer = gtk.CellRendererText()
+
+ column_name = gtk.TreeViewColumn("Name", text_renderer, text=0)
+ column_uri = gtk.TreeViewColumn("URI", text_renderer, text=1)
+ column_license = gtk.TreeViewColumn("License", text_renderer, text=2)
+ column_author = gtk.TreeViewColumn("Author", text_renderer, text=3)
- column_name = gtk.TreeViewColumn("Name", text_renderer, text=0)
- column_uri = gtk.TreeViewColumn("URI", text_renderer, text=1)
- column_license = gtk.TreeViewColumn("License", text_renderer, text=2)
- column_author = gtk.TreeViewColumn("Author", text_renderer, text=3)
+ column_name.set_sort_column_id(0)
+ column_uri.set_sort_column_id(1)
+ column_license.set_sort_column_id(2)
+ column_author.set_sort_column_id(3)
- column_name.set_sort_column_id(0)
- column_uri.set_sort_column_id(1)
- column_license.set_sort_column_id(2)
- column_author.set_sort_column_id(3)
+ plugin_repo_widget.append_column(column_name)
+ plugin_repo_widget.append_column(column_uri)
+ plugin_repo_widget.append_column(column_license)
+ plugin_repo_widget.append_column(column_author)
- plugin_repo_widget.append_column(column_name)
- plugin_repo_widget.append_column(column_uri)
- plugin_repo_widget.append_column(column_license)
- plugin_repo_widget.append_column(column_author)
+ store.set_sort_column_id(0, gtk.SORT_ASCENDING)
- plugin_repo_widget.set_model(store)
- def on_row_activated(widget, path, column):
- dialog.response(0)
- plugin_repo_widget.connect("row-activated", on_row_activated)
+ plugin_repo_widget.set_model(store)
+ def on_row_activated(widget, path, column):
+ dialog.response(0)
+ plugin_repo_widget.connect("row-activated", on_row_activated)
dialog.show()
- self.rescan_plugins(store, progressbar, False)
+ self.rescan_plugins(plugin_repo_widget, progressbar, False)
while True:
ret = dialog.run()
if ret == 0:
@@ -2307,7 +2533,7 @@ class host:
self.progress_window.hide()
return
elif ret == 1:
- self.rescan_plugins(store, progressbar, True)
+ self.rescan_plugins(plugin_repo_widget, progressbar, True)
else:
dialog.hide()
return
@@ -2497,11 +2723,7 @@ class host:
self.engine.ui_run()
return True
- def run(self):
- ui_run_callback_id = gobject.timeout_add(40, self.ui_run)
-
- gtk.main()
- gobject.source_remove(ui_run_callback_id)
+ def run_done(self):
if self.lash_client:
#print "removing lash handler, host object refcount is %u" % sys.getrefcount(self)
gobject.source_remove(self.lash_check_events_callback_id)
@@ -2513,6 +2735,12 @@ class host:
self.engine.disconnect(self.progress_connect_id)
+ def run(self):
+ ui_run_callback_id = gobject.timeout_add(40, self.ui_run)
+ gtk.main()
+ gobject.source_remove(ui_run_callback_id)
+ self.run_done()
+
def on_test(self, obj1, obj2):
print "on_test() called !!!!!!!!!!!!!!!!!!"
print repr(obj1)
@@ -2524,20 +2752,39 @@ class ZynjackuHost(host):
host.__init__(self, zynjacku.Engine(), client_name, preset_extension, preset_name, lash_client)
+def run_about_dialog(transient_for, program_data):
+ about = gtk.AboutDialog()
+ about.set_transient_for(transient_for)
+ about.set_name(program_data['name'])
+ if program_data.has_key('comments'):
+ about.set_name(program_data['comments'])
+ if program_data.has_key('version'):
+ about.set_version(program_data['version'])
+ about.set_license(program_data['license'])
+ about.set_website(program_data['website'])
+ about.set_authors(program_data['authors'])
+ if program_data.has_key('artists'):
+ about.set_artists(program_data['artists'])
+ if program_data.has_key('logo'):
+ about.set_logo(gtk.gdk.pixbuf_new_from_file(program_data['logo']))
+ about.show()
+ about.run()
+ about.hide()
+
class ZynjackuHostMulti(ZynjackuHost):
- def __init__(self, data_dir, glade_xml, client_name, the_license, uris, lash_client):
+ def __init__(self, program_data, client_name, uris, lash_client):
#print "ZynjackuHostMulti constructor called."
ZynjackuHost.__init__(self, client_name, "zynjacku", "synth stack", lash_client)
- self.data_dir = data_dir
- self.glade_xml = glade_xml
+ self.program_data = program_data
+ self.glade_xml = program_data['glade_xml']
- self.main_window = glade_xml.get_widget("zynjacku_main")
+ self.main_window = self.glade_xml.get_widget("zynjacku_main")
self.main_window.set_title(client_name)
self.statusbar = self.glade_xml.get_widget("statusbar")
- self.hbox_menubar = glade_xml.get_widget("hbox_menubar")
+ self.hbox_menubar = self.glade_xml.get_widget("hbox_menubar")
self.midi_led = midi_led()
self.midi_led_frame = gtk.Frame()
self.midi_led_frame.set_shadow_type(gtk.SHADOW_OUT)
@@ -2555,17 +2802,21 @@ class ZynjackuHostMulti(ZynjackuHost):
self.signal_ids = []
for k, v in dic.items():
- w = glade_xml.get_widget(k)
+ w = self.glade_xml.get_widget(k)
if not w:
print "failed to get glade widget '%s'" % k
continue
self.signal_ids.append([w, w.connect("activate", v)])
- self.the_license = the_license
+ self.synths_widget = self.glade_xml.get_widget("treeview_synths")
- self.synths_widget = glade_xml.get_widget("treeview_synths")
+ self.store = gtk.ListStore(
+ gobject.TYPE_BOOLEAN, # UI visible
+ gobject.TYPE_STRING, # Instance name
+ gobject.TYPE_STRING, # Plugin name
+ gobject.TYPE_STRING, # Plugin URI
+ gobject.TYPE_PYOBJECT) # Plugin object
- self.store = gtk.ListStore(gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
text_renderer = gtk.CellRendererText()
self.toggle_renderer = gtk.CellRendererToggle()
self.toggle_renderer.set_property('activatable', True)
@@ -2620,6 +2871,68 @@ class ZynjackuHostMulti(ZynjackuHost):
self.midi_led.set(self.engine.get_midi_activity())
return True
+ def check_plugin(self, plugin):
+ ports_count = len(plugin.ports)
+ audio_in_ports_count = 0
+ audio_out_ports_count = 0
+ midi_in_ports_count = 0
+ control_ports_count = 0
+ string_ports_count = 0
+ event_ports_count = 0
+ midi_event_in_ports_count = 0
+
+ for port in plugin.ports:
+ if port.isAudio:
+ if port.isInput:
+ audio_in_ports_count += 1
+ continue
+ if port.isOutput:
+ audio_out_ports_count += 1
+ continue
+ continue
+ if port.isLarslMidi:
+ if port.isInput:
+ midi_in_ports_count += 1
+ continue
+ continue
+ if port.isEvent:
+ event_ports_count += 1
+ if port.isInput and "http://lv2plug.in/ns/ext/midi#MidiEvent" in port.events:
+ midi_event_in_ports_count += 1
+ continue
+ continue
+ if port.isControl:
+ control_ports_count += 1
+ continue
+ if port.isString:
+ string_ports_count += 1
+ continue
+
+ # TODO: we must be smarter and check for "optional connect" property
+ if (midi_in_ports_count + control_ports_count + string_ports_count + event_ports_count + audio_out_ports_count != ports_count) or \
+ (midi_in_ports_count + midi_event_in_ports_count != 1) or \
+ (audio_out_ports_count == 0):
+ #print "Skipping %s (%s), [synth] plugin with unsupported port configuration" % (plugin.name, plugin.uri)
+ #print " midi input ports: %d" % midi_in_ports_count
+ #print " control ports: %d" % control_ports_count
+ #print " string ports: %d" % string_ports_count
+ #print " event ports: %d" % event_ports_count
+ #print " event midi input ports: %d" % midi_event_in_ports_count
+ #print " audio input ports: %d" % audio_in_ports_count
+ #print " audio output ports: %d" % audio_out_ports_count
+ #print " total ports %d" % ports_count
+ return False
+
+# print "Found \"simple\" synth plugin '%s' %s" % (plugin.name, plugin.uri)
+# print " midi input ports: %d" % midi_in_ports_count
+# print " control ports: %d" % control_ports_count
+# print " event ports: %d" % event_ports_count
+# print " event midi input ports: %d" % midi_event_in_ports_count
+# print " audio input ports: %d" % audio_in_ports_count
+# print " audio output ports: %d" % audio_out_ports_count
+# print " total ports %d" % ports_count
+ return True
+
def load_plugin(self, uri, parameters=[], maps={}):
statusbar_context_id = self.statusbar.get_context_id("loading plugin")
statusbar_id = self.statusbar.push(statusbar_context_id, "Loading %s" % uri)
@@ -2630,7 +2943,7 @@ class ZynjackuHostMulti(ZynjackuHost):
if not synth:
self.statusbar.push(statusbar_context_id, "Failed to construct %s" % uri)
else:
- row = False, synth.get_instance_name(), synth.get_name(), synth.get_uri(), synth
+ row = False, synth.get_instance_name(), synth.get_name(), synth.uri, synth
self.store.append(row)
self.statusbar.remove(statusbar_context_id, statusbar_id)
@@ -2664,24 +2977,10 @@ class ZynjackuHostMulti(ZynjackuHost):
if model[path][4].ui_win.show():
model[path][0] = True
else:
- self.statusbar.push(statusbar_context_id, "Failed to construct show synth UI")
+ self.statusbar.push(statusbar_context_id, "Failed to show synth UI")
def on_about(self, widget):
- about = gtk.AboutDialog()
- about.set_transient_for(self.main_window)
- about.set_name("zynjacku")
- if zynjacku.zynjacku_get_version() == "dev":
- about.set_comments("(development snapshot)")
- else:
- about.set_version(zynjacku.zynjacku_get_version())
- about.set_license(self.the_license)
- about.set_website("http://home.gna.org/zynjacku/")
- about.set_authors(["Nedko Arnaudov"])
- about.set_artists(["Thorsten Wilms"])
- about.set_logo(gtk.gdk.pixbuf_new_from_file("%s/logo.png" % self.data_dir))
- about.show()
- about.run()
- about.hide()
+ run_about_dialog(self.main_window, self.program_data)
def on_preset_load(self, widget):
self.preset_load_ask()
@@ -2703,23 +3002,19 @@ class ZynjackuHostMulti(ZynjackuHost):
self.plugins_load("LV2 synth plugins")
def on_synth_clear(self, widget):
- self.store.clear();
+ self.store.clear()
self.clear_plugins()
class ZynjackuHostOne(ZynjackuHost):
- def __init__(self, glade_xml, client_name, uri):
+ def __init__(self, program_data, client_name, uri):
#print "ZynjackuHostOne constructor called."
- ZynjackuHost.__init__(self, client_name)
+ ZynjackuHost.__init__(self, client_name, "zynjacku")
self.plugin = self.new_plugin(uri)
if not self.plugin:
print"Failed to construct %s" % uri
return
- if not ZynjackuHost.plugin_ui_available(self, self.plugin):
- print"Synth window not available"
- return
-
if not ZynjackuHost.create_plugin_ui(self, self.plugin):
print"Failed to create synth window"
return
@@ -2738,6 +3033,7 @@ class ZynjackuHostOne(ZynjackuHost):
def run(self):
if not self.plugin:
+ self.run_done()
return
self.plugin.ui_win.show()
@@ -2748,7 +3044,15 @@ class ZynjackuHostOne(ZynjackuHost):
ZynjackuHost.__del__(self)
-def file_setup():
+def get_program_data(program_name):
+ program_data = {}
+
+ program_data['name'] = program_name
+ if zynjacku.zynjacku_get_version() == "dev":
+ program_data['comments'] = "(development snapshot)"
+ else:
+ program_data['version'] = zynjacku.zynjacku_get_version()
+
data_dir = os.path.dirname(sys.argv[0])
# since ppl tend to run "python zynjacku.py", lets assume that it is in current directory
@@ -2761,15 +3065,37 @@ def file_setup():
if not os.path.isfile(glade_file):
data_dir = data_dir + os.sep + ".." + os.sep + "share"+ os.sep + "zynjacku"
glade_file = data_dir + os.sep + "zynjacku.glade"
+ logo_dir = data_dir
+ else:
+ logo_dir = data_dir + os.sep + 'art' + os.sep + 'logo'
#print 'data dir is "%s"' % data_dir
#print 'Loading glade from "%s"' % glade_file
- the_license = file(data_dir + os.sep + "gpl.txt").read()
+ program_data['license'] = file(data_dir + os.sep + "gpl.txt").read()
+
+ program_data['glade_xml'] = gtk.glade.XML(glade_file)
+
+
+ program_data['website'] = "http://home.gna.org/zynjacku/"
+
+ program_data['authors'] = [
+ "Nedko Arnaudov",
+ "Krzysztof Foltman",
+ "Stefano D'Angelo",
+ ]
+
+ program_data['logo'] = "%s/logo.png" % logo_dir
+ program_data['artists'] = [
+ "Thorsten Wilms",
+ "Lapo Calamandrei",
+ ]
- glade_xml = gtk.glade.XML(glade_file)
+ if program_name != 'zynjacku':
+ del program_data['artists']
+ del program_data['logo']
- return data_dir, glade_xml, the_license
+ return program_data
def register_types():
gobject.signal_new("zynjacku-parameter-changed", PluginUIUniversalParameter, gobject.SIGNAL_RUN_FIRST | gobject.SIGNAL_ACTION, gobject.TYPE_NONE, [])
@@ -2781,7 +3107,7 @@ def register_types():
gobject.type_register(PluginUIUniversalParameterBool)
def main():
- data_dir, glade_xml, the_license = file_setup()
+ program_data = get_program_data('zynjacku')
register_types()
@@ -2801,9 +3127,9 @@ def main():
print "Successfully connected to LASH server at " + lash.lash_get_server_name(lash_client)
if len(sys.argv) == 2 and sys.argv[1][-9:] != ".zynjacku":
- host = ZynjackuHostOne(glade_xml, client_name, sys.argv[1])
+ host = ZynjackuHostOne(program_data, client_name, sys.argv[1])
else:
- host = ZynjackuHostMulti(data_dir, glade_xml, client_name, the_license, sys.argv[1:], lash_client)
+ host = ZynjackuHostMulti(program_data, client_name, sys.argv[1:], lash_client)
host.run()
diff --git a/zynjacku_ttl.c b/zynjacku_ttl.c
new file mode 100644
index 0000000..e9e82e4
--- /dev/null
+++ b/zynjacku_ttl.c
@@ -0,0 +1,50 @@
+#include <Python.h>
+#include "flex_ttl.h"
+#include "ttl_lexer.h"
+
+//////////////////////////////////////////////////// calfpytools
+
+static PyObject * scan_file(PyObject *self, PyObject *args)
+{
+ char *ttl_name = NULL;
+ PyObject *tmp = NULL;
+ yyscan_t scanner;
+ if (!PyArg_ParseTuple(args, "s:scan_file", &ttl_name))
+ return NULL;
+
+ tmp = ttl_list = PyList_New(0);
+ yylex_init(&scanner);
+ yyset_in(fopen(ttl_name, "r"), scanner);
+ yylex(scanner);
+ yylex_destroy(scanner);
+ ttl_list = NULL;
+ return tmp;
+}
+
+static PyObject * scan_string(PyObject *self, PyObject *args)
+{
+ char *ttl_text = NULL;
+ PyObject *tmp = NULL;
+ yyscan_t scanner;
+ if (!PyArg_ParseTuple(args, "s:scan_string", &ttl_text))
+ return NULL;
+
+ tmp = ttl_list = PyList_New(0);
+ yylex_init(&scanner);
+ yyset_in(fmemopen(ttl_text, strlen(ttl_text), "r"), scanner);
+ yylex(scanner);
+ yylex_destroy(scanner);
+ ttl_list = NULL;
+ return tmp;
+}
+
+static PyMethodDef module_methods[] = {
+ {"scan_file", scan_file, METH_VARARGS, "Scan a TTL file, return a list of token tuples"},
+ {"scan_string", scan_string, METH_VARARGS, "Scan a string, return a list of token tuples"},
+ {NULL, NULL, 0, NULL}
+};
+
+PyMODINIT_FUNC initzynjacku_ttl()
+{
+ Py_InitModule3("zynjacku_ttl", module_methods, "Flex Turtle parser");
+}
diff --git a/zynjacku_wrap.c b/zynjacku_wrap.c
index 0767bb0..aaa5963 100644
--- a/zynjacku_wrap.c
+++ b/zynjacku_wrap.c
@@ -15,7 +15,11 @@
#include "enum.h"
#include "hints.h"
#include "midi_cc_map.h"
-#line 19 "zynjacku.c"
+
+char *
+zynjacku_lv2_dman_get(
+ const char * dlpath);
+#line 23 "zynjacku.c"
/* ---------- types from other modules ---------- */
@@ -31,7 +35,7 @@ PyTypeObject G_GNUC_INTERNAL PyZynjackuMidiCcMap_Type;
PyTypeObject G_GNUC_INTERNAL PyZynjackuPlugin_Type;
PyTypeObject G_GNUC_INTERNAL PyZynjackuRack_Type;
-#line 35 "zynjacku.c"
+#line 39 "zynjacku.c"
@@ -97,20 +101,50 @@ _wrap_zynjacku_engine_get_midi_activity(PyGObject *self)
}
static PyObject *
-_wrap_zynjacku_engine_iterate_plugins(PyGObject *self, PyObject *args, PyObject *kwargs)
+_wrap_zynjacku_engine_get_supported_feature(PyGObject *self, PyObject *args, PyObject *kwargs)
{
- static char *kwlist[] = { "force", NULL };
- int force;
+ static char *kwlist[] = { "index", NULL };
+ PyObject *py_index = NULL;
+ const gchar *ret;
+ guint index = 0;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,"i:ZynjackuEngine.iterate_plugins", kwlist, &force))
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O:ZynjackuEngine.get_supported_feature", kwlist, &py_index))
return NULL;
+ if (py_index) {
+ if (PyLong_Check(py_index))
+ index = PyLong_AsUnsignedLong(py_index);
+ else if (PyInt_Check(py_index))
+ index = PyInt_AsLong(py_index);
+ else
+ PyErr_SetString(PyExc_TypeError, "Parameter 'index' must be an int or a long");
+ if (PyErr_Occurred())
+ return NULL;
+ }
- zynjacku_engine_iterate_plugins(ZYNJACKU_ENGINE(self->obj), force);
+ ret = zynjacku_engine_get_supported_feature(ZYNJACKU_ENGINE(self->obj), index);
+ if (ret)
+ return PyString_FromString(ret);
Py_INCREF(Py_None);
return Py_None;
}
+static PyObject *
+_wrap_zynjacku_engine_construct_plugin(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "plugin_obj_ptr", NULL };
+ PyGObject *plugin_obj_ptr;
+ int ret;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:ZynjackuEngine.construct_plugin", kwlist, &PyZynjackuPlugin_Type, &plugin_obj_ptr))
+ return NULL;
+
+ ret = zynjacku_engine_construct_plugin(ZYNJACKU_ENGINE(self->obj), ZYNJACKU_PLUGIN(plugin_obj_ptr->obj));
+
+ return PyBool_FromLong(ret);
+
+}
+
static const PyMethodDef _PyZynjackuEngine_methods[] = {
{ "start_jack", (PyCFunction)_wrap_zynjacku_engine_start_jack, METH_VARARGS|METH_KEYWORDS,
NULL },
@@ -122,7 +156,9 @@ static const PyMethodDef _PyZynjackuEngine_methods[] = {
NULL },
{ "get_midi_activity", (PyCFunction)_wrap_zynjacku_engine_get_midi_activity, METH_NOARGS,
NULL },
- { "iterate_plugins", (PyCFunction)_wrap_zynjacku_engine_iterate_plugins, METH_VARARGS|METH_KEYWORDS,
+ { "get_supported_feature", (PyCFunction)_wrap_zynjacku_engine_get_supported_feature, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "construct_plugin", (PyCFunction)_wrap_zynjacku_engine_construct_plugin, METH_VARARGS|METH_KEYWORDS,
NULL },
{ NULL, NULL, 0, NULL }
};
@@ -633,22 +669,6 @@ PyTypeObject G_GNUC_INTERNAL PyZynjackuMidiCcMap_Type = {
/* ----------- ZynjackuPlugin ----------- */
static PyObject *
-_wrap_zynjacku_plugin_construct(PyGObject *self, PyObject *args, PyObject *kwargs)
-{
- static char *kwlist[] = { "engine_obj_ptr", NULL };
- PyGObject *engine_obj_ptr;
- int ret;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:ZynjackuPlugin.construct", kwlist, &PyGObject_Type, &engine_obj_ptr))
- return NULL;
-
- ret = zynjacku_plugin_construct(ZYNJACKU_PLUGIN(self->obj), G_OBJECT(engine_obj_ptr->obj));
-
- return PyBool_FromLong(ret);
-
-}
-
-static PyObject *
_wrap_zynjacku_plugin_destruct(PyGObject *self)
{
@@ -659,30 +679,6 @@ _wrap_zynjacku_plugin_destruct(PyGObject *self)
}
static PyObject *
-_wrap_zynjacku_plugin_supports_generic_ui(PyGObject *self)
-{
- int ret;
-
-
- ret = zynjacku_plugin_supports_generic_ui(ZYNJACKU_PLUGIN(self->obj));
-
- return PyBool_FromLong(ret);
-
-}
-
-static PyObject *
-_wrap_zynjacku_plugin_supports_custom_ui(PyGObject *self)
-{
- int ret;
-
-
- ret = zynjacku_plugin_supports_custom_ui(ZYNJACKU_PLUGIN(self->obj));
-
- return PyBool_FromLong(ret);
-
-}
-
-static PyObject *
_wrap_zynjacku_plugin_get_instance_name(PyGObject *self)
{
const gchar *ret;
@@ -725,12 +721,16 @@ _wrap_zynjacku_plugin_get_uri(PyGObject *self)
}
static PyObject *
-_wrap_zynjacku_plugin_ui_on(PyGObject *self)
+_wrap_zynjacku_plugin_ui_on(PyGObject *self, PyObject *args, PyObject *kwargs)
{
+ static char *kwlist[] = { "ui_uri", "ui_type_uri", "ui_binary_path", "ui_bundle_path", NULL };
+ char *ui_uri = NULL, *ui_type_uri = NULL, *ui_binary_path = NULL, *ui_bundle_path = NULL;
int ret;
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"|zzzz:ZynjackuPlugin.ui_on", kwlist, &ui_uri, &ui_type_uri, &ui_binary_path, &ui_bundle_path))
+ return NULL;
- ret = zynjacku_plugin_ui_on(ZYNJACKU_PLUGIN(self->obj));
+ ret = zynjacku_plugin_ui_on(ZYNJACKU_PLUGIN(self->obj), ui_uri, ui_type_uri, ui_binary_path, ui_bundle_path);
return PyBool_FromLong(ret);
@@ -897,22 +897,201 @@ _wrap_zynjacku_plugin_set_midi_cc_map(PyGObject *self, PyObject *args, PyObject
}
+static PyObject *
+_wrap_zynjacku_plugin_add_supported_feature(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "feature_uri", NULL };
+ char *feature_uri;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"s:ZynjackuPlugin.add_supported_feature", kwlist, &feature_uri))
+ return NULL;
+
+ zynjacku_plugin_add_supported_feature(ZYNJACKU_PLUGIN(self->obj), feature_uri);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+_wrap_zynjacku_plugin_create_oldmidi_input_port(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "port_index", "symbol", NULL };
+ PyObject *py_port_index = NULL;
+ char *symbol;
+ int ret;
+ guint port_index = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"Os:ZynjackuPlugin.create_oldmidi_input_port", kwlist, &py_port_index, &symbol))
+ return NULL;
+ if (py_port_index) {
+ if (PyLong_Check(py_port_index))
+ port_index = PyLong_AsUnsignedLong(py_port_index);
+ else if (PyInt_Check(py_port_index))
+ port_index = PyInt_AsLong(py_port_index);
+ else
+ PyErr_SetString(PyExc_TypeError, "Parameter 'port_index' must be an int or a long");
+ if (PyErr_Occurred())
+ return NULL;
+ }
+
+ ret = zynjacku_plugin_create_oldmidi_input_port(ZYNJACKU_PLUGIN(self->obj), port_index, symbol);
+
+ return PyBool_FromLong(ret);
+
+}
+
+static PyObject *
+_wrap_zynjacku_plugin_create_eventmidi_input_port(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "port_index", "symbol", NULL };
+ PyObject *py_port_index = NULL;
+ char *symbol;
+ int ret;
+ guint port_index = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"Os:ZynjackuPlugin.create_eventmidi_input_port", kwlist, &py_port_index, &symbol))
+ return NULL;
+ if (py_port_index) {
+ if (PyLong_Check(py_port_index))
+ port_index = PyLong_AsUnsignedLong(py_port_index);
+ else if (PyInt_Check(py_port_index))
+ port_index = PyInt_AsLong(py_port_index);
+ else
+ PyErr_SetString(PyExc_TypeError, "Parameter 'port_index' must be an int or a long");
+ if (PyErr_Occurred())
+ return NULL;
+ }
+
+ ret = zynjacku_plugin_create_eventmidi_input_port(ZYNJACKU_PLUGIN(self->obj), port_index, symbol);
+
+ return PyBool_FromLong(ret);
+
+}
+
+static PyObject *
+_wrap_zynjacku_plugin_create_audio_port(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "port_index", "symbol", "input", NULL };
+ PyObject *py_port_index = NULL;
+ char *symbol;
+ int input, ret;
+ guint port_index = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"Osi:ZynjackuPlugin.create_audio_port", kwlist, &py_port_index, &symbol, &input))
+ return NULL;
+ if (py_port_index) {
+ if (PyLong_Check(py_port_index))
+ port_index = PyLong_AsUnsignedLong(py_port_index);
+ else if (PyInt_Check(py_port_index))
+ port_index = PyInt_AsLong(py_port_index);
+ else
+ PyErr_SetString(PyExc_TypeError, "Parameter 'port_index' must be an int or a long");
+ if (PyErr_Occurred())
+ return NULL;
+ }
+
+ ret = zynjacku_plugin_create_audio_port(ZYNJACKU_PLUGIN(self->obj), port_index, symbol, input);
+
+ return PyBool_FromLong(ret);
+
+}
+
+static PyObject *
+_wrap_zynjacku_plugin_create_float_parameter_port(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "port_index", "symbol", "name", "msgcontext", "default_provided", "default_value", "min_provided", "min_value", "max_provided", "max_value", NULL };
+ PyObject *py_port_index = NULL;
+ char *symbol, *name;
+ int msgcontext, default_provided, min_provided, max_provided, ret;
+ guint port_index = 0;
+ double default_value, min_value, max_value;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"Ossiididid:ZynjackuPlugin.create_float_parameter_port", kwlist, &py_port_index, &symbol, &name, &msgcontext, &default_provided, &default_value, &min_provided, &min_value, &max_provided, &max_value))
+ return NULL;
+ if (py_port_index) {
+ if (PyLong_Check(py_port_index))
+ port_index = PyLong_AsUnsignedLong(py_port_index);
+ else if (PyInt_Check(py_port_index))
+ port_index = PyInt_AsLong(py_port_index);
+ else
+ PyErr_SetString(PyExc_TypeError, "Parameter 'port_index' must be an int or a long");
+ if (PyErr_Occurred())
+ return NULL;
+ }
+
+ ret = zynjacku_plugin_create_float_parameter_port(ZYNJACKU_PLUGIN(self->obj), port_index, symbol, name, msgcontext, default_provided, default_value, min_provided, min_value, max_provided, max_value);
+
+ return PyBool_FromLong(ret);
+
+}
+
+static PyObject *
+_wrap_zynjacku_plugin_create_float_measure_port(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "port_index", "symbol", "msgcontext", NULL };
+ PyObject *py_port_index = NULL;
+ char *symbol;
+ int msgcontext, ret;
+ guint port_index = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"Osi:ZynjackuPlugin.create_float_measure_port", kwlist, &py_port_index, &symbol, &msgcontext))
+ return NULL;
+ if (py_port_index) {
+ if (PyLong_Check(py_port_index))
+ port_index = PyLong_AsUnsignedLong(py_port_index);
+ else if (PyInt_Check(py_port_index))
+ port_index = PyInt_AsLong(py_port_index);
+ else
+ PyErr_SetString(PyExc_TypeError, "Parameter 'port_index' must be an int or a long");
+ if (PyErr_Occurred())
+ return NULL;
+ }
+
+ ret = zynjacku_plugin_create_float_measure_port(ZYNJACKU_PLUGIN(self->obj), port_index, symbol, msgcontext);
+
+ return PyBool_FromLong(ret);
+
+}
+
+static PyObject *
+_wrap_zynjacku_plugin_create_string_parameter_port(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "port_index", "symbol", "name", "msgcontext", "default_value", "maxlen", NULL };
+ PyObject *py_port_index = NULL;
+ char *symbol, *name, *default_value;
+ int msgcontext, ret;
+ guint port_index = 0;
+ gsize maxlen;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"Ossisk:ZynjackuPlugin.create_string_parameter_port", kwlist, &py_port_index, &symbol, &name, &msgcontext, &default_value, &maxlen))
+ return NULL;
+ if (py_port_index) {
+ if (PyLong_Check(py_port_index))
+ port_index = PyLong_AsUnsignedLong(py_port_index);
+ else if (PyInt_Check(py_port_index))
+ port_index = PyInt_AsLong(py_port_index);
+ else
+ PyErr_SetString(PyExc_TypeError, "Parameter 'port_index' must be an int or a long");
+ if (PyErr_Occurred())
+ return NULL;
+ }
+
+ ret = zynjacku_plugin_create_string_parameter_port(ZYNJACKU_PLUGIN(self->obj), port_index, symbol, name, msgcontext, default_value, maxlen);
+
+ return PyBool_FromLong(ret);
+
+}
+
static const PyMethodDef _PyZynjackuPlugin_methods[] = {
- { "construct", (PyCFunction)_wrap_zynjacku_plugin_construct, METH_VARARGS|METH_KEYWORDS,
- NULL },
{ "destruct", (PyCFunction)_wrap_zynjacku_plugin_destruct, METH_NOARGS,
NULL },
- { "supports_generic_ui", (PyCFunction)_wrap_zynjacku_plugin_supports_generic_ui, METH_NOARGS,
- NULL },
- { "supports_custom_ui", (PyCFunction)_wrap_zynjacku_plugin_supports_custom_ui, METH_NOARGS,
- NULL },
{ "get_instance_name", (PyCFunction)_wrap_zynjacku_plugin_get_instance_name, METH_NOARGS,
NULL },
{ "get_name", (PyCFunction)_wrap_zynjacku_plugin_get_name, METH_NOARGS,
NULL },
{ "get_uri", (PyCFunction)_wrap_zynjacku_plugin_get_uri, METH_NOARGS,
NULL },
- { "ui_on", (PyCFunction)_wrap_zynjacku_plugin_ui_on, METH_NOARGS,
+ { "ui_on", (PyCFunction)_wrap_zynjacku_plugin_ui_on, METH_VARARGS|METH_KEYWORDS,
NULL },
{ "ui_off", (PyCFunction)_wrap_zynjacku_plugin_ui_off, METH_NOARGS,
NULL },
@@ -932,6 +1111,20 @@ static const PyMethodDef _PyZynjackuPlugin_methods[] = {
NULL },
{ "set_midi_cc_map", (PyCFunction)_wrap_zynjacku_plugin_set_midi_cc_map, METH_VARARGS|METH_KEYWORDS,
NULL },
+ { "add_supported_feature", (PyCFunction)_wrap_zynjacku_plugin_add_supported_feature, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "create_oldmidi_input_port", (PyCFunction)_wrap_zynjacku_plugin_create_oldmidi_input_port, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "create_eventmidi_input_port", (PyCFunction)_wrap_zynjacku_plugin_create_eventmidi_input_port, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "create_audio_port", (PyCFunction)_wrap_zynjacku_plugin_create_audio_port, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "create_float_parameter_port", (PyCFunction)_wrap_zynjacku_plugin_create_float_parameter_port, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "create_float_measure_port", (PyCFunction)_wrap_zynjacku_plugin_create_float_measure_port, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "create_string_parameter_port", (PyCFunction)_wrap_zynjacku_plugin_create_string_parameter_port, METH_VARARGS|METH_KEYWORDS,
+ NULL },
{ NULL, NULL, 0, NULL }
};
@@ -1032,20 +1225,50 @@ _wrap_zynjacku_rack_ui_run(PyGObject *self)
}
static PyObject *
-_wrap_zynjacku_rack_iterate_plugins(PyGObject *self, PyObject *args, PyObject *kwargs)
+_wrap_zynjacku_rack_get_supported_feature(PyGObject *self, PyObject *args, PyObject *kwargs)
{
- static char *kwlist[] = { "force", NULL };
- int force;
+ static char *kwlist[] = { "index", NULL };
+ PyObject *py_index = NULL;
+ const gchar *ret;
+ guint index = 0;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,"i:ZynjackuRack.iterate_plugins", kwlist, &force))
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O:ZynjackuRack.get_supported_feature", kwlist, &py_index))
return NULL;
+ if (py_index) {
+ if (PyLong_Check(py_index))
+ index = PyLong_AsUnsignedLong(py_index);
+ else if (PyInt_Check(py_index))
+ index = PyInt_AsLong(py_index);
+ else
+ PyErr_SetString(PyExc_TypeError, "Parameter 'index' must be an int or a long");
+ if (PyErr_Occurred())
+ return NULL;
+ }
- zynjacku_rack_iterate_plugins(ZYNJACKU_RACK(self->obj), force);
+ ret = zynjacku_rack_get_supported_feature(ZYNJACKU_RACK(self->obj), index);
+ if (ret)
+ return PyString_FromString(ret);
Py_INCREF(Py_None);
return Py_None;
}
+static PyObject *
+_wrap_zynjacku_rack_construct_plugin(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "plugin_obj_ptr", NULL };
+ PyGObject *plugin_obj_ptr;
+ int ret;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:ZynjackuRack.construct_plugin", kwlist, &PyZynjackuPlugin_Type, &plugin_obj_ptr))
+ return NULL;
+
+ ret = zynjacku_rack_construct_plugin(ZYNJACKU_RACK(self->obj), ZYNJACKU_PLUGIN(plugin_obj_ptr->obj));
+
+ return PyBool_FromLong(ret);
+
+}
+
static const PyMethodDef _PyZynjackuRack_methods[] = {
{ "start_jack", (PyCFunction)_wrap_zynjacku_rack_start_jack, METH_VARARGS|METH_KEYWORDS,
NULL },
@@ -1055,7 +1278,9 @@ static const PyMethodDef _PyZynjackuRack_methods[] = {
NULL },
{ "ui_run", (PyCFunction)_wrap_zynjacku_rack_ui_run, METH_NOARGS,
NULL },
- { "iterate_plugins", (PyCFunction)_wrap_zynjacku_rack_iterate_plugins, METH_VARARGS|METH_KEYWORDS,
+ { "get_supported_feature", (PyCFunction)_wrap_zynjacku_rack_get_supported_feature, METH_VARARGS|METH_KEYWORDS,
+ NULL },
+ { "construct_plugin", (PyCFunction)_wrap_zynjacku_rack_construct_plugin, METH_VARARGS|METH_KEYWORDS,
NULL },
{ NULL, NULL, 0, NULL }
};
@@ -1137,11 +1362,34 @@ _wrap_zynjacku_rack_get_version(PyObject *self)
return Py_None;
}
+static PyObject *
+_wrap_zynjacku_lv2_dman_get(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "dlpath", NULL };
+ char *dlpath;
+ gchar *ret;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"s:zynjacku_lv2_dman_get", kwlist, &dlpath))
+ return NULL;
+
+ ret = zynjacku_lv2_dman_get(dlpath);
+
+ if (ret) {
+ PyObject *py_ret = PyString_FromString(ret);
+ g_free(ret);
+ return py_ret;
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
const PyMethodDef zynjacku_c_functions[] = {
{ "zynjacku_get_version", (PyCFunction)_wrap_zynjacku_get_version, METH_NOARGS,
NULL },
{ "zynjacku_rack_get_version", (PyCFunction)_wrap_zynjacku_rack_get_version, METH_NOARGS,
NULL },
+ { "zynjacku_lv2_dman_get", (PyCFunction)_wrap_zynjacku_lv2_dman_get, METH_VARARGS|METH_KEYWORDS,
+ NULL },
{ NULL, NULL, 0, NULL }
};
@@ -1165,7 +1413,7 @@ zynjacku_c_register_classes(PyObject *d)
}
-#line 1169 "zynjacku.c"
+#line 1417 "zynjacku.c"
pygobject_register_class(d, "ZynjackuEngine", ZYNJACKU_TYPE_ENGINE, &PyZynjackuEngine_Type, Py_BuildValue("(O)", &PyGObject_Type));
pyg_set_object_has_new_constructor(ZYNJACKU_TYPE_ENGINE);
pygobject_register_class(d, "ZynjackuEnum", ZYNJACKU_TYPE_ENUM, &PyZynjackuEnum_Type, Py_BuildValue("(O)", &PyGObject_Type));
diff --git a/zynspect.py b/zynspect.py
new file mode 100755
index 0000000..e8b9972
--- /dev/null
+++ b/zynspect.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+import os
+import sys
+from distutils import sysconfig
+
+old_path = sys.path
+
+inplace_libs = os.path.join(os.path.dirname(sys.argv[0]), ".libs")
+if os.access(inplace_libs, os.R_OK):
+ sys.path.append(inplace_libs)
+
+try:
+ from zynworld import lv2
+except Exception, e:
+ print "Failed to import zynjacku internal python modules"
+ print repr(e)
+ print "These directories were searched"
+ for path in sys.path:
+ print " " + path
+ sys.exit(1)
+
+sys.path = old_path
+
+def show_plugin_info(plugin):
+ print "Plugin: %s" % plugin.name
+ print "URI: %s" % plugin.uri
+ if plugin.microname != None:
+ print "Tiny name: %s" % plugin.microname
+ if plugin.maintainers:
+ print "Maintainers: %s" % plugin.maintainers
+ print "License: %s" % plugin.license
+ print "Classes: %s" % plugin.classes
+ print "Required features: %s" % list(plugin.requiredFeatures)
+ print "Optional features: %s" % list(plugin.optionalFeatures)
+ print "Binary: " + plugin.binary
+
+ print
+ if plugin.presets:
+ print "Presets:"
+ for preset in plugin.presets:
+ print " URI: " + preset
+ info = db.get_preset_info(plugin.uri, preset)
+ #print " " + info.name
+ print " Name: " + info.name
+ print " Port values:"
+ for port in info.ports:
+ print " %s: %s" % (port.symbol, port.value)
+ print
+ else:
+ print "No presets"
+ print
+
+ print "Ports:"
+ types = ["Audio", "Control", "Event", "Input", "Output", "String", "LarslMidi"]
+ for port in plugin.ports:
+ extra = []
+ for type in types:
+ if port.__dict__["is" + type]:
+ extra.append(type)
+ for sp in ["defaultValue", "minimum", "maximum", "microname"]:
+ if port.__dict__[sp] != None:
+ extra.append("%s=%s" % (sp, repr(port.__dict__[sp])))
+ if len(port.events):
+ s = list()
+ for evt in port.events:
+ if evt in lv2.event_type_names:
+ s.append(lv2.event_type_names[evt])
+ else:
+ s.append(evt)
+ extra.append("events=%s" % ",".join(s))
+ if len(port.properties):
+ s = list()
+ for prop in port.properties:
+ if prop in lv2.port_property_names:
+ s.append(lv2.port_property_names[prop])
+ else:
+ s.append(prop)
+ extra.append("properties=%s" % ",".join(s))
+ if len(port.contexts):
+ s = list()
+ for context in port.contexts:
+ if context in lv2.context_names:
+ s.append(lv2.context_names[context])
+ else:
+ s.append(context)
+ extra.append("contexts=%s" % ",".join(s))
+ print "%4s %-20s %-40s %s" % (port.index, port.symbol, port.name, ", ".join(extra))
+ splist = port.scalePoints
+ splist.sort(lambda x, y: cmp(x[1], y[1]))
+ if len(splist):
+ for sp in splist:
+ print " Scale point %s: %s" % (sp[1], sp[0])
+ #print port
+ print
+
+ if plugin.ui:
+ print "UI bundles:"
+ for ui_uri in plugin.ui:
+ print " " + ui_uri
+ ui = db.get_ui_info(plugin.uri, ui_uri)
+ print " Type: " + ui.type
+ print " Binary: " + ui.binary
+ print " Required features: " + repr(ui.requiredFeatures)
+ print " Optional features: " + repr(ui.optionalFeatures)
+ print
+ print
+
+ print "Sources:"
+ for source in plugin.sources:
+ print " " + source
+ print
+
+def list_plugins(verbose):
+ plugins = db.getPluginList()
+
+ for uri in plugins:
+ if verbose:
+ plugin = db.getPluginInfo(uri)
+ if plugin == None:
+ continue
+ show_plugin_info(plugin)
+ else:
+ print uri
+
+db = lv2.LV2DB()
+
+if len(sys.argv) >= 2:
+ if sys.argv[1] == "dump":
+ list_plugins(True)
+ else:
+ uri = sys.argv[1]
+
+ plugin = db.getPluginInfo(uri)
+
+ if plugin == None:
+ print 'Plugin URI "%s" is unknown' % uri
+ sys.exit(1)
+
+ show_plugin_info(plugin)
+else:
+ list_plugins(False)
diff --git a/zynworld/__init__.py b/zynworld/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/zynworld/lv2.py b/zynworld/lv2.py
new file mode 100644
index 0000000..1d40866
--- /dev/null
+++ b/zynworld/lv2.py
@@ -0,0 +1,595 @@
+import re
+import os
+import sys
+import glob
+import zynjacku_ttl
+import zynjacku_c
+
+lv2 = "http://lv2plug.in/ns/lv2core#"
+lv2evt = "http://lv2plug.in/ns/ext/event#"
+lv2str = "http://lv2plug.in/ns/dev/string-port#"
+lv2ctx = "http://lv2plug.in/ns/dev/contexts#"
+rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+rdfs = "http://www.w3.org/2000/01/rdf-schema#"
+epi = "http://lv2plug.in/ns/dev/extportinfo#"
+rdf_type = rdf + "type"
+rdfs_see_also = rdfs + "seeAlso"
+rdfs_label = rdfs + "label"
+rdfs_subclass_of = rdfs + "subClassOf"
+tinyname_uri = "http://lv2plug.in/ns/dev/tiny-name"
+foaf = "http://xmlns.com/foaf/0.1/"
+doap = "http://usefulinc.com/ns/doap#"
+lv2ui = "http://lv2plug.in/ns/extensions/ui#"
+lv2ui_ui = lv2ui + "ui"
+lv2ui_binary = lv2ui + "binary"
+lv2preset = "http://lv2plug.in/ns/dev/presets#"
+lv2preset_preset = lv2preset + "Preset"
+lv2preset_appliesTo = lv2preset + "appliesTo"
+lv2preset_hasPreset = lv2preset + "hasPreset"
+lv2preset_value = lv2preset + "value"
+dc = "http://dublincore.org/documents/dcmi-namespace/"
+dc_title = dc + "title"
+dman = "http://naspro.atheme.org/rdf/old-dman#"
+
+event_type_names = {
+ "http://lv2plug.in/ns/ext/midi#MidiEvent" : "MIDI"
+}
+
+port_property_names = {
+ "http://lv2plug.in/ns/lv2core#reportsLatency": "reportsLatency",
+ "http://lv2plug.in/ns/lv2core#toggled": "toggled",
+ "http://lv2plug.in/ns/lv2core#integer": "integer",
+ "http://lv2plug.in/ns/lv2core#connectionOptional": "connectionOptional",
+ "http://lv2plug.in/ns/lv2core#sampleRate": "sampleRate",
+ "http://lv2plug.in/ns/dev/extportinfo#hasStrictBounds": "hasStrictBounds",
+ "http://lv2plug.in/ns/dev/extportinfo#logarithmic": "logarithmic",
+ "http://lv2plug.in/ns/dev/extportinfo#notAutomatic": "notAutomatic",
+ "http://lv2plug.in/ns/dev/extportinfo#trigger": "trigger",
+ "http://lv2plug.in/ns/dev/extportinfo#outputGain": "outputGain",
+ "http://lv2plug.in/ns/dev/extportinfo#reportsBpm": "reportsBpm",
+}
+
+context_names = {
+ "http://lv2plug.in/ns/dev/contexts#MessageContext": "MessageContext",
+}
+
+def uniq_seq(seq):
+ return {}.fromkeys(seq).keys()
+
+class DumpRDFModel:
+ def addTriple(self, s, p, o):
+ print "%s [%s] %s" % (s, p, repr(o))
+
+class SimpleRDFModel:
+ def __init__(self):
+ self.bySubject = {}
+ self.byPredicate = {}
+ #self.byObject = {}
+ self.byClass = {}
+ self.object_sources = {}
+ self.sources = set()
+ self.len = 0
+
+ def size(self):
+ return self.len
+
+ def getByType(self, classname):
+ if classname in self.byClass:
+ return self.byClass[classname]
+ return []
+ def getByPropType(self, propname):
+ if propname in self.byPredicate:
+ return self.byPredicate[propname]
+ return []
+ def getProperty(self, subject, props, optional = False, single = False):
+ #print "getProperty(%s, %s)" % (repr(subject), repr(props))
+ if type(props) is list:
+ prop = props[0]
+ else:
+ prop = props
+ if type(subject) is str or type(subject) is unicode:
+ if not self.bySubject.has_key(subject):
+ return None
+ subject = self.bySubject[subject]
+ elif type(subject) is dict:
+ pass
+ else:
+ #print "subject type is %s" % type(subject)
+ if single:
+ return None
+ else:
+ return []
+ anyprops = set()
+ if prop in subject:
+ for o in subject[prop]:
+ anyprops.add(o)
+ if type(props) is list:
+ if len(props) > 1:
+ result = set()
+ for v in anyprops:
+ if single:
+ value = self.getProperty(v, props[1:], optional = optional, single = True)
+ if value != None:
+ return value
+ else:
+ result |= set(self.getProperty(v, props[1:], optional = optional, single = False))
+ if single:
+ return None
+ else:
+ return list(result)
+ if single:
+ if len(anyprops) > 0:
+ if len(anyprops) > 1:
+ raise Exception, "More than one value of " + prop
+ return list(anyprops)[0]
+ else:
+ return None
+ return list(anyprops)
+
+ def add_object_source(self, uri, source):
+ if o not in self.object_sources:
+ self.object_sources[o] = set((source,))
+ else:
+ self.object_sources[o].add(source)
+
+ def addTriple(self, s, p, o, source=None):
+ self.len += 1
+
+ #if p == lv2 + "binary":
+ # print 'binary "%s" of %s found' % (o, s)
+ if o not in self.object_sources:
+ self.object_sources[o] = set((source,))
+ else:
+ self.object_sources[o].add(source)
+ if p == rdf_type:
+ p = "a"
+ #if p == 'a' and o == lv2preset_preset:
+ # print 'preset "%s" found' % s
+
+ if s in self.bySubject:
+ predicates = self.bySubject[s]
+ if p in predicates:
+ predicates[p].append(o)
+ else:
+ predicates[p] = [o]
+ else:
+ self.bySubject[s] = { p : [o] }
+
+ if p in self.byPredicate:
+ subjects = self.byPredicate[p]
+ if s in subjects:
+ subjects[s].append(o)
+ else:
+ subjects[s] = [o]
+ else:
+ self.byPredicate[p] = { s : [o] }
+
+ #if o not in self.byObject:
+ # self.byObject[o] = {}
+ #if p not in self.byObject[o]:
+ # self.byObject[o][p] = []
+ #self.byObject[o][p].append(s)
+
+ if p == "a":
+ if s not in self.object_sources:
+ self.object_sources[s] = set()
+ self.object_sources[s].add(source)
+ if o in self.byClass:
+ self.byClass[o].append(s)
+ else:
+ self.byClass[o] = [s]
+ def copyFrom(self, src):
+ #print " *** RDF Model Copy *** ",
+ self.bySubject = {}
+ self.byPredicate = {}
+ self.object_sources = {}
+ self.byClass = {}
+ for s, src_s in src.bySubject.iteritems():
+ dst_s = self.bySubject[s] = {}
+ for p, plist in src_s.iteritems():
+ dst_s[p] = list(plist)
+ for p, src_p in src.byPredicate.iteritems():
+ dst_p = self.byPredicate[p] = {}
+ for s, slist in src_p.iteritems():
+ dst_p[s] = list(slist)
+ for o, val in src.object_sources.iteritems():
+ self.object_sources[o] = set(val)
+ for c, val in src.byClass.iteritems():
+ self.byClass[c] = list(set(val))
+ self.len = src.len
+ def dump(self):
+ for s in self.bySubject.keys():
+ for p in self.bySubject[s].keys():
+ print "%s %s %s" % (s, p, self.bySubject[s][p])
+
+def parseTTL(uri, content, model, debug):
+ #print " *** Parse TTL *** ",
+ # Missing stuff: translated literals, blank nodes
+ if debug:
+ print "Parsing: %s" % uri
+ prefixes = {}
+ spo_stack = []
+ spo = ["", "", ""]
+ item = 0
+ anoncnt = 1
+ for x in zynjacku_ttl.scan_string(content):
+ if x[0] == '':
+ continue
+ if x[0] == "URI_": x = ('URI', x[1][1:-1])
+ if x[0] == "float": x = ('number', float(x[1]))
+ if x[0] == 'prefix':
+ spo[0] = "@prefix"
+ item = 1
+ continue
+ elif (x[0] == '.' and spo_stack == []) or x[0] == ';' or x[0] == ',':
+ if item == 3:
+ if spo[0] == "@prefix":
+ prefixes[spo[1][:-1]] = spo[2]
+ else:
+ model.addTriple(spo[0], spo[1], spo[2], uri)
+ if x[0] == '.': item = 0
+ elif x[0] == ';': item = 1
+ elif x[0] == ',': item = 2
+ else:
+ if x[0] == '.':
+ item = 0
+ elif item != 0:
+ raise Exception, uri+": Unexpected " + x[0]
+ elif x[0] == "prnot" and item < 3:
+ prnot = x[1].split(":")
+ if item != 0 and spo[0] == "@prefix":
+ spo[item] = x[1]
+ elif prnot[0] == "_":
+ spo[item] = uri + "#" + prnot[1]
+ else:
+ if prnot[0] not in prefixes:
+ print 'WARNING %s: Prefix %s not defined. Ignoring %s:%s' % (uri, prnot[0], prnot[0], prnot[1])
+ else:
+ spo[item] = prefixes[prnot[0]] + prnot[1]
+ item += 1
+ elif (x[0] == 'URI' or x[0] == "string" or x[0] == "number" or (x[0] == "symbol" and x[1] == "a" and item == 1)) and (item < 3):
+ if x[0] == "URI" and x[1] == "":
+ x = ("URI", uri)
+ elif x[0] == "URI" and x[1].find(":") == -1 and x[1] != "" and x[1][0] != "/":
+ # This is quite silly
+ x = ("URI", os.path.dirname(uri) + "/" + x[1])
+ spo[item] = x[1]
+ item += 1
+ elif x[0] == '[':
+ if item != 2:
+ raise Exception, "Incorrect use of ["
+ uri2 = uri + "$anon$" + str(anoncnt)
+ spo[2] = uri2
+ spo_stack.append(spo)
+ spo = [uri2, "", ""]
+ item = 1
+ anoncnt += 1
+ elif x[0] == ']' or x[0] == ')':
+ if item == 3:
+ model.addTriple(spo[0], spo[1], spo[2], uri)
+ item = 0
+ spo = spo_stack[-1]
+ spo_stack = spo_stack[:-1]
+ item = 3
+ elif x[0] == '(':
+ if item != 2:
+ raise Exception, "Incorrect use of ("
+ uri2 = uri + "$anon$" + str(anoncnt)
+ spo[2] = uri2
+ spo_stack.append(spo)
+ spo = [uri2, "", ""]
+ item = 2
+ anoncnt += 1
+ else:
+ print uri + ": Unexpected: " + repr(x)
+
+class LV2Port(object):
+ def __init__(self):
+ pass
+ def connectableTo(self, port):
+ if not ((self.isInput and port.isOutput) or (self.isOutput and port.isInput)):
+ return False
+ if self.isAudio != port.isAudio or self.isControl != port.isControl or self.isEvent != port.isEvent:
+ return False
+ if not self.isAudio and not self.isControl and not self.isEvent:
+ return False
+ return True
+
+class LV2Plugin(object):
+ def __init__(self):
+ pass
+
+class LV2UI(object):
+ def __init__(self):
+ pass
+
+class LV2Preset(object):
+ def __init__(self):
+ pass
+
+class LV2DB:
+ def __init__(self, sources=[], debug = False):
+ self.debug = debug
+ self.sources = sources
+ self.initManifests()
+
+ def initManifests(self):
+ if os.environ.has_key("LV2_PATH"):
+ lv2path = os.environ["LV2_PATH"].split(':')
+ else:
+ lv2path = []
+
+ if os.environ.has_key("HOME"):
+ if sys.platform == "darwin":
+ lv2path.append(os.environ["HOME"] + "/Library/Audio/Plug-Ins/LV2")
+ else:
+ lv2path.append(os.environ["HOME"] + "/.lv2")
+
+ if sys.platform == "darwin":
+ lv2path.append("/Library/Audio/Plug-Ins/LV2")
+
+ lv2path += ["/usr/local/lib/lv2", "/usr/lib/lv2"]
+
+ print "LV2_PATH not set, defaulting to %s" % repr(lv2path)
+
+ self.manifests = SimpleRDFModel()
+ self.dynmanifests = []
+ self.paths = {}
+ self.plugin_info = dict()
+
+ if not self.sources:
+ # Scan manifests
+ for dir in lv2path:
+ for bundle in glob.iglob(dir + "/*.lv2"):
+ fn = bundle+"/manifest.ttl"
+ if os.path.exists(fn):
+ parseTTL(fn, file(fn).read(), self.manifests, self.debug)
+ # Read all specifications from all manifests
+ if lv2 + "Specification" in self.manifests.byClass:
+ specs = self.manifests.getByType(lv2 + "Specification")
+ filenames = set()
+ for spec in specs:
+ subj = self.manifests.bySubject[spec]
+ if rdfs_see_also in subj:
+ for fn in subj[rdfs_see_also]:
+ filenames.add(fn)
+ for fn in filenames:
+ parseTTL(fn, file(fn).read(), self.manifests, self.debug)
+ #print "%u triples in global world" % self.manifests.size()
+ else:
+ for source in self.sources:
+ parseTTL(source, file(source).read(), self.manifests, self.debug)
+ #fn = "/usr/lib/lv2/lv2core.lv2/lv2.ttl"
+ #parseTTL(fn, file(fn).read(), self.manifests, self.debug)
+
+ self.plugins = set(self.manifests.getByType(lv2 + "Plugin"))
+
+ # Read dynamic manifests
+ wrappers = self.manifests.getByType(dman + "DynManifest")
+ for w in wrappers:
+ subj = self.manifests.bySubject[w]
+ if lv2 + "binary" in subj:
+ #print " *** Parse dynamic TTL *** ",
+ manifest = SimpleRDFModel()
+ filename = subj[lv2 + "binary"][0]
+ data = zynjacku_c.zynjacku_lv2_dman_get(filename)
+ #print data
+ parseTTL(filename, data, manifest, self.debug)
+ #print "%u triples in %s dynmanifest world" % (manifest.size(), filename)
+ # add wrapper filename to list of sources so it gets cached
+ for source in self.manifests.object_sources[w]:
+ #print "adding wrapper ttl " + source
+ manifest.sources.add(source)
+ self.dynmanifests.append(manifest)
+ for plugin in manifest.getByType(lv2 + "Plugin"):
+ self.plugins.add(plugin)
+
+ self.categories = set()
+ self.category_paths = []
+ self.add_category_recursive([], lv2 + "Plugin")
+
+ def add_category_recursive(self, tree_pos, category):
+ cat_name = self.manifests.getProperty(category, rdfs_label, single = True, optional = True)
+ if not cat_name:
+ return
+ self.category_paths.append(((tree_pos + [cat_name])[1:], category))
+ self.categories.add(category)
+ items = self.manifests.byPredicate[rdfs_subclass_of]
+ for subj in items:
+ if subj in self.categories:
+ continue
+ for o in items[subj]:
+ if o == category and subj not in self.categories:
+ self.add_category_recursive(list(tree_pos) + [cat_name], subj)
+
+ def get_categories(self):
+ return self.category_paths
+
+ def getPluginList(self):
+ return self.plugins
+
+ def get_plugin_full_model(self, uri):
+ sources = []
+ model = None
+
+ if uri in self.plugin_info:
+ model = self.plugin_info[uri]
+ return model, sources
+
+ if self.manifests.bySubject.has_key(uri):
+ if self.sources: # cache/subset preloaded
+ self.plugin_info[uri] = self.manifests
+ model = self.manifests
+ return model, self.sources
+
+ world = SimpleRDFModel()
+ world.copyFrom(self.manifests)
+ #msg = "#%u#" % world.size()
+ #print msg,
+ seeAlso = self.manifests.bySubject[uri][rdfs_see_also]
+ try:
+ for doc in seeAlso:
+ #print "Loading " + doc + " for plugin " + uri
+ parseTTL(doc, file(doc).read(), world, self.debug)
+ #msg = "#%u#" % world.size()
+ #print msg,
+ world.sources.add(doc)
+ self.plugin_info[uri] = world
+ except Exception, e:
+ print "ERROR %s: %s" % (uri, str(e))
+ return None
+ for source in self.manifests.object_sources[uri]:
+ world.sources.add(source)
+ sources = world.sources
+ #print "%u triples in %s world" % (world.size(), uri)
+ return world, sources
+
+ for model in self.dynmanifests:
+ if model.bySubject.has_key(uri):
+ self.plugin_info[uri] = model
+ #print model.sources
+ return model, model.sources
+
+ #print 'no subject "%s"' % uri
+ return None
+
+ def getPluginInfo(self, uri):
+ #print "getting info for plugin " + uri
+
+ info, sources = self.get_plugin_full_model(uri)
+ if not info:
+ return None
+
+ dest = LV2Plugin()
+ dest.uri = uri
+
+ dest.binary = info.getProperty(uri, lv2 + "binary", optional = True)
+ if not dest.binary:
+ #print "No binary"
+ return None
+ dest.binary = dest.binary[0]
+
+ dest.name = info.getProperty(uri, doap + 'name', optional = True)
+ if not dest.name:
+ return None
+ dest.name = dest.name[0]
+
+ dest.license = info.bySubject[uri][doap + 'license'][0]
+ dest.classes = info.bySubject[uri]["a"]
+ dest.requiredFeatures = info.getProperty(uri, lv2 + "requiredFeature", optional = True)
+ dest.optionalFeatures = info.getProperty(uri, lv2 + "optionalFeature", optional = True)
+ dest.microname = info.getProperty(uri, tinyname_uri, optional = True)
+ if len(dest.microname):
+ dest.microname = dest.microname[0]
+ else:
+ dest.microname = None
+ dest.maintainers = []
+ if info.bySubject[uri].has_key(doap + "maintainer"):
+ for maintainer in info.bySubject[uri][doap + "maintainer"]:
+ maintainersubj = info.bySubject[maintainer]
+ maintainerdict = {}
+ maintainerdict['name'] = info.getProperty(maintainersubj, foaf + "name")[0]
+ homepages = info.getProperty(maintainersubj, foaf + "homepage")
+ if homepages:
+ maintainerdict['homepage'] = homepages[0]
+ mboxes = info.getProperty(maintainersubj, foaf + "mbox")
+ if mboxes:
+ maintainerdict['mbox'] = mboxes[0]
+ dest.maintainers.append(maintainerdict)
+
+ ports = []
+ portDict = {}
+ porttypes = {
+ "isAudio" : lv2 + "AudioPort",
+ "isControl" : lv2 + "ControlPort",
+ "isEvent" : lv2evt + "EventPort",
+ "isString" : lv2str + "StringPort",
+ "isInput" : lv2 + "InputPort",
+ "isOutput" : lv2 + "OutputPort",
+ "isLarslMidi" : "http://ll-plugins.nongnu.org/lv2/ext/MidiPort",
+ }
+
+ for port in info.bySubject[uri][lv2 + "port"]:
+ psubj = info.bySubject[port]
+ pdata = LV2Port()
+ pdata.uri = port
+ pdata.index = int(info.getProperty(psubj, lv2 + "index")[0])
+ pdata.symbol = info.getProperty(psubj, lv2 + "symbol")[0]
+ pdata.name = info.getProperty(psubj, lv2 + "name")[0]
+ classes = set(info.getProperty(psubj, "a"))
+ pdata.classes = classes
+ for pt in porttypes.keys():
+ pdata.__dict__[pt] = porttypes[pt] in classes
+ sp = info.getProperty(psubj, lv2 + "scalePoint")
+ if sp and len(sp):
+ splist = []
+ for pt in sp:
+ name = info.getProperty(pt, rdfs_label, optional = True, single = True)
+ if name != None:
+ value = info.getProperty(pt, rdf + "value", optional = True, single = True)
+ if value != None:
+ splist.append((name, value))
+ pdata.scalePoints = splist
+ else:
+ pdata.scalePoints = []
+ if pdata.isControl:
+ pdata.defaultValue = info.getProperty(psubj, [lv2 + "default"], optional = True, single = True)
+ elif pdata.isString:
+ pdata.defaultValue = info.getProperty(psubj, [lv2str + "default"], optional = True, single = True)
+ else:
+ pdata.defaultValue = None
+ pdata.minimum = info.getProperty(psubj, [lv2 + "minimum"], optional = True, single = True)
+ pdata.maximum = info.getProperty(psubj, [lv2 + "maximum"], optional = True, single = True)
+ pdata.microname = info.getProperty(psubj, [tinyname_uri], optional = True, single = True)
+ pdata.properties = set(info.getProperty(psubj, [lv2 + "portProperty"], optional = True))
+ pdata.events = set(info.getProperty(psubj, [lv2evt + "supportsEvent"], optional = True))
+ pdata.contexts = set(info.getProperty(psubj, [lv2ctx + "context"], optional = True))
+ ports.append(pdata)
+ portDict[pdata.uri] = pdata
+ ports.sort(lambda x, y: cmp(x.index, y.index))
+ dest.ports = ports
+ dest.portDict = portDict
+
+ if info.bySubject[uri].has_key(lv2ui_ui):
+ dest.ui = uniq_seq(info.bySubject[uri][lv2ui_ui])
+ else:
+ dest.ui = []
+
+ if info.bySubject[uri].has_key(lv2preset_hasPreset):
+ dest.presets = info.bySubject[uri][lv2preset_hasPreset]
+ else:
+ dest.presets = []
+
+ dest.sources = sources
+
+ return dest
+
+ def get_ui_info(self, plugin_uri, uri):
+ info = self.plugin_info[plugin_uri]
+
+ dest = LV2Plugin()
+ dest.uri = uri
+ dest.type = set(info.getProperty(uri, "a")).intersection(set([lv2ui + 'GtkUI', lv2ui + 'external'])).pop()
+ dest.binary = info.getProperty(uri, lv2ui_binary)[0]
+ dest.requiredFeatures = info.getProperty(uri, lv2ui + "requiredFeature", optional = True)
+ dest.optionalFeatures = info.getProperty(uri, lv2ui + "optionalFeature", optional = True)
+
+ return dest
+
+ def get_preset_info(self, plugin_uri, uri):
+ info = self.plugin_info[plugin_uri]
+
+ dest = LV2Preset()
+ dest.uri = uri
+ dest.name = info.getProperty(uri, dc_title)[0]
+
+ dest.ports = []
+ for port in info.bySubject[uri][lv2 + "port"]:
+ psubj = info.bySubject[port]
+ pdata = LV2Port()
+ pdata.uri = port
+ pdata.symbol = info.getProperty(psubj, lv2 + "symbol")[0]
+ pdata.value = info.getProperty(psubj, lv2preset_value)[0]
+ dest.ports.append(pdata)
+
+ return dest
--
zynjacku packaging
More information about the pkg-multimedia-commits
mailing list