[SCM] gsequencer/master: New upstream version 0.7.122.16

jkraehemann-guest at users.alioth.debian.org jkraehemann-guest at users.alioth.debian.org
Sat Apr 1 16:38:36 UTC 2017


The following commit has been merged in the master branch:
commit f8a34133a857bae9012f636f67083c3d4e20293d
Author: Joël Krähemann <jkraehemann-guest at users.alioth.debian.org>
Date:   Sat Apr 1 18:30:57 2017 +0200

    New upstream version 0.7.122.16

diff --git a/ChangeLog b/ChangeLog
index a7c6614..00d9a62 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,131 @@
+ags (0.7.122.16)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* fixed memory corruption of AgsFFPlayer destruction
+	* fixed some AgsConnectable::disconnect() of machines
+	* fixed potential infinite loop in ags_machine_resize_audio_channels()
+	* added functional test add and destroy machine
+	* added functional tests resize pads and audio channels
+
+ags (0.7.122.15)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* fixed missing connect of AgsOscillator
+	* fixed noise creation in AgsSynth
+	* fixed SIGSEGV as adding plugin to AgsLine
+
+ags (0.7.122.14)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* implemented notebook resize in automation editor
+	* fixed NULL pointer dereference in ags_matrix.c
+	* fixed resize pad to distinguish between input and output
+
+ags (0.7.122.13)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* stability improvements
+
+ags (0.7.122.12)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* decoupled gui thread
+
+ags (0.7.122.11)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* fixes to configuration in place
+	* fixes to audio connection editor
+
+ags (0.7.122.10)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* TODO:JK: implemented ags-play-pattern recall
+	* fixed broken optical feedback of peak
+	* removed auto-scroll feature because it costs too much performance
+
+ags (0.7.122.9)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* implemented non-deterministic mode i.e. performance mode
+	* implemented ags_input_next_active() and ags_input_is_active()
+	* implemented restore and persist of AgsLv2Bridge preset
+	* disabled lv2 worker feature if not requested by plugin
+	* fixed memory leak related to AgsReturnableThread
+	* fixed crash related to notation offset cached
+	* note disabled some signals
+
+ags (0.7.122.8)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* refactored ags-copy recall to instantiate like ags-buffer
+	* implemented LV2 presets
+	* implemented presets in AgsLv2Bridge
+	* implemented ags-prepare recall
+	* implemented AgsConditionManager to use with AgsThread tree lock functions
+	* implemented worker threads
+	* implemented destroy worker
+	* improved AgsDelayAudio port instantiation to use default values
+	* fixed using default values as no soundcard available
+	* fixed crash as no soundcard configured within GUI
+	* fixed AgsThread tree lock functions
+	* added more unit tests in ags_thread_test.c
+
+ags (0.7.122.7)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* implemented AgsHLedArray and AgsVLedArray
+	* implemented missing properties of AgsPlaybackDomain and AgsPlayback
+	* implemented GObject::dispose()
+	* refactored AgsCellPattern and AgsPatternBox to use AgsHLedArray
+	* fixed reference counting of libags, libags_audio
+	* fixed division by zero caused by AgsOscillator
+	* fixed serious memory corruption in ags_pattern_set_dim()
+	* fixed segmentation fault of AgsFFPlayer restore
+	* fixed missing connection menu of AgsLv2Bridge after restore
+	* extended unit tests
+
+ags (0.7.122.6)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* back-ported seemless mode of AgsDial
+	* back-ported Lv2ui support
+	* improved default theme
+	* fixed configuration to use default values as soundcard busy
+	* fixed clear configuration and provide default values as applying
+
+ags (0.7.122.5)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* providing default theme
+	* fixed ags.rc support
+	* fixed cell pattern painting
+	* minor fixes
+
+ags (0.7.122.4)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* minor fixes
+
+ags (0.7.122.3)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* minor fixes
+
+ags (0.7.122.2)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* back-ported enable output ports to plugins
+	* back-ported disable output ports on automation
+	* back-ported enable built-in effects to do automation
+	* fixed configuration in-place to reset frequency of appropriate thread
+	* minor fixes
+
+ags (0.7.122.1)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
+	* minor fixes
+
 ags (0.7.122)
 
 	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
diff --git a/Makefile.am b/Makefile.am
index eee85a3..7943e9c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -30,15 +30,15 @@ bin_PROGRAMS = gsequencer midi2xml
 libgsequencerdir = $(libdir)/gsequencer
 libgsequencer_LTLIBRARIES = libgsequencer.la
 
-EXTRA_DIST = COPYING.docs config.h config.h.in gtk-doc.make gsequencer.share acsite.m4 aclocal.m4 gsequencer.1 README ags_example.xml gsequencer-documentation midi2xml.1
+EXTRA_DIST = COPYING.docs config.h config.h.in gtk-doc.make gsequencer.share acsite.m4 aclocal.m4 gsequencer.1 README ags_example.xml gsequencer-documentation midi2xml.1 ags_functional_note_edit_test.xml
 
 EXTRA_DIST += \
 	docs/reference/libags/libags-sections.txt \
 	docs/reference/libags/libags.types \
-	docs/reference/libags_audio/libags_audio-sections.txt \
-	docs/reference/libags_audio/libags_audio.types \
-	docs/reference/libags_gui/libags_gui-sections.txt \
-	docs/reference/libags_gui/libags_gui.types
+	docs/reference/libags-audio/libags_audio-sections.txt \
+	docs/reference/libags-audio/libags_audio.types \
+	docs/reference/libags-gui/libags_gui-sections.txt \
+	docs/reference/libags-gui/libags_gui.types
 
 man1_MANS = gsequencer.1 midi2xml.1
 
@@ -72,11 +72,11 @@ EXTRA_DIST += \
 EXTRA_DIST += docs/reference/libags/git.mk docs/reference/libags/gtk-doc.make docs/reference/libags/Makefile.am docs/reference/libags/Makefile.in
 EXTRA_DIST += docs/reference/libags/libags-overrides.txt docs/reference/libags/libags-sections.txt docs/reference/libags/libags.types docs/reference/libags/libags.xml
 
-EXTRA_DIST += docs/reference/libags_audio/git.mk docs/reference/libags_audio/gtk-doc.make docs/reference/libags_audio/Makefile.am docs/reference/libags_audio/Makefile.in
-EXTRA_DIST += docs/reference/libags_audio/libags_audio-overrides.txt  docs/reference/libags_audio/libags_audio-sections.txt docs/reference/libags_audio/libags_audio.types docs/reference/libags_audio/libags_audio.xml
+EXTRA_DIST += docs/reference/libags-audio/git.mk docs/reference/libags-audio/gtk-doc.make docs/reference/libags-audio/Makefile.am docs/reference/libags-audio/Makefile.in
+EXTRA_DIST += docs/reference/libags-audio/libags_audio-overrides.txt  docs/reference/libags-audio/libags_audio-sections.txt docs/reference/libags-audio/libags_audio.types docs/reference/libags-audio/libags_audio.xml
 
-EXTRA_DIST += docs/reference/libags_gui/git.mk docs/reference/libags_gui/gtk-doc.make docs/reference/libags_gui/Makefile.am docs/reference/libags_gui/Makefile.in
-EXTRA_DIST += docs/reference/libags_gui/libags_gui-overrides.txt docs/reference/libags_gui/libags_gui-sections.txt docs/reference/libags_gui/libags_gui.types docs/reference/libags_gui/libags_gui.xml
+EXTRA_DIST += docs/reference/libags-gui/git.mk docs/reference/libags-gui/gtk-doc.make docs/reference/libags-gui/Makefile.am docs/reference/libags-gui/Makefile.in
+EXTRA_DIST += docs/reference/libags-gui/libags_gui-overrides.txt docs/reference/libags-gui/libags_gui-sections.txt docs/reference/libags-gui/libags_gui.types docs/reference/libags-gui/libags_gui.xml
 
 EXTRA_DIST += docs/reference/libgsequencer/git.mk docs/reference/libgsequencer/gtk-doc.make docs/reference/libgsequencer/Makefile.am docs/reference/libgsequencer/Makefile.in
 EXTRA_DIST += docs/reference/libgsequencer/libgsequencer-overrides.txt docs/reference/libgsequencer/libgsequencer.xml
@@ -182,138 +182,71 @@ EXTRA_DIST += \
 	$(top_srcdir)/ags/audio/midi/ags_midi_file.dtd \
 	$(top_srcdir)/ags/file/ags_file.dtd \
 	$(top_srcdir)/ags/X/file/ags_simple_file.dtd \
-	$(top_srcdir)/ags.xsl $(top_srcdir)/ags/object/ags_marshallers.list
+	$(top_srcdir)/ags.xsl $(top_srcdir)/ags-simple.xsl $(top_srcdir)/ags/object/ags_marshallers.list
 
 # libraries and gsequencer
 libags_la_SOURCES = $(libags_c_sources) $(libags_util_c_sources) $(libags_object_c_sources) $(libags_file_c_sources) $(libags_file_task_c_sources)
 libags_la_HEADERS_0 = ags/libags.h $(libags_h_sources) $(libags_util_h_sources) $(libags_object_h_sources) $(libags_file_h_sources) $(libags_file_task_h_sources)
+
 libags_thread_la_SOURCES = $(libags_thread_c_sources) $(libags_thread_file_c_sources) $(libags_thread_task_c_sources)
 libags_thread_la_HEADERS_0 = $(libags_thread_h_sources) $(libags_thread_file_h_sources) $(libags_thread_task_h_sources)
+
 libags_server_la_SOURCES = $(libags_server_c_sources)
 libags_server_la_HEADERS_0 = $(libags_server_h_sources)
+
 libags_audio_la_SOURCES = $(libags_audio_c_sources) $(libags_audio_client_c_sources) $(libags_audio_thread_c_sources) $(libags_audio_file_c_sources) $(libags_audio_midi_c_sources) $(libags_audio_jack_c_sources) $(libags_audio_task_c_sources) $(libags_audio_task_recall_c_sources) $(libags_audio_recall_c_sources)  $(libags_plugin_c_sources)
 libags_audio_la_HEADERS_0 = ags/libags-audio.h $(libags_audio_h_sources) $(libags_audio_client_h_sources) $(libags_audio_thread_h_sources) $(libags_audio_file_h_sources) $(libags_audio_midi_h_sources) $(libags_audio_jack_h_sources) $(libags_audio_task_h_sources) $(libags_audio_task_recall_h_sources) $(libags_audio_recall_h_sources)  $(libags_plugin_h_sources)
+
 libags_gui_la_SOURCES = $(libags_gui_c_sources)
 libags_gui_la_HEADERS_0 = ags/libags-gui.h $(libags_gui_h_sources)
-# libgsequencer_la_SOURCES = $(libgsequencer_c_sources) $(libgsequencer_file_c_sources) $(libgsequencer_thread_c_sources) $(libgsequencer_task_c_sources) $(libgsequencer_import_c_sources) $(libgsequencer_machine_c_sources) $(libgsequencer_editor_c_sources)
-# libgsequencer_la_HEADERS_0 = $(libgsequencer_h_sources) $(libgsequencer_file_h_sources) $(libgsequencer_thread_h_sources) $(libgsequencer_task_h_sources) $(libgsequencer_import_h_sources) $(libgsequencer_machine_h_sources) $(libgsequencer_editor_h_sources)
+
 libgsequencer_la_HEADERS_0 = $(libgsequencer_h_sources) $(libgsequencer_file_h_sources) $(libgsequencer_thread_h_sources) $(libgsequencer_task_h_sources) $(libgsequencer_import_h_sources) $(libgsequencer_machine_h_sources) $(libgsequencer_editor_h_sources)
 libgsequencer_la_SOURCES = $(libgsequencer_la_HEADERS_0) $(libgsequencer_c_sources) $(libgsequencer_file_c_sources) $(libgsequencer_thread_c_sources) $(libgsequencer_task_c_sources) $(libgsequencer_import_c_sources) $(libgsequencer_machine_c_sources) $(libgsequencer_editor_c_sources)
 
 # library libags
 libags_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(UUID_CFLAGS) $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS) $(GIO_CFLAGS)
-libags_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname -ldl -lm -pthread -lrt  $(UUID_LIBS) $(LIBXML2_LIBS) $(GOBJECT_LIBS) $(GIO_LIBS)
+libags_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname,libags.so -pthread
+libags_la_LIBADD = -ldl -lm $(UUID_LIBS) $(LIBXML2_LIBS) $(GOBJECT_LIBS) $(GIO_LIBS)
 
 # library libags-thread
-libags_thread_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(UUID_CFLAGS) $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS)
-libags_thread_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_thread.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname -ldl -lm -pthread -lrt $(UUID_LIBS) $(LIBXML2_LIBS) $(GOBJECT_LIBS)
-libags_thread_la_LIBADD = libags.la
+libags_thread_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS)
+libags_thread_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_thread.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname,libags_thread.so -pthread
+libags_thread_la_LIBADD = libags.la -ldl -lm $(LIBXML2_LIBS) $(GOBJECT_LIBS)
 
 # library libags-server
-libags_server_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(UUID_CFLAGS) $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS)
-libags_server_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_server.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname -ldl -lm -pthread -lrt $(UUID_LIBS) $(LIBXML2_LIBS) $(GOBJECT_LIBS)
-libags_server_la_LIBADD = libags_thread.la libags.la
+libags_server_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS)
+libags_server_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_server.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname,libags_server.so -pthread
+libags_server_la_LIBADD = libags_thread.la libags.la -ldl -lm $(LIBXML2_LIBS) $(GOBJECT_LIBS)
 
 # library libags-audio
-libags_audio_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SAMPLERATE_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-libags_audio_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_audio.sym -version-info 0:7:0 -shared -fPIC -soname -ldl -lm -pthread -lrt -lgmp $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SAMPLERATE_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-libags_audio_la_LIBADD = libags_server.la libags_thread.la libags.la
+libags_audio_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SAMPLERATE_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+libags_audio_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_audio.sym -version-info 0:7:0 -shared -fPIC -soname,libags_audio.so -pthread 
+libags_audio_la_LIBADD = libags_server.la libags_thread.la libags.la -ldl -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SAMPLERATE_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
 
 # library libags-gui
 libags_gui_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(GOBJECT_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
-libags_gui_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_gui.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname -ldl -lm -pthread -lrt $(GOBJECT_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+libags_gui_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_gui.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname,libags_gui.so -pthread
+libags_gui_la_LIBADD = -ldl -lm $(GOBJECT_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
 
 # library libgsequencer
-# libgsequencer_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS) $(JACK_CFLAGS)
-# libgsequencer_la_LDFLAGS = $(LDFLAGS) -version-info 0:1:0 -shared -fPIC -Wl,-soname -ldl -lm -pthread -lrt -lgmp $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS) $(JACK_LIBS)
-# libgsequencer_la_LIBADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-libgsequencer_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS) $(JACK_CFLAGS)
-libgsequencer_la_LDFLAGS =  $(LDFLAGS) -version-info 0:1:0 -shared -fPIC -Wl,-soname -ldl -lm -pthread -lrt -lgmp $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS) $(JACK_LIBS)
-libgsequencer_la_LIBADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-
-# static gsequencer - for testing
+libgsequencer_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS) $(JACK_CFLAGS)
+libgsequencer_la_LDFLAGS = $(LDFLAGS) -version-info 0:1:0 -shared -fPIC -Wl,-soname,libgsequencer.so -pthread
+libgsequencer_la_LIBADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -ldl -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS) $(JACK_LIBS)
+
+# gsequencer
 gsequencer_SOURCES = $(gsequencer_c_sources) $(gsequencerheaders)
 
-gsequencer_CFLAGS += $(UUID_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBAO_CFLAGS) $(LIBXML2_CFLAGS) $(OPENSSL_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS) $(XMLRPC_CFLAGS) $(XMLRPC_UTIL_CFLAGS) $(XMLRPC_SERVER_ABYSS_CFLAGS) $(XMLRPC_SERVER_CGI_CFLAGS) $(XMLRPC_SERVER_CFLAGS) $(PTH_FLAGS) $(JACK_CFLAGS)
-gsequencer_LDFLAGS += -ldl -lm -lrt -pthread -lgmp -lX11 $(UUID_LIBS) $(LIBASOUND2_LIBS) $(LIBAO_LIBS) $(LIBXML2_LIBS) $(OPENSSL_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS) $(XMLRPC_LIBS) $(XMLRPC_UTIL_LIBS) $(XMLRPC_SERVER_ABYSS_LIBS) $(XMLRPC_SERVER_CGI_LIBS) $(XMLRPC_SERVER_LIBS) $(JACK_LIBS)
-gsequencer_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
+gsequencer_CFLAGS += $(LIBASOUND2_CFLAGS) $(LIBAO_CFLAGS) $(LIBXML2_CFLAGS) $(OPENSSL_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS) $(XMLRPC_CFLAGS) $(XMLRPC_UTIL_CFLAGS) $(XMLRPC_SERVER_ABYSS_CFLAGS) $(XMLRPC_SERVER_CGI_CFLAGS) $(XMLRPC_SERVER_CFLAGS) $(PTH_FLAGS) $(JACK_CFLAGS)
+gsequencer_LDFLAGS += -pthread
+gsequencer_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -ldl -lm -lrt -lX11 $(LIBASOUND2_LIBS) $(LIBAO_LIBS) $(LIBXML2_LIBS) $(OPENSSL_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS) $(XMLRPC_LIBS) $(XMLRPC_UTIL_LIBS) $(XMLRPC_SERVER_ABYSS_LIBS) $(XMLRPC_SERVER_CGI_LIBS) $(XMLRPC_SERVER_LIBS) $(JACK_LIBS)
 
 # unit and functional tests
-check_PROGRAMS = \
-	ags_thread_test \
-	ags_turtle_test \
-	ags_audio_test \
-	ags_channel_test \
-	ags_recycling_test \
-	ags_audio_signal_test \
-	ags_recall_test \
-	ags_pattern_test \
-	ags_notation_test \
-	ags_automation_test \
-	ags_midi_buffer_util_test \
-	ags_functional_audio_test
+check_PROGRAMS = 
 
-TESTS = $(check_PROGRAMS)
+include $(top_srcdir)/unit-tests.mk
+include $(top_srcdir)/functional-tests.mk
 
-ags_thread_test_SOURCES = ags/test/thread/ags_thread_test.c
-ags_thread_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS)
-ags_thread_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBXML2_LIBS) $(GOBJECT_LIBS)
-ags_thread_test_LDADD = libags_thread.la libags.la
-
-ags_turtle_test_SOURCES = ags/test/lib/ags_turtle_test.c
-ags_turtle_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_turtle_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_turtle_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-
-ags_audio_test_SOURCES = ags/test/audio/ags_audio_test.c
-ags_audio_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_audio_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_audio_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-
-ags_functional_audio_test_SOURCES = ags/test/audio/ags_functional_audio_test.c
-ags_functional_audio_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_functional_audio_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_functional_audio_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-
-ags_channel_test_SOURCES = ags/test/audio/ags_channel_test.c
-ags_channel_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_channel_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_channel_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-
-ags_recycling_test_SOURCES = ags/test/audio/ags_recycling_test.c
-ags_recycling_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_recycling_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_recycling_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-
-ags_audio_signal_test_SOURCES = ags/test/audio/ags_audio_signal_test.c
-ags_audio_signal_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_audio_signal_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_audio_signal_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-
-ags_recall_test_SOURCES = ags/test/audio/ags_recall_test.c
-ags_recall_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_recall_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_recall_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-
-ags_pattern_test_SOURCES = ags/test/audio/ags_pattern_test.c
-ags_pattern_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_pattern_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_pattern_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-
-ags_notation_test_SOURCES = ags/test/audio/ags_notation_test.c
-ags_notation_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_notation_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_notation_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-
-ags_automation_test_SOURCES = ags/test/audio/ags_automation_test.c
-ags_automation_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_automation_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_automation_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-
-ags_midi_buffer_util_test_SOURCES = ags/test/audio/midi/ags_midi_buffer_util_test.c
-ags_midi_buffer_util_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_midi_buffer_util_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_midi_buffer_util_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
+TESTS = $(check_PROGRAMS)
 
 # libags all files
 deprecated_libags_h_sources =
@@ -351,13 +284,17 @@ deprecated_libags_util_h_sources =
 # libags - util
 libags_util_h_sources = \
 	$(deprecated_libags_util_h_sources) \
-	ags/util/ags_id_generator.h
+	ags/util/ags_destroy_util.h \
+	ags/util/ags_id_generator.h \
+	ags/util/ags_list_util.h
 
 deprecated_libags_util_c_sources =
 
 libags_util_c_sources = \
 	$(deprecated_libags_util_c_sources) \
-	ags/util/ags_id_generator.c
+	ags/util/ags_destroy_util.c \
+	ags/util/ags_id_generator.c \
+	ags/util/ags_list_util.c
 
 deprecated_libags_object_h_sources =
 
@@ -446,6 +383,8 @@ libags_thread_h_sources = \
 	$(deprecated_libags_thread_h_sources) \
 	ags/thread/ags_autosave_thread.h \
 	ags/thread/ags_concurrency_provider.h \
+	ags/thread/ags_condition_manager.h \
+	ags/thread/ags_destroy_worker.h \
 	ags/thread/ags_generic_main_loop.h \
 	ags/thread/ags_history.h \
 	ags/thread/ags_mutex_manager.h \
@@ -461,7 +400,8 @@ libags_thread_h_sources = \
 	ags/thread/ags_thread-posix.h \
 	ags/thread/ags_timestamp_factory.h \
 	ags/thread/ags_timestamp_thread.h \
-	ags/thread/ags_timestamp.h
+	ags/thread/ags_timestamp.h \
+	ags/thread/ags_worker_thread.h
 
 deprecated_libags_thread_c_sources =
 
@@ -469,6 +409,8 @@ libags_thread_c_sources = \
 	$(deprecated_libags_thread_c_sources) \
 	ags/thread/ags_autosave_thread.c \
 	ags/thread/ags_concurrency_provider.c \
+	ags/thread/ags_condition_manager.c \
+	ags/thread/ags_destroy_worker.c \
 	ags/thread/ags_generic_main_loop.c \
 	ags/thread/ags_history.c \
 	ags/thread/ags_mutex_manager.c \
@@ -484,7 +426,8 @@ libags_thread_c_sources = \
 	ags/thread/ags_thread-posix.c \
 	ags/thread/ags_timestamp_factory.c \
 	ags/thread/ags_timestamp_thread.c \
-	ags/thread/ags_timestamp.c
+	ags/thread/ags_timestamp.c \
+	ags/thread/ags_worker_thread.c
 
 # libags-thread - file
 deprecated_libags_thread_file_h_sources =
@@ -698,6 +641,7 @@ libags_plugin_h_sources = \
 	ags/plugin/ags_lv2_conversion.h \
 	ags/plugin/ags_lv2_manager.h \
 	ags/plugin/ags_lv2_plugin.h \
+	ags/plugin/ags_lv2_preset.h \
 	ags/plugin/ags_lv2_event_manager.h \
 	ags/plugin/ags_lv2_log_manager.h \
 	ags/plugin/ags_lv2_uri_map_manager.h \
@@ -721,6 +665,7 @@ libags_plugin_c_sources = \
 	ags/plugin/ags_lv2_conversion.c \
 	ags/plugin/ags_lv2_manager.c \
 	ags/plugin/ags_lv2_plugin.c \
+	ags/plugin/ags_lv2_preset.c \
 	ags/plugin/ags_lv2_log_manager.c \
 	ags/plugin/ags_lv2_event_manager.c \
 	ags/plugin/ags_lv2_uri_map_manager.c \
@@ -855,6 +800,10 @@ libags_audio_recall_h_sources = \
 	ags/audio/recall/ags_play_notation_audio_run.h \
 	ags/audio/recall/ags_play_note.h \
 	ags/audio/recall/ags_play_recycling.h \
+	ags/audio/recall/ags_prepare_audio_signal.h \
+	ags/audio/recall/ags_prepare_channel.h \
+	ags/audio/recall/ags_prepare_channel_run.h \
+	ags/audio/recall/ags_prepare_recycling.h \
 	ags/audio/recall/ags_record_midi_audio.h \
 	ags/audio/recall/ags_record_midi_audio_run.h \
 	ags/audio/recall/ags_route_dssi_audio.h \
@@ -923,6 +872,10 @@ libags_audio_recall_c_sources = \
 	ags/audio/recall/ags_play_notation_audio_run.c \
 	ags/audio/recall/ags_play_note.c \
 	ags/audio/recall/ags_play_recycling.c \
+	ags/audio/recall/ags_prepare_audio_signal.c \
+	ags/audio/recall/ags_prepare_channel.c \
+	ags/audio/recall/ags_prepare_channel_run.c \
+	ags/audio/recall/ags_prepare_recycling.c \
 	ags/audio/recall/ags_record_midi_audio.c \
 	ags/audio/recall/ags_record_midi_audio_run.c \
 	ags/audio/recall/ags_route_dssi_audio.c \
@@ -963,6 +916,7 @@ libags_audio_task_h_sources = \
 	ags/audio/task/ags_cancel_channel.h \
 	ags/audio/task/ags_cancel_recall.h \
 	ags/audio/task/ags_change_soundcard.h \
+	ags/audio/task/ags_clear_buffer.h \
 	ags/audio/task/ags_export_output.h \
 	ags/audio/task/ags_free_selection.h \
 	ags/audio/task/ags_init_audio.h \
@@ -1024,6 +978,7 @@ libags_audio_task_c_sources = \
 	ags/audio/task/ags_cancel_channel.c \
 	ags/audio/task/ags_cancel_recall.c \
 	ags/audio/task/ags_change_soundcard.c \
+	ags/audio/task/ags_clear_buffer.c \
 	ags/audio/task/ags_export_output.c \
 	ags/audio/task/ags_free_selection.c \
 	ags/audio/task/ags_init_audio.c \
@@ -1072,13 +1027,16 @@ libags_gui_h_sources = \
 	ags/widget/ags_expander.h \
 	ags/widget/ags_expander_set.h \
 	ags/widget/ags_hindicator.h \
+	ags/widget/ags_hled_array.h \
 	ags/widget/ags_htimebar.h \
 	ags/widget/ags_indicator.h \
 	ags/widget/ags_led.h \
+	ags/widget/ags_led_array.h \
 	ags/widget/ags_ruler.h \
 	ags/widget/ags_table.h \
 	ags/widget/ags_timebar.h \
 	ags/widget/ags_vindicator.h \
+	ags/widget/ags_vled_array.h \
 	ags/widget/ags_waveform.h \
 	ags/widget/ags_container.h
 
@@ -1091,13 +1049,16 @@ libags_gui_c_sources = \
 	ags/widget/ags_expander.c \
 	ags/widget/ags_expander_set.c \
 	ags/widget/ags_hindicator.c \
+	ags/widget/ags_hled_array.c \
 	ags/widget/ags_htimebar.c \
 	ags/widget/ags_indicator.c \
 	ags/widget/ags_led.c \
+	ags/widget/ags_led_array.c \
 	ags/widget/ags_ruler.c \
 	ags/widget/ags_table.c \
 	ags/widget/ags_timebar.c \
 	ags/widget/ags_vindicator.c \
+	ags/widget/ags_vled_array.c \
 	ags/widget/ags_waveform.c \
 	ags/widget/ags_container.c
 
@@ -1106,8 +1067,6 @@ deprecated_libgsequencer_h_sources =
 
 libgsequencer_h_sources = \
 	$(deprecated_libgsequencer_h_sources) \
-	ags/X/ags_audio_connection_collection_editor_callbacks.h \
-	ags/X/ags_audio_connection_collection_editor.h \
 	ags/X/ags_automation_editor_callbacks.h \
 	ags/X/ags_automation_editor.h \
 	ags/X/ags_automation_window_callbacks.h \
@@ -1168,6 +1127,12 @@ libgsequencer_h_sources = \
 	ags/X/ags_midi_preferences_callbacks.h \
 	ags/X/ags_navigation_callbacks.h \
 	ags/X/ags_navigation.h \
+	ags/X/ags_output_collection_editor_callbacks.h \
+	ags/X/ags_output_collection_editor.h \
+	ags/X/ags_output_editor.h \
+	ags/X/ags_output_editor_callbacks.h \
+	ags/X/ags_output_listing_editor.h \
+	ags/X/ags_output_listing_editor_callbacks.h \
 	ags/X/ags_pad_callbacks.h \
 	ags/X/ags_pad_editor_callbacks.h \
 	ags/X/ags_pad_editor.h \
@@ -1200,8 +1165,6 @@ deprecated_libgsequencer_c_sources =
 
 libgsequencer_c_sources = \
 	$(deprecated_libgsequencer_c_sources) \
-	ags/X/ags_audio_connection_collection_editor_callbacks.c \
-	ags/X/ags_audio_connection_collection_editor.c \
 	ags/X/ags_automation_editor.c \
 	ags/X/ags_automation_editor_callbacks.c \
 	ags/X/ags_automation_window.c \
@@ -1262,6 +1225,12 @@ libgsequencer_c_sources = \
 	ags/X/ags_midi_preferences_callbacks.c \
 	ags/X/ags_navigation.c \
 	ags/X/ags_navigation_callbacks.c \
+	ags/X/ags_output_collection_editor_callbacks.c \
+	ags/X/ags_output_collection_editor.c \
+	ags/X/ags_output_editor.c \
+	ags/X/ags_output_editor_callbacks.c \
+	ags/X/ags_output_listing_editor.c \
+	ags/X/ags_output_listing_editor_callbacks.c \
 	ags/X/ags_pad.c \
 	ags/X/ags_pad_callbacks.c \
 	ags/X/ags_pad_editor.c \
@@ -1576,7 +1545,7 @@ gsequencerheaders = \
 gsequencer_c_sources = \
 	ags/gsequencer_main.c
 
-midi2xml_CFLAGS += -I./ -I/usr/include $(UUID_CFLAGS) $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS) $(GIO_CFLAGS)
+midi2xml_CFLAGS += -I./ -I/usr/include $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS) $(GIO_CFLAGS)
 midi2xml_LDFLAGS += -ldl $(LIBXML2_LIBS) $(GOBJECT_LIBS)
 midi2xml_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
 
@@ -1585,9 +1554,11 @@ midi2xml_SOURCES = ags/midi2xml_main.c
 ags-docs-local:
 	$(MAKE) -C $(top_srcdir)/docs/reference/libags
 	cd $(top_srcdir)
-	$(MAKE) -C $(top_srcdir)/docs/reference/libags_audio
+	$(MAKE) -C $(top_srcdir)/docs/reference/libags-audio
+	cd $(top_srcdir)
+	$(MAKE) -C $(top_srcdir)/docs/reference/libags-gui
 	cd $(top_srcdir)
-	$(MAKE) -C $(top_srcdir)/docs/reference/libags_gui
+	$(MAKE) -C $(top_srcdir)/docs/reference/libgsequencer
 	cd $(top_srcdir)
 
 libtool: $(LIBTOOL_DEPS)
@@ -1612,14 +1583,17 @@ install-data-local:
 	mkdir -p $(DESTDIR)/$(datadir)/doc-base
 	mkdir -p $(DESTDIR)/$(datadir)/gsequencer/icons
 	mkdir -p $(DESTDIR)/$(datadir)/gsequencer/images
+	mkdir -p $(DESTDIR)/$(datadir)/gsequencer/styles
 	mkdir -p $(DESTDIR)/$(datadir)/xml/gsequencer/{schema/dtd/$(PACKAGE_VERSION)/,stylesheet/ags-xsl/midi-xml/}
 	install -c -p -m 644 $(top_srcdir)/gsequencer.share/icons/ags.xpm $(DESTDIR)/$(datadir)/gsequencer/icons/ags.xpm
 	install -c -p -m 644 $(top_srcdir)/gsequencer.share/images/ags.png $(DESTDIR)/$(datadir)/gsequencer/images/ags.png
 	install -c -p -m 644 $(top_srcdir)/gsequencer.share/images/ags_supermoon-800x450.png $(DESTDIR)/$(datadir)/gsequencer/images/ags_supermoon-800x450.png
+	install -c -p -m 644 $(top_srcdir)/gsequencer.share/styles/ags.rc $(DESTDIR)/$(datadir)/gsequencer/styles/ags.rc
 	install -c -p -m 644 $(top_srcdir)/ags/X/file/ags_simple_file.dtd $(DESTDIR)/$(datadir)/xml/gsequencer/schema/dtd/$(PACKAGE_VERSION)/
 	install -c -p -m 644 $(top_srcdir)/ags/audio/midi/ags_midi_file.dtd $(DESTDIR)/$(datadir)/xml/gsequencer/schema/dtd/$(PACKAGE_VERSION)/
 	install -c -p -m 644 $(top_srcdir)/ags/file/ags_file.dtd $(DESTDIR)/$(datadir)/xml/gsequencer/schema/dtd/$(PACKAGE_VERSION)/
 	install -c -p -m 644 $(top_srcdir)/ags.xsl $(DESTDIR)/$(datadir)/xml/gsequencer/stylesheet/ags-xsl/midi-xml/
+	install -c -p -m 644 $(top_srcdir)/ags-simple.xsl $(DESTDIR)/$(datadir)/xml/gsequencer/stylesheet/ags-xsl/midi-xml/
 	install -c -p -m 644 $(top_srcdir)/gsequencer-documentation $(DESTDIR)/$(datadir)/doc-base/
 	mkdir -p $(DESTDIR)/$(datadir)/doc/gsequencer/
 	gzip -9 -c $(top_srcdir)/ChangeLog > $(DESTDIR)/$(datadir)/doc/gsequencer/changelog.gz
@@ -1637,12 +1611,15 @@ install-ags-docs: ags-docs
 	mkdir -p $(DESTDIR)/$(datadir)/doc/libags-doc/api
 	mkdir -p $(DESTDIR)/$(datadir)/doc/libags-audio-doc/api
 	mkdir -p $(DESTDIR)/$(datadir)/doc/libags-gui-doc/api
+	mkdir -p $(DESTDIR)/$(datadir)/doc/libgsequencer-doc/api
 	install -c -p -m 644 $(top_srcdir)/docs/reference/libags/html/* $(DESTDIR)/$(datadir)/doc/libags-doc/api
-	install -c -p -m 644 $(top_srcdir)/docs/reference/libags_audio/html/* $(DESTDIR)/$(datadir)/doc/libags-audio-doc/api
-	install -c -p -m 644 $(top_srcdir)/docs/reference/libags_gui/html/* $(DESTDIR)/$(datadir)/doc/libags-gui-doc/api
+	install -c -p -m 644 $(top_srcdir)/docs/reference/libags-audio/html/* $(DESTDIR)/$(datadir)/doc/libags-audio-doc/api
+	install -c -p -m 644 $(top_srcdir)/docs/reference/libags-gui/html/* $(DESTDIR)/$(datadir)/doc/libags-gui-doc/api
+	install -c -p -m 644 $(top_srcdir)/docs/reference/libgsequencer/html/* $(DESTDIR)/$(datadir)/doc/libgsequencer-doc/api
 	ln -s ../../doc/libags-doc/api $(DESTDIR)/$(datadir)/gtk-doc/html/libags
-	ln -s ../../doc/libags-audio-doc/api $(DESTDIR)/$(datadir)/gtk-doc/html/libags_audio
-	ln -s ../../doc/libags-gui-doc/api $(DESTDIR)/$(datadir)/gtk-doc/html/libags_gui
+	ln -s ../../doc/libags-audio-doc/api $(DESTDIR)/$(datadir)/gtk-doc/html/libags-audio
+	ln -s ../../doc/libags-gui-doc/api $(DESTDIR)/$(datadir)/gtk-doc/html/libags-gui
+	ln -s ../../doc/libgsequencer-doc/api $(DESTDIR)/$(datadir)/gtk-doc/html/libgsequencer
 
 uninstall-hook:
 	rm -rf $(DESTDIR)/$(datadir)/gsequencer
@@ -1658,24 +1635,26 @@ uninstall-hook:
 	rm -f $(DESTDIR)/$(pkgconfigdir)/libags.pc
 	rm -f $(DESTDIR)/$(pkgconfigdir)/libags_audio.pc
 	rm -f $(DESTDIR)/$(pkgconfigdir)/libags_gui.pc
+	rm -f $(DESTDIR)/$(pkgconfigdir)/libgsequencer.pc
 
 clean-local:
 	rm -rf $(top_srcdir)/html
 	rm -rf $(top_srcdir)/docs/reference/libags/xml
 	rm -rf $(top_srcdir)/docs/reference/libags/html
 	rm -rf $(top_srcdir)/docs/reference/libags/tmpl
-	rm -rf $(top_srcdir)/docs/reference/libags_audio/xml
-	rm -rf $(top_srcdir)/docs/reference/libags_audio/html
-	rm -rf $(top_srcdir)/docs/reference/libags_audio/tmpl
-	rm -rf $(top_srcdir)/docs/reference/libags_gui/xml
-	rm -rf $(top_srcdir)/docs/reference/libags_gui/html
-	rm -rf $(top_srcdir)/docs/reference/libags_gui/tmpl
+	rm -rf $(top_srcdir)/docs/reference/libags-audio/xml
+	rm -rf $(top_srcdir)/docs/reference/libags-audio/html
+	rm -rf $(top_srcdir)/docs/reference/libags-audio/tmpl
+	rm -rf $(top_srcdir)/docs/reference/libags-gui/xml
+	rm -rf $(top_srcdir)/docs/reference/libags-gui/html
+	rm -rf $(top_srcdir)/docs/reference/libags-gui/tmpl
 	rm -rf $(top_srcdir)/docs/reference/libgsequencer/xml
 	rm -rf $(top_srcdir)/docs/reference/libgsequencer/html
 	rm -rf $(top_srcdir)/docs/reference/libgsequencer/tmpl
 	rm -f $(top_builddir)/docs/reference/libags/Makefile
-	rm -f $(top_builddir)/docs/reference/libags_audio/Makefile
-	rm -f $(top_builddir)/docs/reference/libags_gui/Makefile
+	rm -f $(top_builddir)/docs/reference/libags-audio/Makefile
+	rm -f $(top_builddir)/docs/reference/libags-gui/Makefile
+	rm -f $(top_builddir)/docs/reference/libgsequencer/Makefile
 
 
 gen-symbols-ags:
diff --git a/Makefile.in b/Makefile.in
index a6fc78e..f82ff8b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -93,12 +93,23 @@ build_triplet = @build@
 host_triplet = @host@
 bin_PROGRAMS = gsequencer$(EXEEXT) midi2xml$(EXEEXT)
 check_PROGRAMS = ags_thread_test$(EXEEXT) ags_turtle_test$(EXEEXT) \
-	ags_audio_test$(EXEEXT) ags_channel_test$(EXEEXT) \
-	ags_recycling_test$(EXEEXT) ags_audio_signal_test$(EXEEXT) \
-	ags_recall_test$(EXEEXT) ags_pattern_test$(EXEEXT) \
-	ags_notation_test$(EXEEXT) ags_automation_test$(EXEEXT) \
+	ags_audio_application_context_test$(EXEEXT) \
+	ags_devout_test$(EXEEXT) ags_audio_test$(EXEEXT) \
+	ags_channel_test$(EXEEXT) ags_recycling_test$(EXEEXT) \
+	ags_audio_signal_test$(EXEEXT) ags_recall_test$(EXEEXT) \
+	ags_pattern_test$(EXEEXT) ags_notation_test$(EXEEXT) \
+	ags_automation_test$(EXEEXT) \
 	ags_midi_buffer_util_test$(EXEEXT) \
-	ags_functional_audio_test$(EXEEXT)
+	ags_xorg_application_context_test$(EXEEXT) \
+	ags_functional_audio_test$(EXEEXT) \
+	ags_functional_machine_add_and_destroy_test$(EXEEXT) \
+	ags_functional_panel_test$(EXEEXT) \
+	ags_functional_mixer_test$(EXEEXT) \
+	ags_functional_drum_test$(EXEEXT) \
+	ags_functional_matrix_test$(EXEEXT) \
+	ags_functional_synth_test$(EXEEXT) \
+	ags_functional_ffplayer_test$(EXEEXT) \
+	ags_functional_note_edit_test$(EXEEXT)
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \
@@ -115,7 +126,8 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
  configure.lineno config.status.lineno
 mkinstalldirs = $(install_sh) -d
 CONFIG_HEADER = $(top_builddir)/ags/config.h
-CONFIG_CLEAN_FILES = libags.pc libags_audio.pc libags_gui.pc
+CONFIG_CLEAN_FILES = libags.pc libags_audio.pc libags_gui.pc \
+	libgsequencer.pc
 CONFIG_CLEAN_VPATH_FILES =
 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
 am__vpath_adj = case $$p in \
@@ -149,8 +161,11 @@ am__installdirs = "$(DESTDIR)$(libdir)" \
 	"$(DESTDIR)$(man1dir)" "$(DESTDIR)$(appdatadir)" \
 	"$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgconfigdir)" \
 	"$(DESTDIR)$(includedir)"
-LTLIBRARIES = $(lib_LTLIBRARIES) $(libgsequencer_LTLIBRARIES)
-libags_la_LIBADD =
+LTLIBRARIES = $(lib_LTLIBRARIES) $(libgsequencer_LTLIBRARIES) \
+	$(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libags_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am__objects_1 =
 am__dirstamp = $(am__leading_dot)dirstamp
 am__objects_2 = $(am__objects_1) ags/lib/libags_la-ags_complex.lo \
@@ -162,7 +177,9 @@ am__objects_2 = $(am__objects_1) ags/lib/libags_la-ags_complex.lo \
 	ags/lib/libags_la-ags_time.lo ags/lib/libags_la-ags_turtle.lo \
 	ags/lib/libags_la-ags_turtle_manager.lo
 am__objects_3 = $(am__objects_1) \
-	ags/util/libags_la-ags_id_generator.lo
+	ags/util/libags_la-ags_destroy_util.lo \
+	ags/util/libags_la-ags_id_generator.lo \
+	ags/util/libags_la-ags_list_util.lo
 am__objects_4 = $(am__objects_1) \
 	ags/object/libags_la-ags_applicable.lo \
 	ags/object/libags_la-ags_application_context.lo \
@@ -203,7 +220,10 @@ libags_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libags_la_CFLAGS) \
 	$(CFLAGS) $(libags_la_LDFLAGS) $(LDFLAGS) -o $@
 libags_audio_la_DEPENDENCIES = libags_server.la libags_thread.la \
-	libags.la
+	libags.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 am__objects_6 = $(am__objects_1) \
 	ags/audio/libags_audio_la-ags_acceleration.lo \
 	ags/audio/libags_audio_la-ags_audio.lo \
@@ -308,6 +328,7 @@ am__objects_12 = $(am__objects_1) \
 	ags/audio/task/libags_audio_la-ags_cancel_channel.lo \
 	ags/audio/task/libags_audio_la-ags_cancel_recall.lo \
 	ags/audio/task/libags_audio_la-ags_change_soundcard.lo \
+	ags/audio/task/libags_audio_la-ags_clear_buffer.lo \
 	ags/audio/task/libags_audio_la-ags_export_output.lo \
 	ags/audio/task/libags_audio_la-ags_free_selection.lo \
 	ags/audio/task/libags_audio_la-ags_init_audio.lo \
@@ -394,6 +415,10 @@ am__objects_13 = $(am__objects_1) \
 	ags/audio/recall/libags_audio_la-ags_play_notation_audio_run.lo \
 	ags/audio/recall/libags_audio_la-ags_play_note.lo \
 	ags/audio/recall/libags_audio_la-ags_play_recycling.lo \
+	ags/audio/recall/libags_audio_la-ags_prepare_audio_signal.lo \
+	ags/audio/recall/libags_audio_la-ags_prepare_channel.lo \
+	ags/audio/recall/libags_audio_la-ags_prepare_channel_run.lo \
+	ags/audio/recall/libags_audio_la-ags_prepare_recycling.lo \
 	ags/audio/recall/libags_audio_la-ags_record_midi_audio.lo \
 	ags/audio/recall/libags_audio_la-ags_record_midi_audio_run.lo \
 	ags/audio/recall/libags_audio_la-ags_route_dssi_audio.lo \
@@ -419,6 +444,7 @@ am__objects_14 = $(am__objects_1) \
 	ags/plugin/libags_audio_la-ags_lv2_conversion.lo \
 	ags/plugin/libags_audio_la-ags_lv2_manager.lo \
 	ags/plugin/libags_audio_la-ags_lv2_plugin.lo \
+	ags/plugin/libags_audio_la-ags_lv2_preset.lo \
 	ags/plugin/libags_audio_la-ags_lv2_log_manager.lo \
 	ags/plugin/libags_audio_la-ags_lv2_event_manager.lo \
 	ags/plugin/libags_audio_la-ags_lv2_uri_map_manager.lo \
@@ -437,20 +463,25 @@ libags_audio_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(libags_audio_la_CFLAGS) $(CFLAGS) $(libags_audio_la_LDFLAGS) \
 	$(LDFLAGS) -o $@
-libags_gui_la_LIBADD =
+libags_gui_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 am__objects_15 = $(am__objects_1) \
 	ags/widget/libags_gui_la-ags_cartesian.lo \
 	ags/widget/libags_gui_la-ags_dial.lo \
 	ags/widget/libags_gui_la-ags_expander.lo \
 	ags/widget/libags_gui_la-ags_expander_set.lo \
 	ags/widget/libags_gui_la-ags_hindicator.lo \
+	ags/widget/libags_gui_la-ags_hled_array.lo \
 	ags/widget/libags_gui_la-ags_htimebar.lo \
 	ags/widget/libags_gui_la-ags_indicator.lo \
 	ags/widget/libags_gui_la-ags_led.lo \
+	ags/widget/libags_gui_la-ags_led_array.lo \
 	ags/widget/libags_gui_la-ags_ruler.lo \
 	ags/widget/libags_gui_la-ags_table.lo \
 	ags/widget/libags_gui_la-ags_timebar.lo \
 	ags/widget/libags_gui_la-ags_vindicator.lo \
+	ags/widget/libags_gui_la-ags_vled_array.lo \
 	ags/widget/libags_gui_la-ags_waveform.lo \
 	ags/widget/libags_gui_la-ags_container.lo
 am_libags_gui_la_OBJECTS = $(am__objects_15)
@@ -458,7 +489,8 @@ libags_gui_la_OBJECTS = $(am_libags_gui_la_OBJECTS)
 libags_gui_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libags_gui_la_CFLAGS) \
 	$(CFLAGS) $(libags_gui_la_LDFLAGS) $(LDFLAGS) -o $@
-libags_server_la_DEPENDENCIES = libags_thread.la libags.la
+libags_server_la_DEPENDENCIES = libags_thread.la libags.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am__objects_16 = $(am__objects_1) \
 	ags/server/libags_server_la-ags_registry.lo \
 	ags/server/libags_server_la-ags_remote_task.lo \
@@ -471,10 +503,13 @@ libags_server_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(libags_server_la_CFLAGS) $(CFLAGS) \
 	$(libags_server_la_LDFLAGS) $(LDFLAGS) -o $@
-libags_thread_la_DEPENDENCIES = libags.la
+libags_thread_la_DEPENDENCIES = libags.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 am__objects_17 = $(am__objects_1) \
 	ags/thread/libags_thread_la-ags_autosave_thread.lo \
 	ags/thread/libags_thread_la-ags_concurrency_provider.lo \
+	ags/thread/libags_thread_la-ags_condition_manager.lo \
+	ags/thread/libags_thread_la-ags_destroy_worker.lo \
 	ags/thread/libags_thread_la-ags_generic_main_loop.lo \
 	ags/thread/libags_thread_la-ags_history.lo \
 	ags/thread/libags_thread_la-ags_mutex_manager.lo \
@@ -490,7 +525,8 @@ am__objects_17 = $(am__objects_1) \
 	ags/thread/libags_thread_la-ags_thread-posix.lo \
 	ags/thread/libags_thread_la-ags_timestamp_factory.lo \
 	ags/thread/libags_thread_la-ags_timestamp_thread.lo \
-	ags/thread/libags_thread_la-ags_timestamp.lo
+	ags/thread/libags_thread_la-ags_timestamp.lo \
+	ags/thread/libags_thread_la-ags_worker_thread.lo
 am__objects_18 = $(am__objects_1) \
 	ags/thread/file/libags_thread_la-ags_thread_file_xml.lo
 am_libags_thread_la_OBJECTS = $(am__objects_17) $(am__objects_18)
@@ -500,14 +536,16 @@ libags_thread_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(libags_thread_la_CFLAGS) $(CFLAGS) \
 	$(libags_thread_la_LDFLAGS) $(LDFLAGS) -o $@
 libgsequencer_la_DEPENDENCIES = libags_audio.la libags_server.la \
-	libags_gui.la libags_thread.la libags.la
+	libags_gui.la libags_thread.la libags.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am__objects_19 = $(am__objects_1)
 am__objects_20 = $(am__objects_19) $(am__objects_19) $(am__objects_19) \
 	$(am__objects_19) $(am__objects_19) $(am__objects_19) \
 	$(am__objects_19)
 am__objects_21 = $(am__objects_1) \
-	ags/X/libgsequencer_la-ags_audio_connection_collection_editor_callbacks.lo \
-	ags/X/libgsequencer_la-ags_audio_connection_collection_editor.lo \
 	ags/X/libgsequencer_la-ags_automation_editor.lo \
 	ags/X/libgsequencer_la-ags_automation_editor_callbacks.lo \
 	ags/X/libgsequencer_la-ags_automation_window.lo \
@@ -568,6 +606,12 @@ am__objects_21 = $(am__objects_1) \
 	ags/X/libgsequencer_la-ags_midi_preferences_callbacks.lo \
 	ags/X/libgsequencer_la-ags_navigation.lo \
 	ags/X/libgsequencer_la-ags_navigation_callbacks.lo \
+	ags/X/libgsequencer_la-ags_output_collection_editor_callbacks.lo \
+	ags/X/libgsequencer_la-ags_output_collection_editor.lo \
+	ags/X/libgsequencer_la-ags_output_editor.lo \
+	ags/X/libgsequencer_la-ags_output_editor_callbacks.lo \
+	ags/X/libgsequencer_la-ags_output_listing_editor.lo \
+	ags/X/libgsequencer_la-ags_output_listing_editor_callbacks.lo \
 	ags/X/libgsequencer_la-ags_pad.lo \
 	ags/X/libgsequencer_la-ags_pad_callbacks.lo \
 	ags/X/libgsequencer_la-ags_pad_editor.lo \
@@ -715,11 +759,41 @@ libgsequencer_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(libgsequencer_la_CFLAGS) $(CFLAGS) \
 	$(libgsequencer_la_LDFLAGS) $(LDFLAGS) -o $@
+libgsequencer_test_la_DEPENDENCIES = libgsequencer.la libags_audio.la \
+	libags_server.la libags_gui.la libags_thread.la libags.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_libgsequencer_test_la_OBJECTS =  \
+	ags/test/X/libgsequencer_test_la-gsequencer_setup_util.lo \
+	ags/test/X/libgsequencer_test_la-ags_functional_test_util.lo
+libgsequencer_test_la_OBJECTS = $(am_libgsequencer_test_la_OBJECTS)
+libgsequencer_test_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(libgsequencer_test_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
 PROGRAMS = $(bin_PROGRAMS)
+am_ags_audio_application_context_test_OBJECTS = ags/test/audio/ags_audio_application_context_test-ags_audio_application_context_test.$(OBJEXT)
+ags_audio_application_context_test_OBJECTS =  \
+	$(am_ags_audio_application_context_test_OBJECTS)
+ags_audio_application_context_test_DEPENDENCIES = libags_audio.la \
+	libags_server.la libags_gui.la libags_thread.la libags.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ags_audio_application_context_test_LINK = $(LIBTOOL) $(AM_V_lt) \
+	--tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
+	$(CCLD) $(ags_audio_application_context_test_CFLAGS) $(CFLAGS) \
+	$(ags_audio_application_context_test_LDFLAGS) $(LDFLAGS) -o $@
 am_ags_audio_signal_test_OBJECTS = ags/test/audio/ags_audio_signal_test-ags_audio_signal_test.$(OBJEXT)
 ags_audio_signal_test_OBJECTS = $(am_ags_audio_signal_test_OBJECTS)
 ags_audio_signal_test_DEPENDENCIES = libags_audio.la libags_server.la \
-	libags_gui.la libags_thread.la libags.la
+	libags_gui.la libags_thread.la libags.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 ags_audio_signal_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(ags_audio_signal_test_CFLAGS) $(CFLAGS) \
@@ -728,7 +802,10 @@ am_ags_audio_test_OBJECTS =  \
 	ags/test/audio/ags_audio_test-ags_audio_test.$(OBJEXT)
 ags_audio_test_OBJECTS = $(am_ags_audio_test_OBJECTS)
 ags_audio_test_DEPENDENCIES = libags_audio.la libags_server.la \
-	libags_gui.la libags_thread.la libags.la
+	libags_gui.la libags_thread.la libags.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 ags_audio_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(ags_audio_test_CFLAGS) $(CFLAGS) $(ags_audio_test_LDFLAGS) \
@@ -736,7 +813,10 @@ ags_audio_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 am_ags_automation_test_OBJECTS = ags/test/audio/ags_automation_test-ags_automation_test.$(OBJEXT)
 ags_automation_test_OBJECTS = $(am_ags_automation_test_OBJECTS)
 ags_automation_test_DEPENDENCIES = libags_audio.la libags_server.la \
-	libags_gui.la libags_thread.la libags.la
+	libags_gui.la libags_thread.la libags.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 ags_automation_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(ags_automation_test_CFLAGS) $(CFLAGS) \
@@ -745,25 +825,169 @@ am_ags_channel_test_OBJECTS =  \
 	ags/test/audio/ags_channel_test-ags_channel_test.$(OBJEXT)
 ags_channel_test_OBJECTS = $(am_ags_channel_test_OBJECTS)
 ags_channel_test_DEPENDENCIES = libags_audio.la libags_server.la \
-	libags_gui.la libags_thread.la libags.la
+	libags_gui.la libags_thread.la libags.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 ags_channel_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(ags_channel_test_CFLAGS) $(CFLAGS) \
 	$(ags_channel_test_LDFLAGS) $(LDFLAGS) -o $@
+am_ags_devout_test_OBJECTS =  \
+	ags/test/audio/ags_devout_test-ags_devout_test.$(OBJEXT)
+ags_devout_test_OBJECTS = $(am_ags_devout_test_OBJECTS)
+ags_devout_test_DEPENDENCIES = libags_audio.la libags_server.la \
+	libags_gui.la libags_thread.la libags.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
+ags_devout_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(ags_devout_test_CFLAGS) $(CFLAGS) $(ags_devout_test_LDFLAGS) \
+	$(LDFLAGS) -o $@
 am_ags_functional_audio_test_OBJECTS = ags/test/audio/ags_functional_audio_test-ags_functional_audio_test.$(OBJEXT)
 ags_functional_audio_test_OBJECTS =  \
 	$(am_ags_functional_audio_test_OBJECTS)
 ags_functional_audio_test_DEPENDENCIES = libags_audio.la \
-	libags_server.la libags_gui.la libags_thread.la libags.la
+	libags_server.la libags_gui.la libags_thread.la libags.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 ags_functional_audio_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(ags_functional_audio_test_CFLAGS) $(CFLAGS) \
 	$(ags_functional_audio_test_LDFLAGS) $(LDFLAGS) -o $@
+am_ags_functional_drum_test_OBJECTS = ags/test/X/machine/ags_functional_drum_test-ags_functional_drum_test.$(OBJEXT)
+ags_functional_drum_test_OBJECTS =  \
+	$(am_ags_functional_drum_test_OBJECTS)
+ags_functional_drum_test_DEPENDENCIES = libgsequencer.la \
+	libags_audio.la libags_server.la libags_gui.la \
+	libags_thread.la libags.la libgsequencer_test.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ags_functional_drum_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(ags_functional_drum_test_CFLAGS) $(CFLAGS) \
+	$(ags_functional_drum_test_LDFLAGS) $(LDFLAGS) -o $@
+am_ags_functional_ffplayer_test_OBJECTS = ags/test/X/machine/ags_functional_ffplayer_test-ags_functional_ffplayer_test.$(OBJEXT)
+ags_functional_ffplayer_test_OBJECTS =  \
+	$(am_ags_functional_ffplayer_test_OBJECTS)
+ags_functional_ffplayer_test_DEPENDENCIES = libgsequencer.la \
+	libags_audio.la libags_server.la libags_gui.la \
+	libags_thread.la libags.la libgsequencer_test.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ags_functional_ffplayer_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(ags_functional_ffplayer_test_CFLAGS) $(CFLAGS) \
+	$(ags_functional_ffplayer_test_LDFLAGS) $(LDFLAGS) -o $@
+am_ags_functional_machine_add_and_destroy_test_OBJECTS = ags/test/X/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.$(OBJEXT)
+ags_functional_machine_add_and_destroy_test_OBJECTS =  \
+	$(am_ags_functional_machine_add_and_destroy_test_OBJECTS)
+ags_functional_machine_add_and_destroy_test_DEPENDENCIES =  \
+	libgsequencer.la libags_audio.la libags_server.la \
+	libags_gui.la libags_thread.la libags.la libgsequencer_test.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ags_functional_machine_add_and_destroy_test_LINK = $(LIBTOOL) \
+	$(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) \
+	$(ags_functional_machine_add_and_destroy_test_CFLAGS) \
+	$(CFLAGS) \
+	$(ags_functional_machine_add_and_destroy_test_LDFLAGS) \
+	$(LDFLAGS) -o $@
+am_ags_functional_matrix_test_OBJECTS = ags/test/X/machine/ags_functional_matrix_test-ags_functional_matrix_test.$(OBJEXT)
+ags_functional_matrix_test_OBJECTS =  \
+	$(am_ags_functional_matrix_test_OBJECTS)
+ags_functional_matrix_test_DEPENDENCIES = libgsequencer.la \
+	libags_audio.la libags_server.la libags_gui.la \
+	libags_thread.la libags.la libgsequencer_test.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ags_functional_matrix_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(ags_functional_matrix_test_CFLAGS) $(CFLAGS) \
+	$(ags_functional_matrix_test_LDFLAGS) $(LDFLAGS) -o $@
+am_ags_functional_mixer_test_OBJECTS = ags/test/X/machine/ags_functional_mixer_test-ags_functional_mixer_test.$(OBJEXT)
+ags_functional_mixer_test_OBJECTS =  \
+	$(am_ags_functional_mixer_test_OBJECTS)
+ags_functional_mixer_test_DEPENDENCIES = libgsequencer.la \
+	libags_audio.la libags_server.la libags_gui.la \
+	libags_thread.la libags.la libgsequencer_test.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ags_functional_mixer_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(ags_functional_mixer_test_CFLAGS) $(CFLAGS) \
+	$(ags_functional_mixer_test_LDFLAGS) $(LDFLAGS) -o $@
+am_ags_functional_note_edit_test_OBJECTS = ags/test/X/ags_functional_note_edit_test-ags_functional_note_edit_test.$(OBJEXT)
+ags_functional_note_edit_test_OBJECTS =  \
+	$(am_ags_functional_note_edit_test_OBJECTS)
+ags_functional_note_edit_test_DEPENDENCIES = libgsequencer.la \
+	libags_audio.la libags_server.la libags_gui.la \
+	libags_thread.la libags.la libgsequencer_test.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ags_functional_note_edit_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(ags_functional_note_edit_test_CFLAGS) $(CFLAGS) \
+	$(ags_functional_note_edit_test_LDFLAGS) $(LDFLAGS) -o $@
+am_ags_functional_panel_test_OBJECTS = ags/test/X/machine/ags_functional_panel_test-ags_functional_panel_test.$(OBJEXT)
+ags_functional_panel_test_OBJECTS =  \
+	$(am_ags_functional_panel_test_OBJECTS)
+ags_functional_panel_test_DEPENDENCIES = libgsequencer.la \
+	libags_audio.la libags_server.la libags_gui.la \
+	libags_thread.la libags.la libgsequencer_test.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ags_functional_panel_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(ags_functional_panel_test_CFLAGS) $(CFLAGS) \
+	$(ags_functional_panel_test_LDFLAGS) $(LDFLAGS) -o $@
+am_ags_functional_synth_test_OBJECTS = ags/test/X/machine/ags_functional_synth_test-ags_functional_synth_test.$(OBJEXT)
+ags_functional_synth_test_OBJECTS =  \
+	$(am_ags_functional_synth_test_OBJECTS)
+ags_functional_synth_test_DEPENDENCIES = libgsequencer.la \
+	libags_audio.la libags_server.la libags_gui.la \
+	libags_thread.la libags.la libgsequencer_test.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ags_functional_synth_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(ags_functional_synth_test_CFLAGS) $(CFLAGS) \
+	$(ags_functional_synth_test_LDFLAGS) $(LDFLAGS) -o $@
 am_ags_midi_buffer_util_test_OBJECTS = ags/test/audio/midi/ags_midi_buffer_util_test-ags_midi_buffer_util_test.$(OBJEXT)
 ags_midi_buffer_util_test_OBJECTS =  \
 	$(am_ags_midi_buffer_util_test_OBJECTS)
 ags_midi_buffer_util_test_DEPENDENCIES = libags_audio.la \
-	libags_server.la libags_gui.la libags_thread.la libags.la
+	libags_server.la libags_gui.la libags_thread.la libags.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 ags_midi_buffer_util_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(ags_midi_buffer_util_test_CFLAGS) $(CFLAGS) \
@@ -772,7 +996,10 @@ am_ags_notation_test_OBJECTS =  \
 	ags/test/audio/ags_notation_test-ags_notation_test.$(OBJEXT)
 ags_notation_test_OBJECTS = $(am_ags_notation_test_OBJECTS)
 ags_notation_test_DEPENDENCIES = libags_audio.la libags_server.la \
-	libags_gui.la libags_thread.la libags.la
+	libags_gui.la libags_thread.la libags.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 ags_notation_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(ags_notation_test_CFLAGS) $(CFLAGS) \
@@ -781,7 +1008,10 @@ am_ags_pattern_test_OBJECTS =  \
 	ags/test/audio/ags_pattern_test-ags_pattern_test.$(OBJEXT)
 ags_pattern_test_OBJECTS = $(am_ags_pattern_test_OBJECTS)
 ags_pattern_test_DEPENDENCIES = libags_audio.la libags_server.la \
-	libags_gui.la libags_thread.la libags.la
+	libags_gui.la libags_thread.la libags.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 ags_pattern_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(ags_pattern_test_CFLAGS) $(CFLAGS) \
@@ -790,7 +1020,10 @@ am_ags_recall_test_OBJECTS =  \
 	ags/test/audio/ags_recall_test-ags_recall_test.$(OBJEXT)
 ags_recall_test_OBJECTS = $(am_ags_recall_test_OBJECTS)
 ags_recall_test_DEPENDENCIES = libags_audio.la libags_server.la \
-	libags_gui.la libags_thread.la libags.la
+	libags_gui.la libags_thread.la libags.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 ags_recall_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(ags_recall_test_CFLAGS) $(CFLAGS) $(ags_recall_test_LDFLAGS) \
@@ -798,7 +1031,10 @@ ags_recall_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 am_ags_recycling_test_OBJECTS = ags/test/audio/ags_recycling_test-ags_recycling_test.$(OBJEXT)
 ags_recycling_test_OBJECTS = $(am_ags_recycling_test_OBJECTS)
 ags_recycling_test_DEPENDENCIES = libags_audio.la libags_server.la \
-	libags_gui.la libags_thread.la libags.la
+	libags_gui.la libags_thread.la libags.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 ags_recycling_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(ags_recycling_test_CFLAGS) $(CFLAGS) \
@@ -815,16 +1051,41 @@ am_ags_turtle_test_OBJECTS =  \
 	ags/test/lib/ags_turtle_test-ags_turtle_test.$(OBJEXT)
 ags_turtle_test_OBJECTS = $(am_ags_turtle_test_OBJECTS)
 ags_turtle_test_DEPENDENCIES = libags_audio.la libags_server.la \
-	libags_gui.la libags_thread.la libags.la
+	libags_gui.la libags_thread.la libags.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 ags_turtle_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(ags_turtle_test_CFLAGS) $(CFLAGS) $(ags_turtle_test_LDFLAGS) \
 	$(LDFLAGS) -o $@
+am_ags_xorg_application_context_test_OBJECTS = ags/test/X/ags_xorg_application_context_test-ags_xorg_application_context_test.$(OBJEXT)
+ags_xorg_application_context_test_OBJECTS =  \
+	$(am_ags_xorg_application_context_test_OBJECTS)
+ags_xorg_application_context_test_DEPENDENCIES = libgsequencer.la \
+	libags_audio.la libags_server.la libags_gui.la \
+	libags_thread.la libags.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
+ags_xorg_application_context_test_LINK = $(LIBTOOL) $(AM_V_lt) \
+	--tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
+	$(CCLD) $(ags_xorg_application_context_test_CFLAGS) $(CFLAGS) \
+	$(ags_xorg_application_context_test_LDFLAGS) $(LDFLAGS) -o $@
 am__objects_28 = ags/gsequencer-gsequencer_main.$(OBJEXT)
 am_gsequencer_OBJECTS = $(am__objects_28) $(am__objects_1)
 gsequencer_OBJECTS = $(am_gsequencer_OBJECTS)
 gsequencer_DEPENDENCIES = libgsequencer.la libags_audio.la \
-	libags_server.la libags_gui.la libags_thread.la libags.la
+	libags_server.la libags_gui.la libags_thread.la libags.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 gsequencer_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(gsequencer_CFLAGS) \
 	$(CFLAGS) $(gsequencer_LDFLAGS) $(LDFLAGS) -o $@
@@ -872,24 +1133,48 @@ am__v_CCLD_1 =
 SOURCES = $(libags_la_SOURCES) $(libags_audio_la_SOURCES) \
 	$(libags_gui_la_SOURCES) $(libags_server_la_SOURCES) \
 	$(libags_thread_la_SOURCES) $(libgsequencer_la_SOURCES) \
+	$(libgsequencer_test_la_SOURCES) \
+	$(ags_audio_application_context_test_SOURCES) \
 	$(ags_audio_signal_test_SOURCES) $(ags_audio_test_SOURCES) \
 	$(ags_automation_test_SOURCES) $(ags_channel_test_SOURCES) \
+	$(ags_devout_test_SOURCES) \
 	$(ags_functional_audio_test_SOURCES) \
+	$(ags_functional_drum_test_SOURCES) \
+	$(ags_functional_ffplayer_test_SOURCES) \
+	$(ags_functional_machine_add_and_destroy_test_SOURCES) \
+	$(ags_functional_matrix_test_SOURCES) \
+	$(ags_functional_mixer_test_SOURCES) \
+	$(ags_functional_note_edit_test_SOURCES) \
+	$(ags_functional_panel_test_SOURCES) \
+	$(ags_functional_synth_test_SOURCES) \
 	$(ags_midi_buffer_util_test_SOURCES) \
 	$(ags_notation_test_SOURCES) $(ags_pattern_test_SOURCES) \
 	$(ags_recall_test_SOURCES) $(ags_recycling_test_SOURCES) \
 	$(ags_thread_test_SOURCES) $(ags_turtle_test_SOURCES) \
+	$(ags_xorg_application_context_test_SOURCES) \
 	$(gsequencer_SOURCES) $(midi2xml_SOURCES)
 DIST_SOURCES = $(libags_la_SOURCES) $(libags_audio_la_SOURCES) \
 	$(libags_gui_la_SOURCES) $(libags_server_la_SOURCES) \
 	$(libags_thread_la_SOURCES) $(libgsequencer_la_SOURCES) \
+	$(libgsequencer_test_la_SOURCES) \
+	$(ags_audio_application_context_test_SOURCES) \
 	$(ags_audio_signal_test_SOURCES) $(ags_audio_test_SOURCES) \
 	$(ags_automation_test_SOURCES) $(ags_channel_test_SOURCES) \
+	$(ags_devout_test_SOURCES) \
 	$(ags_functional_audio_test_SOURCES) \
+	$(ags_functional_drum_test_SOURCES) \
+	$(ags_functional_ffplayer_test_SOURCES) \
+	$(ags_functional_machine_add_and_destroy_test_SOURCES) \
+	$(ags_functional_matrix_test_SOURCES) \
+	$(ags_functional_mixer_test_SOURCES) \
+	$(ags_functional_note_edit_test_SOURCES) \
+	$(ags_functional_panel_test_SOURCES) \
+	$(ags_functional_synth_test_SOURCES) \
 	$(ags_midi_buffer_util_test_SOURCES) \
 	$(ags_notation_test_SOURCES) $(ags_pattern_test_SOURCES) \
 	$(ags_recall_test_SOURCES) $(ags_recycling_test_SOURCES) \
 	$(ags_thread_test_SOURCES) $(ags_turtle_test_SOURCES) \
+	$(ags_xorg_application_context_test_SOURCES) \
 	$(gsequencer_SOURCES) $(midi2xml_SOURCES)
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
@@ -1101,9 +1386,11 @@ TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
 	$(TEST_LOG_FLAGS)
 am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/libags.pc.in \
 	$(srcdir)/libags_audio.pc.in $(srcdir)/libags_gui.pc.in \
-	$(top_srcdir)/ags/config.h.in AUTHORS COPYING ChangeLog \
-	INSTALL NEWS README TODO compile config.guess config.rpath \
-	config.sub depcomp install-sh ltmain.sh missing test-driver
+	$(srcdir)/libgsequencer.pc.in $(top_srcdir)/ags/config.h.in \
+	$(top_srcdir)/functional-tests.mk $(top_srcdir)/unit-tests.mk \
+	AUTHORS COPYING ChangeLog INSTALL NEWS README TODO compile \
+	config.guess config.rpath config.sub depcomp install-sh \
+	ltmain.sh missing test-driver
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 distdir = $(PACKAGE)-$(VERSION)
 top_distdir = $(distdir)
@@ -1302,24 +1589,16 @@ AUTOMAKE_OPTIONS = foreign
 # SUBDIRS = . docs/reference/ags
 ACLOCAL_AMFLAGS = -I m4
 AM_CPPFLAGS = -std=gnu99 -include /usr/include/errno.h -I$(top_srcdir) -DDESTDIR=\"$(DESTDIR)$(datadir)\" -DPACKAGE_VERSION=\"$(PACKAGE_VERSION)\" -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security
-gsequencer_CFLAGS = @GSEQUENCER_CFLAGS@ $(UUID_CFLAGS) \
-	$(LIBASOUND2_CFLAGS) $(LIBAO_CFLAGS) $(LIBXML2_CFLAGS) \
-	$(OPENSSL_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) \
-	$(GOBJECT_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) \
-	$(CAIRO_CFLAGS) $(GTK_CFLAGS) $(XMLRPC_CFLAGS) \
-	$(XMLRPC_UTIL_CFLAGS) $(XMLRPC_SERVER_ABYSS_CFLAGS) \
-	$(XMLRPC_SERVER_CGI_CFLAGS) $(XMLRPC_SERVER_CFLAGS) \
-	$(PTH_FLAGS) $(JACK_CFLAGS)
-gsequencer_LDFLAGS = @GSEQUENCER_LDFLAGS@ -ldl -lm -lrt -pthread -lgmp \
-	-lX11 $(UUID_LIBS) $(LIBASOUND2_LIBS) $(LIBAO_LIBS) \
-	$(LIBXML2_LIBS) $(OPENSSL_LIBS) $(SNDFILE_LIBS) \
-	$(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(FONTCONFIG_LIBS) \
-	$(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS) $(XMLRPC_LIBS) \
-	$(XMLRPC_UTIL_LIBS) $(XMLRPC_SERVER_ABYSS_LIBS) \
-	$(XMLRPC_SERVER_CGI_LIBS) $(XMLRPC_SERVER_LIBS) $(JACK_LIBS)
+gsequencer_CFLAGS = @GSEQUENCER_CFLAGS@ $(LIBASOUND2_CFLAGS) \
+	$(LIBAO_CFLAGS) $(LIBXML2_CFLAGS) $(OPENSSL_CFLAGS) \
+	$(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) \
+	$(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) \
+	$(GTK_CFLAGS) $(XMLRPC_CFLAGS) $(XMLRPC_UTIL_CFLAGS) \
+	$(XMLRPC_SERVER_ABYSS_CFLAGS) $(XMLRPC_SERVER_CGI_CFLAGS) \
+	$(XMLRPC_SERVER_CFLAGS) $(PTH_FLAGS) $(JACK_CFLAGS)
+gsequencer_LDFLAGS = @GSEQUENCER_LDFLAGS@ -pthread
 midi2xml_CFLAGS = @GSEQUENCER_CFLAGS@ -I./ -I/usr/include \
-	$(UUID_CFLAGS) $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS) \
-	$(GIO_CFLAGS)
+	$(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS) $(GIO_CFLAGS)
 midi2xml_LDFLAGS = @GSEQUENCER_LDFLAGS@ -ldl $(LIBXML2_LIBS) \
 	$(GOBJECT_LIBS)
 
@@ -1337,12 +1616,13 @@ libgsequencer_LTLIBRARIES = libgsequencer.la
 EXTRA_DIST = COPYING.docs config.h config.h.in gtk-doc.make \
 	gsequencer.share acsite.m4 aclocal.m4 gsequencer.1 README \
 	ags_example.xml gsequencer-documentation midi2xml.1 \
+	ags_functional_note_edit_test.xml \
 	docs/reference/libags/libags-sections.txt \
 	docs/reference/libags/libags.types \
-	docs/reference/libags_audio/libags_audio-sections.txt \
-	docs/reference/libags_audio/libags_audio.types \
-	docs/reference/libags_gui/libags_gui-sections.txt \
-	docs/reference/libags_gui/libags_gui.types libags.pc.in \
+	docs/reference/libags-audio/libags_audio-sections.txt \
+	docs/reference/libags-audio/libags_audio.types \
+	docs/reference/libags-gui/libags_gui-sections.txt \
+	docs/reference/libags-gui/libags_gui.types libags.pc.in \
 	libags_audio.pc.in libags_gui.pc.in libgsequencer.pc.in \
 	gsequencer.desktop.in libags.sym libags_thread.sym \
 	libags_server.sym libags_audio.sym libags_gui.sym \
@@ -1354,22 +1634,22 @@ EXTRA_DIST = COPYING.docs config.h config.h.in gtk-doc.make \
 	docs/reference/libags/libags-sections.txt \
 	docs/reference/libags/libags.types \
 	docs/reference/libags/libags.xml \
-	docs/reference/libags_audio/git.mk \
-	docs/reference/libags_audio/gtk-doc.make \
-	docs/reference/libags_audio/Makefile.am \
-	docs/reference/libags_audio/Makefile.in \
-	docs/reference/libags_audio/libags_audio-overrides.txt \
-	docs/reference/libags_audio/libags_audio-sections.txt \
-	docs/reference/libags_audio/libags_audio.types \
-	docs/reference/libags_audio/libags_audio.xml \
-	docs/reference/libags_gui/git.mk \
-	docs/reference/libags_gui/gtk-doc.make \
-	docs/reference/libags_gui/Makefile.am \
-	docs/reference/libags_gui/Makefile.in \
-	docs/reference/libags_gui/libags_gui-overrides.txt \
-	docs/reference/libags_gui/libags_gui-sections.txt \
-	docs/reference/libags_gui/libags_gui.types \
-	docs/reference/libags_gui/libags_gui.xml \
+	docs/reference/libags-audio/git.mk \
+	docs/reference/libags-audio/gtk-doc.make \
+	docs/reference/libags-audio/Makefile.am \
+	docs/reference/libags-audio/Makefile.in \
+	docs/reference/libags-audio/libags_audio-overrides.txt \
+	docs/reference/libags-audio/libags_audio-sections.txt \
+	docs/reference/libags-audio/libags_audio.types \
+	docs/reference/libags-audio/libags_audio.xml \
+	docs/reference/libags-gui/git.mk \
+	docs/reference/libags-gui/gtk-doc.make \
+	docs/reference/libags-gui/Makefile.am \
+	docs/reference/libags-gui/Makefile.in \
+	docs/reference/libags-gui/libags_gui-overrides.txt \
+	docs/reference/libags-gui/libags_gui-sections.txt \
+	docs/reference/libags-gui/libags_gui.types \
+	docs/reference/libags-gui/libags_gui.xml \
 	docs/reference/libgsequencer/git.mk \
 	docs/reference/libgsequencer/gtk-doc.make \
 	docs/reference/libgsequencer/Makefile.am \
@@ -1381,7 +1661,7 @@ EXTRA_DIST = COPYING.docs config.h config.h.in gtk-doc.make \
 	$(top_srcdir)/ags/audio/midi/ags_midi_file.dtd \
 	$(top_srcdir)/ags/file/ags_file.dtd \
 	$(top_srcdir)/ags/X/file/ags_simple_file.dtd \
-	$(top_srcdir)/ags.xsl \
+	$(top_srcdir)/ags.xsl $(top_srcdir)/ags-simple.xsl \
 	$(top_srcdir)/ags/object/ags_marshallers.list
 man1_MANS = gsequencer.1 midi2xml.1
 
@@ -1500,94 +1780,196 @@ libags_audio_la_SOURCES = $(libags_audio_c_sources) $(libags_audio_client_c_sour
 libags_audio_la_HEADERS_0 = ags/libags-audio.h $(libags_audio_h_sources) $(libags_audio_client_h_sources) $(libags_audio_thread_h_sources) $(libags_audio_file_h_sources) $(libags_audio_midi_h_sources) $(libags_audio_jack_h_sources) $(libags_audio_task_h_sources) $(libags_audio_task_recall_h_sources) $(libags_audio_recall_h_sources)  $(libags_plugin_h_sources)
 libags_gui_la_SOURCES = $(libags_gui_c_sources)
 libags_gui_la_HEADERS_0 = ags/libags-gui.h $(libags_gui_h_sources)
-# libgsequencer_la_SOURCES = $(libgsequencer_c_sources) $(libgsequencer_file_c_sources) $(libgsequencer_thread_c_sources) $(libgsequencer_task_c_sources) $(libgsequencer_import_c_sources) $(libgsequencer_machine_c_sources) $(libgsequencer_editor_c_sources)
-# libgsequencer_la_HEADERS_0 = $(libgsequencer_h_sources) $(libgsequencer_file_h_sources) $(libgsequencer_thread_h_sources) $(libgsequencer_task_h_sources) $(libgsequencer_import_h_sources) $(libgsequencer_machine_h_sources) $(libgsequencer_editor_h_sources)
 libgsequencer_la_HEADERS_0 = $(libgsequencer_h_sources) $(libgsequencer_file_h_sources) $(libgsequencer_thread_h_sources) $(libgsequencer_task_h_sources) $(libgsequencer_import_h_sources) $(libgsequencer_machine_h_sources) $(libgsequencer_editor_h_sources)
 libgsequencer_la_SOURCES = $(libgsequencer_la_HEADERS_0) $(libgsequencer_c_sources) $(libgsequencer_file_c_sources) $(libgsequencer_thread_c_sources) $(libgsequencer_task_c_sources) $(libgsequencer_import_c_sources) $(libgsequencer_machine_c_sources) $(libgsequencer_editor_c_sources)
 
 # library libags
 libags_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(UUID_CFLAGS) $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS) $(GIO_CFLAGS)
-libags_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname -ldl -lm -pthread -lrt  $(UUID_LIBS) $(LIBXML2_LIBS) $(GOBJECT_LIBS) $(GIO_LIBS)
+libags_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname,libags.so -pthread
+libags_la_LIBADD = -ldl -lm $(UUID_LIBS) $(LIBXML2_LIBS) $(GOBJECT_LIBS) $(GIO_LIBS)
 
 # library libags-thread
-libags_thread_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(UUID_CFLAGS) $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS)
-libags_thread_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_thread.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname -ldl -lm -pthread -lrt $(UUID_LIBS) $(LIBXML2_LIBS) $(GOBJECT_LIBS)
-libags_thread_la_LIBADD = libags.la
+libags_thread_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS)
+libags_thread_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_thread.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname,libags_thread.so -pthread
+libags_thread_la_LIBADD = libags.la -ldl -lm $(LIBXML2_LIBS) $(GOBJECT_LIBS)
 
 # library libags-server
-libags_server_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(UUID_CFLAGS) $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS)
-libags_server_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_server.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname -ldl -lm -pthread -lrt $(UUID_LIBS) $(LIBXML2_LIBS) $(GOBJECT_LIBS)
-libags_server_la_LIBADD = libags_thread.la libags.la
+libags_server_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS)
+libags_server_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_server.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname,libags_server.so -pthread
+libags_server_la_LIBADD = libags_thread.la libags.la -ldl -lm $(LIBXML2_LIBS) $(GOBJECT_LIBS)
 
 # library libags-audio
-libags_audio_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SAMPLERATE_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-libags_audio_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_audio.sym -version-info 0:7:0 -shared -fPIC -soname -ldl -lm -pthread -lrt -lgmp $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SAMPLERATE_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-libags_audio_la_LIBADD = libags_server.la libags_thread.la libags.la
+libags_audio_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SAMPLERATE_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+libags_audio_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_audio.sym -version-info 0:7:0 -shared -fPIC -soname,libags_audio.so -pthread 
+libags_audio_la_LIBADD = libags_server.la libags_thread.la libags.la -ldl -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SAMPLERATE_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
 
 # library libags-gui
 libags_gui_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(GOBJECT_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
-libags_gui_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_gui.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname -ldl -lm -pthread -lrt $(GOBJECT_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+libags_gui_la_LDFLAGS = $(LDFLAGS) -export-symbols $(top_srcdir)/libags_gui.sym -version-info 0:7:0 -shared -fPIC -Wl,-soname,libags_gui.so -pthread
+libags_gui_la_LIBADD = -ldl -lm $(GOBJECT_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
 
 # library libgsequencer
-# libgsequencer_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS) $(JACK_CFLAGS)
-# libgsequencer_la_LDFLAGS = $(LDFLAGS) -version-info 0:1:0 -shared -fPIC -Wl,-soname -ldl -lm -pthread -lrt -lgmp $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS) $(JACK_LIBS)
-# libgsequencer_la_LIBADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-libgsequencer_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS) $(JACK_CFLAGS)
-libgsequencer_la_LDFLAGS = $(LDFLAGS) -version-info 0:1:0 -shared -fPIC -Wl,-soname -ldl -lm -pthread -lrt -lgmp $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS) $(JACK_LIBS)
-libgsequencer_la_LIBADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-
-# static gsequencer - for testing
+libgsequencer_la_CFLAGS = $(CFLAGS) $(COMPILER_FLAGS) $(WARN_FLAGS) -O -I./ -I/usr/include $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS) $(JACK_CFLAGS)
+libgsequencer_la_LDFLAGS = $(LDFLAGS) -version-info 0:1:0 -shared -fPIC -Wl,-soname,libgsequencer.so -pthread
+libgsequencer_la_LIBADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -ldl -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS) $(JACK_LIBS)
+
+# gsequencer
 gsequencer_SOURCES = $(gsequencer_c_sources) $(gsequencerheaders)
-gsequencer_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-TESTS = $(check_PROGRAMS)
+gsequencer_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -ldl -lm -lrt -lX11 $(LIBASOUND2_LIBS) $(LIBAO_LIBS) $(LIBXML2_LIBS) $(OPENSSL_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS) $(XMLRPC_LIBS) $(XMLRPC_UTIL_LIBS) $(XMLRPC_SERVER_ABYSS_LIBS) $(XMLRPC_SERVER_CGI_LIBS) $(XMLRPC_SERVER_LIBS) $(JACK_LIBS)
+
+# thread unit test
 ags_thread_test_SOURCES = ags/test/thread/ags_thread_test.c
-ags_thread_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS)
-ags_thread_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBXML2_LIBS) $(GOBJECT_LIBS)
+ags_thread_test_CFLAGS = $(CFLAGS) $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS)
+ags_thread_test_LDFLAGS = -lcunit -lm -pthread -lrt $(LDFLAGS) $(LIBXML2_LIBS) $(GOBJECT_LIBS)
 ags_thread_test_LDADD = libags_thread.la libags.la
+
+# turtle unit test
 ags_turtle_test_SOURCES = ags/test/lib/ags_turtle_test.c
-ags_turtle_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_turtle_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_turtle_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
+ags_turtle_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_turtle_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_turtle_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# audio application context unit test
+ags_audio_application_context_test_SOURCES = ags/test/audio/ags_audio_application_context_test.c
+ags_audio_application_context_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_audio_application_context_test_LDFLAGS = $(LDFLAGS) -pthread
+ags_audio_application_context_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# devout unit test
+ags_devout_test_SOURCES = ags/test/audio/ags_devout_test.c
+ags_devout_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_devout_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_devout_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# audio unit test
 ags_audio_test_SOURCES = ags/test/audio/ags_audio_test.c
-ags_audio_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_audio_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_audio_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
-ags_functional_audio_test_SOURCES = ags/test/audio/ags_functional_audio_test.c
-ags_functional_audio_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_functional_audio_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_functional_audio_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
+ags_audio_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_audio_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_audio_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# channel unit test
 ags_channel_test_SOURCES = ags/test/audio/ags_channel_test.c
-ags_channel_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_channel_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_channel_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
+ags_channel_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_channel_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_channel_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# recycling unit test
 ags_recycling_test_SOURCES = ags/test/audio/ags_recycling_test.c
-ags_recycling_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_recycling_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_recycling_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
+ags_recycling_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_recycling_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_recycling_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# audio signal unit test
 ags_audio_signal_test_SOURCES = ags/test/audio/ags_audio_signal_test.c
-ags_audio_signal_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_audio_signal_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_audio_signal_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
+ags_audio_signal_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_audio_signal_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_audio_signal_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# recall unit test
 ags_recall_test_SOURCES = ags/test/audio/ags_recall_test.c
-ags_recall_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_recall_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_recall_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
+ags_recall_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_recall_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_recall_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# pattern unit test
 ags_pattern_test_SOURCES = ags/test/audio/ags_pattern_test.c
-ags_pattern_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_pattern_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_pattern_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
+ags_pattern_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_pattern_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_pattern_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lm -lrt $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# notation unit test
 ags_notation_test_SOURCES = ags/test/audio/ags_notation_test.c
-ags_notation_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_notation_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_notation_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
+ags_notation_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_notation_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_notation_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lm -lrt $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# automation unit test
 ags_automation_test_SOURCES = ags/test/audio/ags_automation_test.c
-ags_automation_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_automation_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_automation_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
+ags_automation_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_automation_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_automation_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lm -lrt $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# midi buffer util unit test
 ags_midi_buffer_util_test_SOURCES = ags/test/audio/midi/ags_midi_buffer_util_test.c
-ags_midi_buffer_util_test_CFLAGS = $(CFLAGS) $(UUID_CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
-ags_midi_buffer_util_test_LDFLAGS = -lcunit -lm -pthread -lrt -lgmp $(LDFLAGS) $(UUID_LIBS) $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
-ags_midi_buffer_util_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la
+ags_midi_buffer_util_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_midi_buffer_util_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_midi_buffer_util_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lm -lrt  $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# xorg application context unit test
+ags_xorg_application_context_test_SOURCES = ags/test/X/ags_xorg_application_context_test.c
+ags_xorg_application_context_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_xorg_application_context_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_xorg_application_context_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lm -lrt $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+noinst_LTLIBRARIES = libgsequencer_test.la
+
+# functional test util library
+libgsequencer_test_la_SOURCES = ags/test/X/gsequencer_setup_util.c ags/test/X/gsequencer_setup_util.h ags/test/X/ags_functional_test_util.c ags/test/X/ags_functional_test_util.h ags/test/X/libgsequencer.h
+libgsequencer_test_la_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+libgsequencer_test_la_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+libgsequencer_test_la_LIBADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional audio test
+ags_functional_audio_test_SOURCES = ags/test/audio/ags_functional_audio_test.c
+ags_functional_audio_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_functional_audio_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_audio_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# functional machine add and destroy test
+ags_functional_machine_add_and_destroy_test_SOURCES = ags/test/X/ags_functional_machine_add_and_destroy_test.c
+ags_functional_machine_add_and_destroy_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_machine_add_and_destroy_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_machine_add_and_destroy_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_machine_add_and_destroy_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional panel test
+ags_functional_panel_test_SOURCES = ags/test/X/machine/ags_functional_panel_test.c
+ags_functional_panel_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_panel_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_panel_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_panel_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional mixer test
+ags_functional_mixer_test_SOURCES = ags/test/X/machine/ags_functional_mixer_test.c
+ags_functional_mixer_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_mixer_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_mixer_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_mixer_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional drum test
+ags_functional_drum_test_SOURCES = ags/test/X/machine/ags_functional_drum_test.c
+ags_functional_drum_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_drum_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_drum_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_drum_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional matrix test
+ags_functional_matrix_test_SOURCES = ags/test/X/machine/ags_functional_matrix_test.c
+ags_functional_matrix_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_matrix_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_matrix_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_matrix_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional synth test
+ags_functional_synth_test_SOURCES = ags/test/X/machine/ags_functional_synth_test.c
+ags_functional_synth_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_synth_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_synth_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_synth_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional ffplayer test
+ags_functional_ffplayer_test_SOURCES = ags/test/X/machine/ags_functional_ffplayer_test.c
+ags_functional_ffplayer_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_ffplayer_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_ffplayer_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_ffplayer_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional note edit test
+ags_functional_note_edit_test_SOURCES = ags/test/X/ags_functional_note_edit_test.c
+ags_functional_note_edit_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_note_edit_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_note_edit_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_note_edit_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+TESTS = $(check_PROGRAMS)
 
 # libags all files
 deprecated_libags_h_sources = 
@@ -1623,12 +2005,16 @@ deprecated_libags_util_h_sources =
 # libags - util
 libags_util_h_sources = \
 	$(deprecated_libags_util_h_sources) \
-	ags/util/ags_id_generator.h
+	ags/util/ags_destroy_util.h \
+	ags/util/ags_id_generator.h \
+	ags/util/ags_list_util.h
 
 deprecated_libags_util_c_sources = 
 libags_util_c_sources = \
 	$(deprecated_libags_util_c_sources) \
-	ags/util/ags_id_generator.c
+	ags/util/ags_destroy_util.c \
+	ags/util/ags_id_generator.c \
+	ags/util/ags_list_util.c
 
 deprecated_libags_object_h_sources = 
 
@@ -1715,6 +2101,8 @@ libags_thread_h_sources = \
 	$(deprecated_libags_thread_h_sources) \
 	ags/thread/ags_autosave_thread.h \
 	ags/thread/ags_concurrency_provider.h \
+	ags/thread/ags_condition_manager.h \
+	ags/thread/ags_destroy_worker.h \
 	ags/thread/ags_generic_main_loop.h \
 	ags/thread/ags_history.h \
 	ags/thread/ags_mutex_manager.h \
@@ -1730,13 +2118,16 @@ libags_thread_h_sources = \
 	ags/thread/ags_thread-posix.h \
 	ags/thread/ags_timestamp_factory.h \
 	ags/thread/ags_timestamp_thread.h \
-	ags/thread/ags_timestamp.h
+	ags/thread/ags_timestamp.h \
+	ags/thread/ags_worker_thread.h
 
 deprecated_libags_thread_c_sources = 
 libags_thread_c_sources = \
 	$(deprecated_libags_thread_c_sources) \
 	ags/thread/ags_autosave_thread.c \
 	ags/thread/ags_concurrency_provider.c \
+	ags/thread/ags_condition_manager.c \
+	ags/thread/ags_destroy_worker.c \
 	ags/thread/ags_generic_main_loop.c \
 	ags/thread/ags_history.c \
 	ags/thread/ags_mutex_manager.c \
@@ -1752,7 +2143,8 @@ libags_thread_c_sources = \
 	ags/thread/ags_thread-posix.c \
 	ags/thread/ags_timestamp_factory.c \
 	ags/thread/ags_timestamp_thread.c \
-	ags/thread/ags_timestamp.c
+	ags/thread/ags_timestamp.c \
+	ags/thread/ags_worker_thread.c
 
 
 # libags-thread - file
@@ -1960,6 +2352,7 @@ libags_plugin_h_sources = \
 	ags/plugin/ags_lv2_conversion.h \
 	ags/plugin/ags_lv2_manager.h \
 	ags/plugin/ags_lv2_plugin.h \
+	ags/plugin/ags_lv2_preset.h \
 	ags/plugin/ags_lv2_event_manager.h \
 	ags/plugin/ags_lv2_log_manager.h \
 	ags/plugin/ags_lv2_uri_map_manager.h \
@@ -1982,6 +2375,7 @@ libags_plugin_c_sources = \
 	ags/plugin/ags_lv2_conversion.c \
 	ags/plugin/ags_lv2_manager.c \
 	ags/plugin/ags_lv2_plugin.c \
+	ags/plugin/ags_lv2_preset.c \
 	ags/plugin/ags_lv2_log_manager.c \
 	ags/plugin/ags_lv2_event_manager.c \
 	ags/plugin/ags_lv2_uri_map_manager.c \
@@ -2113,6 +2507,10 @@ libags_audio_recall_h_sources = \
 	ags/audio/recall/ags_play_notation_audio_run.h \
 	ags/audio/recall/ags_play_note.h \
 	ags/audio/recall/ags_play_recycling.h \
+	ags/audio/recall/ags_prepare_audio_signal.h \
+	ags/audio/recall/ags_prepare_channel.h \
+	ags/audio/recall/ags_prepare_channel_run.h \
+	ags/audio/recall/ags_prepare_recycling.h \
 	ags/audio/recall/ags_record_midi_audio.h \
 	ags/audio/recall/ags_record_midi_audio_run.h \
 	ags/audio/recall/ags_route_dssi_audio.h \
@@ -2180,6 +2578,10 @@ libags_audio_recall_c_sources = \
 	ags/audio/recall/ags_play_notation_audio_run.c \
 	ags/audio/recall/ags_play_note.c \
 	ags/audio/recall/ags_play_recycling.c \
+	ags/audio/recall/ags_prepare_audio_signal.c \
+	ags/audio/recall/ags_prepare_channel.c \
+	ags/audio/recall/ags_prepare_channel_run.c \
+	ags/audio/recall/ags_prepare_recycling.c \
 	ags/audio/recall/ags_record_midi_audio.c \
 	ags/audio/recall/ags_record_midi_audio_run.c \
 	ags/audio/recall/ags_route_dssi_audio.c \
@@ -2220,6 +2622,7 @@ libags_audio_task_h_sources = \
 	ags/audio/task/ags_cancel_channel.h \
 	ags/audio/task/ags_cancel_recall.h \
 	ags/audio/task/ags_change_soundcard.h \
+	ags/audio/task/ags_clear_buffer.h \
 	ags/audio/task/ags_export_output.h \
 	ags/audio/task/ags_free_selection.h \
 	ags/audio/task/ags_init_audio.h \
@@ -2280,6 +2683,7 @@ libags_audio_task_c_sources = \
 	ags/audio/task/ags_cancel_channel.c \
 	ags/audio/task/ags_cancel_recall.c \
 	ags/audio/task/ags_change_soundcard.c \
+	ags/audio/task/ags_clear_buffer.c \
 	ags/audio/task/ags_export_output.c \
 	ags/audio/task/ags_free_selection.c \
 	ags/audio/task/ags_init_audio.c \
@@ -2328,13 +2732,16 @@ libags_gui_h_sources = \
 	ags/widget/ags_expander.h \
 	ags/widget/ags_expander_set.h \
 	ags/widget/ags_hindicator.h \
+	ags/widget/ags_hled_array.h \
 	ags/widget/ags_htimebar.h \
 	ags/widget/ags_indicator.h \
 	ags/widget/ags_led.h \
+	ags/widget/ags_led_array.h \
 	ags/widget/ags_ruler.h \
 	ags/widget/ags_table.h \
 	ags/widget/ags_timebar.h \
 	ags/widget/ags_vindicator.h \
+	ags/widget/ags_vled_array.h \
 	ags/widget/ags_waveform.h \
 	ags/widget/ags_container.h
 
@@ -2346,13 +2753,16 @@ libags_gui_c_sources = \
 	ags/widget/ags_expander.c \
 	ags/widget/ags_expander_set.c \
 	ags/widget/ags_hindicator.c \
+	ags/widget/ags_hled_array.c \
 	ags/widget/ags_htimebar.c \
 	ags/widget/ags_indicator.c \
 	ags/widget/ags_led.c \
+	ags/widget/ags_led_array.c \
 	ags/widget/ags_ruler.c \
 	ags/widget/ags_table.c \
 	ags/widget/ags_timebar.c \
 	ags/widget/ags_vindicator.c \
+	ags/widget/ags_vled_array.c \
 	ags/widget/ags_waveform.c \
 	ags/widget/ags_container.c
 
@@ -2361,8 +2771,6 @@ libags_gui_c_sources = \
 deprecated_libgsequencer_h_sources = 
 libgsequencer_h_sources = \
 	$(deprecated_libgsequencer_h_sources) \
-	ags/X/ags_audio_connection_collection_editor_callbacks.h \
-	ags/X/ags_audio_connection_collection_editor.h \
 	ags/X/ags_automation_editor_callbacks.h \
 	ags/X/ags_automation_editor.h \
 	ags/X/ags_automation_window_callbacks.h \
@@ -2423,6 +2831,12 @@ libgsequencer_h_sources = \
 	ags/X/ags_midi_preferences_callbacks.h \
 	ags/X/ags_navigation_callbacks.h \
 	ags/X/ags_navigation.h \
+	ags/X/ags_output_collection_editor_callbacks.h \
+	ags/X/ags_output_collection_editor.h \
+	ags/X/ags_output_editor.h \
+	ags/X/ags_output_editor_callbacks.h \
+	ags/X/ags_output_listing_editor.h \
+	ags/X/ags_output_listing_editor_callbacks.h \
 	ags/X/ags_pad_callbacks.h \
 	ags/X/ags_pad_editor_callbacks.h \
 	ags/X/ags_pad_editor.h \
@@ -2454,8 +2868,6 @@ libgsequencer_h_sources = \
 deprecated_libgsequencer_c_sources = 
 libgsequencer_c_sources = \
 	$(deprecated_libgsequencer_c_sources) \
-	ags/X/ags_audio_connection_collection_editor_callbacks.c \
-	ags/X/ags_audio_connection_collection_editor.c \
 	ags/X/ags_automation_editor.c \
 	ags/X/ags_automation_editor_callbacks.c \
 	ags/X/ags_automation_window.c \
@@ -2516,6 +2928,12 @@ libgsequencer_c_sources = \
 	ags/X/ags_midi_preferences_callbacks.c \
 	ags/X/ags_navigation.c \
 	ags/X/ags_navigation_callbacks.c \
+	ags/X/ags_output_collection_editor_callbacks.c \
+	ags/X/ags_output_collection_editor.c \
+	ags/X/ags_output_editor.c \
+	ags/X/ags_output_editor_callbacks.c \
+	ags/X/ags_output_listing_editor.c \
+	ags/X/ags_output_listing_editor_callbacks.c \
 	ags/X/ags_pad.c \
 	ags/X/ags_pad_callbacks.c \
 	ags/X/ags_pad_editor.c \
@@ -2833,7 +3251,7 @@ all: all-am
 .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
 am--refresh: Makefile
 	@:
-$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am $(top_srcdir)/unit-tests.mk $(top_srcdir)/functional-tests.mk $(am__configure_deps)
 	@for dep in $?; do \
 	  case '$(am__configure_deps)' in \
 	    *$$dep*) \
@@ -2855,6 +3273,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
 	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
 	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
 	esac;
+$(top_srcdir)/unit-tests.mk $(top_srcdir)/functional-tests.mk $(am__empty):
 
 $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
 	$(SHELL) ./config.status --recheck
@@ -2885,6 +3304,8 @@ libags_audio.pc: $(top_builddir)/config.status $(srcdir)/libags_audio.pc.in
 	cd $(top_builddir) && $(SHELL) ./config.status $@
 libags_gui.pc: $(top_builddir)/config.status $(srcdir)/libags_gui.pc.in
 	cd $(top_builddir) && $(SHELL) ./config.status $@
+libgsequencer.pc: $(top_builddir)/config.status $(srcdir)/libgsequencer.pc.in
+	cd $(top_builddir) && $(SHELL) ./config.status $@
 
 install-libLTLIBRARIES: $(lib_LTLIBRARIES)
 	@$(NORMAL_INSTALL)
@@ -2955,6 +3376,17 @@ clean-libgsequencerLTLIBRARIES:
 	  echo rm -f $${locs}; \
 	  rm -f $${locs}; \
 	}
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
 ags/lib/$(am__dirstamp):
 	@$(MKDIR_P) ags/lib
 	@: > ags/lib/$(am__dirstamp)
@@ -2987,8 +3419,12 @@ ags/util/$(am__dirstamp):
 ags/util/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) ags/util/$(DEPDIR)
 	@: > ags/util/$(DEPDIR)/$(am__dirstamp)
+ags/util/libags_la-ags_destroy_util.lo: ags/util/$(am__dirstamp) \
+	ags/util/$(DEPDIR)/$(am__dirstamp)
 ags/util/libags_la-ags_id_generator.lo: ags/util/$(am__dirstamp) \
 	ags/util/$(DEPDIR)/$(am__dirstamp)
+ags/util/libags_la-ags_list_util.lo: ags/util/$(am__dirstamp) \
+	ags/util/$(DEPDIR)/$(am__dirstamp)
 ags/object/$(am__dirstamp):
 	@$(MKDIR_P) ags/object
 	@: > ags/object/$(am__dirstamp)
@@ -3352,6 +3788,9 @@ ags/audio/task/libags_audio_la-ags_cancel_recall.lo:  \
 ags/audio/task/libags_audio_la-ags_change_soundcard.lo:  \
 	ags/audio/task/$(am__dirstamp) \
 	ags/audio/task/$(DEPDIR)/$(am__dirstamp)
+ags/audio/task/libags_audio_la-ags_clear_buffer.lo:  \
+	ags/audio/task/$(am__dirstamp) \
+	ags/audio/task/$(DEPDIR)/$(am__dirstamp)
 ags/audio/task/libags_audio_la-ags_export_output.lo:  \
 	ags/audio/task/$(am__dirstamp) \
 	ags/audio/task/$(DEPDIR)/$(am__dirstamp)
@@ -3619,6 +4058,18 @@ ags/audio/recall/libags_audio_la-ags_play_note.lo:  \
 ags/audio/recall/libags_audio_la-ags_play_recycling.lo:  \
 	ags/audio/recall/$(am__dirstamp) \
 	ags/audio/recall/$(DEPDIR)/$(am__dirstamp)
+ags/audio/recall/libags_audio_la-ags_prepare_audio_signal.lo:  \
+	ags/audio/recall/$(am__dirstamp) \
+	ags/audio/recall/$(DEPDIR)/$(am__dirstamp)
+ags/audio/recall/libags_audio_la-ags_prepare_channel.lo:  \
+	ags/audio/recall/$(am__dirstamp) \
+	ags/audio/recall/$(DEPDIR)/$(am__dirstamp)
+ags/audio/recall/libags_audio_la-ags_prepare_channel_run.lo:  \
+	ags/audio/recall/$(am__dirstamp) \
+	ags/audio/recall/$(DEPDIR)/$(am__dirstamp)
+ags/audio/recall/libags_audio_la-ags_prepare_recycling.lo:  \
+	ags/audio/recall/$(am__dirstamp) \
+	ags/audio/recall/$(DEPDIR)/$(am__dirstamp)
 ags/audio/recall/libags_audio_la-ags_record_midi_audio.lo:  \
 	ags/audio/recall/$(am__dirstamp) \
 	ags/audio/recall/$(DEPDIR)/$(am__dirstamp)
@@ -3697,6 +4148,9 @@ ags/plugin/libags_audio_la-ags_lv2_manager.lo:  \
 ags/plugin/libags_audio_la-ags_lv2_plugin.lo:  \
 	ags/plugin/$(am__dirstamp) \
 	ags/plugin/$(DEPDIR)/$(am__dirstamp)
+ags/plugin/libags_audio_la-ags_lv2_preset.lo:  \
+	ags/plugin/$(am__dirstamp) \
+	ags/plugin/$(DEPDIR)/$(am__dirstamp)
 ags/plugin/libags_audio_la-ags_lv2_log_manager.lo:  \
 	ags/plugin/$(am__dirstamp) \
 	ags/plugin/$(DEPDIR)/$(am__dirstamp)
@@ -3745,12 +4199,17 @@ ags/widget/libags_gui_la-ags_expander_set.lo:  \
 ags/widget/libags_gui_la-ags_hindicator.lo:  \
 	ags/widget/$(am__dirstamp) \
 	ags/widget/$(DEPDIR)/$(am__dirstamp)
+ags/widget/libags_gui_la-ags_hled_array.lo:  \
+	ags/widget/$(am__dirstamp) \
+	ags/widget/$(DEPDIR)/$(am__dirstamp)
 ags/widget/libags_gui_la-ags_htimebar.lo: ags/widget/$(am__dirstamp) \
 	ags/widget/$(DEPDIR)/$(am__dirstamp)
 ags/widget/libags_gui_la-ags_indicator.lo: ags/widget/$(am__dirstamp) \
 	ags/widget/$(DEPDIR)/$(am__dirstamp)
 ags/widget/libags_gui_la-ags_led.lo: ags/widget/$(am__dirstamp) \
 	ags/widget/$(DEPDIR)/$(am__dirstamp)
+ags/widget/libags_gui_la-ags_led_array.lo: ags/widget/$(am__dirstamp) \
+	ags/widget/$(DEPDIR)/$(am__dirstamp)
 ags/widget/libags_gui_la-ags_ruler.lo: ags/widget/$(am__dirstamp) \
 	ags/widget/$(DEPDIR)/$(am__dirstamp)
 ags/widget/libags_gui_la-ags_table.lo: ags/widget/$(am__dirstamp) \
@@ -3760,6 +4219,9 @@ ags/widget/libags_gui_la-ags_timebar.lo: ags/widget/$(am__dirstamp) \
 ags/widget/libags_gui_la-ags_vindicator.lo:  \
 	ags/widget/$(am__dirstamp) \
 	ags/widget/$(DEPDIR)/$(am__dirstamp)
+ags/widget/libags_gui_la-ags_vled_array.lo:  \
+	ags/widget/$(am__dirstamp) \
+	ags/widget/$(DEPDIR)/$(am__dirstamp)
 ags/widget/libags_gui_la-ags_waveform.lo: ags/widget/$(am__dirstamp) \
 	ags/widget/$(DEPDIR)/$(am__dirstamp)
 ags/widget/libags_gui_la-ags_container.lo: ags/widget/$(am__dirstamp) \
@@ -3802,6 +4264,12 @@ ags/thread/libags_thread_la-ags_autosave_thread.lo:  \
 ags/thread/libags_thread_la-ags_concurrency_provider.lo:  \
 	ags/thread/$(am__dirstamp) \
 	ags/thread/$(DEPDIR)/$(am__dirstamp)
+ags/thread/libags_thread_la-ags_condition_manager.lo:  \
+	ags/thread/$(am__dirstamp) \
+	ags/thread/$(DEPDIR)/$(am__dirstamp)
+ags/thread/libags_thread_la-ags_destroy_worker.lo:  \
+	ags/thread/$(am__dirstamp) \
+	ags/thread/$(DEPDIR)/$(am__dirstamp)
 ags/thread/libags_thread_la-ags_generic_main_loop.lo:  \
 	ags/thread/$(am__dirstamp) \
 	ags/thread/$(DEPDIR)/$(am__dirstamp)
@@ -3849,6 +4317,9 @@ ags/thread/libags_thread_la-ags_timestamp_thread.lo:  \
 ags/thread/libags_thread_la-ags_timestamp.lo:  \
 	ags/thread/$(am__dirstamp) \
 	ags/thread/$(DEPDIR)/$(am__dirstamp)
+ags/thread/libags_thread_la-ags_worker_thread.lo:  \
+	ags/thread/$(am__dirstamp) \
+	ags/thread/$(DEPDIR)/$(am__dirstamp)
 ags/thread/file/$(am__dirstamp):
 	@$(MKDIR_P) ags/thread/file
 	@: > ags/thread/file/$(am__dirstamp)
@@ -3867,10 +4338,6 @@ ags/X/$(am__dirstamp):
 ags/X/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) ags/X/$(DEPDIR)
 	@: > ags/X/$(DEPDIR)/$(am__dirstamp)
-ags/X/libgsequencer_la-ags_audio_connection_collection_editor_callbacks.lo:  \
-	ags/X/$(am__dirstamp) ags/X/$(DEPDIR)/$(am__dirstamp)
-ags/X/libgsequencer_la-ags_audio_connection_collection_editor.lo:  \
-	ags/X/$(am__dirstamp) ags/X/$(DEPDIR)/$(am__dirstamp)
 ags/X/libgsequencer_la-ags_automation_editor.lo:  \
 	ags/X/$(am__dirstamp) ags/X/$(DEPDIR)/$(am__dirstamp)
 ags/X/libgsequencer_la-ags_automation_editor_callbacks.lo:  \
@@ -3991,6 +4458,18 @@ ags/X/libgsequencer_la-ags_navigation.lo: ags/X/$(am__dirstamp) \
 	ags/X/$(DEPDIR)/$(am__dirstamp)
 ags/X/libgsequencer_la-ags_navigation_callbacks.lo:  \
 	ags/X/$(am__dirstamp) ags/X/$(DEPDIR)/$(am__dirstamp)
+ags/X/libgsequencer_la-ags_output_collection_editor_callbacks.lo:  \
+	ags/X/$(am__dirstamp) ags/X/$(DEPDIR)/$(am__dirstamp)
+ags/X/libgsequencer_la-ags_output_collection_editor.lo:  \
+	ags/X/$(am__dirstamp) ags/X/$(DEPDIR)/$(am__dirstamp)
+ags/X/libgsequencer_la-ags_output_editor.lo: ags/X/$(am__dirstamp) \
+	ags/X/$(DEPDIR)/$(am__dirstamp)
+ags/X/libgsequencer_la-ags_output_editor_callbacks.lo:  \
+	ags/X/$(am__dirstamp) ags/X/$(DEPDIR)/$(am__dirstamp)
+ags/X/libgsequencer_la-ags_output_listing_editor.lo:  \
+	ags/X/$(am__dirstamp) ags/X/$(DEPDIR)/$(am__dirstamp)
+ags/X/libgsequencer_la-ags_output_listing_editor_callbacks.lo:  \
+	ags/X/$(am__dirstamp) ags/X/$(DEPDIR)/$(am__dirstamp)
 ags/X/libgsequencer_la-ags_pad.lo: ags/X/$(am__dirstamp) \
 	ags/X/$(DEPDIR)/$(am__dirstamp)
 ags/X/libgsequencer_la-ags_pad_callbacks.lo: ags/X/$(am__dirstamp) \
@@ -4402,6 +4881,21 @@ ags/X/editor/libgsequencer_la-ags_toolbar_callbacks.lo:  \
 
 libgsequencer.la: $(libgsequencer_la_OBJECTS) $(libgsequencer_la_DEPENDENCIES) $(EXTRA_libgsequencer_la_DEPENDENCIES) 
 	$(AM_V_CCLD)$(libgsequencer_la_LINK) -rpath $(libgsequencerdir) $(libgsequencer_la_OBJECTS) $(libgsequencer_la_LIBADD) $(LIBS)
+ags/test/X/$(am__dirstamp):
+	@$(MKDIR_P) ags/test/X
+	@: > ags/test/X/$(am__dirstamp)
+ags/test/X/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) ags/test/X/$(DEPDIR)
+	@: > ags/test/X/$(DEPDIR)/$(am__dirstamp)
+ags/test/X/libgsequencer_test_la-gsequencer_setup_util.lo:  \
+	ags/test/X/$(am__dirstamp) \
+	ags/test/X/$(DEPDIR)/$(am__dirstamp)
+ags/test/X/libgsequencer_test_la-ags_functional_test_util.lo:  \
+	ags/test/X/$(am__dirstamp) \
+	ags/test/X/$(DEPDIR)/$(am__dirstamp)
+
+libgsequencer_test.la: $(libgsequencer_test_la_OBJECTS) $(libgsequencer_test_la_DEPENDENCIES) $(EXTRA_libgsequencer_test_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(libgsequencer_test_la_LINK)  $(libgsequencer_test_la_OBJECTS) $(libgsequencer_test_la_LIBADD) $(LIBS)
 install-binPROGRAMS: $(bin_PROGRAMS)
 	@$(NORMAL_INSTALL)
 	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
@@ -4466,6 +4960,13 @@ ags/test/audio/$(am__dirstamp):
 ags/test/audio/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) ags/test/audio/$(DEPDIR)
 	@: > ags/test/audio/$(DEPDIR)/$(am__dirstamp)
+ags/test/audio/ags_audio_application_context_test-ags_audio_application_context_test.$(OBJEXT):  \
+	ags/test/audio/$(am__dirstamp) \
+	ags/test/audio/$(DEPDIR)/$(am__dirstamp)
+
+ags_audio_application_context_test$(EXEEXT): $(ags_audio_application_context_test_OBJECTS) $(ags_audio_application_context_test_DEPENDENCIES) $(EXTRA_ags_audio_application_context_test_DEPENDENCIES) 
+	@rm -f ags_audio_application_context_test$(EXEEXT)
+	$(AM_V_CCLD)$(ags_audio_application_context_test_LINK) $(ags_audio_application_context_test_OBJECTS) $(ags_audio_application_context_test_LDADD) $(LIBS)
 ags/test/audio/ags_audio_signal_test-ags_audio_signal_test.$(OBJEXT):  \
 	ags/test/audio/$(am__dirstamp) \
 	ags/test/audio/$(DEPDIR)/$(am__dirstamp)
@@ -4494,6 +4995,13 @@ ags/test/audio/ags_channel_test-ags_channel_test.$(OBJEXT):  \
 ags_channel_test$(EXEEXT): $(ags_channel_test_OBJECTS) $(ags_channel_test_DEPENDENCIES) $(EXTRA_ags_channel_test_DEPENDENCIES) 
 	@rm -f ags_channel_test$(EXEEXT)
 	$(AM_V_CCLD)$(ags_channel_test_LINK) $(ags_channel_test_OBJECTS) $(ags_channel_test_LDADD) $(LIBS)
+ags/test/audio/ags_devout_test-ags_devout_test.$(OBJEXT):  \
+	ags/test/audio/$(am__dirstamp) \
+	ags/test/audio/$(DEPDIR)/$(am__dirstamp)
+
+ags_devout_test$(EXEEXT): $(ags_devout_test_OBJECTS) $(ags_devout_test_DEPENDENCIES) $(EXTRA_ags_devout_test_DEPENDENCIES) 
+	@rm -f ags_devout_test$(EXEEXT)
+	$(AM_V_CCLD)$(ags_devout_test_LINK) $(ags_devout_test_OBJECTS) $(ags_devout_test_LDADD) $(LIBS)
 ags/test/audio/ags_functional_audio_test-ags_functional_audio_test.$(OBJEXT):  \
 	ags/test/audio/$(am__dirstamp) \
 	ags/test/audio/$(DEPDIR)/$(am__dirstamp)
@@ -4501,6 +5009,68 @@ ags/test/audio/ags_functional_audio_test-ags_functional_audio_test.$(OBJEXT):  \
 ags_functional_audio_test$(EXEEXT): $(ags_functional_audio_test_OBJECTS) $(ags_functional_audio_test_DEPENDENCIES) $(EXTRA_ags_functional_audio_test_DEPENDENCIES) 
 	@rm -f ags_functional_audio_test$(EXEEXT)
 	$(AM_V_CCLD)$(ags_functional_audio_test_LINK) $(ags_functional_audio_test_OBJECTS) $(ags_functional_audio_test_LDADD) $(LIBS)
+ags/test/X/machine/$(am__dirstamp):
+	@$(MKDIR_P) ags/test/X/machine
+	@: > ags/test/X/machine/$(am__dirstamp)
+ags/test/X/machine/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) ags/test/X/machine/$(DEPDIR)
+	@: > ags/test/X/machine/$(DEPDIR)/$(am__dirstamp)
+ags/test/X/machine/ags_functional_drum_test-ags_functional_drum_test.$(OBJEXT):  \
+	ags/test/X/machine/$(am__dirstamp) \
+	ags/test/X/machine/$(DEPDIR)/$(am__dirstamp)
+
+ags_functional_drum_test$(EXEEXT): $(ags_functional_drum_test_OBJECTS) $(ags_functional_drum_test_DEPENDENCIES) $(EXTRA_ags_functional_drum_test_DEPENDENCIES) 
+	@rm -f ags_functional_drum_test$(EXEEXT)
+	$(AM_V_CCLD)$(ags_functional_drum_test_LINK) $(ags_functional_drum_test_OBJECTS) $(ags_functional_drum_test_LDADD) $(LIBS)
+ags/test/X/machine/ags_functional_ffplayer_test-ags_functional_ffplayer_test.$(OBJEXT):  \
+	ags/test/X/machine/$(am__dirstamp) \
+	ags/test/X/machine/$(DEPDIR)/$(am__dirstamp)
+
+ags_functional_ffplayer_test$(EXEEXT): $(ags_functional_ffplayer_test_OBJECTS) $(ags_functional_ffplayer_test_DEPENDENCIES) $(EXTRA_ags_functional_ffplayer_test_DEPENDENCIES) 
+	@rm -f ags_functional_ffplayer_test$(EXEEXT)
+	$(AM_V_CCLD)$(ags_functional_ffplayer_test_LINK) $(ags_functional_ffplayer_test_OBJECTS) $(ags_functional_ffplayer_test_LDADD) $(LIBS)
+ags/test/X/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.$(OBJEXT):  \
+	ags/test/X/$(am__dirstamp) \
+	ags/test/X/$(DEPDIR)/$(am__dirstamp)
+
+ags_functional_machine_add_and_destroy_test$(EXEEXT): $(ags_functional_machine_add_and_destroy_test_OBJECTS) $(ags_functional_machine_add_and_destroy_test_DEPENDENCIES) $(EXTRA_ags_functional_machine_add_and_destroy_test_DEPENDENCIES) 
+	@rm -f ags_functional_machine_add_and_destroy_test$(EXEEXT)
+	$(AM_V_CCLD)$(ags_functional_machine_add_and_destroy_test_LINK) $(ags_functional_machine_add_and_destroy_test_OBJECTS) $(ags_functional_machine_add_and_destroy_test_LDADD) $(LIBS)
+ags/test/X/machine/ags_functional_matrix_test-ags_functional_matrix_test.$(OBJEXT):  \
+	ags/test/X/machine/$(am__dirstamp) \
+	ags/test/X/machine/$(DEPDIR)/$(am__dirstamp)
+
+ags_functional_matrix_test$(EXEEXT): $(ags_functional_matrix_test_OBJECTS) $(ags_functional_matrix_test_DEPENDENCIES) $(EXTRA_ags_functional_matrix_test_DEPENDENCIES) 
+	@rm -f ags_functional_matrix_test$(EXEEXT)
+	$(AM_V_CCLD)$(ags_functional_matrix_test_LINK) $(ags_functional_matrix_test_OBJECTS) $(ags_functional_matrix_test_LDADD) $(LIBS)
+ags/test/X/machine/ags_functional_mixer_test-ags_functional_mixer_test.$(OBJEXT):  \
+	ags/test/X/machine/$(am__dirstamp) \
+	ags/test/X/machine/$(DEPDIR)/$(am__dirstamp)
+
+ags_functional_mixer_test$(EXEEXT): $(ags_functional_mixer_test_OBJECTS) $(ags_functional_mixer_test_DEPENDENCIES) $(EXTRA_ags_functional_mixer_test_DEPENDENCIES) 
+	@rm -f ags_functional_mixer_test$(EXEEXT)
+	$(AM_V_CCLD)$(ags_functional_mixer_test_LINK) $(ags_functional_mixer_test_OBJECTS) $(ags_functional_mixer_test_LDADD) $(LIBS)
+ags/test/X/ags_functional_note_edit_test-ags_functional_note_edit_test.$(OBJEXT):  \
+	ags/test/X/$(am__dirstamp) \
+	ags/test/X/$(DEPDIR)/$(am__dirstamp)
+
+ags_functional_note_edit_test$(EXEEXT): $(ags_functional_note_edit_test_OBJECTS) $(ags_functional_note_edit_test_DEPENDENCIES) $(EXTRA_ags_functional_note_edit_test_DEPENDENCIES) 
+	@rm -f ags_functional_note_edit_test$(EXEEXT)
+	$(AM_V_CCLD)$(ags_functional_note_edit_test_LINK) $(ags_functional_note_edit_test_OBJECTS) $(ags_functional_note_edit_test_LDADD) $(LIBS)
+ags/test/X/machine/ags_functional_panel_test-ags_functional_panel_test.$(OBJEXT):  \
+	ags/test/X/machine/$(am__dirstamp) \
+	ags/test/X/machine/$(DEPDIR)/$(am__dirstamp)
+
+ags_functional_panel_test$(EXEEXT): $(ags_functional_panel_test_OBJECTS) $(ags_functional_panel_test_DEPENDENCIES) $(EXTRA_ags_functional_panel_test_DEPENDENCIES) 
+	@rm -f ags_functional_panel_test$(EXEEXT)
+	$(AM_V_CCLD)$(ags_functional_panel_test_LINK) $(ags_functional_panel_test_OBJECTS) $(ags_functional_panel_test_LDADD) $(LIBS)
+ags/test/X/machine/ags_functional_synth_test-ags_functional_synth_test.$(OBJEXT):  \
+	ags/test/X/machine/$(am__dirstamp) \
+	ags/test/X/machine/$(DEPDIR)/$(am__dirstamp)
+
+ags_functional_synth_test$(EXEEXT): $(ags_functional_synth_test_OBJECTS) $(ags_functional_synth_test_DEPENDENCIES) $(EXTRA_ags_functional_synth_test_DEPENDENCIES) 
+	@rm -f ags_functional_synth_test$(EXEEXT)
+	$(AM_V_CCLD)$(ags_functional_synth_test_LINK) $(ags_functional_synth_test_OBJECTS) $(ags_functional_synth_test_LDADD) $(LIBS)
 ags/test/audio/midi/$(am__dirstamp):
 	@$(MKDIR_P) ags/test/audio/midi
 	@: > ags/test/audio/midi/$(am__dirstamp)
@@ -4568,6 +5138,13 @@ ags/test/lib/ags_turtle_test-ags_turtle_test.$(OBJEXT):  \
 ags_turtle_test$(EXEEXT): $(ags_turtle_test_OBJECTS) $(ags_turtle_test_DEPENDENCIES) $(EXTRA_ags_turtle_test_DEPENDENCIES) 
 	@rm -f ags_turtle_test$(EXEEXT)
 	$(AM_V_CCLD)$(ags_turtle_test_LINK) $(ags_turtle_test_OBJECTS) $(ags_turtle_test_LDADD) $(LIBS)
+ags/test/X/ags_xorg_application_context_test-ags_xorg_application_context_test.$(OBJEXT):  \
+	ags/test/X/$(am__dirstamp) \
+	ags/test/X/$(DEPDIR)/$(am__dirstamp)
+
+ags_xorg_application_context_test$(EXEEXT): $(ags_xorg_application_context_test_OBJECTS) $(ags_xorg_application_context_test_DEPENDENCIES) $(EXTRA_ags_xorg_application_context_test_DEPENDENCIES) 
+	@rm -f ags_xorg_application_context_test$(EXEEXT)
+	$(AM_V_CCLD)$(ags_xorg_application_context_test_LINK) $(ags_xorg_application_context_test_OBJECTS) $(ags_xorg_application_context_test_LDADD) $(LIBS)
 ags/$(am__dirstamp):
 	@$(MKDIR_P) ags
 	@: > ags/$(am__dirstamp)
@@ -4632,6 +5209,9 @@ mostlyclean-compile:
 	-rm -f ags/plugin/*.lo
 	-rm -f ags/server/*.$(OBJEXT)
 	-rm -f ags/server/*.lo
+	-rm -f ags/test/X/*.$(OBJEXT)
+	-rm -f ags/test/X/*.lo
+	-rm -f ags/test/X/machine/*.$(OBJEXT)
 	-rm -f ags/test/audio/*.$(OBJEXT)
 	-rm -f ags/test/audio/midi/*.$(OBJEXT)
 	-rm -f ags/test/lib/*.$(OBJEXT)
@@ -4650,8 +5230,6 @@ distclean-compile:
 
 @AMDEP_TRUE@@am__include@ @am__quote at ags/$(DEPDIR)/gsequencer-gsequencer_main.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/$(DEPDIR)/midi2xml-midi2xml_main.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_audio_connection_collection_editor.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_audio_connection_collection_editor_callbacks.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_audio_preferences.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_audio_preferences_callbacks.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_automation_editor.Plo at am__quote@
@@ -4712,6 +5290,12 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_midi_preferences_callbacks.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_navigation.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_navigation_callbacks.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_output_collection_editor.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_output_collection_editor_callbacks.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_output_editor.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_output_editor_callbacks.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_output_listing_editor.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_output_listing_editor_callbacks.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_pad.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_pad_callbacks.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/X/$(DEPDIR)/libgsequencer_la-ags_pad_editor.Plo at am__quote@
@@ -4961,6 +5545,10 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_play_notation_audio_run.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_play_note.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_play_recycling.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_audio_signal.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_channel.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_channel_run.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_recycling.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_record_midi_audio.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_record_midi_audio_run.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_route_dssi_audio.Plo at am__quote@
@@ -4995,6 +5583,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ags/audio/task/$(DEPDIR)/libags_audio_la-ags_cancel_channel.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/audio/task/$(DEPDIR)/libags_audio_la-ags_cancel_recall.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/audio/task/$(DEPDIR)/libags_audio_la-ags_change_soundcard.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/audio/task/$(DEPDIR)/libags_audio_la-ags_clear_buffer.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/audio/task/$(DEPDIR)/libags_audio_la-ags_export_output.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/audio/task/$(DEPDIR)/libags_audio_la-ags_free_selection.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/audio/task/$(DEPDIR)/libags_audio_la-ags_init_audio.Plo at am__quote@
@@ -5091,6 +5680,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ags/plugin/$(DEPDIR)/libags_audio_la-ags_lv2_log_manager.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/plugin/$(DEPDIR)/libags_audio_la-ags_lv2_manager.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/plugin/$(DEPDIR)/libags_audio_la-ags_lv2_plugin.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/plugin/$(DEPDIR)/libags_audio_la-ags_lv2_preset.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/plugin/$(DEPDIR)/libags_audio_la-ags_lv2_uri_map_manager.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/plugin/$(DEPDIR)/libags_audio_la-ags_lv2_urid_manager.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/plugin/$(DEPDIR)/libags_audio_la-ags_lv2_worker.Plo at am__quote@
@@ -5103,10 +5693,23 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ags/server/$(DEPDIR)/libags_server_la-ags_server.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/server/$(DEPDIR)/libags_server_la-ags_server_application_context.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/server/$(DEPDIR)/libags_server_la-ags_service_provider.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/test/X/$(DEPDIR)/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/test/X/$(DEPDIR)/ags_functional_note_edit_test-ags_functional_note_edit_test.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/test/X/$(DEPDIR)/ags_xorg_application_context_test-ags_xorg_application_context_test.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/test/X/$(DEPDIR)/libgsequencer_test_la-ags_functional_test_util.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/test/X/$(DEPDIR)/libgsequencer_test_la-gsequencer_setup_util.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/test/X/machine/$(DEPDIR)/ags_functional_drum_test-ags_functional_drum_test.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/test/X/machine/$(DEPDIR)/ags_functional_ffplayer_test-ags_functional_ffplayer_test.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/test/X/machine/$(DEPDIR)/ags_functional_matrix_test-ags_functional_matrix_test.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/test/X/machine/$(DEPDIR)/ags_functional_mixer_test-ags_functional_mixer_test.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/test/X/machine/$(DEPDIR)/ags_functional_panel_test-ags_functional_panel_test.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/test/X/machine/$(DEPDIR)/ags_functional_synth_test-ags_functional_synth_test.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/test/audio/$(DEPDIR)/ags_audio_application_context_test-ags_audio_application_context_test.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/test/audio/$(DEPDIR)/ags_audio_signal_test-ags_audio_signal_test.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/test/audio/$(DEPDIR)/ags_audio_test-ags_audio_test.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/test/audio/$(DEPDIR)/ags_automation_test-ags_automation_test.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/test/audio/$(DEPDIR)/ags_channel_test-ags_channel_test.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/test/audio/$(DEPDIR)/ags_devout_test-ags_devout_test.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/test/audio/$(DEPDIR)/ags_functional_audio_test-ags_functional_audio_test.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/test/audio/$(DEPDIR)/ags_notation_test-ags_notation_test.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/test/audio/$(DEPDIR)/ags_pattern_test-ags_pattern_test.Po at am__quote@
@@ -5117,6 +5720,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ags/test/thread/$(DEPDIR)/ags_thread_test-ags_thread_test.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/thread/$(DEPDIR)/libags_thread_la-ags_autosave_thread.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/thread/$(DEPDIR)/libags_thread_la-ags_concurrency_provider.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/thread/$(DEPDIR)/libags_thread_la-ags_condition_manager.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/thread/$(DEPDIR)/libags_thread_la-ags_destroy_worker.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/thread/$(DEPDIR)/libags_thread_la-ags_generic_main_loop.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/thread/$(DEPDIR)/libags_thread_la-ags_history.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/thread/$(DEPDIR)/libags_thread_la-ags_mutex_manager.Plo at am__quote@
@@ -5133,21 +5738,27 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ags/thread/$(DEPDIR)/libags_thread_la-ags_timestamp.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/thread/$(DEPDIR)/libags_thread_la-ags_timestamp_factory.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/thread/$(DEPDIR)/libags_thread_la-ags_timestamp_thread.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/thread/$(DEPDIR)/libags_thread_la-ags_worker_thread.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/thread/file/$(DEPDIR)/libags_thread_la-ags_thread_file_xml.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/util/$(DEPDIR)/libags_la-ags_destroy_util.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/util/$(DEPDIR)/libags_la-ags_id_generator.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/util/$(DEPDIR)/libags_la-ags_list_util.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_cartesian.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_container.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_dial.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_expander.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_expander_set.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_hindicator.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_hled_array.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_htimebar.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_indicator.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_led.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_led_array.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_ruler.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_table.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_timebar.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_vindicator.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_vled_array.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ags/widget/$(DEPDIR)/libags_gui_la-ags_waveform.Plo at am__quote@
 
 .c.o:
@@ -5244,6 +5855,13 @@ ags/lib/libags_la-ags_turtle_manager.lo: ags/lib/ags_turtle_manager.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_la_CFLAGS) $(CFLAGS) -c -o ags/lib/libags_la-ags_turtle_manager.lo `test -f 'ags/lib/ags_turtle_manager.c' || echo '$(srcdir)/'`ags/lib/ags_turtle_manager.c
 
+ags/util/libags_la-ags_destroy_util.lo: ags/util/ags_destroy_util.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_la_CFLAGS) $(CFLAGS) -MT ags/util/libags_la-ags_destroy_util.lo -MD -MP -MF ags/util/$(DEPDIR)/libags_la-ags_destroy_util.Tpo -c -o ags/util/libags_la-ags_destroy_util.lo `test -f 'ags/util/ags_destroy_util.c' || echo '$(srcdir)/'`ags/util/ags_destroy_util.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/util/$(DEPDIR)/libags_la-ags_destroy_util.Tpo ags/util/$(DEPDIR)/libags_la-ags_destroy_util.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/util/ags_destroy_util.c' object='ags/util/libags_la-ags_destroy_util.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_la_CFLAGS) $(CFLAGS) -c -o ags/util/libags_la-ags_destroy_util.lo `test -f 'ags/util/ags_destroy_util.c' || echo '$(srcdir)/'`ags/util/ags_destroy_util.c
+
 ags/util/libags_la-ags_id_generator.lo: ags/util/ags_id_generator.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_la_CFLAGS) $(CFLAGS) -MT ags/util/libags_la-ags_id_generator.lo -MD -MP -MF ags/util/$(DEPDIR)/libags_la-ags_id_generator.Tpo -c -o ags/util/libags_la-ags_id_generator.lo `test -f 'ags/util/ags_id_generator.c' || echo '$(srcdir)/'`ags/util/ags_id_generator.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/util/$(DEPDIR)/libags_la-ags_id_generator.Tpo ags/util/$(DEPDIR)/libags_la-ags_id_generator.Plo
@@ -5251,6 +5869,13 @@ ags/util/libags_la-ags_id_generator.lo: ags/util/ags_id_generator.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_la_CFLAGS) $(CFLAGS) -c -o ags/util/libags_la-ags_id_generator.lo `test -f 'ags/util/ags_id_generator.c' || echo '$(srcdir)/'`ags/util/ags_id_generator.c
 
+ags/util/libags_la-ags_list_util.lo: ags/util/ags_list_util.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_la_CFLAGS) $(CFLAGS) -MT ags/util/libags_la-ags_list_util.lo -MD -MP -MF ags/util/$(DEPDIR)/libags_la-ags_list_util.Tpo -c -o ags/util/libags_la-ags_list_util.lo `test -f 'ags/util/ags_list_util.c' || echo '$(srcdir)/'`ags/util/ags_list_util.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/util/$(DEPDIR)/libags_la-ags_list_util.Tpo ags/util/$(DEPDIR)/libags_la-ags_list_util.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/util/ags_list_util.c' object='ags/util/libags_la-ags_list_util.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_la_CFLAGS) $(CFLAGS) -c -o ags/util/libags_la-ags_list_util.lo `test -f 'ags/util/ags_list_util.c' || echo '$(srcdir)/'`ags/util/ags_list_util.c
+
 ags/object/libags_la-ags_applicable.lo: ags/object/ags_applicable.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_la_CFLAGS) $(CFLAGS) -MT ags/object/libags_la-ags_applicable.lo -MD -MP -MF ags/object/$(DEPDIR)/libags_la-ags_applicable.Tpo -c -o ags/object/libags_la-ags_applicable.lo `test -f 'ags/object/ags_applicable.c' || echo '$(srcdir)/'`ags/object/ags_applicable.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/object/$(DEPDIR)/libags_la-ags_applicable.Tpo ags/object/$(DEPDIR)/libags_la-ags_applicable.Plo
@@ -6126,6 +6751,13 @@ ags/audio/task/libags_audio_la-ags_change_soundcard.lo: ags/audio/task/ags_chang
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -c -o ags/audio/task/libags_audio_la-ags_change_soundcard.lo `test -f 'ags/audio/task/ags_change_soundcard.c' || echo '$(srcdir)/'`ags/audio/task/ags_change_soundcard.c
 
+ags/audio/task/libags_audio_la-ags_clear_buffer.lo: ags/audio/task/ags_clear_buffer.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -MT ags/audio/task/libags_audio_la-ags_clear_buffer.lo -MD -MP -MF ags/audio/task/$(DEPDIR)/libags_audio_la-ags_clear_buffer.Tpo -c -o ags/audio/task/libags_audio_la-ags_clear_buffer.lo `test -f 'ags/audio/task/ags_clear_buffer.c' || echo '$(srcdir)/'`ags/audio/task/ags_clear_buffer.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/audio/task/$(DEPDIR)/libags_audio_la-ags_clear_buffer.Tpo ags/audio/task/$(DEPDIR)/libags_audio_la-ags_clear_buffer.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/audio/task/ags_clear_buffer.c' object='ags/audio/task/libags_audio_la-ags_clear_buffer.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -c -o ags/audio/task/libags_audio_la-ags_clear_buffer.lo `test -f 'ags/audio/task/ags_clear_buffer.c' || echo '$(srcdir)/'`ags/audio/task/ags_clear_buffer.c
+
 ags/audio/task/libags_audio_la-ags_export_output.lo: ags/audio/task/ags_export_output.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -MT ags/audio/task/libags_audio_la-ags_export_output.lo -MD -MP -MF ags/audio/task/$(DEPDIR)/libags_audio_la-ags_export_output.Tpo -c -o ags/audio/task/libags_audio_la-ags_export_output.lo `test -f 'ags/audio/task/ags_export_output.c' || echo '$(srcdir)/'`ags/audio/task/ags_export_output.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/audio/task/$(DEPDIR)/libags_audio_la-ags_export_output.Tpo ags/audio/task/$(DEPDIR)/libags_audio_la-ags_export_output.Plo
@@ -6721,6 +7353,34 @@ ags/audio/recall/libags_audio_la-ags_play_recycling.lo: ags/audio/recall/ags_pla
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -c -o ags/audio/recall/libags_audio_la-ags_play_recycling.lo `test -f 'ags/audio/recall/ags_play_recycling.c' || echo '$(srcdir)/'`ags/audio/recall/ags_play_recycling.c
 
+ags/audio/recall/libags_audio_la-ags_prepare_audio_signal.lo: ags/audio/recall/ags_prepare_audio_signal.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -MT ags/audio/recall/libags_audio_la-ags_prepare_audio_signal.lo -MD -MP -MF ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_audio_signal.Tpo -c -o ags/audio/recall/libags_audio_la-ags_prepare_audio_signal.lo `test -f 'ags/audio/recall/ags_prepare_audio_signal.c' || echo '$(srcdir)/'`ags/audio/recall/ags_prepare_audio_signal.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_audio_signal.Tpo ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_audio_signal.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/audio/recall/ags_prepare_audio_signal.c' object='ags/audio/recall/libags_audio_la-ags_prepare_audio_signal.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -c -o ags/audio/recall/libags_audio_la-ags_prepare_audio_signal.lo `test -f 'ags/audio/recall/ags_prepare_audio_signal.c' || echo '$(srcdir)/'`ags/audio/recall/ags_prepare_audio_signal.c
+
+ags/audio/recall/libags_audio_la-ags_prepare_channel.lo: ags/audio/recall/ags_prepare_channel.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -MT ags/audio/recall/libags_audio_la-ags_prepare_channel.lo -MD -MP -MF ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_channel.Tpo -c -o ags/audio/recall/libags_audio_la-ags_prepare_channel.lo `test -f 'ags/audio/recall/ags_prepare_channel.c' || echo '$(srcdir)/'`ags/audio/recall/ags_prepare_channel.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_channel.Tpo ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_channel.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/audio/recall/ags_prepare_channel.c' object='ags/audio/recall/libags_audio_la-ags_prepare_channel.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -c -o ags/audio/recall/libags_audio_la-ags_prepare_channel.lo `test -f 'ags/audio/recall/ags_prepare_channel.c' || echo '$(srcdir)/'`ags/audio/recall/ags_prepare_channel.c
+
+ags/audio/recall/libags_audio_la-ags_prepare_channel_run.lo: ags/audio/recall/ags_prepare_channel_run.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -MT ags/audio/recall/libags_audio_la-ags_prepare_channel_run.lo -MD -MP -MF ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_channel_run.Tpo -c -o ags/audio/recall/libags_audio_la-ags_prepare_channel_run.lo `test -f 'ags/audio/recall/ags_prepare_channel_run.c' || echo '$(srcdir)/'`ags/audio/recall/ags_prepare_channel_run.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_channel_run.Tpo ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_channel_run.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/audio/recall/ags_prepare_channel_run.c' object='ags/audio/recall/libags_audio_la-ags_prepare_channel_run.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -c -o ags/audio/recall/libags_audio_la-ags_prepare_channel_run.lo `test -f 'ags/audio/recall/ags_prepare_channel_run.c' || echo '$(srcdir)/'`ags/audio/recall/ags_prepare_channel_run.c
+
+ags/audio/recall/libags_audio_la-ags_prepare_recycling.lo: ags/audio/recall/ags_prepare_recycling.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -MT ags/audio/recall/libags_audio_la-ags_prepare_recycling.lo -MD -MP -MF ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_recycling.Tpo -c -o ags/audio/recall/libags_audio_la-ags_prepare_recycling.lo `test -f 'ags/audio/recall/ags_prepare_recycling.c' || echo '$(srcdir)/'`ags/audio/recall/ags_prepare_recycling.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_recycling.Tpo ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_prepare_recycling.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/audio/recall/ags_prepare_recycling.c' object='ags/audio/recall/libags_audio_la-ags_prepare_recycling.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -c -o ags/audio/recall/libags_audio_la-ags_prepare_recycling.lo `test -f 'ags/audio/recall/ags_prepare_recycling.c' || echo '$(srcdir)/'`ags/audio/recall/ags_prepare_recycling.c
+
 ags/audio/recall/libags_audio_la-ags_record_midi_audio.lo: ags/audio/recall/ags_record_midi_audio.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -MT ags/audio/recall/libags_audio_la-ags_record_midi_audio.lo -MD -MP -MF ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_record_midi_audio.Tpo -c -o ags/audio/recall/libags_audio_la-ags_record_midi_audio.lo `test -f 'ags/audio/recall/ags_record_midi_audio.c' || echo '$(srcdir)/'`ags/audio/recall/ags_record_midi_audio.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_record_midi_audio.Tpo ags/audio/recall/$(DEPDIR)/libags_audio_la-ags_record_midi_audio.Plo
@@ -6889,6 +7549,13 @@ ags/plugin/libags_audio_la-ags_lv2_plugin.lo: ags/plugin/ags_lv2_plugin.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -c -o ags/plugin/libags_audio_la-ags_lv2_plugin.lo `test -f 'ags/plugin/ags_lv2_plugin.c' || echo '$(srcdir)/'`ags/plugin/ags_lv2_plugin.c
 
+ags/plugin/libags_audio_la-ags_lv2_preset.lo: ags/plugin/ags_lv2_preset.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -MT ags/plugin/libags_audio_la-ags_lv2_preset.lo -MD -MP -MF ags/plugin/$(DEPDIR)/libags_audio_la-ags_lv2_preset.Tpo -c -o ags/plugin/libags_audio_la-ags_lv2_preset.lo `test -f 'ags/plugin/ags_lv2_preset.c' || echo '$(srcdir)/'`ags/plugin/ags_lv2_preset.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/plugin/$(DEPDIR)/libags_audio_la-ags_lv2_preset.Tpo ags/plugin/$(DEPDIR)/libags_audio_la-ags_lv2_preset.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/plugin/ags_lv2_preset.c' object='ags/plugin/libags_audio_la-ags_lv2_preset.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -c -o ags/plugin/libags_audio_la-ags_lv2_preset.lo `test -f 'ags/plugin/ags_lv2_preset.c' || echo '$(srcdir)/'`ags/plugin/ags_lv2_preset.c
+
 ags/plugin/libags_audio_la-ags_lv2_log_manager.lo: ags/plugin/ags_lv2_log_manager.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_audio_la_CFLAGS) $(CFLAGS) -MT ags/plugin/libags_audio_la-ags_lv2_log_manager.lo -MD -MP -MF ags/plugin/$(DEPDIR)/libags_audio_la-ags_lv2_log_manager.Tpo -c -o ags/plugin/libags_audio_la-ags_lv2_log_manager.lo `test -f 'ags/plugin/ags_lv2_log_manager.c' || echo '$(srcdir)/'`ags/plugin/ags_lv2_log_manager.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/plugin/$(DEPDIR)/libags_audio_la-ags_lv2_log_manager.Tpo ags/plugin/$(DEPDIR)/libags_audio_la-ags_lv2_log_manager.Plo
@@ -6987,6 +7654,13 @@ ags/widget/libags_gui_la-ags_hindicator.lo: ags/widget/ags_hindicator.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_gui_la_CFLAGS) $(CFLAGS) -c -o ags/widget/libags_gui_la-ags_hindicator.lo `test -f 'ags/widget/ags_hindicator.c' || echo '$(srcdir)/'`ags/widget/ags_hindicator.c
 
+ags/widget/libags_gui_la-ags_hled_array.lo: ags/widget/ags_hled_array.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_gui_la_CFLAGS) $(CFLAGS) -MT ags/widget/libags_gui_la-ags_hled_array.lo -MD -MP -MF ags/widget/$(DEPDIR)/libags_gui_la-ags_hled_array.Tpo -c -o ags/widget/libags_gui_la-ags_hled_array.lo `test -f 'ags/widget/ags_hled_array.c' || echo '$(srcdir)/'`ags/widget/ags_hled_array.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/widget/$(DEPDIR)/libags_gui_la-ags_hled_array.Tpo ags/widget/$(DEPDIR)/libags_gui_la-ags_hled_array.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/widget/ags_hled_array.c' object='ags/widget/libags_gui_la-ags_hled_array.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_gui_la_CFLAGS) $(CFLAGS) -c -o ags/widget/libags_gui_la-ags_hled_array.lo `test -f 'ags/widget/ags_hled_array.c' || echo '$(srcdir)/'`ags/widget/ags_hled_array.c
+
 ags/widget/libags_gui_la-ags_htimebar.lo: ags/widget/ags_htimebar.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_gui_la_CFLAGS) $(CFLAGS) -MT ags/widget/libags_gui_la-ags_htimebar.lo -MD -MP -MF ags/widget/$(DEPDIR)/libags_gui_la-ags_htimebar.Tpo -c -o ags/widget/libags_gui_la-ags_htimebar.lo `test -f 'ags/widget/ags_htimebar.c' || echo '$(srcdir)/'`ags/widget/ags_htimebar.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/widget/$(DEPDIR)/libags_gui_la-ags_htimebar.Tpo ags/widget/$(DEPDIR)/libags_gui_la-ags_htimebar.Plo
@@ -7008,6 +7682,13 @@ ags/widget/libags_gui_la-ags_led.lo: ags/widget/ags_led.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_gui_la_CFLAGS) $(CFLAGS) -c -o ags/widget/libags_gui_la-ags_led.lo `test -f 'ags/widget/ags_led.c' || echo '$(srcdir)/'`ags/widget/ags_led.c
 
+ags/widget/libags_gui_la-ags_led_array.lo: ags/widget/ags_led_array.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_gui_la_CFLAGS) $(CFLAGS) -MT ags/widget/libags_gui_la-ags_led_array.lo -MD -MP -MF ags/widget/$(DEPDIR)/libags_gui_la-ags_led_array.Tpo -c -o ags/widget/libags_gui_la-ags_led_array.lo `test -f 'ags/widget/ags_led_array.c' || echo '$(srcdir)/'`ags/widget/ags_led_array.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/widget/$(DEPDIR)/libags_gui_la-ags_led_array.Tpo ags/widget/$(DEPDIR)/libags_gui_la-ags_led_array.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/widget/ags_led_array.c' object='ags/widget/libags_gui_la-ags_led_array.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_gui_la_CFLAGS) $(CFLAGS) -c -o ags/widget/libags_gui_la-ags_led_array.lo `test -f 'ags/widget/ags_led_array.c' || echo '$(srcdir)/'`ags/widget/ags_led_array.c
+
 ags/widget/libags_gui_la-ags_ruler.lo: ags/widget/ags_ruler.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_gui_la_CFLAGS) $(CFLAGS) -MT ags/widget/libags_gui_la-ags_ruler.lo -MD -MP -MF ags/widget/$(DEPDIR)/libags_gui_la-ags_ruler.Tpo -c -o ags/widget/libags_gui_la-ags_ruler.lo `test -f 'ags/widget/ags_ruler.c' || echo '$(srcdir)/'`ags/widget/ags_ruler.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/widget/$(DEPDIR)/libags_gui_la-ags_ruler.Tpo ags/widget/$(DEPDIR)/libags_gui_la-ags_ruler.Plo
@@ -7036,6 +7717,13 @@ ags/widget/libags_gui_la-ags_vindicator.lo: ags/widget/ags_vindicator.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_gui_la_CFLAGS) $(CFLAGS) -c -o ags/widget/libags_gui_la-ags_vindicator.lo `test -f 'ags/widget/ags_vindicator.c' || echo '$(srcdir)/'`ags/widget/ags_vindicator.c
 
+ags/widget/libags_gui_la-ags_vled_array.lo: ags/widget/ags_vled_array.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_gui_la_CFLAGS) $(CFLAGS) -MT ags/widget/libags_gui_la-ags_vled_array.lo -MD -MP -MF ags/widget/$(DEPDIR)/libags_gui_la-ags_vled_array.Tpo -c -o ags/widget/libags_gui_la-ags_vled_array.lo `test -f 'ags/widget/ags_vled_array.c' || echo '$(srcdir)/'`ags/widget/ags_vled_array.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/widget/$(DEPDIR)/libags_gui_la-ags_vled_array.Tpo ags/widget/$(DEPDIR)/libags_gui_la-ags_vled_array.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/widget/ags_vled_array.c' object='ags/widget/libags_gui_la-ags_vled_array.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_gui_la_CFLAGS) $(CFLAGS) -c -o ags/widget/libags_gui_la-ags_vled_array.lo `test -f 'ags/widget/ags_vled_array.c' || echo '$(srcdir)/'`ags/widget/ags_vled_array.c
+
 ags/widget/libags_gui_la-ags_waveform.lo: ags/widget/ags_waveform.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_gui_la_CFLAGS) $(CFLAGS) -MT ags/widget/libags_gui_la-ags_waveform.lo -MD -MP -MF ags/widget/$(DEPDIR)/libags_gui_la-ags_waveform.Tpo -c -o ags/widget/libags_gui_la-ags_waveform.lo `test -f 'ags/widget/ags_waveform.c' || echo '$(srcdir)/'`ags/widget/ags_waveform.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/widget/$(DEPDIR)/libags_gui_la-ags_waveform.Tpo ags/widget/$(DEPDIR)/libags_gui_la-ags_waveform.Plo
@@ -7099,6 +7787,20 @@ ags/thread/libags_thread_la-ags_concurrency_provider.lo: ags/thread/ags_concurre
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_thread_la_CFLAGS) $(CFLAGS) -c -o ags/thread/libags_thread_la-ags_concurrency_provider.lo `test -f 'ags/thread/ags_concurrency_provider.c' || echo '$(srcdir)/'`ags/thread/ags_concurrency_provider.c
 
+ags/thread/libags_thread_la-ags_condition_manager.lo: ags/thread/ags_condition_manager.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_thread_la_CFLAGS) $(CFLAGS) -MT ags/thread/libags_thread_la-ags_condition_manager.lo -MD -MP -MF ags/thread/$(DEPDIR)/libags_thread_la-ags_condition_manager.Tpo -c -o ags/thread/libags_thread_la-ags_condition_manager.lo `test -f 'ags/thread/ags_condition_manager.c' || echo '$(srcdir)/'`ags/thread/ags_condition_manager.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/thread/$(DEPDIR)/libags_thread_la-ags_condition_manager.Tpo ags/thread/$(DEPDIR)/libags_thread_la-ags_condition_manager.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/thread/ags_condition_manager.c' object='ags/thread/libags_thread_la-ags_condition_manager.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_thread_la_CFLAGS) $(CFLAGS) -c -o ags/thread/libags_thread_la-ags_condition_manager.lo `test -f 'ags/thread/ags_condition_manager.c' || echo '$(srcdir)/'`ags/thread/ags_condition_manager.c
+
+ags/thread/libags_thread_la-ags_destroy_worker.lo: ags/thread/ags_destroy_worker.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_thread_la_CFLAGS) $(CFLAGS) -MT ags/thread/libags_thread_la-ags_destroy_worker.lo -MD -MP -MF ags/thread/$(DEPDIR)/libags_thread_la-ags_destroy_worker.Tpo -c -o ags/thread/libags_thread_la-ags_destroy_worker.lo `test -f 'ags/thread/ags_destroy_worker.c' || echo '$(srcdir)/'`ags/thread/ags_destroy_worker.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/thread/$(DEPDIR)/libags_thread_la-ags_destroy_worker.Tpo ags/thread/$(DEPDIR)/libags_thread_la-ags_destroy_worker.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/thread/ags_destroy_worker.c' object='ags/thread/libags_thread_la-ags_destroy_worker.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_thread_la_CFLAGS) $(CFLAGS) -c -o ags/thread/libags_thread_la-ags_destroy_worker.lo `test -f 'ags/thread/ags_destroy_worker.c' || echo '$(srcdir)/'`ags/thread/ags_destroy_worker.c
+
 ags/thread/libags_thread_la-ags_generic_main_loop.lo: ags/thread/ags_generic_main_loop.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_thread_la_CFLAGS) $(CFLAGS) -MT ags/thread/libags_thread_la-ags_generic_main_loop.lo -MD -MP -MF ags/thread/$(DEPDIR)/libags_thread_la-ags_generic_main_loop.Tpo -c -o ags/thread/libags_thread_la-ags_generic_main_loop.lo `test -f 'ags/thread/ags_generic_main_loop.c' || echo '$(srcdir)/'`ags/thread/ags_generic_main_loop.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/thread/$(DEPDIR)/libags_thread_la-ags_generic_main_loop.Tpo ags/thread/$(DEPDIR)/libags_thread_la-ags_generic_main_loop.Plo
@@ -7211,6 +7913,13 @@ ags/thread/libags_thread_la-ags_timestamp.lo: ags/thread/ags_timestamp.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_thread_la_CFLAGS) $(CFLAGS) -c -o ags/thread/libags_thread_la-ags_timestamp.lo `test -f 'ags/thread/ags_timestamp.c' || echo '$(srcdir)/'`ags/thread/ags_timestamp.c
 
+ags/thread/libags_thread_la-ags_worker_thread.lo: ags/thread/ags_worker_thread.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_thread_la_CFLAGS) $(CFLAGS) -MT ags/thread/libags_thread_la-ags_worker_thread.lo -MD -MP -MF ags/thread/$(DEPDIR)/libags_thread_la-ags_worker_thread.Tpo -c -o ags/thread/libags_thread_la-ags_worker_thread.lo `test -f 'ags/thread/ags_worker_thread.c' || echo '$(srcdir)/'`ags/thread/ags_worker_thread.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/thread/$(DEPDIR)/libags_thread_la-ags_worker_thread.Tpo ags/thread/$(DEPDIR)/libags_thread_la-ags_worker_thread.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/thread/ags_worker_thread.c' object='ags/thread/libags_thread_la-ags_worker_thread.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_thread_la_CFLAGS) $(CFLAGS) -c -o ags/thread/libags_thread_la-ags_worker_thread.lo `test -f 'ags/thread/ags_worker_thread.c' || echo '$(srcdir)/'`ags/thread/ags_worker_thread.c
+
 ags/thread/file/libags_thread_la-ags_thread_file_xml.lo: ags/thread/file/ags_thread_file_xml.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_thread_la_CFLAGS) $(CFLAGS) -MT ags/thread/file/libags_thread_la-ags_thread_file_xml.lo -MD -MP -MF ags/thread/file/$(DEPDIR)/libags_thread_la-ags_thread_file_xml.Tpo -c -o ags/thread/file/libags_thread_la-ags_thread_file_xml.lo `test -f 'ags/thread/file/ags_thread_file_xml.c' || echo '$(srcdir)/'`ags/thread/file/ags_thread_file_xml.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/thread/file/$(DEPDIR)/libags_thread_la-ags_thread_file_xml.Tpo ags/thread/file/$(DEPDIR)/libags_thread_la-ags_thread_file_xml.Plo
@@ -7218,20 +7927,6 @@ ags/thread/file/libags_thread_la-ags_thread_file_xml.lo: ags/thread/file/ags_thr
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libags_thread_la_CFLAGS) $(CFLAGS) -c -o ags/thread/file/libags_thread_la-ags_thread_file_xml.lo `test -f 'ags/thread/file/ags_thread_file_xml.c' || echo '$(srcdir)/'`ags/thread/file/ags_thread_file_xml.c
 
-ags/X/libgsequencer_la-ags_audio_connection_collection_editor_callbacks.lo: ags/X/ags_audio_connection_collection_editor_callbacks.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -MT ags/X/libgsequencer_la-ags_audio_connection_collection_editor_callbacks.lo -MD -MP -MF ags/X/$(DEPDIR)/libgsequencer_la-ags_audio_connection_collection_editor_callbacks.Tpo -c -o ags/X/libgsequencer_la-ags_audio_connection_collection_editor_callbacks.lo `test -f 'ags/X/ags_audio_connection_collection_editor_callbacks.c' || echo '$(srcdir)/'`ags/X/ags_audio_connection_collection_editor_callbacks.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/X/$(DEPDIR)/libgsequencer_la-ags_audio_connection_collection_editor_callbacks.Tpo ags/X/$(DEPDIR)/libgsequencer_la-ags_audio_connection_collection_editor_callbacks.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/X/ags_audio_connection_collection_editor_callbacks.c' object='ags/X/libgsequencer_la-ags_audio_connection_collection_editor_callbacks.lo' libtool=yes @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -c -o ags/X/libgsequencer_la-ags_audio_connection_collection_editor_callbacks.lo `test -f 'ags/X/ags_audio_connection_collection_editor_callbacks.c' || echo '$(srcdir)/'`ags/X/ags_audio_connection_collection_editor_callbacks.c
-
-ags/X/libgsequencer_la-ags_audio_connection_collection_editor.lo: ags/X/ags_audio_connection_collection_editor.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -MT ags/X/libgsequencer_la-ags_audio_connection_collection_editor.lo -MD -MP -MF ags/X/$(DEPDIR)/libgsequencer_la-ags_audio_connection_collection_editor.Tpo -c -o ags/X/libgsequencer_la-ags_audio_connection_collection_editor.lo `test -f 'ags/X/ags_audio_connection_collection_editor.c' || echo '$(srcdir)/'`ags/X/ags_audio_connection_collection_editor.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/X/$(DEPDIR)/libgsequencer_la-ags_audio_connection_collection_editor.Tpo ags/X/$(DEPDIR)/libgsequencer_la-ags_audio_connection_collection_editor.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/X/ags_audio_connection_collection_editor.c' object='ags/X/libgsequencer_la-ags_audio_connection_collection_editor.lo' libtool=yes @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -c -o ags/X/libgsequencer_la-ags_audio_connection_collection_editor.lo `test -f 'ags/X/ags_audio_connection_collection_editor.c' || echo '$(srcdir)/'`ags/X/ags_audio_connection_collection_editor.c
-
 ags/X/libgsequencer_la-ags_automation_editor.lo: ags/X/ags_automation_editor.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -MT ags/X/libgsequencer_la-ags_automation_editor.lo -MD -MP -MF ags/X/$(DEPDIR)/libgsequencer_la-ags_automation_editor.Tpo -c -o ags/X/libgsequencer_la-ags_automation_editor.lo `test -f 'ags/X/ags_automation_editor.c' || echo '$(srcdir)/'`ags/X/ags_automation_editor.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/X/$(DEPDIR)/libgsequencer_la-ags_automation_editor.Tpo ags/X/$(DEPDIR)/libgsequencer_la-ags_automation_editor.Plo
@@ -7652,6 +8347,48 @@ ags/X/libgsequencer_la-ags_navigation_callbacks.lo: ags/X/ags_navigation_callbac
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -c -o ags/X/libgsequencer_la-ags_navigation_callbacks.lo `test -f 'ags/X/ags_navigation_callbacks.c' || echo '$(srcdir)/'`ags/X/ags_navigation_callbacks.c
 
+ags/X/libgsequencer_la-ags_output_collection_editor_callbacks.lo: ags/X/ags_output_collection_editor_callbacks.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -MT ags/X/libgsequencer_la-ags_output_collection_editor_callbacks.lo -MD -MP -MF ags/X/$(DEPDIR)/libgsequencer_la-ags_output_collection_editor_callbacks.Tpo -c -o ags/X/libgsequencer_la-ags_output_collection_editor_callbacks.lo `test -f 'ags/X/ags_output_collection_editor_callbacks.c' || echo '$(srcdir)/'`ags/X/ags_output_collection_editor_callbacks.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/X/$(DEPDIR)/libgsequencer_la-ags_output_collection_editor_callbacks.Tpo ags/X/$(DEPDIR)/libgsequencer_la-ags_output_collection_editor_callbacks.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/X/ags_output_collection_editor_callbacks.c' object='ags/X/libgsequencer_la-ags_output_collection_editor_callbacks.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -c -o ags/X/libgsequencer_la-ags_output_collection_editor_callbacks.lo `test -f 'ags/X/ags_output_collection_editor_callbacks.c' || echo '$(srcdir)/'`ags/X/ags_output_collection_editor_callbacks.c
+
+ags/X/libgsequencer_la-ags_output_collection_editor.lo: ags/X/ags_output_collection_editor.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -MT ags/X/libgsequencer_la-ags_output_collection_editor.lo -MD -MP -MF ags/X/$(DEPDIR)/libgsequencer_la-ags_output_collection_editor.Tpo -c -o ags/X/libgsequencer_la-ags_output_collection_editor.lo `test -f 'ags/X/ags_output_collection_editor.c' || echo '$(srcdir)/'`ags/X/ags_output_collection_editor.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/X/$(DEPDIR)/libgsequencer_la-ags_output_collection_editor.Tpo ags/X/$(DEPDIR)/libgsequencer_la-ags_output_collection_editor.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/X/ags_output_collection_editor.c' object='ags/X/libgsequencer_la-ags_output_collection_editor.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -c -o ags/X/libgsequencer_la-ags_output_collection_editor.lo `test -f 'ags/X/ags_output_collection_editor.c' || echo '$(srcdir)/'`ags/X/ags_output_collection_editor.c
+
+ags/X/libgsequencer_la-ags_output_editor.lo: ags/X/ags_output_editor.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -MT ags/X/libgsequencer_la-ags_output_editor.lo -MD -MP -MF ags/X/$(DEPDIR)/libgsequencer_la-ags_output_editor.Tpo -c -o ags/X/libgsequencer_la-ags_output_editor.lo `test -f 'ags/X/ags_output_editor.c' || echo '$(srcdir)/'`ags/X/ags_output_editor.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/X/$(DEPDIR)/libgsequencer_la-ags_output_editor.Tpo ags/X/$(DEPDIR)/libgsequencer_la-ags_output_editor.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/X/ags_output_editor.c' object='ags/X/libgsequencer_la-ags_output_editor.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -c -o ags/X/libgsequencer_la-ags_output_editor.lo `test -f 'ags/X/ags_output_editor.c' || echo '$(srcdir)/'`ags/X/ags_output_editor.c
+
+ags/X/libgsequencer_la-ags_output_editor_callbacks.lo: ags/X/ags_output_editor_callbacks.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -MT ags/X/libgsequencer_la-ags_output_editor_callbacks.lo -MD -MP -MF ags/X/$(DEPDIR)/libgsequencer_la-ags_output_editor_callbacks.Tpo -c -o ags/X/libgsequencer_la-ags_output_editor_callbacks.lo `test -f 'ags/X/ags_output_editor_callbacks.c' || echo '$(srcdir)/'`ags/X/ags_output_editor_callbacks.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/X/$(DEPDIR)/libgsequencer_la-ags_output_editor_callbacks.Tpo ags/X/$(DEPDIR)/libgsequencer_la-ags_output_editor_callbacks.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/X/ags_output_editor_callbacks.c' object='ags/X/libgsequencer_la-ags_output_editor_callbacks.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -c -o ags/X/libgsequencer_la-ags_output_editor_callbacks.lo `test -f 'ags/X/ags_output_editor_callbacks.c' || echo '$(srcdir)/'`ags/X/ags_output_editor_callbacks.c
+
+ags/X/libgsequencer_la-ags_output_listing_editor.lo: ags/X/ags_output_listing_editor.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -MT ags/X/libgsequencer_la-ags_output_listing_editor.lo -MD -MP -MF ags/X/$(DEPDIR)/libgsequencer_la-ags_output_listing_editor.Tpo -c -o ags/X/libgsequencer_la-ags_output_listing_editor.lo `test -f 'ags/X/ags_output_listing_editor.c' || echo '$(srcdir)/'`ags/X/ags_output_listing_editor.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/X/$(DEPDIR)/libgsequencer_la-ags_output_listing_editor.Tpo ags/X/$(DEPDIR)/libgsequencer_la-ags_output_listing_editor.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/X/ags_output_listing_editor.c' object='ags/X/libgsequencer_la-ags_output_listing_editor.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -c -o ags/X/libgsequencer_la-ags_output_listing_editor.lo `test -f 'ags/X/ags_output_listing_editor.c' || echo '$(srcdir)/'`ags/X/ags_output_listing_editor.c
+
+ags/X/libgsequencer_la-ags_output_listing_editor_callbacks.lo: ags/X/ags_output_listing_editor_callbacks.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -MT ags/X/libgsequencer_la-ags_output_listing_editor_callbacks.lo -MD -MP -MF ags/X/$(DEPDIR)/libgsequencer_la-ags_output_listing_editor_callbacks.Tpo -c -o ags/X/libgsequencer_la-ags_output_listing_editor_callbacks.lo `test -f 'ags/X/ags_output_listing_editor_callbacks.c' || echo '$(srcdir)/'`ags/X/ags_output_listing_editor_callbacks.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/X/$(DEPDIR)/libgsequencer_la-ags_output_listing_editor_callbacks.Tpo ags/X/$(DEPDIR)/libgsequencer_la-ags_output_listing_editor_callbacks.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/X/ags_output_listing_editor_callbacks.c' object='ags/X/libgsequencer_la-ags_output_listing_editor_callbacks.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -c -o ags/X/libgsequencer_la-ags_output_listing_editor_callbacks.lo `test -f 'ags/X/ags_output_listing_editor_callbacks.c' || echo '$(srcdir)/'`ags/X/ags_output_listing_editor_callbacks.c
+
 ags/X/libgsequencer_la-ags_pad.lo: ags/X/ags_pad.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -MT ags/X/libgsequencer_la-ags_pad.lo -MD -MP -MF ags/X/$(DEPDIR)/libgsequencer_la-ags_pad.Tpo -c -o ags/X/libgsequencer_la-ags_pad.lo `test -f 'ags/X/ags_pad.c' || echo '$(srcdir)/'`ags/X/ags_pad.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/X/$(DEPDIR)/libgsequencer_la-ags_pad.Tpo ags/X/$(DEPDIR)/libgsequencer_la-ags_pad.Plo
@@ -8583,6 +9320,34 @@ ags/X/editor/libgsequencer_la-ags_toolbar_callbacks.lo: ags/X/editor/ags_toolbar
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_la_CFLAGS) $(CFLAGS) -c -o ags/X/editor/libgsequencer_la-ags_toolbar_callbacks.lo `test -f 'ags/X/editor/ags_toolbar_callbacks.c' || echo '$(srcdir)/'`ags/X/editor/ags_toolbar_callbacks.c
 
+ags/test/X/libgsequencer_test_la-gsequencer_setup_util.lo: ags/test/X/gsequencer_setup_util.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgsequencer_test_la_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_test_la_CFLAGS) $(CFLAGS) -MT ags/test/X/libgsequencer_test_la-gsequencer_setup_util.lo -MD -MP -MF ags/test/X/$(DEPDIR)/libgsequencer_test_la-gsequencer_setup_util.Tpo -c -o ags/test/X/libgsequencer_test_la-gsequencer_setup_util.lo `test -f 'ags/test/X/gsequencer_setup_util.c' || echo '$(srcdir)/'`ags/test/X/gsequencer_setup_util.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/$(DEPDIR)/libgsequencer_test_la-gsequencer_setup_util.Tpo ags/test/X/$(DEPDIR)/libgsequencer_test_la-gsequencer_setup_util.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/gsequencer_setup_util.c' object='ags/test/X/libgsequencer_test_la-gsequencer_setup_util.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgsequencer_test_la_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_test_la_CFLAGS) $(CFLAGS) -c -o ags/test/X/libgsequencer_test_la-gsequencer_setup_util.lo `test -f 'ags/test/X/gsequencer_setup_util.c' || echo '$(srcdir)/'`ags/test/X/gsequencer_setup_util.c
+
+ags/test/X/libgsequencer_test_la-ags_functional_test_util.lo: ags/test/X/ags_functional_test_util.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgsequencer_test_la_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_test_la_CFLAGS) $(CFLAGS) -MT ags/test/X/libgsequencer_test_la-ags_functional_test_util.lo -MD -MP -MF ags/test/X/$(DEPDIR)/libgsequencer_test_la-ags_functional_test_util.Tpo -c -o ags/test/X/libgsequencer_test_la-ags_functional_test_util.lo `test -f 'ags/test/X/ags_functional_test_util.c' || echo '$(srcdir)/'`ags/test/X/ags_functional_test_util.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/$(DEPDIR)/libgsequencer_test_la-ags_functional_test_util.Tpo ags/test/X/$(DEPDIR)/libgsequencer_test_la-ags_functional_test_util.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/ags_functional_test_util.c' object='ags/test/X/libgsequencer_test_la-ags_functional_test_util.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgsequencer_test_la_CPPFLAGS) $(CPPFLAGS) $(libgsequencer_test_la_CFLAGS) $(CFLAGS) -c -o ags/test/X/libgsequencer_test_la-ags_functional_test_util.lo `test -f 'ags/test/X/ags_functional_test_util.c' || echo '$(srcdir)/'`ags/test/X/ags_functional_test_util.c
+
+ags/test/audio/ags_audio_application_context_test-ags_audio_application_context_test.o: ags/test/audio/ags_audio_application_context_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_audio_application_context_test_CFLAGS) $(CFLAGS) -MT ags/test/audio/ags_audio_application_context_test-ags_audio_application_context_test.o -MD -MP -MF ags/test/audio/$(DEPDIR)/ags_audio_application_context_test-ags_audio_application_context_test.Tpo -c -o ags/test/audio/ags_audio_application_context_test-ags_audio_application_context_test.o `test -f 'ags/test/audio/ags_audio_application_context_test.c' || echo '$(srcdir)/'`ags/test/audio/ags_audio_application_context_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/audio/$(DEPDIR)/ags_audio_application_context_test-ags_audio_application_context_test.Tpo ags/test/audio/$(DEPDIR)/ags_audio_application_context_test-ags_audio_application_context_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/audio/ags_audio_application_context_test.c' object='ags/test/audio/ags_audio_application_context_test-ags_audio_application_context_test.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_audio_application_context_test_CFLAGS) $(CFLAGS) -c -o ags/test/audio/ags_audio_application_context_test-ags_audio_application_context_test.o `test -f 'ags/test/audio/ags_audio_application_context_test.c' || echo '$(srcdir)/'`ags/test/audio/ags_audio_application_context_test.c
+
+ags/test/audio/ags_audio_application_context_test-ags_audio_application_context_test.obj: ags/test/audio/ags_audio_application_context_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_audio_application_context_test_CFLAGS) $(CFLAGS) -MT ags/test/audio/ags_audio_application_context_test-ags_audio_application_context_test.obj -MD -MP -MF ags/test/audio/$(DEPDIR)/ags_audio_application_context_test-ags_audio_application_context_test.Tpo -c -o ags/test/audio/ags_audio_application_context_test-ags_audio_application_context_test.obj `if test -f 'ags/test/audio/ags_audio_application_context_test.c'; then $(CYGPATH_W) 'ags/test/audio/ags_audio_application_context_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/audio/ags_audio_application_context_test.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/audio/$(DEPDIR)/ags_audio_application_context_test-ags_audio_application_context_test.Tpo ags/test/audio/$(DEPDIR)/ags_audio_application_context_test-ags_audio_application_context_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/audio/ags_audio_application_context_test.c' object='ags/test/audio/ags_audio_application_context_test-ags_audio_application_context_test.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_audio_application_context_test_CFLAGS) $(CFLAGS) -c -o ags/test/audio/ags_audio_application_context_test-ags_audio_application_context_test.obj `if test -f 'ags/test/audio/ags_audio_application_context_test.c'; then $(CYGPATH_W) 'ags/test/audio/ags_audio_application_context_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/audio/ags_audio_application_context_test.c'; fi`
+
 ags/test/audio/ags_audio_signal_test-ags_audio_signal_test.o: ags/test/audio/ags_audio_signal_test.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_audio_signal_test_CFLAGS) $(CFLAGS) -MT ags/test/audio/ags_audio_signal_test-ags_audio_signal_test.o -MD -MP -MF ags/test/audio/$(DEPDIR)/ags_audio_signal_test-ags_audio_signal_test.Tpo -c -o ags/test/audio/ags_audio_signal_test-ags_audio_signal_test.o `test -f 'ags/test/audio/ags_audio_signal_test.c' || echo '$(srcdir)/'`ags/test/audio/ags_audio_signal_test.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/audio/$(DEPDIR)/ags_audio_signal_test-ags_audio_signal_test.Tpo ags/test/audio/$(DEPDIR)/ags_audio_signal_test-ags_audio_signal_test.Po
@@ -8639,6 +9404,20 @@ ags/test/audio/ags_channel_test-ags_channel_test.obj: ags/test/audio/ags_channel
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_channel_test_CFLAGS) $(CFLAGS) -c -o ags/test/audio/ags_channel_test-ags_channel_test.obj `if test -f 'ags/test/audio/ags_channel_test.c'; then $(CYGPATH_W) 'ags/test/audio/ags_channel_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/audio/ags_channel_test.c'; fi`
 
+ags/test/audio/ags_devout_test-ags_devout_test.o: ags/test/audio/ags_devout_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_devout_test_CFLAGS) $(CFLAGS) -MT ags/test/audio/ags_devout_test-ags_devout_test.o -MD -MP -MF ags/test/audio/$(DEPDIR)/ags_devout_test-ags_devout_test.Tpo -c -o ags/test/audio/ags_devout_test-ags_devout_test.o `test -f 'ags/test/audio/ags_devout_test.c' || echo '$(srcdir)/'`ags/test/audio/ags_devout_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/audio/$(DEPDIR)/ags_devout_test-ags_devout_test.Tpo ags/test/audio/$(DEPDIR)/ags_devout_test-ags_devout_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/audio/ags_devout_test.c' object='ags/test/audio/ags_devout_test-ags_devout_test.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_devout_test_CFLAGS) $(CFLAGS) -c -o ags/test/audio/ags_devout_test-ags_devout_test.o `test -f 'ags/test/audio/ags_devout_test.c' || echo '$(srcdir)/'`ags/test/audio/ags_devout_test.c
+
+ags/test/audio/ags_devout_test-ags_devout_test.obj: ags/test/audio/ags_devout_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_devout_test_CFLAGS) $(CFLAGS) -MT ags/test/audio/ags_devout_test-ags_devout_test.obj -MD -MP -MF ags/test/audio/$(DEPDIR)/ags_devout_test-ags_devout_test.Tpo -c -o ags/test/audio/ags_devout_test-ags_devout_test.obj `if test -f 'ags/test/audio/ags_devout_test.c'; then $(CYGPATH_W) 'ags/test/audio/ags_devout_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/audio/ags_devout_test.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/audio/$(DEPDIR)/ags_devout_test-ags_devout_test.Tpo ags/test/audio/$(DEPDIR)/ags_devout_test-ags_devout_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/audio/ags_devout_test.c' object='ags/test/audio/ags_devout_test-ags_devout_test.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_devout_test_CFLAGS) $(CFLAGS) -c -o ags/test/audio/ags_devout_test-ags_devout_test.obj `if test -f 'ags/test/audio/ags_devout_test.c'; then $(CYGPATH_W) 'ags/test/audio/ags_devout_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/audio/ags_devout_test.c'; fi`
+
 ags/test/audio/ags_functional_audio_test-ags_functional_audio_test.o: ags/test/audio/ags_functional_audio_test.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_functional_audio_test_CFLAGS) $(CFLAGS) -MT ags/test/audio/ags_functional_audio_test-ags_functional_audio_test.o -MD -MP -MF ags/test/audio/$(DEPDIR)/ags_functional_audio_test-ags_functional_audio_test.Tpo -c -o ags/test/audio/ags_functional_audio_test-ags_functional_audio_test.o `test -f 'ags/test/audio/ags_functional_audio_test.c' || echo '$(srcdir)/'`ags/test/audio/ags_functional_audio_test.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/audio/$(DEPDIR)/ags_functional_audio_test-ags_functional_audio_test.Tpo ags/test/audio/$(DEPDIR)/ags_functional_audio_test-ags_functional_audio_test.Po
@@ -8653,6 +9432,118 @@ ags/test/audio/ags_functional_audio_test-ags_functional_audio_test.obj: ags/test
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_functional_audio_test_CFLAGS) $(CFLAGS) -c -o ags/test/audio/ags_functional_audio_test-ags_functional_audio_test.obj `if test -f 'ags/test/audio/ags_functional_audio_test.c'; then $(CYGPATH_W) 'ags/test/audio/ags_functional_audio_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/audio/ags_functional_audio_test.c'; fi`
 
+ags/test/X/machine/ags_functional_drum_test-ags_functional_drum_test.o: ags/test/X/machine/ags_functional_drum_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_drum_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_drum_test_CFLAGS) $(CFLAGS) -MT ags/test/X/machine/ags_functional_drum_test-ags_functional_drum_test.o -MD -MP -MF ags/test/X/machine/$(DEPDIR)/ags_functional_drum_test-ags_functional_drum_test.Tpo -c -o ags/test/X/machine/ags_functional_drum_test-ags_functional_drum_test.o `test -f 'ags/test/X/machine/ags_functional_drum_test.c' || echo '$(srcdir)/'`ags/test/X/machine/ags_functional_drum_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/machine/$(DEPDIR)/ags_functional_drum_test-ags_functional_drum_test.Tpo ags/test/X/machine/$(DEPDIR)/ags_functional_drum_test-ags_functional_drum_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/machine/ags_functional_drum_test.c' object='ags/test/X/machine/ags_functional_drum_test-ags_functional_drum_test.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_drum_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_drum_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/machine/ags_functional_drum_test-ags_functional_drum_test.o `test -f 'ags/test/X/machine/ags_functional_drum_test.c' || echo '$(srcdir)/'`ags/test/X/machine/ags_functional_drum_test.c
+
+ags/test/X/machine/ags_functional_drum_test-ags_functional_drum_test.obj: ags/test/X/machine/ags_functional_drum_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_drum_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_drum_test_CFLAGS) $(CFLAGS) -MT ags/test/X/machine/ags_functional_drum_test-ags_functional_drum_test.obj -MD -MP -MF ags/test/X/machine/$(DEPDIR)/ags_functional_drum_test-ags_functional_drum_test.Tpo -c -o ags/test/X/machine/ags_functional_drum_test-ags_functional_drum_test.obj `if test -f 'ags/test/X/machine/ags_functional_drum_test.c'; then $(CYGPATH_W) 'ags/test/X/machine/ags_functional_drum_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/machine/ags_functional_drum_test.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/machine/$(DEPDIR)/ags_functional_drum_test-ags_functional_drum_test.Tpo ags/test/X/machine/$(DEPDIR)/ags_functional_drum_test-ags_functional_drum_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/machine/ags_functional_drum_test.c' object='ags/test/X/machine/ags_functional_drum_test-ags_functional_drum_test.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_drum_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_drum_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/machine/ags_functional_drum_test-ags_functional_drum_test.obj `if test -f 'ags/test/X/machine/ags_functional_drum_test.c'; then $(CYGPATH_W) 'ags/test/X/machine/ags_functional_drum_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/machine/ags_functional_drum_test.c'; fi`
+
+ags/test/X/machine/ags_functional_ffplayer_test-ags_functional_ffplayer_test.o: ags/test/X/machine/ags_functional_ffplayer_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_ffplayer_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_ffplayer_test_CFLAGS) $(CFLAGS) -MT ags/test/X/machine/ags_functional_ffplayer_test-ags_functional_ffplayer_test.o -MD -MP -MF ags/test/X/machine/$(DEPDIR)/ags_functional_ffplayer_test-ags_functional_ffplayer_test.Tpo -c -o ags/test/X/machine/ags_functional_ffplayer_test-ags_functional_ffplayer_test.o `test -f 'ags/test/X/machine/ags_functional_ffplayer_test.c' || echo '$(srcdir)/'`ags/test/X/machine/ags_functional_ffplayer_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/machine/$(DEPDIR)/ags_functional_ffplayer_test-ags_functional_ffplayer_test.Tpo ags/test/X/machine/$(DEPDIR)/ags_functional_ffplayer_test-ags_functional_ffplayer_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/machine/ags_functional_ffplayer_test.c' object='ags/test/X/machine/ags_functional_ffplayer_test-ags_functional_ffplayer_test.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_ffplayer_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_ffplayer_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/machine/ags_functional_ffplayer_test-ags_functional_ffplayer_test.o `test -f 'ags/test/X/machine/ags_functional_ffplayer_test.c' || echo '$(srcdir)/'`ags/test/X/machine/ags_functional_ffplayer_test.c
+
+ags/test/X/machine/ags_functional_ffplayer_test-ags_functional_ffplayer_test.obj: ags/test/X/machine/ags_functional_ffplayer_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_ffplayer_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_ffplayer_test_CFLAGS) $(CFLAGS) -MT ags/test/X/machine/ags_functional_ffplayer_test-ags_functional_ffplayer_test.obj -MD -MP -MF ags/test/X/machine/$(DEPDIR)/ags_functional_ffplayer_test-ags_functional_ffplayer_test.Tpo -c -o ags/test/X/machine/ags_functional_ffplayer_test-ags_functional_ffplayer_test.obj `if test -f 'ags/test/X/machine/ags_functional_ffplayer_test.c'; then $(CYGPATH_W) 'ags/test/X/machine/ags_functional_ffplayer_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/machine/ags_functional_ffplayer_test.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/machine/$(DEPDIR)/ags_functional_ffplayer_test-ags_functional_ffplayer_test.Tpo ags/test/X/machine/$(DEPDIR)/ags_functional_ffplayer_test-ags_functional_ffplayer_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/machine/ags_functional_ffplayer_test.c' object='ags/test/X/machine/ags_functional_ffplayer_test-ags_functional_ffplayer_test.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_ffplayer_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_ffplayer_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/machine/ags_functional_ffplayer_test-ags_functional_ffplayer_test.obj `if test -f 'ags/test/X/machine/ags_functional_ffplayer_test.c'; then $(CYGPATH_W) 'ags/test/X/machine/ags_functional_ffplayer_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/machine/ags_functional_ffplayer_test.c'; fi`
+
+ags/test/X/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.o: ags/test/X/ags_functional_machine_add_and_destroy_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_machine_add_and_destroy_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_machine_add_and_destroy_test_CFLAGS) $(CFLAGS) -MT ags/test/X/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.o -MD -MP -MF ags/test/X/$(DEPDIR)/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.Tpo -c -o ags/test/X/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.o `test -f 'ags/test/X/ags_functional_machine_add_and_destroy_test.c' || echo '$(srcdir)/'`ags/test/X/ags_functional_machine_add_and_destroy_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/$(DEPDIR)/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.Tpo ags/test/X/$(DEPDIR)/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/ags_functional_machine_add_and_destroy_test.c' object='ags/test/X/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_machine_add_and_destroy_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_machine_add_and_destroy_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.o `test -f 'ags/test/X/ags_functional_machine_add_and_destroy_test.c' || echo '$(srcdir)/'`ags/test/X/ags_functional_machine_add_and_destroy_test.c
+
+ags/test/X/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.obj: ags/test/X/ags_functional_machine_add_and_destroy_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_machine_add_and_destroy_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_machine_add_and_destroy_test_CFLAGS) $(CFLAGS) -MT ags/test/X/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.obj -MD -MP -MF ags/test/X/$(DEPDIR)/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.Tpo -c -o ags/test/X/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.obj `if test -f 'ags/test/X/ags_functional_machine_add_and_destroy_test.c'; then $(CYGPATH_W) 'ags/test/X/ags_functional_machine_add_and_destroy_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/ags_functional_machine_add_and_destroy_test.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/$(DEPDIR)/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.Tpo ags/test/X/$(DEPDIR)/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/ags_functional_machine_add_and_destroy_test.c' object='ags/test/X/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_machine_add_and_destroy_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_machine_add_and_destroy_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/ags_functional_machine_add_and_destroy_test-ags_functional_machine_add_and_destroy_test.obj `if test -f 'ags/test/X/ags_functional_machine_add_and_destroy_test.c'; then $(CYGPATH_W) 'ags/test/X/ags_functional_machine_add_and_destroy_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/ags_functional_machine_add_and_destroy_test.c'; fi`
+
+ags/test/X/machine/ags_functional_matrix_test-ags_functional_matrix_test.o: ags/test/X/machine/ags_functional_matrix_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_matrix_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_matrix_test_CFLAGS) $(CFLAGS) -MT ags/test/X/machine/ags_functional_matrix_test-ags_functional_matrix_test.o -MD -MP -MF ags/test/X/machine/$(DEPDIR)/ags_functional_matrix_test-ags_functional_matrix_test.Tpo -c -o ags/test/X/machine/ags_functional_matrix_test-ags_functional_matrix_test.o `test -f 'ags/test/X/machine/ags_functional_matrix_test.c' || echo '$(srcdir)/'`ags/test/X/machine/ags_functional_matrix_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/machine/$(DEPDIR)/ags_functional_matrix_test-ags_functional_matrix_test.Tpo ags/test/X/machine/$(DEPDIR)/ags_functional_matrix_test-ags_functional_matrix_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/machine/ags_functional_matrix_test.c' object='ags/test/X/machine/ags_functional_matrix_test-ags_functional_matrix_test.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_matrix_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_matrix_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/machine/ags_functional_matrix_test-ags_functional_matrix_test.o `test -f 'ags/test/X/machine/ags_functional_matrix_test.c' || echo '$(srcdir)/'`ags/test/X/machine/ags_functional_matrix_test.c
+
+ags/test/X/machine/ags_functional_matrix_test-ags_functional_matrix_test.obj: ags/test/X/machine/ags_functional_matrix_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_matrix_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_matrix_test_CFLAGS) $(CFLAGS) -MT ags/test/X/machine/ags_functional_matrix_test-ags_functional_matrix_test.obj -MD -MP -MF ags/test/X/machine/$(DEPDIR)/ags_functional_matrix_test-ags_functional_matrix_test.Tpo -c -o ags/test/X/machine/ags_functional_matrix_test-ags_functional_matrix_test.obj `if test -f 'ags/test/X/machine/ags_functional_matrix_test.c'; then $(CYGPATH_W) 'ags/test/X/machine/ags_functional_matrix_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/machine/ags_functional_matrix_test.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/machine/$(DEPDIR)/ags_functional_matrix_test-ags_functional_matrix_test.Tpo ags/test/X/machine/$(DEPDIR)/ags_functional_matrix_test-ags_functional_matrix_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/machine/ags_functional_matrix_test.c' object='ags/test/X/machine/ags_functional_matrix_test-ags_functional_matrix_test.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_matrix_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_matrix_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/machine/ags_functional_matrix_test-ags_functional_matrix_test.obj `if test -f 'ags/test/X/machine/ags_functional_matrix_test.c'; then $(CYGPATH_W) 'ags/test/X/machine/ags_functional_matrix_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/machine/ags_functional_matrix_test.c'; fi`
+
+ags/test/X/machine/ags_functional_mixer_test-ags_functional_mixer_test.o: ags/test/X/machine/ags_functional_mixer_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_mixer_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_mixer_test_CFLAGS) $(CFLAGS) -MT ags/test/X/machine/ags_functional_mixer_test-ags_functional_mixer_test.o -MD -MP -MF ags/test/X/machine/$(DEPDIR)/ags_functional_mixer_test-ags_functional_mixer_test.Tpo -c -o ags/test/X/machine/ags_functional_mixer_test-ags_functional_mixer_test.o `test -f 'ags/test/X/machine/ags_functional_mixer_test.c' || echo '$(srcdir)/'`ags/test/X/machine/ags_functional_mixer_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/machine/$(DEPDIR)/ags_functional_mixer_test-ags_functional_mixer_test.Tpo ags/test/X/machine/$(DEPDIR)/ags_functional_mixer_test-ags_functional_mixer_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/machine/ags_functional_mixer_test.c' object='ags/test/X/machine/ags_functional_mixer_test-ags_functional_mixer_test.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_mixer_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_mixer_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/machine/ags_functional_mixer_test-ags_functional_mixer_test.o `test -f 'ags/test/X/machine/ags_functional_mixer_test.c' || echo '$(srcdir)/'`ags/test/X/machine/ags_functional_mixer_test.c
+
+ags/test/X/machine/ags_functional_mixer_test-ags_functional_mixer_test.obj: ags/test/X/machine/ags_functional_mixer_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_mixer_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_mixer_test_CFLAGS) $(CFLAGS) -MT ags/test/X/machine/ags_functional_mixer_test-ags_functional_mixer_test.obj -MD -MP -MF ags/test/X/machine/$(DEPDIR)/ags_functional_mixer_test-ags_functional_mixer_test.Tpo -c -o ags/test/X/machine/ags_functional_mixer_test-ags_functional_mixer_test.obj `if test -f 'ags/test/X/machine/ags_functional_mixer_test.c'; then $(CYGPATH_W) 'ags/test/X/machine/ags_functional_mixer_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/machine/ags_functional_mixer_test.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/machine/$(DEPDIR)/ags_functional_mixer_test-ags_functional_mixer_test.Tpo ags/test/X/machine/$(DEPDIR)/ags_functional_mixer_test-ags_functional_mixer_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/machine/ags_functional_mixer_test.c' object='ags/test/X/machine/ags_functional_mixer_test-ags_functional_mixer_test.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_mixer_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_mixer_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/machine/ags_functional_mixer_test-ags_functional_mixer_test.obj `if test -f 'ags/test/X/machine/ags_functional_mixer_test.c'; then $(CYGPATH_W) 'ags/test/X/machine/ags_functional_mixer_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/machine/ags_functional_mixer_test.c'; fi`
+
+ags/test/X/ags_functional_note_edit_test-ags_functional_note_edit_test.o: ags/test/X/ags_functional_note_edit_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_note_edit_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_note_edit_test_CFLAGS) $(CFLAGS) -MT ags/test/X/ags_functional_note_edit_test-ags_functional_note_edit_test.o -MD -MP -MF ags/test/X/$(DEPDIR)/ags_functional_note_edit_test-ags_functional_note_edit_test.Tpo -c -o ags/test/X/ags_functional_note_edit_test-ags_functional_note_edit_test.o `test -f 'ags/test/X/ags_functional_note_edit_test.c' || echo '$(srcdir)/'`ags/test/X/ags_functional_note_edit_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/$(DEPDIR)/ags_functional_note_edit_test-ags_functional_note_edit_test.Tpo ags/test/X/$(DEPDIR)/ags_functional_note_edit_test-ags_functional_note_edit_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/ags_functional_note_edit_test.c' object='ags/test/X/ags_functional_note_edit_test-ags_functional_note_edit_test.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_note_edit_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_note_edit_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/ags_functional_note_edit_test-ags_functional_note_edit_test.o `test -f 'ags/test/X/ags_functional_note_edit_test.c' || echo '$(srcdir)/'`ags/test/X/ags_functional_note_edit_test.c
+
+ags/test/X/ags_functional_note_edit_test-ags_functional_note_edit_test.obj: ags/test/X/ags_functional_note_edit_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_note_edit_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_note_edit_test_CFLAGS) $(CFLAGS) -MT ags/test/X/ags_functional_note_edit_test-ags_functional_note_edit_test.obj -MD -MP -MF ags/test/X/$(DEPDIR)/ags_functional_note_edit_test-ags_functional_note_edit_test.Tpo -c -o ags/test/X/ags_functional_note_edit_test-ags_functional_note_edit_test.obj `if test -f 'ags/test/X/ags_functional_note_edit_test.c'; then $(CYGPATH_W) 'ags/test/X/ags_functional_note_edit_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/ags_functional_note_edit_test.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/$(DEPDIR)/ags_functional_note_edit_test-ags_functional_note_edit_test.Tpo ags/test/X/$(DEPDIR)/ags_functional_note_edit_test-ags_functional_note_edit_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/ags_functional_note_edit_test.c' object='ags/test/X/ags_functional_note_edit_test-ags_functional_note_edit_test.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_note_edit_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_note_edit_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/ags_functional_note_edit_test-ags_functional_note_edit_test.obj `if test -f 'ags/test/X/ags_functional_note_edit_test.c'; then $(CYGPATH_W) 'ags/test/X/ags_functional_note_edit_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/ags_functional_note_edit_test.c'; fi`
+
+ags/test/X/machine/ags_functional_panel_test-ags_functional_panel_test.o: ags/test/X/machine/ags_functional_panel_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_panel_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_panel_test_CFLAGS) $(CFLAGS) -MT ags/test/X/machine/ags_functional_panel_test-ags_functional_panel_test.o -MD -MP -MF ags/test/X/machine/$(DEPDIR)/ags_functional_panel_test-ags_functional_panel_test.Tpo -c -o ags/test/X/machine/ags_functional_panel_test-ags_functional_panel_test.o `test -f 'ags/test/X/machine/ags_functional_panel_test.c' || echo '$(srcdir)/'`ags/test/X/machine/ags_functional_panel_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/machine/$(DEPDIR)/ags_functional_panel_test-ags_functional_panel_test.Tpo ags/test/X/machine/$(DEPDIR)/ags_functional_panel_test-ags_functional_panel_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/machine/ags_functional_panel_test.c' object='ags/test/X/machine/ags_functional_panel_test-ags_functional_panel_test.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_panel_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_panel_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/machine/ags_functional_panel_test-ags_functional_panel_test.o `test -f 'ags/test/X/machine/ags_functional_panel_test.c' || echo '$(srcdir)/'`ags/test/X/machine/ags_functional_panel_test.c
+
+ags/test/X/machine/ags_functional_panel_test-ags_functional_panel_test.obj: ags/test/X/machine/ags_functional_panel_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_panel_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_panel_test_CFLAGS) $(CFLAGS) -MT ags/test/X/machine/ags_functional_panel_test-ags_functional_panel_test.obj -MD -MP -MF ags/test/X/machine/$(DEPDIR)/ags_functional_panel_test-ags_functional_panel_test.Tpo -c -o ags/test/X/machine/ags_functional_panel_test-ags_functional_panel_test.obj `if test -f 'ags/test/X/machine/ags_functional_panel_test.c'; then $(CYGPATH_W) 'ags/test/X/machine/ags_functional_panel_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/machine/ags_functional_panel_test.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/machine/$(DEPDIR)/ags_functional_panel_test-ags_functional_panel_test.Tpo ags/test/X/machine/$(DEPDIR)/ags_functional_panel_test-ags_functional_panel_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/machine/ags_functional_panel_test.c' object='ags/test/X/machine/ags_functional_panel_test-ags_functional_panel_test.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_panel_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_panel_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/machine/ags_functional_panel_test-ags_functional_panel_test.obj `if test -f 'ags/test/X/machine/ags_functional_panel_test.c'; then $(CYGPATH_W) 'ags/test/X/machine/ags_functional_panel_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/machine/ags_functional_panel_test.c'; fi`
+
+ags/test/X/machine/ags_functional_synth_test-ags_functional_synth_test.o: ags/test/X/machine/ags_functional_synth_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_synth_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_synth_test_CFLAGS) $(CFLAGS) -MT ags/test/X/machine/ags_functional_synth_test-ags_functional_synth_test.o -MD -MP -MF ags/test/X/machine/$(DEPDIR)/ags_functional_synth_test-ags_functional_synth_test.Tpo -c -o ags/test/X/machine/ags_functional_synth_test-ags_functional_synth_test.o `test -f 'ags/test/X/machine/ags_functional_synth_test.c' || echo '$(srcdir)/'`ags/test/X/machine/ags_functional_synth_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/machine/$(DEPDIR)/ags_functional_synth_test-ags_functional_synth_test.Tpo ags/test/X/machine/$(DEPDIR)/ags_functional_synth_test-ags_functional_synth_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/machine/ags_functional_synth_test.c' object='ags/test/X/machine/ags_functional_synth_test-ags_functional_synth_test.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_synth_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_synth_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/machine/ags_functional_synth_test-ags_functional_synth_test.o `test -f 'ags/test/X/machine/ags_functional_synth_test.c' || echo '$(srcdir)/'`ags/test/X/machine/ags_functional_synth_test.c
+
+ags/test/X/machine/ags_functional_synth_test-ags_functional_synth_test.obj: ags/test/X/machine/ags_functional_synth_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_synth_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_synth_test_CFLAGS) $(CFLAGS) -MT ags/test/X/machine/ags_functional_synth_test-ags_functional_synth_test.obj -MD -MP -MF ags/test/X/machine/$(DEPDIR)/ags_functional_synth_test-ags_functional_synth_test.Tpo -c -o ags/test/X/machine/ags_functional_synth_test-ags_functional_synth_test.obj `if test -f 'ags/test/X/machine/ags_functional_synth_test.c'; then $(CYGPATH_W) 'ags/test/X/machine/ags_functional_synth_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/machine/ags_functional_synth_test.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/machine/$(DEPDIR)/ags_functional_synth_test-ags_functional_synth_test.Tpo ags/test/X/machine/$(DEPDIR)/ags_functional_synth_test-ags_functional_synth_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/machine/ags_functional_synth_test.c' object='ags/test/X/machine/ags_functional_synth_test-ags_functional_synth_test.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ags_functional_synth_test_CPPFLAGS) $(CPPFLAGS) $(ags_functional_synth_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/machine/ags_functional_synth_test-ags_functional_synth_test.obj `if test -f 'ags/test/X/machine/ags_functional_synth_test.c'; then $(CYGPATH_W) 'ags/test/X/machine/ags_functional_synth_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/machine/ags_functional_synth_test.c'; fi`
+
 ags/test/audio/midi/ags_midi_buffer_util_test-ags_midi_buffer_util_test.o: ags/test/audio/midi/ags_midi_buffer_util_test.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_midi_buffer_util_test_CFLAGS) $(CFLAGS) -MT ags/test/audio/midi/ags_midi_buffer_util_test-ags_midi_buffer_util_test.o -MD -MP -MF ags/test/audio/midi/$(DEPDIR)/ags_midi_buffer_util_test-ags_midi_buffer_util_test.Tpo -c -o ags/test/audio/midi/ags_midi_buffer_util_test-ags_midi_buffer_util_test.o `test -f 'ags/test/audio/midi/ags_midi_buffer_util_test.c' || echo '$(srcdir)/'`ags/test/audio/midi/ags_midi_buffer_util_test.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/audio/midi/$(DEPDIR)/ags_midi_buffer_util_test-ags_midi_buffer_util_test.Tpo ags/test/audio/midi/$(DEPDIR)/ags_midi_buffer_util_test-ags_midi_buffer_util_test.Po
@@ -8751,6 +9642,20 @@ ags/test/lib/ags_turtle_test-ags_turtle_test.obj: ags/test/lib/ags_turtle_test.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_turtle_test_CFLAGS) $(CFLAGS) -c -o ags/test/lib/ags_turtle_test-ags_turtle_test.obj `if test -f 'ags/test/lib/ags_turtle_test.c'; then $(CYGPATH_W) 'ags/test/lib/ags_turtle_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/lib/ags_turtle_test.c'; fi`
 
+ags/test/X/ags_xorg_application_context_test-ags_xorg_application_context_test.o: ags/test/X/ags_xorg_application_context_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_xorg_application_context_test_CFLAGS) $(CFLAGS) -MT ags/test/X/ags_xorg_application_context_test-ags_xorg_application_context_test.o -MD -MP -MF ags/test/X/$(DEPDIR)/ags_xorg_application_context_test-ags_xorg_application_context_test.Tpo -c -o ags/test/X/ags_xorg_application_context_test-ags_xorg_application_context_test.o `test -f 'ags/test/X/ags_xorg_application_context_test.c' || echo '$(srcdir)/'`ags/test/X/ags_xorg_application_context_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/$(DEPDIR)/ags_xorg_application_context_test-ags_xorg_application_context_test.Tpo ags/test/X/$(DEPDIR)/ags_xorg_application_context_test-ags_xorg_application_context_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/ags_xorg_application_context_test.c' object='ags/test/X/ags_xorg_application_context_test-ags_xorg_application_context_test.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_xorg_application_context_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/ags_xorg_application_context_test-ags_xorg_application_context_test.o `test -f 'ags/test/X/ags_xorg_application_context_test.c' || echo '$(srcdir)/'`ags/test/X/ags_xorg_application_context_test.c
+
+ags/test/X/ags_xorg_application_context_test-ags_xorg_application_context_test.obj: ags/test/X/ags_xorg_application_context_test.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_xorg_application_context_test_CFLAGS) $(CFLAGS) -MT ags/test/X/ags_xorg_application_context_test-ags_xorg_application_context_test.obj -MD -MP -MF ags/test/X/$(DEPDIR)/ags_xorg_application_context_test-ags_xorg_application_context_test.Tpo -c -o ags/test/X/ags_xorg_application_context_test-ags_xorg_application_context_test.obj `if test -f 'ags/test/X/ags_xorg_application_context_test.c'; then $(CYGPATH_W) 'ags/test/X/ags_xorg_application_context_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/ags_xorg_application_context_test.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/test/X/$(DEPDIR)/ags_xorg_application_context_test-ags_xorg_application_context_test.Tpo ags/test/X/$(DEPDIR)/ags_xorg_application_context_test-ags_xorg_application_context_test.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='ags/test/X/ags_xorg_application_context_test.c' object='ags/test/X/ags_xorg_application_context_test-ags_xorg_application_context_test.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ags_xorg_application_context_test_CFLAGS) $(CFLAGS) -c -o ags/test/X/ags_xorg_application_context_test-ags_xorg_application_context_test.obj `if test -f 'ags/test/X/ags_xorg_application_context_test.c'; then $(CYGPATH_W) 'ags/test/X/ags_xorg_application_context_test.c'; else $(CYGPATH_W) '$(srcdir)/ags/test/X/ags_xorg_application_context_test.c'; fi`
+
 ags/gsequencer-gsequencer_main.o: ags/gsequencer_main.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -MT ags/gsequencer-gsequencer_main.o -MD -MP -MF ags/$(DEPDIR)/gsequencer-gsequencer_main.Tpo -c -o ags/gsequencer-gsequencer_main.o `test -f 'ags/gsequencer_main.c' || echo '$(srcdir)/'`ags/gsequencer_main.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) ags/$(DEPDIR)/gsequencer-gsequencer_main.Tpo ags/$(DEPDIR)/gsequencer-gsequencer_main.Po
@@ -8805,6 +9710,7 @@ clean-libtool:
 	-rm -rf ags/object/.libs ags/object/_libs
 	-rm -rf ags/plugin/.libs ags/plugin/_libs
 	-rm -rf ags/server/.libs ags/server/_libs
+	-rm -rf ags/test/X/.libs ags/test/X/_libs
 	-rm -rf ags/thread/.libs ags/thread/_libs
 	-rm -rf ags/thread/file/.libs ags/thread/file/_libs
 	-rm -rf ags/util/.libs ags/util/_libs
@@ -9156,6 +10062,20 @@ ags_turtle_test.log: ags_turtle_test$(EXEEXT)
 	--log-file $$b.log --trs-file $$b.trs \
 	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
 	"$$tst" $(AM_TESTS_FD_REDIRECT)
+ags_audio_application_context_test.log: ags_audio_application_context_test$(EXEEXT)
+	@p='ags_audio_application_context_test$(EXEEXT)'; \
+	b='ags_audio_application_context_test'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+ags_devout_test.log: ags_devout_test$(EXEEXT)
+	@p='ags_devout_test$(EXEEXT)'; \
+	b='ags_devout_test'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
 ags_audio_test.log: ags_audio_test$(EXEEXT)
 	@p='ags_audio_test$(EXEEXT)'; \
 	b='ags_audio_test'; \
@@ -9219,6 +10139,13 @@ ags_midi_buffer_util_test.log: ags_midi_buffer_util_test$(EXEEXT)
 	--log-file $$b.log --trs-file $$b.trs \
 	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
 	"$$tst" $(AM_TESTS_FD_REDIRECT)
+ags_xorg_application_context_test.log: ags_xorg_application_context_test$(EXEEXT)
+	@p='ags_xorg_application_context_test$(EXEEXT)'; \
+	b='ags_xorg_application_context_test'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
 ags_functional_audio_test.log: ags_functional_audio_test$(EXEEXT)
 	@p='ags_functional_audio_test$(EXEEXT)'; \
 	b='ags_functional_audio_test'; \
@@ -9226,6 +10153,62 @@ ags_functional_audio_test.log: ags_functional_audio_test$(EXEEXT)
 	--log-file $$b.log --trs-file $$b.trs \
 	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
 	"$$tst" $(AM_TESTS_FD_REDIRECT)
+ags_functional_machine_add_and_destroy_test.log: ags_functional_machine_add_and_destroy_test$(EXEEXT)
+	@p='ags_functional_machine_add_and_destroy_test$(EXEEXT)'; \
+	b='ags_functional_machine_add_and_destroy_test'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+ags_functional_panel_test.log: ags_functional_panel_test$(EXEEXT)
+	@p='ags_functional_panel_test$(EXEEXT)'; \
+	b='ags_functional_panel_test'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+ags_functional_mixer_test.log: ags_functional_mixer_test$(EXEEXT)
+	@p='ags_functional_mixer_test$(EXEEXT)'; \
+	b='ags_functional_mixer_test'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+ags_functional_drum_test.log: ags_functional_drum_test$(EXEEXT)
+	@p='ags_functional_drum_test$(EXEEXT)'; \
+	b='ags_functional_drum_test'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+ags_functional_matrix_test.log: ags_functional_matrix_test$(EXEEXT)
+	@p='ags_functional_matrix_test$(EXEEXT)'; \
+	b='ags_functional_matrix_test'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+ags_functional_synth_test.log: ags_functional_synth_test$(EXEEXT)
+	@p='ags_functional_synth_test$(EXEEXT)'; \
+	b='ags_functional_synth_test'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+ags_functional_ffplayer_test.log: ags_functional_ffplayer_test$(EXEEXT)
+	@p='ags_functional_ffplayer_test$(EXEEXT)'; \
+	b='ags_functional_ffplayer_test'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+ags_functional_note_edit_test.log: ags_functional_note_edit_test$(EXEEXT)
+	@p='ags_functional_note_edit_test$(EXEEXT)'; \
+	b='ags_functional_note_edit_test'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
 .test.log:
 	@p='$<'; \
 	$(am__set_b); \
@@ -9489,6 +10472,10 @@ distclean-generic:
 	-rm -f ags/plugin/$(am__dirstamp)
 	-rm -f ags/server/$(DEPDIR)/$(am__dirstamp)
 	-rm -f ags/server/$(am__dirstamp)
+	-rm -f ags/test/X/$(DEPDIR)/$(am__dirstamp)
+	-rm -f ags/test/X/$(am__dirstamp)
+	-rm -f ags/test/X/machine/$(DEPDIR)/$(am__dirstamp)
+	-rm -f ags/test/X/machine/$(am__dirstamp)
 	-rm -f ags/test/audio/$(DEPDIR)/$(am__dirstamp)
 	-rm -f ags/test/audio/$(am__dirstamp)
 	-rm -f ags/test/audio/midi/$(DEPDIR)/$(am__dirstamp)
@@ -9517,11 +10504,12 @@ clean: clean-am
 
 clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
 	clean-libLTLIBRARIES clean-libgsequencerLTLIBRARIES \
-	clean-libtool clean-local mostlyclean-am
+	clean-libtool clean-local clean-noinstLTLIBRARIES \
+	mostlyclean-am
 
 distclean: distclean-am
 	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-	-rm -rf ags/$(DEPDIR) ags/X/$(DEPDIR) ags/X/editor/$(DEPDIR) ags/X/file/$(DEPDIR) ags/X/import/$(DEPDIR) ags/X/machine/$(DEPDIR) ags/X/task/$(DEPDIR) ags/X/thread/$(DEPDIR) ags/audio/$(DEPDIR) ags/audio/client/$(DEPDIR) ags/audio/file/$(DEPDIR) ags/audio/jack/$(DEPDIR) ags/audio/midi/$(DEPDIR) ags/audio/recall/$(DEPDIR) ags/audio/task/$(DEPDIR) ags/audio/task/recall/$(DEPDIR) ags/audio/thread/$(DEPDIR) ags/file/$(DEPDIR) ags/lib/$(DEPDIR) ags/object/$(DEPDIR) ags/plugin/$(DEPDIR) ags/server/$(DEPDIR) ags/test/audio/$(DEPDIR) ags/test/audio/midi/$(DEPDIR) ags/test/lib/$(DEPDIR) ags/test/thread/$(DEPDIR) ags/thread/$(DEPDIR) ags/thread/file/$(DEPDIR) ags/util/$(DEPDIR) ags/widget/$(DEPDIR)
+	-rm -rf ags/$(DEPDIR) ags/X/$(DEPDIR) ags/X/editor/$(DEPDIR) ags/X/file/$(DEPDIR) ags/X/import/$(DEPDIR) ags/X/machine/$(DEPDIR) ags/X/task/$(DEPDIR) ags/X/thread/$(DEPDIR) ags/audio/$(DEPDIR) ags/audio/client/$(DEPDIR) ags/audio/file/$(DEPDIR) ags/audio/jack/$(DEPDIR) ags/audio/midi/$(DEPDIR) ags/audio/recall/$(DEPDIR) ags/audio/task/$(DEPDIR) ags/audio/task/recall/$(DEPDIR) ags/audio/thread/$(DEPDIR) ags/file/$(DEPDIR) ags/lib/$(DEPDIR) ags/object/$(DEPDIR) ags/plugin/$(DEPDIR) ags/server/$(DEPDIR) ags/test/X/$(DEPDIR) ags/test/X/machine/$(DEPDIR) ags/test/audio/$(DEPDIR) ags/test/audio/midi/$(DEPDIR) ags/test/lib/$(DEPDIR) ags/test/thread/$(DEPDIR) ags/thread/$(DEPDIR) ags/thread/file/$(DEPDIR) ags/util/$(DEPDIR) ags/widget/$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-hdr distclean-libtool distclean-tags
@@ -9567,7 +10555,7 @@ installcheck-am:
 maintainer-clean: maintainer-clean-am
 	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
 	-rm -rf $(top_srcdir)/autom4te.cache
-	-rm -rf ags/$(DEPDIR) ags/X/$(DEPDIR) ags/X/editor/$(DEPDIR) ags/X/file/$(DEPDIR) ags/X/import/$(DEPDIR) ags/X/machine/$(DEPDIR) ags/X/task/$(DEPDIR) ags/X/thread/$(DEPDIR) ags/audio/$(DEPDIR) ags/audio/client/$(DEPDIR) ags/audio/file/$(DEPDIR) ags/audio/jack/$(DEPDIR) ags/audio/midi/$(DEPDIR) ags/audio/recall/$(DEPDIR) ags/audio/task/$(DEPDIR) ags/audio/task/recall/$(DEPDIR) ags/audio/thread/$(DEPDIR) ags/file/$(DEPDIR) ags/lib/$(DEPDIR) ags/object/$(DEPDIR) ags/plugin/$(DEPDIR) ags/server/$(DEPDIR) ags/test/audio/$(DEPDIR) ags/test/audio/midi/$(DEPDIR) ags/test/lib/$(DEPDIR) ags/test/thread/$(DEPDIR) ags/thread/$(DEPDIR) ags/thread/file/$(DEPDIR) ags/util/$(DEPDIR) ags/widget/$(DEPDIR)
+	-rm -rf ags/$(DEPDIR) ags/X/$(DEPDIR) ags/X/editor/$(DEPDIR) ags/X/file/$(DEPDIR) ags/X/import/$(DEPDIR) ags/X/machine/$(DEPDIR) ags/X/task/$(DEPDIR) ags/X/thread/$(DEPDIR) ags/audio/$(DEPDIR) ags/audio/client/$(DEPDIR) ags/audio/file/$(DEPDIR) ags/audio/jack/$(DEPDIR) ags/audio/midi/$(DEPDIR) ags/audio/recall/$(DEPDIR) ags/audio/task/$(DEPDIR) ags/audio/task/recall/$(DEPDIR) ags/audio/thread/$(DEPDIR) ags/file/$(DEPDIR) ags/lib/$(DEPDIR) ags/object/$(DEPDIR) ags/plugin/$(DEPDIR) ags/server/$(DEPDIR) ags/test/X/$(DEPDIR) ags/test/X/machine/$(DEPDIR) ags/test/audio/$(DEPDIR) ags/test/audio/midi/$(DEPDIR) ags/test/lib/$(DEPDIR) ags/test/thread/$(DEPDIR) ags/thread/$(DEPDIR) ags/thread/file/$(DEPDIR) ags/util/$(DEPDIR) ags/widget/$(DEPDIR)
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
@@ -9598,17 +10586,17 @@ uninstall-man: uninstall-man1
 	am--refresh check check-TESTS check-am clean clean-binPROGRAMS \
 	clean-checkPROGRAMS clean-cscope clean-generic \
 	clean-libLTLIBRARIES clean-libgsequencerLTLIBRARIES \
-	clean-libtool clean-local cscope cscopelist-am ctags ctags-am \
-	dist dist-all dist-bzip2 dist-gzip dist-lzip dist-shar \
-	dist-tarZ dist-xz dist-zip distcheck distclean \
-	distclean-compile distclean-generic distclean-hdr \
-	distclean-libtool distclean-tags distcleancheck distdir \
-	distuninstallcheck dvi dvi-am html html-am info info-am \
-	install install-am install-appdataDATA install-binPROGRAMS \
-	install-data install-data-am install-data-local \
-	install-docDATA install-dvi install-dvi-am install-exec \
-	install-exec-am install-html install-html-am install-info \
-	install-info-am install-libLTLIBRARIES \
+	clean-libtool clean-local clean-noinstLTLIBRARIES cscope \
+	cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
+	dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \
+	distcheck distclean distclean-compile distclean-generic \
+	distclean-hdr distclean-libtool distclean-tags distcleancheck \
+	distdir distuninstallcheck dvi dvi-am html html-am info \
+	info-am install install-am install-appdataDATA \
+	install-binPROGRAMS install-data install-data-am \
+	install-data-local install-docDATA install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-libLTLIBRARIES \
 	install-libgsequencerLTLIBRARIES install-man install-man1 \
 	install-nobase_includeHEADERS install-pdf install-pdf-am \
 	install-pkgconfigDATA install-ps install-ps-am install-strip \
@@ -9628,9 +10616,11 @@ uninstall-man: uninstall-man1
 ags-docs-local:
 	$(MAKE) -C $(top_srcdir)/docs/reference/libags
 	cd $(top_srcdir)
-	$(MAKE) -C $(top_srcdir)/docs/reference/libags_audio
+	$(MAKE) -C $(top_srcdir)/docs/reference/libags-audio
+	cd $(top_srcdir)
+	$(MAKE) -C $(top_srcdir)/docs/reference/libags-gui
 	cd $(top_srcdir)
-	$(MAKE) -C $(top_srcdir)/docs/reference/libags_gui
+	$(MAKE) -C $(top_srcdir)/docs/reference/libgsequencer
 	cd $(top_srcdir)
 
 libtool: $(LIBTOOL_DEPS)
@@ -9655,14 +10645,17 @@ install-data-local:
 	mkdir -p $(DESTDIR)/$(datadir)/doc-base
 	mkdir -p $(DESTDIR)/$(datadir)/gsequencer/icons
 	mkdir -p $(DESTDIR)/$(datadir)/gsequencer/images
+	mkdir -p $(DESTDIR)/$(datadir)/gsequencer/styles
 	mkdir -p $(DESTDIR)/$(datadir)/xml/gsequencer/{schema/dtd/$(PACKAGE_VERSION)/,stylesheet/ags-xsl/midi-xml/}
 	install -c -p -m 644 $(top_srcdir)/gsequencer.share/icons/ags.xpm $(DESTDIR)/$(datadir)/gsequencer/icons/ags.xpm
 	install -c -p -m 644 $(top_srcdir)/gsequencer.share/images/ags.png $(DESTDIR)/$(datadir)/gsequencer/images/ags.png
 	install -c -p -m 644 $(top_srcdir)/gsequencer.share/images/ags_supermoon-800x450.png $(DESTDIR)/$(datadir)/gsequencer/images/ags_supermoon-800x450.png
+	install -c -p -m 644 $(top_srcdir)/gsequencer.share/styles/ags.rc $(DESTDIR)/$(datadir)/gsequencer/styles/ags.rc
 	install -c -p -m 644 $(top_srcdir)/ags/X/file/ags_simple_file.dtd $(DESTDIR)/$(datadir)/xml/gsequencer/schema/dtd/$(PACKAGE_VERSION)/
 	install -c -p -m 644 $(top_srcdir)/ags/audio/midi/ags_midi_file.dtd $(DESTDIR)/$(datadir)/xml/gsequencer/schema/dtd/$(PACKAGE_VERSION)/
 	install -c -p -m 644 $(top_srcdir)/ags/file/ags_file.dtd $(DESTDIR)/$(datadir)/xml/gsequencer/schema/dtd/$(PACKAGE_VERSION)/
 	install -c -p -m 644 $(top_srcdir)/ags.xsl $(DESTDIR)/$(datadir)/xml/gsequencer/stylesheet/ags-xsl/midi-xml/
+	install -c -p -m 644 $(top_srcdir)/ags-simple.xsl $(DESTDIR)/$(datadir)/xml/gsequencer/stylesheet/ags-xsl/midi-xml/
 	install -c -p -m 644 $(top_srcdir)/gsequencer-documentation $(DESTDIR)/$(datadir)/doc-base/
 	mkdir -p $(DESTDIR)/$(datadir)/doc/gsequencer/
 	gzip -9 -c $(top_srcdir)/ChangeLog > $(DESTDIR)/$(datadir)/doc/gsequencer/changelog.gz
@@ -9680,12 +10673,15 @@ install-ags-docs: ags-docs
 	mkdir -p $(DESTDIR)/$(datadir)/doc/libags-doc/api
 	mkdir -p $(DESTDIR)/$(datadir)/doc/libags-audio-doc/api
 	mkdir -p $(DESTDIR)/$(datadir)/doc/libags-gui-doc/api
+	mkdir -p $(DESTDIR)/$(datadir)/doc/libgsequencer-doc/api
 	install -c -p -m 644 $(top_srcdir)/docs/reference/libags/html/* $(DESTDIR)/$(datadir)/doc/libags-doc/api
-	install -c -p -m 644 $(top_srcdir)/docs/reference/libags_audio/html/* $(DESTDIR)/$(datadir)/doc/libags-audio-doc/api
-	install -c -p -m 644 $(top_srcdir)/docs/reference/libags_gui/html/* $(DESTDIR)/$(datadir)/doc/libags-gui-doc/api
+	install -c -p -m 644 $(top_srcdir)/docs/reference/libags-audio/html/* $(DESTDIR)/$(datadir)/doc/libags-audio-doc/api
+	install -c -p -m 644 $(top_srcdir)/docs/reference/libags-gui/html/* $(DESTDIR)/$(datadir)/doc/libags-gui-doc/api
+	install -c -p -m 644 $(top_srcdir)/docs/reference/libgsequencer/html/* $(DESTDIR)/$(datadir)/doc/libgsequencer-doc/api
 	ln -s ../../doc/libags-doc/api $(DESTDIR)/$(datadir)/gtk-doc/html/libags
-	ln -s ../../doc/libags-audio-doc/api $(DESTDIR)/$(datadir)/gtk-doc/html/libags_audio
-	ln -s ../../doc/libags-gui-doc/api $(DESTDIR)/$(datadir)/gtk-doc/html/libags_gui
+	ln -s ../../doc/libags-audio-doc/api $(DESTDIR)/$(datadir)/gtk-doc/html/libags-audio
+	ln -s ../../doc/libags-gui-doc/api $(DESTDIR)/$(datadir)/gtk-doc/html/libags-gui
+	ln -s ../../doc/libgsequencer-doc/api $(DESTDIR)/$(datadir)/gtk-doc/html/libgsequencer
 
 uninstall-hook:
 	rm -rf $(DESTDIR)/$(datadir)/gsequencer
@@ -9701,24 +10697,26 @@ uninstall-hook:
 	rm -f $(DESTDIR)/$(pkgconfigdir)/libags.pc
 	rm -f $(DESTDIR)/$(pkgconfigdir)/libags_audio.pc
 	rm -f $(DESTDIR)/$(pkgconfigdir)/libags_gui.pc
+	rm -f $(DESTDIR)/$(pkgconfigdir)/libgsequencer.pc
 
 clean-local:
 	rm -rf $(top_srcdir)/html
 	rm -rf $(top_srcdir)/docs/reference/libags/xml
 	rm -rf $(top_srcdir)/docs/reference/libags/html
 	rm -rf $(top_srcdir)/docs/reference/libags/tmpl
-	rm -rf $(top_srcdir)/docs/reference/libags_audio/xml
-	rm -rf $(top_srcdir)/docs/reference/libags_audio/html
-	rm -rf $(top_srcdir)/docs/reference/libags_audio/tmpl
-	rm -rf $(top_srcdir)/docs/reference/libags_gui/xml
-	rm -rf $(top_srcdir)/docs/reference/libags_gui/html
-	rm -rf $(top_srcdir)/docs/reference/libags_gui/tmpl
+	rm -rf $(top_srcdir)/docs/reference/libags-audio/xml
+	rm -rf $(top_srcdir)/docs/reference/libags-audio/html
+	rm -rf $(top_srcdir)/docs/reference/libags-audio/tmpl
+	rm -rf $(top_srcdir)/docs/reference/libags-gui/xml
+	rm -rf $(top_srcdir)/docs/reference/libags-gui/html
+	rm -rf $(top_srcdir)/docs/reference/libags-gui/tmpl
 	rm -rf $(top_srcdir)/docs/reference/libgsequencer/xml
 	rm -rf $(top_srcdir)/docs/reference/libgsequencer/html
 	rm -rf $(top_srcdir)/docs/reference/libgsequencer/tmpl
 	rm -f $(top_builddir)/docs/reference/libags/Makefile
-	rm -f $(top_builddir)/docs/reference/libags_audio/Makefile
-	rm -f $(top_builddir)/docs/reference/libags_gui/Makefile
+	rm -f $(top_builddir)/docs/reference/libags-audio/Makefile
+	rm -f $(top_builddir)/docs/reference/libags-gui/Makefile
+	rm -f $(top_builddir)/docs/reference/libgsequencer/Makefile
 
 gen-symbols-ags:
 	rm -f libags.sym
diff --git a/ags.xsl b/ags-simple.xsl
similarity index 62%
copy from ags.xsl
copy to ags-simple.xsl
index 6b627a1..9b649e2 100644
--- a/ags.xsl
+++ b/ags-simple.xsl
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <!DOCTYPE xsl[
-<!ENTITY version "0.4.2">
+<!ENTITY version "0.7.129">
 <!ENTITY buildid "XSLT">
 <!ENTITY audiochannels "1">
 <!ENTITY defaultsf2 ""> <!-- /usr/share/sounds/sf2/FluidR3_GM.sf2 -->
@@ -82,7 +82,7 @@
       <xsl:variable name="current-tick"><xsl:value-of select="./@delta-time"/></xsl:variable>
 
       <xsl:if test="$parent-sequence=$sequence and $parent-instrument=$instrument">
-	<ags-note>
+	<ags-sf-note>
 	  
 	  <xsl:attribute name="id">note-<xsl:value-of select="position()"/></xsl:attribute>
 	  <xsl:attribute name="flags">0</xsl:attribute>
@@ -111,12 +111,12 @@
 	    </xsl:attribute>
 	  </xsl:if>
 	  
-	  <xsl:if test="not(following-sibling::ags-note[@event='note-off' and @note='$y'])">
+	  <xsl:if test="not(following-sibling::ags-sf-note[@event='note-off' and @note='$y'])">
 	    <xsl:variable name="add-one" select="1"/>
 	    <xsl:attribute name="x1"><xsl:value-of select="round($x0) + $add-one"/></xsl:attribute>
 	  </xsl:if>
 	  
-	</ags-note>
+	</ags-sf-note>
       </xsl:if>
       
     </xsl:if>
@@ -130,22 +130,19 @@
     <xsl:param name="num" select="1"/>
     <xsl:param name="count"/>
 
-    <ags-notation>
+    <ags-sf-notation>
       <xsl:attribute name="id">notation-<xsl:value-of select="position()"/></xsl:attribute>
       <xsl:attribute name="flags">0</xsl:attribute>
       <xsl:attribute name="audio-channel"><xsl:value-of select="$num - 1"/></xsl:attribute>
       <xsl:attribute name="base-note">C</xsl:attribute>
-      
-      <ags-note-list>
-	<xsl:attribute name="id">note-list-<xsl:value-of select="position()"/></xsl:attribute>
 
-	<xsl:apply-templates select="/midi/midi-tracks/midi-track/midi-message">
-	  <xsl:with-param name="parent-sequence" select="$sequence"/>
-	  <xsl:with-param name="parent-instrument" select="$instrument"/>
-	</xsl:apply-templates>
+      <!-- add note -->
+      <xsl:apply-templates select="/midi/midi-tracks/midi-track/midi-message">
+	<xsl:with-param name="parent-sequence" select="$sequence"/>
+	<xsl:with-param name="parent-instrument" select="$instrument"/>
+      </xsl:apply-templates>
 
-      </ags-note-list>
-    </ags-notation>
+    </ags-sf-notation>
     
     <xsl:if test="$num < $count">
       <xsl:call-template name="add-notation">
@@ -156,63 +153,34 @@
     
   </xsl:template>
   
-  <!-- audio node -->
-  <xsl:template name="add-audio">
+  <!-- machine node -->
+  <xsl:template name="add-machine">
     <xsl:param name="sequence"/>
     <xsl:param name="instrument"/>
-    
-    <ags-audio>
-      <xsl:attribute name="id"><xsl:value-of select="$sequence"/>_<xsl:value-of select="$instrument"/></xsl:attribute>
-      <xsl:attribute name="flags">13f</xsl:attribute>
-      <xsl:attribute name="sequence-length">0</xsl:attribute>
-      <xsl:attribute name="audio-channels">&audiochannels;</xsl:attribute>
+
+    <ags-sf-machine>
+      <xsl:attribute name="id">machine-<xsl:value-of select="position()"/></xsl:attribute>
+      <xsl:attribute name="type">AgsFFPlayer</xsl:attribute>
+      <xsl:attribute name="name"><xsl:value-of select="$sequence"/> - <xsl:value-of select="$instrument"/></xsl:attribute>
+      <xsl:attribute name="channels">&audiochannels;</xsl:attribute>
       <xsl:attribute name="output-pads">1</xsl:attribute>
       <xsl:attribute name="input-pads">128</xsl:attribute>
-      <xsl:attribute name="devout">xpath=//ags-devout</xsl:attribute>
-      
-      <ags-notation-list>
-	<xsl:attribute name="id">notation-list-<xsl:value-of select="position()"/></xsl:attribute>
 
+      <!-- add notation -->
+      <ags-sf-notation-list>
 	<xsl:call-template name="add-notation">
 	  <xsl:with-param name="count" select="&audiochannels;"/>
 	  <xsl:with-param name="sequence" select="$sequence"/>
 	  <xsl:with-param name="instrument" select="$instrument"/>
 	</xsl:call-template>
 	
-      </ags-notation-list>
-    </ags-audio>
-    
-  </xsl:template>
-  
-  <!-- machine node -->
-  <xsl:template name="add-machine">
-    <xsl:param name="sequence"/>
-    <xsl:param name="instrument"/>
-
-    <ags-machine>
-      <xsl:attribute name="type">AgsFFPlayer</xsl:attribute>
-      <xsl:attribute name="id">machine-<xsl:value-of select="position()"/></xsl:attribute>
-      <xsl:attribute name="flags">628</xsl:attribute>
-      <xsl:attribute name="version">&version;</xsl:attribute>
-      <xsl:attribute name="build-id">&buildid;</xsl:attribute>
-      <xsl:attribute name="file-input-flags">0</xsl:attribute>
-      <xsl:attribute name="name"><xsl:value-of select="$sequence"/> - <xsl:value-of select="$instrument"/></xsl:attribute>
-      <xsl:attribute name="audio">xpath=//ags-audio[@id='<xsl:value-of select="$sequence"/>_<xsl:value-of select="$instrument"/>']</xsl:attribute>
-
-      <ags-ffplayer>
-	<xsl:attribute name="id">ffplayer-<xsl:value-of select="position()"/></xsl:attribute>
-	<xsl:attribute name="filename">&defaultsf2;</xsl:attribute>
-	<xsl:attribute name="preset">&preset;</xsl:attribute>
-	<xsl:attribute name="instrument">&instrument;</xsl:attribute>
-      </ags-ffplayer>
-    </ags-machine>
+      </ags-sf-notation-list>
+    </ags-sf-machine>
 
   </xsl:template>
 
   <!-- midi track -->
   <xsl:template match="/midi/midi-tracks/midi-track">
-    <xsl:param name="parent"/>
-
     <xsl:if test="not(midi-message[@event='time-signature'])">
       <xsl:variable name="sequence" select="midi-message[boolean(@sequence-name)]/@sequence-name"/>
       <xsl:variable name="instrument" select="midi-message[boolean(@instrument-name)]/@instrument-name"/>
@@ -220,21 +188,14 @@
       <xsl:variable name="previous" select="preceding-sibling::node()"/>
 
       <xsl:if test="not($previous/midi-message/@sequence-name=$sequence and $previous/midi-message/@instrument-name=$instrument)">
-	<xsl:if test="$parent='ags-audio-list'">
-	  <xsl:call-template name="add-audio">
-	    <xsl:with-param name="sequence" select="$sequence"/>
-	    <xsl:with-param name="instrument" select="$instrument"/>
-	  </xsl:call-template>
-	</xsl:if>
-	
-	<xsl:if test="$parent='ags-machine-list'">
-	  <xsl:call-template name="add-machine">
-	    <xsl:with-param name="sequence" select="$sequence"/>
-	    <xsl:with-param name="instrument" select="$instrument"/>
-	  </xsl:call-template>
-	</xsl:if>	
-      </xsl:if>
-    </xsl:if>    
+
+	<!-- add machine -->
+	<xsl:call-template name="add-machine">
+	  <xsl:with-param name="sequence" select="$sequence"/>
+	  <xsl:with-param name="instrument" select="$instrument"/>
+	</xsl:call-template>
+      </xsl:if>	
+    </xsl:if>
   </xsl:template>
 
   <xsl:template match="midi-header">    
@@ -245,48 +206,18 @@
 
   <!-- root node -->
   <xsl:template match="/">    
-    <ags>
-      <ags-main version="&version;" build-id="&buildid;" flags="0">
-	<xsl:attribute name="id">ags-main-<xsl:value-of select="position()"/></xsl:attribute>
-
-	<ags-devout-list>
-	  <xsl:attribute name="id">devout-list-<xsl:value-of select="position()"/></xsl:attribute>
-	  
-	  <ags-devout>
-	    <xsl:attribute name="id">ags-devout-<xsl:value-of select="position()"/></xsl:attribute>
-	    <xsl:attribute name="flags">100</xsl:attribute>
-	    <xsl:attribute name="bpm">
-	      <xsl:call-template name="midi-read-bpm"/>
-	    </xsl:attribute>
-	    
-	    <ags-audio-list>
-	      <xsl:attribute name="id">ags-audio-list-<xsl:value-of select="position()"/></xsl:attribute>
-
-	      <xsl:apply-templates select="/midi/midi-tracks/midi-track">
-		<xsl:with-param name="parent">ags-audio-list</xsl:with-param>
-	      </xsl:apply-templates>
-	      
-	    </ags-audio-list>
-	  </ags-devout>
-	</ags-devout-list>
-	<ags-window>
-	  <xsl:attribute name="id">window-<xsl:value-of select="position()"/></xsl:attribute>
-	  <xsl:attribute name="flags">0</xsl:attribute>
-	  <xsl:attribute name="devout">xpath=//ags-devout</xsl:attribute>
-
-	  <ags-machine-list>
-	    <xsl:attribute name="id">machine-list-<xsl:value-of select="position()"/></xsl:attribute>
-
-	    <xsl:apply-templates select="/midi/midi-tracks/midi-track">
-	      <xsl:with-param name="parent">ags-machine-list</xsl:with-param>
-	    </xsl:apply-templates>
-    	    
-	  </ags-machine-list>
-
-	  <ags-navigation/>
-	</ags-window>
-      </ags-main>
-    </ags>
+    <ags-simple-file>
+      <ags-sf-window>
+	<ags-sf-machine-list>
+
+	  <!-- add machine -->
+	  <xsl:apply-templates select="/midi/midi-tracks/midi-track"/>
+    	  
+	</ags-sf-machine-list>
+
+	<ags-sf-navigation/>
+      </ags-sf-window>
+    </ags-simple-file>
 
   </xsl:template>
 
diff --git a/ags/X/ags_audio_connection_collection_editor.c b/ags/X/ags_audio_connection_collection_editor.c
deleted file mode 100644
index d4a5f76..0000000
--- a/ags/X/ags_audio_connection_collection_editor.c
+++ /dev/null
@@ -1,530 +0,0 @@
-/* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
- *
- * This file is part of GSequencer.
- *
- * GSequencer is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <ags/X/ags_audio_connection_collection_editor.h>
-#include <ags/X/ags_audio_connection_collection_editor_callbacks.h>
-
-#include <ags/object/ags_application_context.h>
-#include <ags/object/ags_connectable.h>
-#include <ags/object/ags_soundcard.h>
-#include <ags/object/ags_applicable.h>
-
-#include <ags/thread/ags_mutex_manager.h>
-#include <ags/thread/ags_task_thread.h>
-
-#include <ags/audio/ags_audio.h>
-#include <ags/audio/ags_input.h>
-
-#include <ags/audio/task/ags_reset_audio_connection.h>
-
-#include <ags/audio/thread/ags_audio_loop.h>
-
-#include <ags/X/ags_window.h>
-#include <ags/X/ags_machine.h>
-#include <ags/X/ags_connection_editor.h>
-
-void ags_audio_connection_collection_editor_class_init(AgsAudioConnectionCollectionEditorClass *audio_connection_collection_editor);
-void ags_audio_connection_collection_editor_connectable_interface_init(AgsConnectableInterface *connectable);
-void ags_audio_connection_collection_editor_applicable_interface_init(AgsApplicableInterface *applicable);
-void ags_audio_connection_collection_editor_init(AgsAudioConnectionCollectionEditor *audio_connection_collection_editor);
-void ags_audio_connection_collection_editor_set_property(GObject *gobject,
-							 guint prop_id,
-							 const GValue *value,
-							 GParamSpec *param_spec);
-void ags_audio_connection_collection_editor_get_property(GObject *gobject,
-							 guint prop_id,
-							 GValue *value,
-							 GParamSpec *param_spec);
-void ags_audio_connection_collection_editor_connect(AgsConnectable *connectable);
-void ags_audio_connection_collection_editor_disconnect(AgsConnectable *connectable);
-void ags_audio_connection_collection_editor_set_update(AgsApplicable *applicable, gboolean update);
-void ags_audio_connection_collection_editor_apply(AgsApplicable *applicable);
-void ags_audio_connection_collection_editor_reset(AgsApplicable *applicable);
-
-/**
- * SECTION:ags_audio_connection_collection_editor
- * @short_description: edit audio connections in bulk mode.
- * @title: AgsAudioConnectionCollectionEditor
- * @section_id:
- * @include: ags/X/ags_audio_connection_collection_editor.h
- *
- * #AgsAudioConnectionCollectionEditor is a composite widget to modify audio connections. A audio_connection collection
- * editor should be packed by a #AgsConnectionEditor.
- */
-
-static gpointer ags_audio_connection_collection_editor_parent_class = NULL;
-
-enum{
-  PROP_0,
-  PROP_CHANNEL_TYPE,
-};
-
-GType
-ags_audio_connection_collection_editor_get_type(void)
-{
-  static GType ags_type_audio_connection_collection_editor = 0;
-
-  if(!ags_type_audio_connection_collection_editor){
-    static const GTypeInfo ags_audio_connection_collection_editor_info = {
-      sizeof (AgsAudioConnectionCollectionEditorClass),
-      NULL, /* base_init */
-      NULL, /* base_finalize */
-      (GClassInitFunc) ags_audio_connection_collection_editor_class_init,
-      NULL, /* class_finalize */
-      NULL, /* class_data */
-      sizeof (AgsAudioConnectionCollectionEditor),
-      0,    /* n_preallocs */
-      (GInstanceInitFunc) ags_audio_connection_collection_editor_init,
-    };
-
-    static const GInterfaceInfo ags_connectable_interface_info = {
-      (GInterfaceInitFunc) ags_audio_connection_collection_editor_connectable_interface_init,
-      NULL, /* interface_finalize */
-      NULL, /* interface_data */
-    };
-
-    static const GInterfaceInfo ags_applicable_interface_info = {
-      (GInterfaceInitFunc) ags_audio_connection_collection_editor_applicable_interface_init,
-      NULL, /* interface_finalize */
-      NULL, /* interface_data */
-    };
-
-    ags_type_audio_connection_collection_editor = g_type_register_static(GTK_TYPE_TABLE,
-									 "AgsAudioConnectionCollectionEditor\0",
-									 &ags_audio_connection_collection_editor_info,
-									 0);
-    
-    g_type_add_interface_static(ags_type_audio_connection_collection_editor,
-				AGS_TYPE_CONNECTABLE,
-				&ags_connectable_interface_info);
-
-    g_type_add_interface_static(ags_type_audio_connection_collection_editor,
-				AGS_TYPE_APPLICABLE,
-				&ags_applicable_interface_info);
-  }
-
-  return(ags_type_audio_connection_collection_editor);
-}
-
-void
-ags_audio_connection_collection_editor_class_init(AgsAudioConnectionCollectionEditorClass *audio_connection_collection_editor)
-{
-  GObjectClass *gobject;
-  GParamSpec *param_spec;
-
-  ags_audio_connection_collection_editor_parent_class = g_type_class_peek_parent(audio_connection_collection_editor);
-
-  /* GObjectClass */
-  gobject = (GObjectClass *) audio_connection_collection_editor;
-
-  gobject->set_property = ags_audio_connection_collection_editor_set_property;
-  gobject->get_property = ags_audio_connection_collection_editor_get_property;
-  
-  /* properties */
-  /**
-   * AgsAudioConnectionCollectionEditor:channel-type:
-   *
-   * The channel type to apply to. Either %AGS_TYPE_INPUT or %AGS_TYPE_OUTPUT.
-   * 
-   * Since: 0.7.65
-   */
-  param_spec = g_param_spec_gtype("channel-type\0",
-				  "assigned channel type\0",
-				  "The channel type which this channel audio_connection collection editor is assigned with\0",
-				  G_TYPE_NONE,
-				  G_PARAM_READABLE | G_PARAM_WRITABLE);
-  g_object_class_install_property(gobject,
-				  PROP_CHANNEL_TYPE,
-				  param_spec);
-}
-
-void
-ags_audio_connection_collection_editor_connectable_interface_init(AgsConnectableInterface *connectable)
-{
-  connectable->connect = ags_audio_connection_collection_editor_connect;
-  connectable->disconnect = ags_audio_connection_collection_editor_disconnect;
-}
-
-void
-ags_audio_connection_collection_editor_applicable_interface_init(AgsApplicableInterface *applicable)
-{
-  applicable->set_update = ags_audio_connection_collection_editor_set_update;
-  applicable->apply = ags_audio_connection_collection_editor_apply;
-  applicable->reset = ags_audio_connection_collection_editor_reset;
-}
-
-void
-ags_audio_connection_collection_editor_init(AgsAudioConnectionCollectionEditor *audio_connection_collection_editor)
-{
-  GtkAlignment *alignment;
-  GtkLabel *label;
-  
-  g_signal_connect_after(GTK_WIDGET(audio_connection_collection_editor), "parent-set\0",
-			 G_CALLBACK(ags_audio_connection_collection_editor_parent_set_callback), audio_connection_collection_editor);
-
-  audio_connection_collection_editor->channel_type = G_TYPE_NONE;
-  
-  gtk_table_resize(GTK_TABLE(audio_connection_collection_editor),
-		   4, 2);
-  gtk_table_set_row_spacings(GTK_TABLE(audio_connection_collection_editor),
-			     4);
-  gtk_table_set_col_spacings(GTK_TABLE(audio_connection_collection_editor),
-			     2);
-
-  /* pad */
-  alignment = (GtkAlignment *) gtk_alignment_new(0.0, 0.5,
-						 0.0, 0.0);
-  gtk_table_attach(GTK_TABLE(audio_connection_collection_editor),
-		   GTK_WIDGET(alignment),
-		   0, 1,
-		   0, 1,
-		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
-		   0, 0);
-
-  label = (GtkLabel *) gtk_label_new("pad\0");
-  gtk_container_add(GTK_CONTAINER(alignment),
-		    GTK_WIDGET(label));
-
-  audio_connection_collection_editor->pad = (GtkSpinButton *) gtk_spin_button_new_with_range(-1.0,
-											     -1.0,
-											     1.0);
-  gtk_table_attach(GTK_TABLE(audio_connection_collection_editor),
-		   GTK_WIDGET(audio_connection_collection_editor->pad),
-		   1, 2,
-		   0, 1,
-		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
-		   0, 0);
-
-  /* audio channel */
-  alignment = (GtkAlignment *) gtk_alignment_new(0.0, 0.5,
-						 0.0, 0.0);
-  gtk_table_attach(GTK_TABLE(audio_connection_collection_editor),
-		   GTK_WIDGET(alignment),
-		   0, 1,
-		   1, 2,
-		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
-		   0, 0);
-
-  label = (GtkLabel *) gtk_label_new("audio channel\0");
-  gtk_container_add(GTK_CONTAINER(alignment),
-		    GTK_WIDGET(label));
-
-  audio_connection_collection_editor->audio_channel = (GtkSpinButton *) gtk_spin_button_new_with_range(-1.0,
-												       -1.0,
-												       1.0);
-  gtk_table_attach(GTK_TABLE(audio_connection_collection_editor),
-		   GTK_WIDGET(audio_connection_collection_editor->audio_channel),
-		   1, 2,
-		   1, 2,
-		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
-		   0, 0);
-
-  /* soundcard */
-  alignment = (GtkAlignment *) gtk_alignment_new(0.0, 0.5,
-						 0.0, 0.0);
-  gtk_table_attach(GTK_TABLE(audio_connection_collection_editor),
-		   GTK_WIDGET(alignment),
-		   0, 1,
-		   2, 3,
-		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
-		   0, 0);
-
-  label = (GtkLabel *) gtk_label_new("soundcard\0");
-  gtk_container_add(GTK_CONTAINER(alignment),
-		    GTK_WIDGET(label));
-
-  audio_connection_collection_editor->soundcard = (GtkComboBoxText *) gtk_combo_box_text_new();
-  gtk_table_attach(GTK_TABLE(audio_connection_collection_editor),
-		   GTK_WIDGET(audio_connection_collection_editor->soundcard),
-		   1, 2,
-		   2, 3,
-		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
-		   0, 0);
-
-  /* soundcard audio channel */
-  alignment = (GtkAlignment *) gtk_alignment_new(0.0, 0.5,
-						 0.0, 0.0);
-  gtk_table_attach(GTK_TABLE(audio_connection_collection_editor),
-		   GTK_WIDGET(alignment),
-		   0, 1,
-		   3, 4,
-		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
-		   0, 0);
-
-  label = (GtkLabel *) gtk_label_new("soundcard audio channel\0");
-  gtk_container_add(GTK_CONTAINER(alignment),
-		    GTK_WIDGET(label));
-
-  audio_connection_collection_editor->soundcard_audio_channel = (GtkSpinButton *) gtk_spin_button_new_with_range(-1.0,
-														 -1.0,
-														 1.0);
-  gtk_table_attach(GTK_TABLE(audio_connection_collection_editor),
-		   GTK_WIDGET(audio_connection_collection_editor->soundcard_audio_channel),
-		   1, 2,
-		   3, 4,
-		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
-		   0, 0);
-}
-
-
-void
-ags_audio_connection_collection_editor_set_property(GObject *gobject,
-						    guint prop_id,
-						    const GValue *value,
-						    GParamSpec *param_spec)
-{
-  AgsAudioConnectionCollectionEditor *audio_connection_collection_editor;
-
-  audio_connection_collection_editor = AGS_AUDIO_CONNECTION_COLLECTION_EDITOR(gobject);
-
-  switch(prop_id){
-  case PROP_CHANNEL_TYPE:
-    audio_connection_collection_editor->channel_type = g_value_get_gtype(value);
-    break;
-  default:
-    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
-    break;
-  }
-}
-
-void
-ags_audio_connection_collection_editor_get_property(GObject *gobject,
-						    guint prop_id,
-						    GValue *value,
-						    GParamSpec *param_spec)
-{
-  AgsAudioConnectionCollectionEditor *audio_connection_collection_editor;
-
-  audio_connection_collection_editor = AGS_AUDIO_CONNECTION_COLLECTION_EDITOR(gobject);
-
-  switch(prop_id){
-  case PROP_CHANNEL_TYPE:
-    g_value_set_gtype(value, audio_connection_collection_editor->channel_type);
-    break;
-  default:
-    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
-    break;
-  }
-}
-
-void
-ags_audio_connection_collection_editor_connect(AgsConnectable *connectable)
-{
-  AgsAudioConnectionCollectionEditor *audio_connection_collection_editor;
-
-  /* AgsAudioConnectionCollectionEditor */
-  audio_connection_collection_editor = AGS_AUDIO_CONNECTION_COLLECTION_EDITOR(connectable);
-
-  g_signal_connect_after(G_OBJECT(audio_connection_collection_editor->soundcard), "changed\0",
-			 G_CALLBACK(ags_audio_connection_collection_editor_soundcard_callback), audio_connection_collection_editor);
-}
-
-void
-ags_audio_connection_collection_editor_disconnect(AgsConnectable *connectable)
-{
-  AgsAudioConnectionCollectionEditor *audio_connection_collection_editor;
-
-  /* AgsAudioConnectionCollectionEditor */
-  audio_connection_collection_editor = AGS_AUDIO_CONNECTION_COLLECTION_EDITOR(connectable);
-
-  g_object_disconnect(G_OBJECT(audio_connection_collection_editor->soundcard),
-		      "changed\0",
-		      G_CALLBACK(ags_audio_connection_collection_editor_soundcard_callback),
-		      audio_connection_collection_editor,
-		      NULL);
-}
-
-void
-ags_audio_connection_collection_editor_set_update(AgsApplicable *applicable, gboolean update)
-{
-  /* empty */
-}
-
-void
-ags_audio_connection_collection_editor_apply(AgsApplicable *applicable)
-{
-  AgsAudioConnectionCollectionEditor *audio_connection_collection_editor;
-  GtkTreeIter iter;
-
-  audio_connection_collection_editor = AGS_AUDIO_CONNECTION_COLLECTION_EDITOR(applicable);
-
-  if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(audio_connection_collection_editor->soundcard),
-				   &iter)){
-    AgsWindow *window;
-    AgsMachine *machine;
-    AgsConnectionEditor *connection_editor;
-
-    AgsAudio *audio;
-
-    AgsResetAudioConnection *reset_audio_connection;
-    
-    AgsMutexManager *mutex_manager;
-    AgsAudioLoop *audio_loop;
-    AgsTaskThread *task_thread;
-
-    AgsApplicationContext *application_context;
-    GObject *soundcard;
-
-    GtkTreeModel *model;
-
-    guint pad, audio_channel;
-    guint soundcard_audio_channel;
-
-    pthread_mutex_t *application_mutex;
-
-    connection_editor = AGS_CONNECTION_EDITOR(gtk_widget_get_ancestor(GTK_WIDGET(audio_connection_collection_editor),
-								      AGS_TYPE_CONNECTION_EDITOR));
-    machine = connection_editor->machine;
-    audio = machine->audio;
-
-    /* get window and application_context  */
-    window = (AgsWindow *) gtk_widget_get_toplevel(GTK_WIDGET(machine));
-  
-    application_context = (AgsApplicationContext *) window->application_context;
-    
-    mutex_manager = ags_mutex_manager_get_instance();
-    application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
-    
-    /* get audio loop */
-    pthread_mutex_lock(application_mutex);
-
-    audio_loop = (AgsAudioLoop *) application_context->main_loop;
-
-    pthread_mutex_unlock(application_mutex);
-
-    /* get task and soundcard thread */
-    task_thread = (AgsTaskThread *) ags_thread_find_type((AgsThread *) audio_loop,
-							 AGS_TYPE_TASK_THREAD);
-
-    /* get mapping and soundcard */
-    pad = (guint) gtk_spin_button_get_value_as_int(audio_connection_collection_editor->pad);
-    audio_channel = (guint) gtk_spin_button_get_value_as_int(audio_connection_collection_editor->audio_channel);
-
-    soundcard_audio_channel = (guint) gtk_spin_button_get_value_as_int(audio_connection_collection_editor->soundcard_audio_channel);
-
-    model = gtk_combo_box_get_model(GTK_COMBO_BOX(audio_connection_collection_editor->soundcard));
-    gtk_tree_model_get(model,
-		       &iter,
-		       1, &soundcard,
-		       -1);
-
-    /* create task */
-    reset_audio_connection = ags_reset_audio_connection_new(soundcard,
-							    audio,
-							    audio_connection_collection_editor->channel_type,
-							    pad,
-							    audio_channel,
-							    soundcard_audio_channel);
-    ags_task_thread_append_task(task_thread,
-				(AgsTask *) reset_audio_connection);
-  }
-}
-
-void
-ags_audio_connection_collection_editor_reset(AgsApplicable *applicable)
-{
-  /* empty */
-}
-
-/**
- * ags_audio_connection_collection_editor_check:
- * @audio_connection_collection_editor: the #AgsAudio_ConnectionCollectionEditor
- *
- * Checks for possible channels to audio_connection. And modifies its ranges.
- * 
- * Since: 0.7.65
- */
-void
-ags_audio_connection_collection_editor_check(AgsAudioConnectionCollectionEditor *audio_connection_collection_editor)
-{
-  AgsConnectionEditor *connection_editor;
-
-  AgsAudio *audio;
-  
-  GtkTreeIter iter;
-
-  connection_editor = AGS_CONNECTION_EDITOR(gtk_widget_get_ancestor(GTK_WIDGET(audio_connection_collection_editor),
-								    AGS_TYPE_CONNECTION_EDITOR));
-  audio = connection_editor->machine->audio;
-
-  if(audio_connection_collection_editor->channel_type == AGS_TYPE_INPUT){
-    gtk_spin_button_set_range(audio_connection_collection_editor->pad,
-			      0.0,
-			      audio->input_pads - 1.0);
-  }else{
-    gtk_spin_button_set_range(audio_connection_collection_editor->pad,
-			      0.0,
-			      audio->output_pads - 1.0);
-  }
-
-  gtk_spin_button_set_range(audio_connection_collection_editor->audio_channel,
-			    0.0,
-			    audio->audio_channels - 1.0);
-
-  if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(audio_connection_collection_editor->soundcard),
-				   &iter)){    
-    GObject *soundcard;
-    
-    GtkTreeModel *model;
-
-    guint soundcard_audio_channels;
-    
-    /* soundcard connection */
-    model = gtk_combo_box_get_model(GTK_COMBO_BOX(audio_connection_collection_editor->soundcard));
-    gtk_tree_model_get(model,
-		       &iter,
-		       1, &soundcard,
-		       -1);
-
-    ags_soundcard_get_presets(AGS_SOUNDCARD(soundcard),
-			      &soundcard_audio_channels,
-			      NULL,
-			      NULL,
-			      NULL);
-
-    gtk_spin_button_set_range(audio_connection_collection_editor->soundcard_audio_channel,
-			      0.0,
-			      soundcard_audio_channels - 1.0);
-  }else{
-    gtk_spin_button_set_range(audio_connection_collection_editor->soundcard_audio_channel,
-			      -1.0, -1.0);
-  }
-}
-
-/**
- * ags_audio_connection_collection_editor_new:
- * @channel_type: either %AGS_TYPE_INPUT or %AGS_TYPE_OUTPUT
- *
- * Creates an #AgsAudioConnectionCollectionEditor
- *
- * Returns: a new #AgsAudioConnectionCollectionEditor
- *
- * Since: 0.7.65
- */
-AgsAudioConnectionCollectionEditor*
-ags_audio_connection_collection_editor_new(GType channel_type)
-{
-  AgsAudioConnectionCollectionEditor *audio_connection_collection_editor;
-  
-  audio_connection_collection_editor = (AgsAudioConnectionCollectionEditor *) g_object_new(AGS_TYPE_AUDIO_CONNECTION_COLLECTION_EDITOR,
-											   "channel_type\0", channel_type,
-											   NULL);
-  
-  return(audio_connection_collection_editor);
-}
diff --git a/ags/X/ags_audio_connection_collection_editor.h b/ags/X/ags_audio_connection_collection_editor.h
deleted file mode 100644
index 068dace..0000000
--- a/ags/X/ags_audio_connection_collection_editor.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
- *
- * This file is part of GSequencer.
- *
- * GSequencer is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __AGS_AUDIO_CONNECTION_COLLECTION_EDITOR_H__
-#define __AGS_AUDIO_CONNECTION_COLLECTION_EDITOR_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include <gtk/gtk.h>
-
-#define AGS_TYPE_AUDIO_CONNECTION_COLLECTION_EDITOR                (ags_audio_connection_collection_editor_get_type())
-#define AGS_AUDIO_CONNECTION_COLLECTION_EDITOR(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_AUDIO_CONNECTION_COLLECTION_EDITOR, AgsAudioConnectionCollectionEditor))
-#define AGS_AUDIO_CONNECTION_COLLECTION_EDITOR_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_AUDIO_CONNECTION_COLLECTION_EDITOR, AgsAudioConnectionCollectionEditorClass))
-#define AGS_IS_AUDIO_CONNECTION_COLLECTION_EDITOR(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_AUDIO_CONNECTION_COLLECTION_EDITOR))
-#define AGS_IS_AUDIO_CONNECTION_COLLECTION_EDITOR_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_AUDIO_CONNECTION_COLLECTION_EDITOR))
-#define AGS_AUDIO_CONNECTION_COLLECTION_EDITOR_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_AUDIO_CONNECTION_COLLECTION_EDITOR, AgsAudioConnectionCollectionEditorClass))
-
-typedef struct _AgsAudioConnectionCollectionEditor AgsAudioConnectionCollectionEditor;
-typedef struct _AgsAudioConnectionCollectionEditorClass AgsAudioConnectionCollectionEditorClass;
-
-struct _AgsAudioConnectionCollectionEditor
-{
-  GtkTable table;
-
-  GType channel_type;
-
-  GtkSpinButton *pad;
-  GtkSpinButton *audio_channel;
-  
-  GtkComboBoxText *soundcard;
-  GtkSpinButton *soundcard_audio_channel;
-};
-
-struct _AgsAudioConnectionCollectionEditorClass
-{
-  GtkTableClass table;
-};
-
-GType ags_audio_connection_collection_editor_get_type();
-
-void ags_audio_connection_collection_editor_check(AgsAudioConnectionCollectionEditor *audio_connection_collection_editor);
-
-AgsAudioConnectionCollectionEditor* ags_audio_connection_collection_editor_new(GType channel_type);
-
-#endif /*__AGS_AUDIO_CONNECTION_COLLECTION_EDITOR_H__*/
diff --git a/ags/X/ags_audio_connection_collection_editor_callbacks.h b/ags/X/ags_audio_connection_collection_editor_callbacks.h
deleted file mode 100644
index fe6bb17..0000000
--- a/ags/X/ags_audio_connection_collection_editor_callbacks.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
- *
- * This file is part of GSequencer.
- *
- * GSequencer is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __AGS_AUDIO_CONNECTION_COLLECTION_EDITOR_CALLBACKS_H__
-#define __AGS_AUDIO_CONNECTION_COLLECTION_EDITOR_CALLBACKS_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include <gtk/gtk.h>
-
-#include <ags/X/ags_audio_connection_collection_editor.h>
-
-int ags_audio_connection_collection_editor_parent_set_callback(GtkWidget *widget, GtkObject *old_parent,
-							       AgsAudioConnectionCollectionEditor *audio_connection_collection_editor);
-
-void ags_audio_connection_collection_editor_soundcard_callback(GtkWidget *combo_box,
-							       AgsAudioConnectionCollectionEditor *audio_connection_collection_editor);
-
-#endif /*__AGS_AUDIO_CONNECTION_COLLECTION_EDITOR_CALLBACKS_H__*/
diff --git a/ags/X/ags_automation_editor_callbacks.c b/ags/X/ags_automation_editor_callbacks.c
index 54f0df4..a7d8a02 100644
--- a/ags/X/ags_automation_editor_callbacks.c
+++ b/ags/X/ags_automation_editor_callbacks.c
@@ -86,7 +86,8 @@ ags_automation_editor_tic_callback(GObject *soundcard,
   task_thread = (AgsTaskThread *) ags_thread_find_type((AgsThread *) audio_loop,
 						       AGS_TYPE_TASK_THREAD);
 
-  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(window->navigation->scroll))){
+  if(window->navigation->scroll != NULL &&
+     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(window->navigation->scroll))){
     AgsScrollOnPlay *scroll_on_play;
     gdouble step;
     
diff --git a/ags/X/ags_bulk_member.c b/ags/X/ags_bulk_member.c
index 8a10478..f1d0282 100644
--- a/ags/X/ags_bulk_member.c
+++ b/ags/X/ags_bulk_member.c
@@ -593,10 +593,26 @@ ags_bulk_member_set_property(GObject *gobject,
       
       port = (AgsPort *) g_value_get_object(value);
 
+      if(port == NULL){
+	return;
+      }
+      
       if(ags_bulk_port_find(bulk_member->bulk_port, port) != NULL){
 	return;
       }
 
+      if((AGS_PORT_INFINITE_RANGE & (port->flags)) != 0){
+	GtkWidget *child;
+
+	child = gtk_bin_get_child(GTK_BIN(bulk_member));
+
+	//TODO:JK: add more types
+
+	if(AGS_IS_DIAL(child)){
+	  AGS_DIAL(child)->flags |= AGS_DIAL_SEEMLESS_MODE;
+	}
+      }
+      
       g_object_ref(port);
       bulk_port = ags_bulk_port_alloc(port);
       bulk_member->bulk_port = g_list_prepend(bulk_member->bulk_port,
@@ -610,6 +626,10 @@ ags_bulk_member_set_property(GObject *gobject,
       
       port = (AgsPort *) g_value_get_object(value);
 
+      if(port == NULL){
+	return;
+      }
+      
       if(ags_bulk_port_find(bulk_member->recall_bulk_port, port) != NULL){
 	return;
       }
@@ -916,7 +936,15 @@ ags_bulk_member_real_change_port(AgsBulkMember *bulk_member,
 	}else if(port->port_value_type == G_TYPE_FLOAT){
 	  gfloat val;
 	  
-	  val = ((gdouble *) port_data)[0];
+	  if(GTK_IS_TOGGLE_BUTTON(gtk_bin_get_child((GtkBin *) bulk_member))){
+	    if(((gboolean *) port_data)[0]){
+	      val = 1.0;
+	    }else{
+	      val = 0.0;
+	    }
+	  }else{
+	    val = ((gdouble *) port_data)[0];
+	  }
 	  
 	  if(bulk_member->conversion != NULL){
 	    gfloat upper, lower, range, step;
@@ -964,11 +992,19 @@ ags_bulk_member_real_change_port(AgsBulkMember *bulk_member,
 		       G_TYPE_FLOAT);
 
 	  g_value_set_float(&value,
-			     val);
+			    val);
 	}else if(port->port_value_type == G_TYPE_DOUBLE){
 	  gdouble val;
 	  
-	  val = ((gdouble *) port_data)[0];
+	  if(GTK_IS_TOGGLE_BUTTON(gtk_bin_get_child((GtkBin *) bulk_member))){
+	    if(((gboolean *) port_data)[0]){
+	      val = 1.0;
+	    }else{
+	      val = 0.0;
+	    }
+	  }else{
+	    val = ((gdouble *) port_data)[0];
+	  }
 	  
 	  if(bulk_member->conversion != NULL){
 	    gdouble upper, lower, range, step;
diff --git a/ags/X/ags_connection_editor.c b/ags/X/ags_connection_editor.c
index 8563cf5..cf982a9 100644
--- a/ags/X/ags_connection_editor.c
+++ b/ags/X/ags_connection_editor.c
@@ -26,7 +26,8 @@
 #include <ags/audio/ags_output.h>
 #include <ags/audio/ags_input.h>
 
-#include <ags/X/ags_audio_connection_collection_editor.h>
+#include <ags/X/ags_output_collection_editor.h>
+#include <ags/X/ags_output_listing_editor.h>
 
 void ags_connection_editor_class_init(AgsConnectionEditorClass *connection_editor);
 void ags_connection_editor_connectable_interface_init(AgsConnectableInterface *connectable);
@@ -205,6 +206,13 @@ ags_connection_editor_init(AgsConnectionEditor *connection_editor)
     notebook = (GtkNotebook *) gtk_notebook_new();
   gtk_box_pack_start((GtkBox *) connection_editor->dialog.vbox, (GtkWidget*) notebook, TRUE, TRUE, 0);
 
+  /* output listing editor */
+  connection_editor->output_listing_editor_scrolled_window =
+    scrolled_window = (GtkScrolledWindow *) gtk_scrolled_window_new(NULL, NULL);
+  gtk_notebook_append_page(notebook,
+			   (GtkWidget *) scrolled_window,
+			   (GtkWidget *) gtk_label_new(g_strdup("output\0")));
+
   /* audio connection editor */
   connection_editor->output_connection_editor_scrolled_window =
     scrolled_window = (GtkScrolledWindow *) gtk_scrolled_window_new(NULL, NULL);
@@ -212,15 +220,15 @@ ags_connection_editor_init(AgsConnectionEditor *connection_editor)
 			   (GtkWidget *) scrolled_window,
 			   (GtkWidget *) gtk_label_new(g_strdup("connect output\0")));
 
-/* GtkButton's in GtkDialog->action_area  */
-connection_editor->apply = (GtkButton *) gtk_button_new_from_stock(GTK_STOCK_APPLY);
-gtk_box_pack_start((GtkBox *) connection_editor->dialog.action_area, (GtkWidget *) connection_editor->apply, FALSE, FALSE, 0);
+  /* GtkButton's in GtkDialog->action_area  */
+  connection_editor->apply = (GtkButton *) gtk_button_new_from_stock(GTK_STOCK_APPLY);
+  gtk_box_pack_start((GtkBox *) connection_editor->dialog.action_area, (GtkWidget *) connection_editor->apply, FALSE, FALSE, 0);
 
-connection_editor->ok = (GtkButton *) gtk_button_new_from_stock(GTK_STOCK_OK);
-gtk_box_pack_start((GtkBox *) connection_editor->dialog.action_area, (GtkWidget *) connection_editor->ok, FALSE, FALSE, 0);
+  connection_editor->ok = (GtkButton *) gtk_button_new_from_stock(GTK_STOCK_OK);
+  gtk_box_pack_start((GtkBox *) connection_editor->dialog.action_area, (GtkWidget *) connection_editor->ok, FALSE, FALSE, 0);
 
-connection_editor->cancel = (GtkButton *) gtk_button_new_from_stock(GTK_STOCK_CANCEL);
-gtk_box_pack_start((GtkBox *) connection_editor->dialog.action_area, (GtkWidget *) connection_editor->cancel, FALSE, FALSE, 0);
+  connection_editor->cancel = (GtkButton *) gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+  gtk_box_pack_start((GtkBox *) connection_editor->dialog.action_area, (GtkWidget *) connection_editor->cancel, FALSE, FALSE, 0);
 }
 
 void
@@ -281,9 +289,9 @@ ags_connection_editor_connect(AgsConnectable *connectable)
 		   G_CALLBACK(ags_connection_editor_switch_page_callback), (gpointer) connection_editor);
 
   /* AgsConnectionEditor tabs */
+  ags_connectable_connect(AGS_CONNECTABLE(connection_editor->output_listing_editor));
   ags_connectable_connect(AGS_CONNECTABLE(connection_editor->output_connection_editor));
 
-
   /* AgsConnectionEditor buttons */
   g_signal_connect((GObject *) connection_editor->apply, "clicked\0",
 		   G_CALLBACK(ags_connection_editor_apply_callback), (gpointer) connection_editor);
@@ -303,6 +311,7 @@ ags_connection_editor_disconnect(AgsConnectable *connectable)
   connection_editor = AGS_CONNECTION_EDITOR(connectable);
 
   /* AgsConnectionEditor tabs */
+  ags_connectable_disconnect(AGS_CONNECTABLE(connection_editor->output_listing_editor));
   ags_connectable_disconnect(AGS_CONNECTABLE(connection_editor->output_connection_editor));
 }
 
@@ -313,6 +322,7 @@ ags_connection_editor_set_update(AgsApplicable *applicable, gboolean update)
 
   connection_editor = AGS_CONNECTION_EDITOR(applicable);
 
+  ags_applicable_set_update(AGS_APPLICABLE(connection_editor->output_listing_editor), update);
   ags_applicable_set_update(AGS_APPLICABLE(connection_editor->output_connection_editor), update);
 }
 
@@ -323,6 +333,7 @@ ags_connection_editor_apply(AgsApplicable *applicable)
 
   connection_editor = AGS_CONNECTION_EDITOR(applicable);
 
+  ags_applicable_apply(AGS_APPLICABLE(connection_editor->output_listing_editor));
   ags_applicable_apply(AGS_APPLICABLE(connection_editor->output_connection_editor));
 }
 
@@ -333,6 +344,7 @@ ags_connection_editor_reset(AgsApplicable *applicable)
 
   connection_editor = AGS_CONNECTION_EDITOR(applicable);
 
+  ags_applicable_reset(AGS_APPLICABLE(connection_editor->output_listing_editor));
   ags_applicable_reset(AGS_APPLICABLE(connection_editor->output_connection_editor));
 }
 
@@ -357,8 +369,13 @@ ags_connection_editor_add_children(AgsConnectionEditor *connection_editor)
   g_value_init(&(output_connection_editor_child_parameter[0].value), G_TYPE_GTYPE);
   g_value_set_gtype(&(output_connection_editor_child_parameter[0].value), AGS_TYPE_OUTPUT);
 
+  /* AgsOutput listing editor */
+  connection_editor->output_listing_editor = ags_output_listing_editor_new(AGS_TYPE_OUTPUT);
+  gtk_scrolled_window_add_with_viewport(connection_editor->output_listing_editor_scrolled_window,
+					(GtkWidget *) connection_editor->output_listing_editor);
+
   /* AgsOutput connection editor */
-  connection_editor->output_connection_editor = ags_property_collection_editor_new(AGS_TYPE_AUDIO_CONNECTION_COLLECTION_EDITOR,
+  connection_editor->output_connection_editor = ags_property_collection_editor_new(AGS_TYPE_OUTPUT_COLLECTION_EDITOR,
 										   1,
 										   output_connection_editor_child_parameter);
   gtk_scrolled_window_add_with_viewport(connection_editor->output_connection_editor_scrolled_window,
@@ -369,6 +386,7 @@ void
 ags_connection_editor_real_set_machine(AgsConnectionEditor *connection_editor, AgsMachine *machine)
 {
   if(connection_editor->machine != NULL){
+    gtk_widget_destroy(GTK_WIDGET(connection_editor->output_listing_editor));
     gtk_widget_destroy(GTK_WIDGET(connection_editor->output_connection_editor));
   }
   
diff --git a/ags/X/ags_connection_editor.h b/ags/X/ags_connection_editor.h
index 49a30bd..e5ebefd 100644
--- a/ags/X/ags_connection_editor.h
+++ b/ags/X/ags_connection_editor.h
@@ -58,6 +58,9 @@ struct _AgsConnectionEditor
 
   GtkNotebook *notebook;
 
+  GtkScrolledWindow *output_listing_editor_scrolled_window;
+  AgsPropertyCollectionEditor *output_listing_editor;
+
   GtkScrolledWindow *output_connection_editor_scrolled_window;
   AgsPropertyCollectionEditor *output_connection_editor;
 
diff --git a/ags/X/ags_connection_editor_callbacks.c b/ags/X/ags_connection_editor_callbacks.c
index 0991669..8bfbf11 100644
--- a/ags/X/ags_connection_editor_callbacks.c
+++ b/ags/X/ags_connection_editor_callbacks.c
@@ -46,6 +46,10 @@ ags_connection_editor_ok_callback(GtkWidget *widget, AgsConnectionEditor *connec
   ags_connectable_disconnect(AGS_CONNECTABLE(connection_editor));
   ags_applicable_apply(AGS_APPLICABLE(connection_editor));
 
+  if(connection_editor->machine != NULL){
+    connection_editor->machine->connection_editor = NULL;
+  }
+  
   gtk_widget_destroy((GtkWidget *) connection_editor);
 
   return(0);
@@ -54,6 +58,10 @@ ags_connection_editor_ok_callback(GtkWidget *widget, AgsConnectionEditor *connec
 int
 ags_connection_editor_cancel_callback(GtkWidget *widget, AgsConnectionEditor *connection_editor)
 {
+  if(connection_editor->machine != NULL){
+    connection_editor->machine->connection_editor = NULL;
+  }
+  
   gtk_widget_destroy((GtkWidget *) connection_editor);
 
   return(0);
diff --git a/ags/X/ags_editor_callbacks.c b/ags/X/ags_editor_callbacks.c
index 46e9226..068ee78 100644
--- a/ags/X/ags_editor_callbacks.c
+++ b/ags/X/ags_editor_callbacks.c
@@ -98,7 +98,8 @@ ags_editor_tic_callback(GObject *soundcard,
   task_thread = (AgsTaskThread *) ags_thread_find_type((AgsThread *) audio_loop,
 						       AGS_TYPE_TASK_THREAD);
 
-  if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(window->navigation->scroll))){
+  if(window->navigation->scroll != NULL &&
+     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(window->navigation->scroll))){
     AgsScrollOnPlay *scroll_on_play;
 
     guint note_offset;  
diff --git a/ags/X/ags_effect_bridge.c b/ags/X/ags_effect_bridge.c
index 6ada513..c8965b9 100644
--- a/ags/X/ags_effect_bridge.c
+++ b/ags/X/ags_effect_bridge.c
@@ -593,7 +593,7 @@ ags_effect_bridge_disconnect(AgsConnectable *connectable)
 
   effect_bridge = AGS_EFFECT_BRIDGE(connectable);
 
-  if((AGS_EFFECT_BRIDGE_CONNECTED & (effect_bridge->flags)) != 0){
+  if((AGS_EFFECT_BRIDGE_CONNECTED & (effect_bridge->flags)) == 0){
     return;
   }
 
@@ -636,6 +636,10 @@ ags_effect_bridge_disconnect(AgsConnectable *connectable)
 
     g_list_free(effect_pad_list_start);
   }
+
+  //TODO:JK: implement me
+  g_signal_handlers_disconnect_by_data(effect_bridge->audio,
+				       effect_bridge);
 }
 
 gchar*
diff --git a/ags/X/ags_effect_bridge_callbacks.c b/ags/X/ags_effect_bridge_callbacks.c
index 3e5adc5..a96fc0e 100644
--- a/ags/X/ags_effect_bridge_callbacks.c
+++ b/ags/X/ags_effect_bridge_callbacks.c
@@ -19,13 +19,29 @@
 
 #include <ags/X/ags_effect_bridge_callbacks.h>
 
+#include <ags/object/ags_application_context.h>
+
+#include <ags/thread/ags_mutex_manager.h>
+
+#include <ags/X/ags_window.h>
+
+#include <ags/X/thread/ags_gui_thread.h>
+
 void
 ags_effect_bridge_set_audio_channels_callback(AgsAudio *audio,
 					      guint audio_channels, guint audio_channels_old,
 					      AgsEffectBridge *effect_bridge)
 {
+  AgsWindow *window;
+  
+  gdk_threads_enter();
+
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) effect_bridge);
+
   ags_effect_bridge_resize_audio_channels(effect_bridge,
 					  audio_channels, audio_channels_old);
+
+  gdk_threads_leave();
 }
 
 void
@@ -34,8 +50,15 @@ ags_effect_bridge_set_pads_callback(AgsAudio *audio,
 				    guint pads, guint pads_old,
 				    AgsEffectBridge *effect_bridge)
 {  
+  AgsWindow *window;
+
+  gdk_threads_enter();
+
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) effect_bridge);
   ags_effect_bridge_resize_pads(effect_bridge,
 				channel_type,
 				pads, pads_old);
+
+  gdk_threads_leave();
 }
 
diff --git a/ags/X/ags_effect_bulk.c b/ags/X/ags_effect_bulk.c
index 7977b6b..40ca29c 100644
--- a/ags/X/ags_effect_bulk.c
+++ b/ags/X/ags_effect_bulk.c
@@ -65,6 +65,8 @@
 #include <ags/audio/task/ags_add_recall_container.h>
 #include <ags/audio/task/ags_add_recall.h>
 
+#include <ags/widget/ags_led.h>
+#include <ags/widget/ags_hindicator.h>
 #include <ags/widget/ags_dial.h>
 
 #include <ags/X/ags_window.h>
@@ -105,6 +107,7 @@ gchar* ags_effect_bulk_get_version(AgsPlugin *plugin);
 void ags_effect_bulk_set_version(AgsPlugin *plugin, gchar *version);
 gchar* ags_effect_bulk_get_build_id(AgsPlugin *plugin);
 void ags_effect_bulk_set_build_id(AgsPlugin *plugin, gchar *build_id);
+void ags_effect_bulk_finalize(GObject *gobject);
 void ags_effect_bulk_show(GtkWidget *widget);
 
 GList* ags_effect_bulk_add_ladspa_effect(AgsEffectBulk *effect_bulk,
@@ -165,6 +168,8 @@ enum{
 static gpointer ags_effect_bulk_parent_class = NULL;
 static guint effect_bulk_signals[LAST_SIGNAL];
 
+GHashTable *ags_effect_bulk_indicator_queue_draw = NULL;
+
 GType
 ags_effect_bulk_get_type(void)
 {
@@ -226,6 +231,7 @@ ags_effect_bulk_class_init(AgsEffectBulkClass *effect_bulk)
   gobject->set_property = ags_effect_bulk_set_property;
   gobject->get_property = ags_effect_bulk_get_property;
 
+  gobject->finalize = ags_effect_bulk_finalize;
   
   /* properties */
   /**
@@ -413,6 +419,12 @@ ags_effect_bulk_init(AgsEffectBulk *effect_bulk)
 {
   GtkAlignment *alignment;
   GtkHBox *hbox;
+
+  if(ags_effect_bulk_indicator_queue_draw == NULL){
+    ags_effect_bulk_indicator_queue_draw = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+								 NULL,
+								 NULL);
+  }
   
   effect_bulk->flags = 0;
 
@@ -478,6 +490,8 @@ ags_effect_bulk_init(AgsEffectBulk *effect_bulk)
 		     0);
 
   effect_bulk->plugin_browser = (GtkDialog *) ags_plugin_browser_new((GtkWidget *) effect_bulk);
+
+  effect_bulk->queued_drawing = NULL;
 }
 
 void
@@ -602,6 +616,9 @@ ags_effect_bulk_connect(AgsConnectable *connectable)
     return;
   }
 
+  effect_bulk->flags |= AGS_EFFECT_BULK_CONNECTED;
+  
+  /*  */
   g_signal_connect(G_OBJECT(effect_bulk->add), "clicked\0",
 		   G_CALLBACK(ags_effect_bulk_add_callback), effect_bulk);
 
@@ -640,13 +657,37 @@ ags_effect_bulk_disconnect(AgsConnectable *connectable)
 {
   AgsEffectBulk *effect_bulk;
 
+  GList *list, *list_start;
+
   effect_bulk = AGS_EFFECT_BULK(connectable);
 
   if((AGS_EFFECT_BULK_CONNECTED & (effect_bulk->flags)) == 0){
     return;
   }
 
+  effect_bulk->flags &= (~AGS_EFFECT_BULK_CONNECTED);
+
+  ags_connectable_disconnect(AGS_CONNECTABLE(effect_bulk->plugin_browser));
+
+  list =
+    list_start = gtk_container_get_children((GtkContainer *) effect_bulk->table);
+
+  while(list != NULL){
+    if(AGS_IS_CONNECTABLE(list->data)){
+      ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
+    }
+
+    list = list->next;
+  }
+
+  g_list_free(list_start);
+
   //TODO:JK: implement me
+
+  if(effect_bulk->audio != NULL){
+    g_signal_handlers_disconnect_by_data(effect_bulk->audio,
+					 effect_bulk);
+  }  
 }
 
 gchar*
@@ -698,6 +739,41 @@ ags_effect_bulk_set_build_id(AgsPlugin *plugin, gchar *build_id)
 }
 
 void
+ags_effect_bulk_finalize(GObject *gobject)
+{
+  AgsEffectBulk *effect_bulk;
+
+  GList *list;
+  
+  effect_bulk = (AgsEffectBulk *) gobject;
+
+  /* unref audio */
+  if(effect_bulk->audio != NULL){
+    g_object_unref(effect_bulk->audio);
+  }
+
+  /* free plugin list */
+  g_list_free_full(effect_bulk->plugin,
+		   ags_effect_bulk_plugin_free);
+
+  /* destroy plugin browser */
+  gtk_widget_destroy(effect_bulk->plugin_browser);
+
+  /* remove of the queued drawing hash */
+  list = effect_bulk->queued_drawing;
+
+  while(list != NULL){
+    g_hash_table_remove(ags_effect_bulk_indicator_queue_draw,
+			list->data);
+
+    list = list->next;
+  }
+  
+  /* call parent */  
+  G_OBJECT_CLASS(ags_effect_bulk_parent_class)->finalize(gobject);
+}
+
+void
 ags_effect_bulk_show(GtkWidget *widget)
 {
   AgsEffectBulk *effect_bulk;
@@ -715,6 +791,17 @@ ags_effect_bulk_show(GtkWidget *widget)
   }
 }
 
+/**
+ * ags_effect_bulk_plugin_alloc:
+ * @filename: the filename as string
+ * @effect: the effect as string
+ * 
+ * Allocate #AgsEffectBulkPlugin-struct.
+ * 
+ * Returns: the newly allocated #AgsEffectBulkPlugin-struct
+ * 
+ * Since: 0.7.128
+ */
 AgsEffectBulkPlugin*
 ags_effect_bulk_plugin_alloc(gchar *filename,
 			     gchar *effect)
@@ -723,14 +810,44 @@ ags_effect_bulk_plugin_alloc(gchar *filename,
 
   effect_plugin = (AgsEffectBulkPlugin *) malloc(sizeof(AgsEffectBulkPlugin));
 
-  effect_plugin->filename = filename;
-  effect_plugin->effect = effect;
+  effect_plugin->filename = g_strdup(filename);
+  effect_plugin->effect = g_strdup(effect);
 
   effect_plugin->control_type_name = NULL;
   
   return(effect_plugin);
 }
 
+/**
+ * ags_effect_bulk_plugin_free:
+ * @effect_bulk_plugin: the #AgsEffectBulkPlugin-struct
+ * 
+ * Free @effect_bulk_plugin.
+ * 
+ * Since: 0.7.128
+ */
+void
+ags_effect_bulk_plugin_free(AgsEffectBulkPlugin *effect_bulk_plugin)
+{
+  if(effect_bulk_plugin == NULL){
+    return;
+  }
+
+  if(effect_bulk_plugin->filename != NULL){
+    free(effect_bulk_plugin->filename);
+  }
+
+  if(effect_bulk_plugin->effect != NULL){
+    free(effect_bulk_plugin->effect);
+  }
+
+  if(effect_bulk_plugin->control_type_name != NULL){
+    g_list_free(effect_bulk_plugin->control_type_name);
+  }
+  
+  free(effect_bulk_plugin);
+}
+
 GList*
 ags_effect_bulk_add_ladspa_effect(AgsEffectBulk *effect_bulk,
 				  GList *control_type_name,
@@ -748,6 +865,7 @@ ags_effect_bulk_add_ladspa_effect(AgsEffectBulk *effect_bulk,
   AgsRecallContainer *recall_container;
   AgsRecallChannelRunDummy *recall_channel_run_dummy;
   AgsRecallLadspa *recall_ladspa;
+  AgsRecallHandler *recall_handler;
 
   AgsAddRecallContainer *add_recall_container;
   AgsAddRecall *add_recall;
@@ -769,6 +887,8 @@ ags_effect_bulk_add_ladspa_effect(AgsEffectBulk *effect_bulk,
   guint pads, audio_channels;
   gdouble step;
   guint port_count;
+  gboolean has_output_port;
+  
   guint x, y;
   guint i, j;
   guint k;
@@ -838,6 +958,8 @@ ags_effect_bulk_add_ladspa_effect(AgsEffectBulk *effect_bulk,
 
   task = NULL;
   retport = NULL;
+
+  has_output_port = FALSE;
   
   for(i = 0; i < pads; i++){
     for(j = 0; j < audio_channels; j++){
@@ -858,6 +980,7 @@ ags_effect_bulk_add_ladspa_effect(AgsEffectBulk *effect_bulk,
 					    filename,
 					    effect,
 					    AGS_BASE_PLUGIN(ladspa_plugin)->effect_index);
+
       g_object_set(G_OBJECT(recall_ladspa),
 		   "soundcard\0", soundcard,
 		   "recall-container\0", recall_container,
@@ -872,6 +995,10 @@ ags_effect_bulk_add_ladspa_effect(AgsEffectBulk *effect_bulk,
 
       port = ags_recall_ladspa_load_ports(recall_ladspa);
 
+      if((AGS_RECALL_HAS_OUTPUT_PORT & (AGS_RECALL(recall_ladspa)->flags)) != 0){
+	has_output_port = TRUE;
+      }
+      
       if(retport == NULL){
 	retport = port;
       }else{
@@ -904,7 +1031,7 @@ ags_effect_bulk_add_ladspa_effect(AgsEffectBulk *effect_bulk,
 			     (GObject *) recall_channel_run_dummy,
 			     FALSE);
       ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
-
+      
       /* ladspa recall */
       recall_container = ags_recall_container_new();
       ags_audio_add_recall_container(effect_bulk->audio,
@@ -960,7 +1087,7 @@ ags_effect_bulk_add_ladspa_effect(AgsEffectBulk *effect_bulk,
 			     (GObject *) recall_channel_run_dummy,
 			     FALSE);
       ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
-
+      
       /* iterate */
       pthread_mutex_lock(channel_mutex);
       
@@ -1001,6 +1128,9 @@ ags_effect_bulk_add_ladspa_effect(AgsEffectBulk *effect_bulk,
       GType widget_type;
 
       guint step_count;
+      gboolean disable_seemless;
+
+      disable_seemless = FALSE;
       
       if(x == AGS_EFFECT_BULK_COLUMNS_COUNT){
 	x = 0;
@@ -1010,15 +1140,27 @@ ags_effect_bulk_add_ladspa_effect(AgsEffectBulk *effect_bulk,
       }
       
       if((AGS_PORT_DESCRIPTOR_TOGGLED & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
-	widget_type = GTK_TYPE_TOGGLE_BUTTON;
+	disable_seemless = TRUE;
+	
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  widget_type = AGS_TYPE_LED;
+	}else{
+	  widget_type = GTK_TYPE_TOGGLE_BUTTON;
+	}
       }else{
-	widget_type = AGS_TYPE_DIAL;
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  widget_type = AGS_TYPE_HINDICATOR;
+	}else{
+	  widget_type = AGS_TYPE_DIAL;
+	}
       }
       
       step_count = AGS_DIAL_DEFAULT_PRECISION;
 
       if((AGS_PORT_DESCRIPTOR_INTEGER & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
 	step_count = AGS_PORT_DESCRIPTOR(port_descriptor->data)->scale_steps;
+
+	disable_seemless = TRUE;	
       }
 
       /* add bulk member */
@@ -1094,6 +1236,10 @@ ags_effect_bulk_add_ladspa_effect(AgsEffectBulk *effect_bulk,
 	
 	dial = (AgsDial *) child_widget;
 
+	if(disable_seemless){
+	  dial->flags &= (~AGS_DIAL_SEEMLESS_MODE);
+	}
+
 	/* add controls of ports and apply range  */
 	lower_bound = g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->lower_value);
 	upper_bound = g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->upper_value);
@@ -1129,6 +1275,13 @@ ags_effect_bulk_add_ladspa_effect(AgsEffectBulk *effect_bulk,
 	
 	gtk_adjustment_set_value(adjustment,
 				 default_value);
+      }else if(AGS_IS_INDICATOR(child_widget) ||
+	       AGS_IS_LED(child_widget)){
+	g_hash_table_insert(ags_effect_bulk_indicator_queue_draw,
+			    child_widget, ags_effect_bulk_indicator_queue_draw_timeout);
+	effect_bulk->queued_drawing = g_list_prepend(effect_bulk->queued_drawing,
+						     child_widget);
+	g_timeout_add(1000 / 30, (GSourceFunc) ags_effect_bulk_indicator_queue_draw_timeout, (gpointer) child_widget);
       }
 
 #ifdef AGS_DEBUG
@@ -1176,6 +1329,7 @@ ags_effect_bulk_add_dssi_effect(AgsEffectBulk *effect_bulk,
   AgsRecallContainer *recall_container;
   AgsRecallChannelRunDummy *recall_channel_run_dummy;
   AgsRecallDssi *recall_dssi;
+  AgsRecallHandler *recall_handler;
 
   AgsAddRecallContainer *add_recall_container;
   AgsAddRecall *add_recall;
@@ -1197,6 +1351,8 @@ ags_effect_bulk_add_dssi_effect(AgsEffectBulk *effect_bulk,
   guint pads, audio_channels;
   gdouble step;
   guint port_count;
+  gboolean has_output_port;
+  
   guint x, y;
   guint i, j;
   guint k;
@@ -1266,6 +1422,8 @@ ags_effect_bulk_add_dssi_effect(AgsEffectBulk *effect_bulk,
 
   task = NULL;
   retport = NULL;
+
+  has_output_port = FALSE;
   
   for(i = 0; i < pads; i++){
     for(j = 0; j < audio_channels; j++){
@@ -1313,6 +1471,10 @@ ags_effect_bulk_add_dssi_effect(AgsEffectBulk *effect_bulk,
 				port);
       }
 
+      if((AGS_RECALL_HAS_OUTPUT_PORT & (AGS_RECALL(recall_dssi)->flags)) != 0){
+	has_output_port = TRUE;
+      }
+
       ags_channel_add_recall(current,
 			     (GObject *) recall_dssi,
 			     TRUE);
@@ -1338,7 +1500,7 @@ ags_effect_bulk_add_dssi_effect(AgsEffectBulk *effect_bulk,
 			     (GObject *) recall_channel_run_dummy,
 			     TRUE);
       ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
-
+            
       /* dssi recall */
       recall_container = ags_recall_container_new();
       ags_audio_add_recall_container(effect_bulk->audio,
@@ -1439,6 +1601,9 @@ ags_effect_bulk_add_dssi_effect(AgsEffectBulk *effect_bulk,
       GType widget_type;
 
       guint step_count;
+      gboolean disable_seemless;
+
+      disable_seemless = FALSE;
       
       if(x == AGS_EFFECT_BULK_COLUMNS_COUNT){
 	x = 0;
@@ -1448,15 +1613,25 @@ ags_effect_bulk_add_dssi_effect(AgsEffectBulk *effect_bulk,
       }
 
       if((AGS_PORT_DESCRIPTOR_TOGGLED & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
-	widget_type = GTK_TYPE_TOGGLE_BUTTON;
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  widget_type = AGS_TYPE_LED;
+	}else{
+	  widget_type = GTK_TYPE_TOGGLE_BUTTON;
+	}
       }else{
-	widget_type = AGS_TYPE_DIAL;
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  widget_type = AGS_TYPE_HINDICATOR;
+	}else{
+	  widget_type = AGS_TYPE_DIAL;
+	}
       }
 
       step_count = AGS_DIAL_DEFAULT_PRECISION;
 
       if((AGS_PORT_DESCRIPTOR_INTEGER & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
 	step_count = AGS_PORT_DESCRIPTOR(port_descriptor->data)->scale_steps;
+
+	disable_seemless = TRUE;	
       }
 
       /* add bulk member */
@@ -1533,6 +1708,10 @@ ags_effect_bulk_add_dssi_effect(AgsEffectBulk *effect_bulk,
 	
 	dial = (AgsDial *) child_widget;
 
+	if(disable_seemless){
+	  dial->flags &= (~AGS_DIAL_SEEMLESS_MODE);
+	}
+
 	/* add controls of ports and apply range  */
 	lower_bound = g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->lower_value);
 	upper_bound = g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->upper_value);
@@ -1571,6 +1750,13 @@ ags_effect_bulk_add_dssi_effect(AgsEffectBulk *effect_bulk,
 #ifdef AGS_DEBUG
 	g_message("dssi bounds: %f %f\0", lower_bound, upper_bound);
 #endif
+      }else if(AGS_IS_INDICATOR(child_widget) ||
+	       AGS_IS_LED(child_widget)){
+	g_hash_table_insert(ags_effect_bulk_indicator_queue_draw,
+			    child_widget, ags_effect_bulk_indicator_queue_draw_timeout);
+	effect_bulk->queued_drawing = g_list_prepend(effect_bulk->queued_drawing,
+						     child_widget);
+	g_timeout_add(1000 / 30, (GSourceFunc) ags_effect_bulk_indicator_queue_draw_timeout, (gpointer) child_widget);
       }
 
       gtk_table_attach(effect_bulk->table,
@@ -1614,6 +1800,7 @@ ags_effect_bulk_add_lv2_effect(AgsEffectBulk *effect_bulk,
   AgsRecallContainer *recall_container;
   AgsRecallChannelRunDummy *recall_channel_run_dummy;
   AgsRecallLv2 *recall_lv2;
+  AgsRecallHandler *recall_handler;
 
   AgsAddRecallContainer *add_recall_container;
   AgsAddRecall *add_recall;
@@ -1641,6 +1828,8 @@ ags_effect_bulk_add_lv2_effect(AgsEffectBulk *effect_bulk,
   gdouble step;
   guint pads, audio_channels;
   guint port_count;
+  gboolean has_output_port;
+
   guint x, y;
   guint i, j;
   guint k;
@@ -1712,6 +1901,8 @@ ags_effect_bulk_add_lv2_effect(AgsEffectBulk *effect_bulk,
 
   task = NULL;
   retport = NULL;
+
+  has_output_port = FALSE;
   
   for(i = 0; i < pads; i++){
     for(j = 0; j < audio_channels; j++){
@@ -1761,6 +1952,10 @@ ags_effect_bulk_add_lv2_effect(AgsEffectBulk *effect_bulk,
 				port);
       }
 
+      if((AGS_RECALL_HAS_OUTPUT_PORT & (AGS_RECALL(recall_lv2)->flags)) != 0){
+	has_output_port = TRUE;
+      }
+      
       ags_channel_add_recall(current,
 			     (GObject *) recall_lv2,
 			     TRUE);
@@ -1850,7 +2045,7 @@ ags_effect_bulk_add_lv2_effect(AgsEffectBulk *effect_bulk,
 			     (GObject *) recall_channel_run_dummy,
 			     FALSE);
       ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
-      
+
       /* iterate */
       pthread_mutex_lock(channel_mutex);
       
@@ -1889,7 +2084,10 @@ ags_effect_bulk_add_lv2_effect(AgsEffectBulk *effect_bulk,
       GType widget_type;
 
       guint step_count;
-      
+      gboolean disable_seemless;
+
+      disable_seemless = FALSE;
+            
       if(x == AGS_EFFECT_BULK_COLUMNS_COUNT){
 	x = 0;
 	y++;
@@ -1898,15 +2096,27 @@ ags_effect_bulk_add_lv2_effect(AgsEffectBulk *effect_bulk,
       }
 
       if((AGS_PORT_DESCRIPTOR_TOGGLED & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
-	widget_type = GTK_TYPE_TOGGLE_BUTTON;
+	disable_seemless = TRUE;
+	
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  widget_type = AGS_TYPE_LED;
+	}else{
+	  widget_type = GTK_TYPE_TOGGLE_BUTTON;
+	}
       }else{
-	widget_type = AGS_TYPE_DIAL;
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  widget_type = AGS_TYPE_HINDICATOR;
+	}else{
+	  widget_type = AGS_TYPE_DIAL;
+	}
       }
 
       step_count = AGS_DIAL_DEFAULT_PRECISION;
 
       if((AGS_PORT_DESCRIPTOR_INTEGER & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
 	step_count = AGS_PORT_DESCRIPTOR(port_descriptor->data)->scale_steps;
+
+	disable_seemless = TRUE;	
       }
 
       /* add bulk member */
@@ -1955,6 +2165,10 @@ ags_effect_bulk_add_lv2_effect(AgsEffectBulk *effect_bulk,
 	
 	dial = (AgsDial *) child_widget;
 
+	if(disable_seemless){
+	  dial->flags &= (~AGS_DIAL_SEEMLESS_MODE);
+	}
+
 	/* add controls of ports and apply range  */
 	lower_bound = g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->lower_value);
 	upper_bound = g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->upper_value);
@@ -1980,6 +2194,13 @@ ags_effect_bulk_add_lv2_effect(AgsEffectBulk *effect_bulk,
 				 upper_bound);
 	gtk_adjustment_set_value(adjustment,
 				 g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->default_value));
+      }else if(AGS_IS_INDICATOR(child_widget) ||
+	       AGS_IS_LED(child_widget)){
+	g_hash_table_insert(ags_effect_bulk_indicator_queue_draw,
+			    child_widget, ags_effect_bulk_indicator_queue_draw_timeout);
+	effect_bulk->queued_drawing = g_list_prepend(effect_bulk->queued_drawing,
+						     child_widget);
+	g_timeout_add(1000 / 30, (GSourceFunc) ags_effect_bulk_indicator_queue_draw_timeout, (gpointer) child_widget);
       }
 
 #ifdef AGS_DEBUG
@@ -2212,6 +2433,16 @@ ags_effect_bulk_real_remove_effect(AgsEffectBulk *effect_bulk,
       }
       
       if(i == nth){
+	GtkWidget *child_widget;
+	
+	child_widget = gtk_bin_get_child(list->data);
+
+	if(AGS_IS_LED(child_widget) ||
+	   AGS_IS_INDICATOR(child_widget)){
+	  g_hash_table_remove(ags_effect_bulk_indicator_queue_draw,
+			      child_widget);
+	}
+
 	gtk_widget_destroy(list->data);
       }
       
@@ -2652,6 +2883,29 @@ ags_effect_bulk_find_port(AgsEffectBulk *effect_bulk)
 }
 
 /**
+ * ags_effect_bulk_indicator_queue_draw_timeout:
+ * @widget: the indicator widgt
+ *
+ * Queue draw widget
+ *
+ * Returns: %TRUE if proceed with redraw, otherwise %FALSE
+ *
+ * Since: 0.7.128
+ */
+gboolean
+ags_effect_bulk_indicator_queue_draw_timeout(GtkWidget *widget)
+{
+  if(g_hash_table_lookup(ags_effect_bulk_indicator_queue_draw,
+			 widget) != NULL){
+    gtk_widget_queue_draw(widget);
+    
+    return(TRUE);
+  }else{
+    return(FALSE);
+  }
+}
+
+/**
  * ags_effect_bulk_new:
  * @audio: the #AgsAudio to visualize
  * @channel_type: either %AGS_TYPE_INPUT or %AGS_TYPE_OUTPUT
diff --git a/ags/X/ags_effect_bulk.h b/ags/X/ags_effect_bulk.h
index 2f80924..4bb0885 100644
--- a/ags/X/ags_effect_bulk.h
+++ b/ags/X/ags_effect_bulk.h
@@ -76,6 +76,8 @@ struct _AgsEffectBulk
 
   GList *plugin;
   GtkDialog *plugin_browser;
+
+  GList *queued_drawing;
 };
 
 struct _AgsEffectBulkClass
@@ -112,6 +114,7 @@ GType ags_effect_bulk_get_type(void);
 
 AgsEffectBulkPlugin* ags_effect_bulk_plugin_alloc(gchar *filename,
 						  gchar *effect);
+void ags_effect_bulk_plugin_free(AgsEffectBulkPlugin *effect_bulk_plugin);
 
 GList* ags_effect_bulk_add_effect(AgsEffectBulk *effect_bulk,
 				  GList *control_type_name,
@@ -130,6 +133,8 @@ void ags_effect_bulk_resize_pads(AgsEffectBulk *effect_bulk,
 void ags_effect_bulk_map_recall(AgsEffectBulk *effect_bulk);
 GList* ags_effect_bulk_find_port(AgsEffectBulk *effect_bulk);
 
+gboolean ags_effect_bulk_indicator_queue_draw_timeout(GtkWidget *widget);
+
 AgsEffectBulk* ags_effect_bulk_new(AgsAudio *audio,
 				   GType channel_type);
 
diff --git a/ags/X/ags_effect_bulk_callbacks.c b/ags/X/ags_effect_bulk_callbacks.c
index 93a59a5..e64b597 100644
--- a/ags/X/ags_effect_bulk_callbacks.c
+++ b/ags/X/ags_effect_bulk_callbacks.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2015,2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -19,9 +19,27 @@
 
 #include <ags/X/ags_effect_bulk_callbacks.h>
 
+#include <ags/object/ags_application_context.h>
+
+#include <ags/thread/ags_mutex_manager.h>
+
+#include <ags/plugin/ags_base_plugin.h>
+
+#include <ags/audio/ags_audio.h>
+#include <ags/audio/ags_channel.h>
+#include <ags/audio/ags_port.h>
+
+#include <ags/widget/ags_led.h>
+#include <ags/widget/ags_vindicator.h>
+#include <ags/widget/ags_hindicator.h>
+
+#include <ags/X/ags_window.h>
 #include <ags/X/ags_machine.h>
+#include <ags/X/ags_bulk_member.h>
 #include <ags/X/ags_plugin_browser.h>
 
+#include <ags/X/thread/ags_gui_thread.h>
+
 void
 ags_effect_bulk_add_callback(GtkWidget *button,
 			     AgsEffectBulk *effect_bulk)
@@ -131,9 +149,17 @@ ags_effect_bulk_set_audio_channels_callback(AgsAudio *audio,
 					    guint audio_channels_old,
 					    AgsEffectBulk *effect_bulk)
 {
+  AgsWindow *window;
+
+  gdk_threads_enter();
+
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) effect_bulk);
+
   ags_effect_bulk_resize_audio_channels(effect_bulk,
 					audio_channels,
 					audio_channels_old);
+
+  gdk_threads_leave();
 }
 
 void
@@ -143,9 +169,161 @@ ags_effect_bulk_set_pads_callback(AgsAudio *audio,
 				  guint pads_old,
 				  AgsEffectBulk *effect_bulk)
 {
+  AgsWindow *window;
+  
+  gdk_threads_enter();
+
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) effect_bulk);
+
   if(channel_type == effect_bulk->channel_type){
     ags_effect_bulk_resize_pads(effect_bulk,
 				pads,
 				pads_old);    
   }
+
+  gdk_threads_leave();
+}
+
+void
+ags_effect_bulk_output_port_run_post_callback(AgsRecall *recall,
+					      AgsEffectBulk *effect_bulk)
+{
+  GtkWidget *child;
+
+  GList *list, *list_start;
+  GList *port, *port_start;
+
+  /* lock gdk threads */
+  gdk_threads_enter();
+  
+  list_start = 
+    list = gtk_container_get_children((GtkContainer *) effect_bulk->table);
+
+  /* check members */
+  while(list != NULL){
+    if(AGS_IS_BULK_MEMBER(list->data) &&
+       (AGS_BULK_MEMBER(list->data)->widget_type == AGS_TYPE_VINDICATOR ||
+	AGS_BULK_MEMBER(list->data)->widget_type == AGS_TYPE_HINDICATOR ||
+	AGS_BULK_MEMBER(list->data)->widget_type == AGS_TYPE_LED)){
+      AgsBulkMember *bulk_member;
+      GtkAdjustment *adjustment;
+
+      gdouble average_peak;
+
+      bulk_member = AGS_BULK_MEMBER(list->data);
+      child = GTK_BIN(bulk_member)->child;
+      
+      average_peak = 0.0;
+      
+      /* copy port list */
+      port_start = g_list_concat(g_list_copy(bulk_member->bulk_port),
+				 g_list_copy(bulk_member->recall_bulk_port));
+
+      /* get display value */
+      port = port_start;
+	
+      while(port != NULL){
+	AgsPort *current;
+	
+	gdouble lower, upper;
+	gdouble range;
+	gdouble peak;
+	  
+	GValue value = {0,};
+
+	current = AGS_BULK_PORT(port->data)->port;
+
+	if(current == NULL){
+	  port = port->next;
+	
+	  continue;
+	}      
+	
+	/* check if output port and specifier matches */
+	pthread_mutex_lock(current->mutex);
+
+	if((AGS_PORT_IS_OUTPUT & (current->flags)) == 0 ||
+	   current->port_descriptor == NULL ||
+	   g_ascii_strcasecmp(current->specifier,
+			      bulk_member->specifier)){
+	  pthread_mutex_unlock(current->mutex);
+	    
+	  port = port->next;
+
+	  continue;
+	}
+
+	/* lower and upper */
+	lower = g_value_get_float(AGS_PORT_DESCRIPTOR(current->port_descriptor)->lower_value);
+	upper = g_value_get_float(AGS_PORT_DESCRIPTOR(current->port_descriptor)->upper_value);
+	  
+	pthread_mutex_unlock(current->mutex);
+
+	/* get range */
+	if(bulk_member->conversion != NULL){
+	  lower = ags_conversion_convert(bulk_member->conversion,
+					 lower,
+					 TRUE);
+	  
+	  upper = ags_conversion_convert(bulk_member->conversion,
+					 upper,
+					 TRUE);
+	}
+
+	range = upper - lower;
+
+	/* port read value */
+	g_value_init(&value, G_TYPE_FLOAT);
+	ags_port_safe_read(current,
+			   &value);
+	  
+	peak = g_value_get_float(&value);
+	g_value_unset(&value);
+
+	if(bulk_member->conversion != NULL){
+	  peak = ags_conversion_convert(bulk_member->conversion,
+					peak,
+					TRUE);
+	}
+	
+	/* calculate peak */
+	if(range == 0.0 ||
+	   current->port_value_type == G_TYPE_BOOLEAN){
+	  if(peak != 0.0){
+	    average_peak = 10.0;
+	    break;
+	  }
+	}else{
+	  average_peak += ((1.0 / (range / peak)) * 10.0);
+	}
+
+	/* iterate port */
+	port = port->next;
+      }
+
+      g_list_free(port_start);
+      
+      /* apply */
+      if(AGS_IS_LED(child)){
+	if(average_peak != 0.0){
+	  ags_led_set_active(child);
+	}
+      }else{
+	g_object_get(child,
+		     "adjustment\0", &adjustment,
+		     NULL);
+	
+	gtk_adjustment_set_value(adjustment,
+				 average_peak);
+      }
+    }
+
+    /* iterate bulk member */
+    list = list->next;
+  }
+
+  g_list_free(list_start);
+
+  /* unlock gdk threads */
+  gdk_threads_leave();
 }
diff --git a/ags/X/ags_effect_bulk_callbacks.h b/ags/X/ags_effect_bulk_callbacks.h
index 725c5c9..637b38a 100644
--- a/ags/X/ags_effect_bulk_callbacks.h
+++ b/ags/X/ags_effect_bulk_callbacks.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2015,2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -22,10 +22,10 @@
 
 #include <glib.h>
 #include <glib-object.h>
+
 #include <gtk/gtk.h>
 
-#include <lv2.h>
-#include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
+#include <ags/audio/ags_recall.h>
 
 #include <ags/X/ags_effect_bulk.h>
 
@@ -48,4 +48,7 @@ void ags_effect_bulk_set_pads_callback(AgsAudio *audio,
 				       guint pads_old,
 				       AgsEffectBulk *effect_bulk);
 
+void ags_effect_bulk_output_port_run_post_callback(AgsRecall *recall,
+						   AgsEffectBulk *effect_bulk);
+
 #endif /*__AGS_EFFECT_BULK_CALLBACKS_H__*/
diff --git a/ags/X/ags_effect_line.c b/ags/X/ags_effect_line.c
index d74a9a5..e52eb76 100644
--- a/ags/X/ags_effect_line.c
+++ b/ags/X/ags_effect_line.c
@@ -43,9 +43,13 @@
 #include <ags/audio/ags_channel.h>
 #include <ags/audio/ags_output.h>
 #include <ags/audio/ags_input.h>
+#include <ags/audio/ags_recall_container.h>
 #include <ags/audio/ags_recall_ladspa.h>
 #include <ags/audio/ags_recall_lv2.h>
 
+#include <ags/widget/ags_led.h>
+#include <ags/widget/ags_vindicator.h>
+#include <ags/widget/ags_hindicator.h>
 #include <ags/widget/ags_dial.h>
 
 #include <ags/X/ags_window.h>
@@ -83,6 +87,7 @@ gchar* ags_effect_line_get_version(AgsPlugin *plugin);
 void ags_effect_line_set_version(AgsPlugin *plugin, gchar *version);
 gchar* ags_effect_line_get_build_id(AgsPlugin *plugin);
 void ags_effect_line_set_build_id(AgsPlugin *plugin, gchar *build_id);
+void ags_effect_line_finalize(GObject *gobject);
 
 GList* ags_effect_line_add_ladspa_effect(AgsEffectLine *effect_line,
 					 GList *control_type_name,
@@ -129,6 +134,8 @@ enum{
 static gpointer ags_effect_line_parent_class = NULL;
 static guint effect_line_signals[LAST_SIGNAL];
 
+GHashTable *ags_effect_line_indicator_queue_draw = NULL;
+
 GType
 ags_effect_line_get_type(void)
 {
@@ -189,6 +196,8 @@ ags_effect_line_class_init(AgsEffectLineClass *effect_line)
   gobject->set_property = ags_effect_line_set_property;
   gobject->get_property = ags_effect_line_get_property;
 
+  gobject->finalize = ags_effect_line_finalize;
+  
   /* properties */
   /**
    * AgsEffectLine:channel:
@@ -327,6 +336,12 @@ ags_effect_line_plugin_interface_init(AgsPluginInterface *plugin)
 void
 ags_effect_line_init(AgsEffectLine *effect_line)
 {
+  if(ags_effect_line_indicator_queue_draw == NULL){
+    ags_effect_line_indicator_queue_draw = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+								 NULL,
+								 NULL);
+  }
+
   effect_line->flags = 0;
 
   effect_line->name = NULL;
@@ -349,6 +364,8 @@ ags_effect_line_init(AgsEffectLine *effect_line)
 		     GTK_WIDGET(effect_line->table),
 		     FALSE, FALSE,
 		     0);
+
+  effect_line->queued_drawing = NULL;
 }
 
 void
@@ -487,6 +504,9 @@ ags_effect_line_disconnect(AgsConnectable *connectable)
   if(list_start != NULL){
     g_list_free(list_start);
   }
+
+  g_signal_handlers_disconnect_by_data(effect_line->channel,
+				       effect_line);
 }
 
 gchar*
@@ -537,6 +557,25 @@ ags_effect_line_set_build_id(AgsPlugin *plugin, gchar *build_id)
   effect_line->build_id = build_id;
 }
 
+void
+ags_effect_line_finalize(GObject *gobject)
+{
+  AgsEffectLine *effect_line;
+  GList *list;
+
+  effect_line = AGS_EFFECT_LINE(gobject);
+  
+  /* remove of the queued drawing hash */
+  list = effect_line->queued_drawing;
+
+  while(list != NULL){
+    g_hash_table_remove(ags_effect_line_indicator_queue_draw,
+			list->data);
+
+    list = list->next;
+  }
+}
+
 GList*
 ags_effect_line_add_ladspa_effect(AgsEffectLine *effect_line,
 				  GList *control_type_name,
@@ -544,8 +583,12 @@ ags_effect_line_add_ladspa_effect(AgsEffectLine *effect_line,
 				  gchar *effect)
 {
   AgsLineMember *line_member;
-  AgsAddLineMember *add_line_member;
+  GtkSeparator *separator;
   GtkAdjustment *adjustment;
+  
+  AgsAddLineMember *add_line_member;
+
+  AgsRecallHandler *recall_handler;
 
   AgsLadspaPlugin *ladspa_plugin;
 
@@ -558,11 +601,17 @@ ags_effect_line_add_ladspa_effect(AgsEffectLine *effect_line,
   
   gdouble step;
   guint port_count;
+  gboolean has_output_port;
+
   guint x, y;
   guint k;
   
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *channel_mutex;
+
+  /* get mutex manager and application mutex */
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
   
   /* load plugin */
   ladspa_plugin = ags_ladspa_manager_find_ladspa_plugin(ags_ladspa_manager_get_instance(),
@@ -582,10 +631,6 @@ ags_effect_line_add_ladspa_effect(AgsEffectLine *effect_line,
     list = list->next;
   }
 
-  /* get mutex manager and application mutex */
-  mutex_manager = ags_mutex_manager_get_instance();
-  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
-
   /* get channel mutex */
   pthread_mutex_lock(application_mutex);
 
@@ -594,13 +639,44 @@ ags_effect_line_add_ladspa_effect(AgsEffectLine *effect_line,
   
   pthread_mutex_unlock(application_mutex);
   
-  /* find ports */
+  /* play - find ports */
   pthread_mutex_lock(channel_mutex);
 
   recall_start =
     recall = ags_recall_get_by_effect(effect_line->channel->play,
 				      filename,
 				      effect);
+
+  if(recall == NULL){
+    pthread_mutex_unlock(channel_mutex);
+    
+    return(NULL);
+  }
+
+  /* check has output port */
+  if((AGS_RECALL_HAS_OUTPUT_PORT & (AGS_RECALL(recall->data)->flags)) != 0){
+    has_output_port = TRUE;
+  }else{
+    has_output_port = FALSE;
+  }
+
+  /* recall handler of output port */
+  if(has_output_port){
+    AgsRecall *recall_channel_run_dummy;
+
+    recall_channel_run_dummy = ags_recall_find_template(AGS_RECALL_CONTAINER(AGS_RECALL(recall->data)->container)->recall_channel_run)->data;
+    
+    /* alloc handler */
+    recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
+
+    recall_handler->signal_name = "run-post\0";
+    recall_handler->callback = G_CALLBACK(ags_effect_line_output_port_run_post_callback);
+    recall_handler->data = (gpointer) effect_line;
+
+    ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
+  }
+  
+  /* recall - find ports */
   recall = g_list_last(recall);
   port = AGS_RECALL(recall->data)->port;
 
@@ -613,10 +689,47 @@ ags_effect_line_add_ladspa_effect(AgsEffectLine *effect_line,
   recall = g_list_last(recall);
 
   recall_port = AGS_RECALL(recall->data)->port;
-  g_list_free(recall_start);
 
+  /* recall handler of output port */
+  if(has_output_port){
+    AgsRecall *recall_channel_run_dummy;
+
+    recall_channel_run_dummy = ags_recall_find_template(AGS_RECALL_CONTAINER(AGS_RECALL(recall->data)->container)->recall_channel_run)->data;
+    
+    /* alloc handler */
+    recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
+
+    recall_handler->signal_name = "run-post\0";
+    recall_handler->callback = G_CALLBACK(ags_effect_line_output_port_run_post_callback);
+    recall_handler->data = (gpointer) effect_line;
+
+    ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
+  }
+
+  g_list_free(recall_start);
+  
   pthread_mutex_unlock(channel_mutex);
 
+  /* add separator */
+  separator = gtk_hseparator_new();
+  gtk_widget_set_size_request(separator,
+			      120, -1);
+  g_object_set_data(separator,
+		    AGS_EFFECT_LINE_SEPARATOR_FILENAME,
+		    filename);
+  g_object_set_data(separator,
+		    AGS_EFFECT_LINE_SEPARATOR_EFFECT,
+		    effect);
+  gtk_table_attach(effect_line->table,
+		   (GtkWidget *) separator,
+		   0, AGS_EFFECT_LINE_COLUMNS_COUNT,
+		   y, y + 1,
+		   GTK_FILL, GTK_FILL,
+		   0, 0);
+  gtk_widget_show(separator);
+
+  y++;
+
   /* load ports */
   port_descriptor = AGS_BASE_PLUGIN(ladspa_plugin)->port;
 
@@ -632,6 +745,9 @@ ags_effect_line_add_ladspa_effect(AgsEffectLine *effect_line,
       GType widget_type;
 
       guint step_count;
+      gboolean disable_seemless;
+
+      disable_seemless = FALSE;
 
       if(x == AGS_EFFECT_LINE_COLUMNS_COUNT){
 	x = 0;
@@ -641,9 +757,19 @@ ags_effect_line_add_ladspa_effect(AgsEffectLine *effect_line,
       }
       
       if((AGS_PORT_DESCRIPTOR_TOGGLED & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
-	widget_type = GTK_TYPE_TOGGLE_BUTTON;
+	disable_seemless = TRUE;
+
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  widget_type = AGS_TYPE_LED;
+	}else{
+	  widget_type = GTK_TYPE_TOGGLE_BUTTON;
+	}
       }else{
-	widget_type = AGS_TYPE_DIAL;
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  widget_type = AGS_TYPE_HINDICATOR;
+	}else{
+	  widget_type = AGS_TYPE_DIAL;
+	}
       }
 
       if(control_type_name != NULL){
@@ -656,6 +782,8 @@ ags_effect_line_add_ladspa_effect(AgsEffectLine *effect_line,
 
       if((AGS_PORT_DESCRIPTOR_INTEGER & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
 	step_count = AGS_PORT_DESCRIPTOR(port_descriptor->data)->scale_steps;
+
+	disable_seemless = TRUE;
       }
       
       /* add line member */
@@ -729,6 +857,10 @@ ags_effect_line_add_ladspa_effect(AgsEffectLine *effect_line,
 	
 	dial = (AgsDial *) child_widget;
 
+	if(disable_seemless){
+	  dial->flags &= (~AGS_DIAL_SEEMLESS_MODE);
+	}
+
 	/* add controls of ports and apply range  */
 	lower_bound = g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->lower_value);
 	upper_bound = g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->upper_value);
@@ -754,6 +886,13 @@ ags_effect_line_add_ladspa_effect(AgsEffectLine *effect_line,
 				 upper_bound);
 	gtk_adjustment_set_value(adjustment,
 				 g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->default_value));
+      }else if(AGS_IS_INDICATOR(child_widget) ||
+	       AGS_IS_LED(child_widget)){
+	g_hash_table_insert(ags_effect_line_indicator_queue_draw,
+			    child_widget, ags_effect_line_indicator_queue_draw_timeout);
+	effect_line->queued_drawing = g_list_prepend(effect_line->queued_drawing,
+						     child_widget);
+	g_timeout_add(1000 / 30, (GSourceFunc) ags_effect_line_indicator_queue_draw_timeout, (gpointer) child_widget);
       }
 
 #ifdef AGS_DEBUG
@@ -762,7 +901,7 @@ ags_effect_line_add_ladspa_effect(AgsEffectLine *effect_line,
 	  
       gtk_table_attach(effect_line->table,
 		       (GtkWidget *) line_member,
-		       x, x + 1,
+		       (x % AGS_EFFECT_LINE_COLUMNS_COUNT), (x % AGS_EFFECT_LINE_COLUMNS_COUNT) + 1,
 		       y, y + 1,
 		       GTK_FILL, GTK_FILL,
 		       0, 0);
@@ -772,6 +911,10 @@ ags_effect_line_add_ladspa_effect(AgsEffectLine *effect_line,
       
       port = port->next;
       x++;
+
+      if(x % AGS_EFFECT_LINE_COLUMNS_COUNT == 0){
+	y++;
+      }
     }
     
     port_descriptor = port_descriptor->next;
@@ -789,9 +932,13 @@ ags_effect_line_add_lv2_effect(AgsEffectLine *effect_line,
 			       gchar *effect)
 {
   AgsLineMember *line_member;
-  AgsAddLineMember *add_line_member;
+  GtkSeparator *separator;
   GtkAdjustment *adjustment;
 
+  AgsAddLineMember *add_line_member;
+
+  AgsRecallHandler *recall_handler;
+
   AgsLv2Plugin *lv2_plugin;
 
   AgsMutexManager *mutex_manager;
@@ -803,12 +950,18 @@ ags_effect_line_add_lv2_effect(AgsEffectLine *effect_line,
   
   gdouble step;
   guint port_count;
+  gboolean has_output_port;
+
   guint x, y;
   guint k;
   
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *channel_mutex;
 
+  /* get mutex manager and application mutex */
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
   /* load plugin */
   lv2_plugin = ags_lv2_manager_find_lv2_plugin(ags_lv2_manager_get_instance(),
 					       filename, effect);
@@ -827,10 +980,6 @@ ags_effect_line_add_lv2_effect(AgsEffectLine *effect_line,
     list = list->next;
   }
 
-  /* get mutex manager and application mutex */
-  mutex_manager = ags_mutex_manager_get_instance();
-  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
-
   /* get channel mutex */
   pthread_mutex_lock(application_mutex);
 
@@ -839,18 +988,49 @@ ags_effect_line_add_lv2_effect(AgsEffectLine *effect_line,
   
   pthread_mutex_unlock(application_mutex);
   
-  /* find ports */
+  /* play - find ports */
   pthread_mutex_lock(channel_mutex);
   
   recall_start =
     recall = ags_recall_get_by_effect(effect_line->channel->play,
 				      filename,
 				      effect);
+
+  if(recall == NULL){
+    pthread_mutex_unlock(channel_mutex);
+    
+    return(NULL);
+  }
+
   recall = g_list_last(recall);
   port = AGS_RECALL(recall->data)->port;
 
+  /* check has output port */
+  if((AGS_RECALL_HAS_OUTPUT_PORT & (AGS_RECALL(recall->data)->flags)) != 0){
+    has_output_port = TRUE;
+  }else{
+    has_output_port = FALSE;
+  }
+
+  /* recall handler of output port */
+  if(has_output_port){
+    AgsRecall *recall_channel_run_dummy;
+
+    recall_channel_run_dummy = ags_recall_find_template(AGS_RECALL_CONTAINER(AGS_RECALL(recall->data)->container)->recall_channel_run)->data;
+    
+    /* alloc handler */
+    recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
+
+    recall_handler->signal_name = "run-post\0";
+    recall_handler->callback = G_CALLBACK(ags_effect_line_output_port_run_post_callback);
+    recall_handler->data = (gpointer) effect_line;
+
+    ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
+  }
+
   g_list_free(recall_start);
 
+  /* recall - find ports */
   recall_start = 
     recall = ags_recall_get_by_effect(effect_line->channel->recall,
 				      filename,
@@ -858,10 +1038,47 @@ ags_effect_line_add_lv2_effect(AgsEffectLine *effect_line,
   recall = g_list_last(recall);
 
   recall_port = AGS_RECALL(recall->data)->port;
-  g_list_free(recall_start);
 
-  pthread_mutex_unlock(channel_mutex);
+  /* recall handler of output port */
+  if(has_output_port){
+    AgsRecall *recall_channel_run_dummy;
+
+    recall_channel_run_dummy = ags_recall_find_template(AGS_RECALL_CONTAINER(AGS_RECALL(recall->data)->container)->recall_channel_run)->data;
+    
+    /* alloc handler */
+    recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
+
+    recall_handler->signal_name = "run-post\0";
+    recall_handler->callback = G_CALLBACK(ags_effect_line_output_port_run_post_callback);
+    recall_handler->data = (gpointer) effect_line;
+
+    ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
+  }
+  
+  g_list_free(recall_start);
   
+  pthread_mutex_unlock(channel_mutex);
+
+  /* add separator */
+  separator = gtk_hseparator_new();
+  gtk_widget_set_size_request(separator,
+			      120, -1);
+  g_object_set_data(separator,
+		    AGS_EFFECT_LINE_SEPARATOR_FILENAME,
+		    filename);
+  g_object_set_data(separator,
+		    AGS_EFFECT_LINE_SEPARATOR_EFFECT,
+		    effect);
+  gtk_table_attach(effect_line->table,
+		   (GtkWidget *) separator,
+		   0, AGS_EFFECT_LINE_COLUMNS_COUNT,
+		   y, y + 1,
+		   GTK_FILL, GTK_FILL,
+		   0, 0);
+  gtk_widget_show(separator);
+
+  y++;
+
   /* load ports */
   port_descriptor = AGS_BASE_PLUGIN(lv2_plugin)->port;
 
@@ -878,6 +1095,9 @@ ags_effect_line_add_lv2_effect(AgsEffectLine *effect_line,
       GType widget_type;
 
       guint step_count;
+      gboolean disable_seemless;
+
+      disable_seemless = FALSE;
 
       if(x == AGS_EFFECT_LINE_COLUMNS_COUNT){
 	x = 0;
@@ -887,9 +1107,19 @@ ags_effect_line_add_lv2_effect(AgsEffectLine *effect_line,
       }
 
       if((AGS_PORT_DESCRIPTOR_TOGGLED & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
-	widget_type = GTK_TYPE_TOGGLE_BUTTON;
+	disable_seemless = TRUE;
+
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  widget_type = AGS_TYPE_LED;
+	}else{
+	  widget_type = GTK_TYPE_TOGGLE_BUTTON;
+	}
       }else{
-	widget_type = AGS_TYPE_DIAL;
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  widget_type = AGS_TYPE_HINDICATOR;
+	}else{
+	  widget_type = AGS_TYPE_DIAL;
+	}
       }
 
       if(control_type_name != NULL){
@@ -902,6 +1132,8 @@ ags_effect_line_add_lv2_effect(AgsEffectLine *effect_line,
 
       if((AGS_PORT_DESCRIPTOR_INTEGER & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
 	step_count = AGS_PORT_DESCRIPTOR(port_descriptor->data)->scale_steps;
+
+	disable_seemless = TRUE;
       }
 
       /* add line member */
@@ -950,6 +1182,10 @@ ags_effect_line_add_lv2_effect(AgsEffectLine *effect_line,
 	
 	dial = (AgsDial *) child_widget;
 
+	if(disable_seemless){
+	  dial->flags &= (~AGS_DIAL_SEEMLESS_MODE);
+	}
+
 	/* add controls of ports and apply range  */
 	lower_bound = g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->lower_value);
 	upper_bound = g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->upper_value);
@@ -975,6 +1211,13 @@ ags_effect_line_add_lv2_effect(AgsEffectLine *effect_line,
 				 upper_bound);
 	gtk_adjustment_set_value(adjustment,
 				 g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->default_value));
+      }else if(AGS_IS_INDICATOR(child_widget) ||
+	       AGS_IS_LED(child_widget)){
+	g_hash_table_insert(ags_effect_line_indicator_queue_draw,
+			    child_widget, ags_effect_line_indicator_queue_draw_timeout);
+	effect_line->queued_drawing = g_list_prepend(effect_line->queued_drawing,
+						     child_widget);
+	g_timeout_add(1000 / 30, (GSourceFunc) ags_effect_line_indicator_queue_draw_timeout, (gpointer) child_widget);
       }
 
 #ifdef AGS_DEBUG
@@ -983,7 +1226,7 @@ ags_effect_line_add_lv2_effect(AgsEffectLine *effect_line,
 	  
       gtk_table_attach(effect_line->table,
 		       (GtkWidget *) line_member,
-		       x, x + 1,
+		       (x % AGS_EFFECT_LINE_COLUMNS_COUNT), (x % AGS_EFFECT_LINE_COLUMNS_COUNT) + 1,
 		       y, y + 1,
 		       GTK_FILL, GTK_FILL,
 		       0, 0);
@@ -993,6 +1236,10 @@ ags_effect_line_add_lv2_effect(AgsEffectLine *effect_line,
 
       port = port->next;
       x++;
+
+      if(x % AGS_EFFECT_LINE_COLUMNS_COUNT == 0){
+	y++;
+      }
     }
 
     port_descriptor = port_descriptor->next;
@@ -1090,10 +1337,11 @@ ags_effect_line_real_remove_effect(AgsEffectLine *effect_line,
 
   AgsMutexManager *mutex_manager;
 
-  GList *control;
+  GList *control, *control_start;
   GList *recall;
   GList *port;
 
+  gchar *filename, *effect;
   gchar **remove_specifier;
 
   guint nth_effect, n_bulk;
@@ -1151,6 +1399,39 @@ ags_effect_line_real_remove_effect(AgsEffectLine *effect_line,
   }
 
   nth_effect--;
+
+  /* destroy separator */
+  filename = NULL;
+  effect = NULL;
+  
+  if(AGS_IS_RECALL_LV2(recall->data)){
+    filename = AGS_RECALL_LV2(recall->data)->filename;
+    effect = AGS_RECALL_LV2(recall->data)->effect;
+  }else if(AGS_IS_RECALL_LADSPA(recall->data)){
+    filename = AGS_RECALL_LADSPA(recall->data)->filename;
+    effect = AGS_RECALL_LADSPA(recall->data)->effect;
+  }
+
+  control_start =
+    control = gtk_container_get_children((GtkContainer *) effect_line->table);
+
+  while(control != NULL){
+    if(GTK_IS_SEPARATOR(control->data) &&
+       !strcmp(filename,
+	       g_object_get_data(control->data,
+				 AGS_EFFECT_LINE_SEPARATOR_FILENAME)) &&
+       !strcmp(effect,
+	       g_object_get_data(control->data,
+				 AGS_EFFECT_LINE_SEPARATOR_EFFECT))){
+      gtk_widget_destroy(control->data);
+      
+      break;
+    }
+
+    control->next;
+  }
+  
+  g_list_free(control_start);
   
   /* destroy controls */
   port = AGS_RECALL(recall->data)->port;
@@ -1158,11 +1439,16 @@ ags_effect_line_real_remove_effect(AgsEffectLine *effect_line,
   i = 0;
   
   while(port != NULL){
-    control = gtk_container_get_children((GtkContainer *) effect_line->table);
-      
+    control_start = 
+      control = gtk_container_get_children((GtkContainer *) effect_line->table);
+    
     while(control != NULL){
       if(AGS_IS_LINE_MEMBER(control->data) &&
 	 AGS_LINE_MEMBER(control->data)->port == port->data){
+	GtkWidget *child_widget;
+	
+	child_widget = gtk_bin_get_child(control->data);
+	
 	/* collect specifier */
 	if(remove_specifier == NULL){
 	  remove_specifier = (gchar **) malloc(2 * sizeof(gchar *));
@@ -1175,6 +1461,12 @@ ags_effect_line_real_remove_effect(AgsEffectLine *effect_line,
 	i++;
 
 	/* remove widget */
+	if(AGS_IS_LED(child_widget) ||
+	   AGS_IS_INDICATOR(child_widget)){
+	  g_hash_table_remove(ags_effect_line_indicator_queue_draw,
+			      child_widget);
+	}
+
 	gtk_widget_destroy(control->data);
 	
 	break;
@@ -1182,7 +1474,9 @@ ags_effect_line_real_remove_effect(AgsEffectLine *effect_line,
 	
       control = control->next;
     }
-      
+
+    g_list_free(control_start);
+    
     port = port->next;
   }
 
@@ -1327,6 +1621,29 @@ ags_effect_line_find_port(AgsEffectLine *effect_line)
 }
 
 /**
+ * ags_effect_line_indicator_queue_draw_timeout:
+ * @widget: the indicator widgt
+ *
+ * Queue draw widget
+ *
+ * Returns: %TRUE if proceed with redraw, otherwise %FALSE
+ *
+ * Since: 0.7.128
+ */
+gboolean
+ags_effect_line_indicator_queue_draw_timeout(GtkWidget *widget)
+{
+  if(g_hash_table_lookup(ags_effect_line_indicator_queue_draw,
+			 widget) != NULL){
+    gtk_widget_queue_draw(widget);
+    
+    return(TRUE);
+  }else{
+    return(FALSE);
+  }
+}
+
+/**
  * ags_effect_line_new:
  * @channel: the #AgsChannel to visualize
  *
diff --git a/ags/X/ags_effect_line.h b/ags/X/ags_effect_line.h
index c75f4a4..f4a49dd 100644
--- a/ags/X/ags_effect_line.h
+++ b/ags/X/ags_effect_line.h
@@ -37,6 +37,8 @@
 #define AGS_EFFECT_LINE_DEFAULT_BUILD_ID "CEST 01-03-2016 00:23\0"
 
 #define AGS_EFFECT_LINE_COLUMNS_COUNT (2)
+#define AGS_EFFECT_LINE_SEPARATOR_FILENAME "ags-effect-line-separator-filename\0"
+#define AGS_EFFECT_LINE_SEPARATOR_EFFECT "ags-effect-line-separator-effect\0"
 
 typedef struct _AgsEffectLine AgsEffectLine;
 typedef struct _AgsEffectLineClass AgsEffectLineClass;
@@ -63,6 +65,8 @@ struct _AgsEffectLine
   GtkLabel *label;
   
   GtkTable *table;
+
+  GList *queued_drawing;
 };
 
 struct _AgsEffectLineClass
@@ -98,6 +102,8 @@ void ags_effect_line_map_recall(AgsEffectLine *effect_line,
 				guint output_pad_start);
 GList* ags_effect_line_find_port(AgsEffectLine *effect_line);
 
+gboolean ags_effect_line_indicator_queue_draw_timeout(GtkWidget *widget);
+
 AgsEffectLine* ags_effect_line_new(AgsChannel *channel);
 
 #endif /*__AGS_EFFECT_LINE_H__*/
diff --git a/ags/X/ags_effect_line_callbacks.c b/ags/X/ags_effect_line_callbacks.c
index 9bd780e..dfb2b81 100644
--- a/ags/X/ags_effect_line_callbacks.c
+++ b/ags/X/ags_effect_line_callbacks.c
@@ -23,7 +23,8 @@
 #include <ags/object/ags_soundcard.h>
 
 #include <ags/thread/ags_mutex_manager.h>
-#include <ags/thread/ags_task_thread.h>
+
+#include <ags/plugin/ags_base_plugin.h>
 
 #include <ags/audio/ags_playback.h>
 #include <ags/audio/ags_recall.h>
@@ -41,8 +42,10 @@
 #include <ags/audio/recall/ags_copy_pattern_channel.h>
 #include <ags/audio/recall/ags_copy_pattern_channel_run.h>
 
-#include <ags/widget/ags_indicator.h>
+#include <ags/widget/ags_led.h>
 #include <ags/widget/ags_vindicator.h>
+#include <ags/widget/ags_hindicator.h>
+#include <ags/widget/ags_dial.h>
 
 #include <ags/X/ags_window.h>
 #include <ags/X/ags_machine.h>
@@ -58,7 +61,7 @@
 #include <ags/X/ags_dssi_browser.h>
 #include <ags/X/ags_lv2_browser.h>
 
-#include <ags/X/task/ags_change_indicator.h>
+#include <ags/X/thread/ags_gui_thread.h>
 
 void
 ags_effect_line_remove_recall_callback(AgsRecall *recall, AgsEffectLine *effect_line)
@@ -84,18 +87,49 @@ ags_effect_line_add_effect_callback(AgsChannel *channel,
 				    gchar *effect,
 				    AgsEffectLine *effect_line)
 {
+  AgsWindow *window;
   AgsMachine *machine;
   AgsMachineEditor *machine_editor;
   AgsLineMemberEditor *line_member_editor;
   AgsPluginBrowser *plugin_browser;
+
+  AgsGuiThread *gui_thread;
+
+  AgsMutexManager *mutex_manager;
+  AgsThread *main_loop;
+
+  AgsApplicationContext *application_context;
   
   GList *pad_editor, *pad_editor_start;
   GList *line_editor, *line_editor_start;
   GList *control_type_name;
   
+  pthread_mutex_t *application_mutex;
+  
   /* lock gdk threads */
   gdk_threads_enter();
 
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) effect_line);
+
+  application_context = (AgsApplicationContext *) window->application_context;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* get audio loop */
+  pthread_mutex_lock(application_mutex);
+
+  main_loop = (AgsAudioLoop *) application_context->main_loop;
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* get task thread */
+  gui_thread = (AgsGuiThread *) ags_thread_find_type((AgsThread *) main_loop,
+						      AGS_TYPE_GUI_THREAD);
+
+  /*  */
+  gdk_threads_enter();
+
   /* get machine and machine editor */
   machine = (AgsMachine *) gtk_widget_get_ancestor((GtkWidget *) effect_line,
 						   AGS_TYPE_MACHINE);
@@ -162,6 +196,21 @@ ags_effect_line_add_effect_callback(AgsChannel *channel,
 	      controls = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(port_control->data));
 
 	      if(!g_ascii_strncasecmp(controls,
+				      "led\0",
+				      4)){
+		control_type_name = g_list_prepend(control_type_name,
+						   "AgsLed\0");
+	      }else if(!g_ascii_strncasecmp(controls,
+				      "vertical indicator\0",
+				      19)){
+		control_type_name = g_list_prepend(control_type_name,
+						   "AgsVIndicator\0");
+	      }else if(!g_ascii_strncasecmp(controls,
+				      "horizontal indicator\0",
+				      19)){
+		control_type_name = g_list_prepend(control_type_name,
+						   "AgsHIndicator\0");
+	      }else if(!g_ascii_strncasecmp(controls,
 				      "spin button\0",
 				      12)){
 		control_type_name = g_list_prepend(control_type_name,
@@ -220,6 +269,8 @@ ags_effect_line_add_effect_callback(AgsChannel *channel,
   g_list_free(pad_editor_start);
   g_list_free(line_editor_start);
 
+  gdk_threads_leave();
+
   /* unlock gdk threads */
   gdk_threads_leave();
 }
@@ -229,13 +280,201 @@ ags_effect_line_remove_effect_callback(AgsChannel *channel,
 				       guint nth,
 				       AgsEffectLine *effect_line)
 {
+  AgsWindow *window;
+
+  AgsGuiThread *gui_thread;
+
+  AgsMutexManager *mutex_manager;
+  AgsThread *main_loop;
+
+  AgsApplicationContext *application_context;
+
+  pthread_mutex_t *application_mutex;
+
   /* lock gdk threads */
   gdk_threads_enter();
 
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) effect_line);
+
+  application_context = (AgsApplicationContext *) window->application_context;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* get audio loop */
+  pthread_mutex_lock(application_mutex);
+
+  main_loop = (AgsAudioLoop *) application_context->main_loop;
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* get task thread */
+  gui_thread = (AgsGuiThread *) ags_thread_find_type((AgsThread *) main_loop,
+						      AGS_TYPE_GUI_THREAD);
+
+  /*  */
+  gdk_threads_enter();
+
   /* remove effect */
   ags_effect_line_remove_effect(effect_line,
 				nth);
 
+  gdk_threads_leave();
+
+  /* unlock gdk threads */
+  gdk_threads_leave();
+}
+
+void
+ags_effect_line_output_port_run_post_callback(AgsRecall *recall,
+					      AgsEffectLine *effect_line)
+{
+  GtkWidget *child;
+
+  GList *list, *list_start;
+  
+  /* lock gdk threads */
+  gdk_threads_enter();
+  
+  list_start = 
+    list = gtk_container_get_children((GtkContainer *) AGS_EFFECT_LINE(effect_line)->table);
+
+  /* check members */
+  while(list != NULL){
+    if(AGS_IS_LINE_MEMBER(list->data) &&
+       (AGS_LINE_MEMBER(list->data)->widget_type == AGS_TYPE_VINDICATOR ||
+	AGS_LINE_MEMBER(list->data)->widget_type == AGS_TYPE_HINDICATOR ||
+	AGS_LINE_MEMBER(list->data)->widget_type == AGS_TYPE_LED)){
+      AgsLineMember *line_member;
+      GtkAdjustment *adjustment;
+
+      AgsPort *current;
+	
+      gdouble average_peak;
+      gdouble lower, upper;
+      gdouble range;
+      gdouble peak;
+
+      GValue value = {0,};
+
+      line_member = AGS_LINE_MEMBER(list->data);
+      child = GTK_BIN(line_member)->child;
+      
+      average_peak = 0.0;
+      
+      /* play port */
+      current = line_member->port;
+
+      if(current == NULL){
+	list = list->next;
+	
+	continue;
+      }
+      
+      /* check if output port and specifier matches */
+      pthread_mutex_lock(current->mutex);
+      
+      if((AGS_PORT_IS_OUTPUT & (current->flags)) == 0 ||
+	 current->port_descriptor == NULL ||
+	 g_ascii_strcasecmp(current->specifier,
+			    line_member->specifier)){
+	pthread_mutex_unlock(current->mutex);
+	
+	list = list->next;
+	
+	continue;
+      }
+
+      /* lower and upper */
+      lower = g_value_get_float(AGS_PORT_DESCRIPTOR(current->port_descriptor)->lower_value);
+      upper = g_value_get_float(AGS_PORT_DESCRIPTOR(current->port_descriptor)->upper_value);
+      
+      pthread_mutex_unlock(current->mutex);
+
+      /* get range */
+      if(line_member->conversion != NULL){
+	lower = ags_conversion_convert(line_member->conversion,
+				       lower,
+				       TRUE);
+
+	upper = ags_conversion_convert(line_member->conversion,
+				       upper,
+				       TRUE);
+      }
+
+      range = upper - lower;
+
+      /* play port - read value */
+      g_value_init(&value, G_TYPE_FLOAT);
+      ags_port_safe_read(current,
+			 &value);
+      
+      peak = g_value_get_float(&value);
+      g_value_unset(&value);
+
+      if(line_member->conversion != NULL){
+	peak = ags_conversion_convert(line_member->conversion,
+				      peak,
+				      TRUE);
+      }
+
+      /* calculate peak */
+      if(range == 0.0 ||
+	 current->port_value_type == G_TYPE_BOOLEAN){
+	if(peak != 0.0){
+	  average_peak = 10.0;
+	}
+      }else{
+	average_peak += ((1.0 / (range / peak)) * 10.0);
+      }
+
+      /* recall port */
+      current = line_member->recall_port;
+
+      /* recall port - read value */
+      g_value_init(&value, G_TYPE_FLOAT);
+      ags_port_safe_read(current,
+			 &value);
+      
+      peak = g_value_get_float(&value);
+      g_value_unset(&value);
+      
+      if(line_member->conversion != NULL){
+	peak = ags_conversion_convert(line_member->conversion,
+				      peak,
+				      TRUE);
+      }
+
+      /* calculate peak */
+      if(range == 0.0 ||
+	 current->port_value_type == G_TYPE_BOOLEAN){
+	if(peak != 0.0){
+	  average_peak = 10.0;
+	}
+      }else{
+	average_peak += ((1.0 / (range / peak)) * 10.0);
+      }
+      
+      /* apply */
+      if(AGS_IS_LED(child)){
+	if(average_peak != 0.0){
+	  ags_led_set_active(child);
+	}
+      }else{
+	g_object_get(child,
+		     "adjustment\0", &adjustment,
+		     NULL);
+	
+	gtk_adjustment_set_value(adjustment,
+				 average_peak);
+      }
+    }
+    
+    list = list->next;
+  }
+
+  g_list_free(list_start);
+
   /* unlock gdk threads */
   gdk_threads_leave();
 }
diff --git a/ags/X/ags_effect_line_callbacks.h b/ags/X/ags_effect_line_callbacks.h
index d59d987..df2c3c2 100644
--- a/ags/X/ags_effect_line_callbacks.h
+++ b/ags/X/ags_effect_line_callbacks.h
@@ -38,4 +38,7 @@ void ags_effect_line_remove_effect_callback(AgsChannel *channel,
 					    guint nth,
 					    AgsEffectLine *effect_line);
 
+void ags_effect_line_output_port_run_post_callback(AgsRecall *recall,
+						   AgsEffectLine *effect_line);
+
 #endif /*__AGS_EFFECT_LINE_CALLBACKS_H__*/
diff --git a/ags/X/ags_effect_pad.c b/ags/X/ags_effect_pad.c
index ce891f6..4933ec7 100644
--- a/ags/X/ags_effect_pad.c
+++ b/ags/X/ags_effect_pad.c
@@ -402,6 +402,9 @@ ags_effect_pad_disconnect(AgsConnectable *connectable)
   }
 
   g_list_free(effect_line_list_start);
+
+  g_signal_handlers_disconnect_by_data(effect_pad->channel,
+				       effect_pad);
 }
 
 gchar*
diff --git a/ags/X/ags_export_soundcard_callbacks.c b/ags/X/ags_export_soundcard_callbacks.c
index 113d1d8..ad728c0 100644
--- a/ags/X/ags_export_soundcard_callbacks.c
+++ b/ags/X/ags_export_soundcard_callbacks.c
@@ -61,12 +61,16 @@ ags_export_soundcard_backend_callback(GtkWidget *combo_box,
   soundcard = NULL;
 
   if(application_context != NULL){
-    soundcard = ags_sound_provider_get_soundcard(AGS_SOUNDCARD(application_context));
+    soundcard = ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context));
   }
 
   backend = gtk_combo_box_text_get_active_text(export_soundcard->backend);
   device = gtk_combo_box_text_get_active_text(export_soundcard->card);
 
+  if(device == NULL){
+    return;
+  }
+  
   found_card = FALSE;
   
   while(soundcard != NULL){
@@ -154,12 +158,16 @@ ags_export_soundcard_card_callback(GtkWidget *combo_box,
   soundcard = NULL;
     
   if(application_context != NULL){
-    soundcard = ags_sound_provider_get_soundcard(AGS_SOUNDCARD(application_context));
+    soundcard = ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context));
   }
 
   backend = gtk_combo_box_text_get_active_text(export_soundcard->backend);
   device = gtk_combo_box_text_get_active_text(export_soundcard->card);
 
+  if(device == NULL){
+    return;
+  }
+  
   found_card = FALSE;
 
   while(soundcard != NULL){
diff --git a/ags/X/ags_export_window.c b/ags/X/ags_export_window.c
index 2c7129c..00a84bd 100644
--- a/ags/X/ags_export_window.c
+++ b/ags/X/ags_export_window.c
@@ -598,6 +598,10 @@ ags_export_window_reload_soundcard_editor(AgsExportWindow *export_window)
   main_window = export_window->main_window;
 
   application_context = export_window->application_context;
+
+  if(application_context == NULL){
+    return;
+  }
   
   /* retrieve soundcard */
   pthread_mutex_lock(application_mutex);
diff --git a/ags/X/ags_export_window_callbacks.c b/ags/X/ags_export_window_callbacks.c
index c86152d..52488d3 100644
--- a/ags/X/ags_export_window_callbacks.c
+++ b/ags/X/ags_export_window_callbacks.c
@@ -105,6 +105,8 @@ ags_export_window_tact_callback(GtkWidget *spin_button,
 
   AgsMutexManager *mutex_manager;
 
+  gchar *str;
+  
   gdouble delay_factor;
   gdouble delay;
 
@@ -134,11 +136,13 @@ ags_export_window_tact_callback(GtkWidget *spin_button,
   pthread_mutex_unlock(soundcard_mutex);
 
   /* update duration */
+  str = ags_time_get_uptime_from_offset(gtk_spin_button_get_value(export_window->tact) * 16.0,
+					window->navigation->bpm->adjustment->value,
+					delay,
+					delay_factor);
   gtk_label_set_text(export_window->duration,
-		     ags_time_get_uptime_from_offset(gtk_spin_button_get_value(export_window->tact) * 16.0,
-						     window->navigation->bpm->adjustment->value,
-						     delay,
-						     delay_factor));
+		     str);
+  g_free(str);
 }
 
 void
diff --git a/ags/X/ags_generic_preferences.c b/ags/X/ags_generic_preferences.c
index a73fc1a..6842e3b 100644
--- a/ags/X/ags_generic_preferences.c
+++ b/ags/X/ags_generic_preferences.c
@@ -140,6 +140,7 @@ ags_generic_preferences_init(AgsGenericPreferences *generic_preferences)
 		     FALSE, FALSE,
 		     0);
 
+  /* segmentation */
   hbox = (GtkHBox *) gtk_hbox_new(FALSE,
 				  0);
   gtk_box_pack_start(GTK_BOX(generic_preferences),
@@ -162,6 +163,33 @@ ags_generic_preferences_init(AgsGenericPreferences *generic_preferences)
 		     GTK_WIDGET(generic_preferences->segmentation),
 		     FALSE, FALSE,
 		     0);
+
+  /* engine mode */
+  hbox = (GtkHBox *) gtk_hbox_new(FALSE,
+				  0);
+  gtk_box_pack_start(GTK_BOX(generic_preferences),
+		     GTK_WIDGET(hbox),
+		     FALSE, FALSE,
+		     0);
+
+  label = (GtkLabel *) gtk_label_new("engine mode\0");
+  gtk_box_pack_start(GTK_BOX(hbox),
+		     GTK_WIDGET(label),
+		     FALSE, FALSE,
+		     0);
+
+  generic_preferences->engine_mode = (GtkComboBoxText *) gtk_combo_box_text_new();
+  gtk_combo_box_text_append_text(generic_preferences->engine_mode,
+				 "deterministic\0");
+  gtk_combo_box_text_append_text(generic_preferences->engine_mode,
+				 "performance\0");
+  gtk_combo_box_set_active(GTK_COMBO_BOX(generic_preferences->engine_mode),
+			   1);
+  
+  gtk_box_pack_start(GTK_BOX(hbox),
+		     GTK_WIDGET(generic_preferences->engine_mode),
+		     FALSE, FALSE,
+		     0);
 }
 
 void
@@ -191,7 +219,12 @@ ags_generic_preferences_apply(AgsApplicable *applicable)
   generic_preferences = AGS_GENERIC_PREFERENCES(applicable);
 
   config = ags_config_get_instance();
-  
+
+  ags_config_set_value(config,
+		       AGS_CONFIG_GENERIC,
+		       "disable-feature\0",
+		       "experimental\0");
+
   if(gtk_toggle_button_get_active((GtkToggleButton *) generic_preferences->autosave_thread)){
     ags_config_set_value(config,
 			 AGS_CONFIG_GENERIC,
@@ -208,6 +241,11 @@ ags_generic_preferences_apply(AgsApplicable *applicable)
 		       AGS_CONFIG_GENERIC,
 		       "segmentation\0",
 		       gtk_combo_box_text_get_active_text(generic_preferences->segmentation));
+
+  ags_config_set_value(config,
+		       AGS_CONFIG_GENERIC,
+		       "engine-mode\0",
+		       gtk_combo_box_text_get_active_text(generic_preferences->engine_mode));
 }
 
 void
diff --git a/ags/X/ags_generic_preferences.h b/ags/X/ags_generic_preferences.h
index f63ac28..9de8b25 100644
--- a/ags/X/ags_generic_preferences.h
+++ b/ags/X/ags_generic_preferences.h
@@ -47,6 +47,8 @@ struct _AgsGenericPreferences
   GtkComboBox *audio_output_module;
 
   GtkComboBoxText *segmentation;
+
+  GtkComboBoxText *engine_mode;
 };
 
 struct _AgsGenericPreferencesClass
diff --git a/ags/X/ags_ladspa_browser.c b/ags/X/ags_ladspa_browser.c
index 000cbbc..9ede857 100644
--- a/ags/X/ags_ladspa_browser.c
+++ b/ags/X/ags_ladspa_browser.c
@@ -357,6 +357,58 @@ ags_ladspa_browser_get_plugin_effect(AgsLadspaBrowser *ladspa_browser)
 }
 
 /**
+ * ags_ladspa_browser_combo_box_output_boolean_controls_new:
+ *
+ * Creates a #GtkComboBox containing suitable widgets as controls.
+ *
+ * Returns: a new #GtkComboBox
+ *
+ * Since: 0.7.128
+ */
+GtkWidget*
+ags_ladspa_browser_combo_box_output_boolean_controls_new()
+{
+  GtkComboBoxText *combo_box;
+
+  combo_box = (GtkComboBoxText *) gtk_combo_box_text_new();
+
+  gtk_combo_box_text_append_text(combo_box,
+				 "led\0");
+
+  gtk_combo_box_set_active((GtkComboBox *) combo_box,
+			   1);
+
+  return((GtkWidget *) combo_box);
+}
+
+/**
+ * ags_ladspa_browser_combo_box_controls_new:
+ *
+ * Creates a #GtkComboBox containing suitable widgets as controls.
+ *
+ * Returns: a new #GtkComboBox
+ *
+ * Since: 0.7.128
+ */
+GtkWidget*
+ags_ladspa_browser_combo_box_output_controls_new()
+{
+  GtkComboBoxText *combo_box;
+
+  combo_box = (GtkComboBoxText *) gtk_combo_box_text_new();
+
+  gtk_combo_box_text_append_text(combo_box,
+				 "vertical indicator\0");
+  gtk_combo_box_text_append_text(combo_box,
+				 "horizontal indicator\0");
+
+  gtk_combo_box_set_active((GtkComboBox *) combo_box,
+			   1);
+
+  return((GtkWidget *) combo_box);
+}
+
+/**
  * ags_ladspa_browser_combo_box_boolean_controls_new:
  *
  * Creates a #GtkComboBox containing suitable widgets as controls.
diff --git a/ags/X/ags_ladspa_browser.h b/ags/X/ags_ladspa_browser.h
index 6b793a0..02d5374 100644
--- a/ags/X/ags_ladspa_browser.h
+++ b/ags/X/ags_ladspa_browser.h
@@ -56,8 +56,12 @@ GType ags_ladspa_browser_get_type(void);
 gchar* ags_ladspa_browser_get_plugin_filename(AgsLadspaBrowser *ladspa_browser);
 gchar* ags_ladspa_browser_get_plugin_effect(AgsLadspaBrowser *ladspa_browser);
 
+GtkWidget* ags_ladspa_browser_combo_box_output_boolean_controls_new();
+GtkWidget* ags_ladspa_browser_combo_box_output_controls_new();
+
 GtkWidget* ags_ladspa_browser_combo_box_boolean_controls_new();
 GtkWidget* ags_ladspa_browser_combo_box_controls_new();
+
 GtkWidget* ags_ladspa_browser_preview_new();
 
 AgsLadspaBrowser* ags_ladspa_browser_new();
diff --git a/ags/X/ags_ladspa_browser_callbacks.c b/ags/X/ags_ladspa_browser_callbacks.c
index 7060150..ff279b8 100644
--- a/ags/X/ags_ladspa_browser_callbacks.c
+++ b/ags/X/ags_ladspa_browser_callbacks.c
@@ -180,15 +180,29 @@ ags_ladspa_browser_plugin_effect_callback(GtkComboBoxText *combo_box,
 				  y, y + 1);
 
 	if(LADSPA_IS_HINT_TOGGLED(plugin_descriptor->PortRangeHints[i].HintDescriptor)){
-	  gtk_table_attach_defaults(table,
-				    GTK_WIDGET(ags_ladspa_browser_combo_box_boolean_controls_new()),
-				    1, 2,
-				    y, y + 1);
+	  if(LADSPA_IS_PORT_OUTPUT(port_descriptor[i])){
+	    gtk_table_attach_defaults(table,
+				      GTK_WIDGET(ags_ladspa_browser_combo_box_output_boolean_controls_new()),
+				      1, 2,
+				      y, y + 1);
+	  }else{
+	    gtk_table_attach_defaults(table,
+				      GTK_WIDGET(ags_ladspa_browser_combo_box_boolean_controls_new()),
+				      1, 2,
+				      y, y + 1);
+	  }
 	}else{
-	  gtk_table_attach_defaults(table,
-				    GTK_WIDGET(ags_ladspa_browser_combo_box_controls_new()),
-				    1, 2,
-				    y, y + 1);
+	  if(LADSPA_IS_PORT_OUTPUT(port_descriptor[i])){
+	    gtk_table_attach_defaults(table,
+				      GTK_WIDGET(ags_ladspa_browser_combo_box_output_controls_new()),
+				      1, 2,
+				      y, y + 1);
+	  }else{
+	    gtk_table_attach_defaults(table,
+				      GTK_WIDGET(ags_ladspa_browser_combo_box_controls_new()),
+				      1, 2,
+				      y, y + 1);
+	  }
 	}
 	
 	y++;
diff --git a/ags/X/ags_line.c b/ags/X/ags_line.c
index 130e376..0f910a5 100644
--- a/ags/X/ags_line.c
+++ b/ags/X/ags_line.c
@@ -43,11 +43,15 @@
 #include <ags/audio/ags_channel.h>
 #include <ags/audio/ags_output.h>
 #include <ags/audio/ags_input.h>
+#include <ags/audio/ags_recall_container.h>
 #include <ags/audio/ags_recall_ladspa.h>
 #include <ags/audio/ags_recall_lv2.h>
 
 #include <ags/audio/recall/ags_peak_channel_run.h>
 
+#include <ags/widget/ags_led.h>
+#include <ags/widget/ags_vindicator.h>
+#include <ags/widget/ags_hindicator.h>
 #include <ags/widget/ags_dial.h>
 
 #include <ags/X/ags_window.h>
@@ -128,7 +132,7 @@ enum{
 static gpointer ags_line_parent_class = NULL;
 static guint line_signals[LAST_SIGNAL];
 
-GHashTable *ags_indicator_queue_draw = NULL;
+GHashTable *ags_line_indicator_queue_draw = NULL;
 
 GType
 ags_line_get_type(void)
@@ -385,8 +389,8 @@ ags_line_plugin_interface_init(AgsPluginInterface *plugin)
 void
 ags_line_init(AgsLine *line)
 {
-  if(ags_indicator_queue_draw == NULL){
-    ags_indicator_queue_draw = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+  if(ags_line_indicator_queue_draw == NULL){
+    ags_line_indicator_queue_draw = g_hash_table_new_full(g_direct_hash, g_direct_equal,
 						     NULL,
 						     NULL);
   }
@@ -436,14 +440,27 @@ void
 ags_line_finalize(GObject *gobject)
 {
   AgsLine *line;
-
-  line = AGS_LINE(gobject);
+  GList *list;
   
+  line = AGS_LINE(gobject);
+
+  /* remove indicator widget */
   if(line->indicator != NULL){
-    g_hash_table_remove(ags_indicator_queue_draw,
+    g_hash_table_remove(ags_line_indicator_queue_draw,
 			line->indicator);
   }
-  
+
+  /* remove of the queued drawing hash */
+  list = line->queued_drawing;
+
+  while(list != NULL){
+    g_hash_table_remove(ags_line_indicator_queue_draw,
+			list->data);
+
+    list = list->next;
+  }
+
+  /* call parent */
   G_OBJECT_CLASS(ags_line_parent_class)->finalize(gobject);
 }
 
@@ -586,11 +603,14 @@ ags_line_disconnect(AgsConnectable *connectable)
 #endif
 
   /* disconnect group button */
-  g_object_disconnect((GObject *) line->group,
-		      "clicked\0",
-		      G_CALLBACK(ags_line_group_clicked_callback),
-		      (gpointer) line,
-		      NULL);
+  if(line->group != NULL &&
+     GTK_IS_BUTTON(line->group)){
+    g_object_disconnect(line->group,
+			"clicked\0",
+			G_CALLBACK(ags_line_group_clicked_callback),
+			(gpointer) line,
+			NULL);
+  }
 
   /* disconnect line members */
   list_start = 
@@ -607,6 +627,9 @@ ags_line_disconnect(AgsConnectable *connectable)
   if(list_start != NULL){
     g_list_free(list_start);
   }
+
+  g_signal_handlers_disconnect_by_data(line->channel,
+				       line);
 }
 
 gchar*
@@ -741,11 +764,12 @@ ags_line_add_ladspa_effect(AgsLine *line,
 			   gchar *effect)
 {
   AgsLineMember *line_member;
+  GtkSeparator *separator;
   GtkAdjustment *adjustment;
 
-  AgsLadspaPlugin *ladspa_plugin;
+  AgsRecallHandler *recall_handler;
 
-  AgsMutexManager *mutex_manager;
+  AgsLadspaPlugin *ladspa_plugin;
 
   GList *list;
   GList *recall, *recall_start;
@@ -754,16 +778,17 @@ ags_line_add_ladspa_effect(AgsLine *line,
 
   gdouble step;
   guint port_count;
+
   guint x, y;
   guint k;
-
-  pthread_mutex_t *application_mutex;
-  pthread_mutex_t *channel_mutex;
   
   /* load plugin */
   ladspa_plugin = ags_ladspa_manager_find_ladspa_plugin(ags_ladspa_manager_get_instance(),
 							filename, effect);
-  
+
+  port = NULL;
+  recall_port = NULL;
+    
   /* retrieve position within table  */
   x = 0;
   y = 0;
@@ -778,47 +803,30 @@ ags_line_add_ladspa_effect(AgsLine *line,
     list = list->next;
   }
 
-  /* get mutex manager and application mutex */
-  mutex_manager = ags_mutex_manager_get_instance();
-  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
-
-  /* get channel mutex */
-  pthread_mutex_lock(application_mutex);
-
-  channel_mutex = ags_mutex_manager_lookup(mutex_manager,
-					   (GObject *) line->channel);
-  
-  pthread_mutex_unlock(application_mutex);
-  
-  /* find ports */
-  pthread_mutex_lock(channel_mutex);
-  
-  recall_start =
-    recall = ags_recall_get_by_effect(line->channel->play,
-				      filename,
-				      effect);
-  recall = g_list_last(recall);
-  port = AGS_RECALL(recall->data)->port;
-
-  g_list_free(recall_start);
-
-  recall_start = 
-    recall = ags_recall_get_by_effect(line->channel->recall,
-				      filename,
-				      effect);
-  recall = g_list_last(recall);
-
-  recall_port = AGS_RECALL(recall->data)->port;
-  g_list_free(recall_start);
-
-  pthread_mutex_unlock(channel_mutex);
+  /* add separator */
+  separator = gtk_hseparator_new();
+  gtk_widget_set_size_request(separator,
+			      120, -1);
+  g_object_set_data(separator,
+		    AGS_LINE_SEPARATOR_FILENAME,
+		    filename);
+  g_object_set_data(separator,
+		    AGS_LINE_SEPARATOR_EFFECT,
+		    effect);
+  ags_expander_add(line->expander,
+		   (GtkWidget *) separator,
+		   0, y,
+		   AGS_LINE_COLUMNS_COUNT, 1);
+  gtk_widget_show(separator);
+
+  y++;
   
   /* load ports */
   port_descriptor = AGS_BASE_PLUGIN(ladspa_plugin)->port;
 
   port_count = g_list_length(port_descriptor);
   k = 0;
-
+  
   while(port_descriptor != NULL){
     if((AGS_PORT_DESCRIPTOR_CONTROL & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
       GtkWidget *child_widget;
@@ -828,11 +836,24 @@ ags_line_add_ladspa_effect(AgsLine *line,
       GType widget_type;
 
       guint step_count;
+      gboolean disable_seemless;
+
+      disable_seemless = FALSE;
       
       if((AGS_PORT_DESCRIPTOR_TOGGLED & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
-	widget_type = GTK_TYPE_TOGGLE_BUTTON;
+	disable_seemless = TRUE;
+	
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  widget_type = AGS_TYPE_LED;
+	}else{
+	  widget_type = GTK_TYPE_TOGGLE_BUTTON;
+	}
       }else{
-	widget_type = AGS_TYPE_DIAL;
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  widget_type = AGS_TYPE_HINDICATOR;
+	}else{
+	  widget_type = AGS_TYPE_DIAL;
+	}
       }
 
       if(control_type_name != NULL){
@@ -845,6 +866,7 @@ ags_line_add_ladspa_effect(AgsLine *line,
 
       if((AGS_PORT_DESCRIPTOR_INTEGER & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
 	step_count = AGS_PORT_DESCRIPTOR(port_descriptor->data)->scale_steps;
+	disable_seemless = TRUE;
       }
       
       /* add line member */
@@ -918,6 +940,10 @@ ags_line_add_ladspa_effect(AgsLine *line,
 	
 	dial = (AgsDial *) child_widget;
 
+	if(disable_seemless){
+	  dial->flags &= (~AGS_DIAL_SEEMLESS_MODE);
+	}
+	
 	/* add controls of ports and apply range  */
 	lower_bound = g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->lower_value);
 	upper_bound = g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->upper_value);
@@ -943,21 +969,32 @@ ags_line_add_ladspa_effect(AgsLine *line,
 				 upper_bound);
 	gtk_adjustment_set_value(adjustment,
 				 g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->default_value));
+      }else if(AGS_IS_INDICATOR(child_widget) ||
+	       AGS_IS_LED(child_widget)){
+	g_hash_table_insert(ags_line_indicator_queue_draw,
+			    child_widget, ags_line_indicator_queue_draw_timeout);
+	line->queued_drawing = g_list_prepend(line->queued_drawing,
+					      child_widget);
+	g_timeout_add(1000 / 30, (GSourceFunc) ags_line_indicator_queue_draw_timeout, (gpointer) child_widget);
       }
-
+      
 #ifdef AGS_DEBUG
       g_message("ladspa bounds: %f %f\0", lower_bound, upper_bound);
 #endif
 	  
       ags_expander_add(line->expander,
 		       (GtkWidget *) line_member,
-		       x, y,
+		       x % AGS_LINE_COLUMNS_COUNT, y,
 		       1, 1);
       ags_connectable_connect(AGS_CONNECTABLE(line_member));
       gtk_widget_show_all((GtkWidget *) line_member);
       
-      port = port->next;
+      //      port = port->next;
       x++;
+
+      if(x % AGS_LINE_COLUMNS_COUNT == 0){
+	y++;
+      }
     }
 
     port_descriptor = port_descriptor->next;
@@ -975,8 +1012,11 @@ ags_line_add_lv2_effect(AgsLine *line,
 			gchar *effect)
 {
   AgsLineMember *line_member;
+  GtkSeparator *separator;
   GtkAdjustment *adjustment;
 
+  AgsRecallHandler *recall_handler;
+
   AgsLv2Plugin *lv2_plugin;
 
   AgsMutexManager *mutex_manager;
@@ -991,6 +1031,7 @@ ags_line_add_lv2_effect(AgsLine *line,
 
   gdouble step;
   guint port_count;
+
   guint x, y;
   guint k;
   
@@ -1001,6 +1042,9 @@ ags_line_add_lv2_effect(AgsLine *line,
   lv2_plugin = ags_lv2_manager_find_lv2_plugin(ags_lv2_manager_get_instance(),
 					       filename, effect);
 
+  port = NULL;
+  recall_port = NULL;
+  
   /* retrieve position within table  */
   x = 0;
   y = 0;
@@ -1015,47 +1059,23 @@ ags_line_add_lv2_effect(AgsLine *line,
     list = list->next;
   }
 
-  /* get mutex manager and application mutex */
-  mutex_manager = ags_mutex_manager_get_instance();
-  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
-
-  /* get channel mutex */
-  pthread_mutex_lock(application_mutex);
-
-  channel_mutex = ags_mutex_manager_lookup(mutex_manager,
-					   (GObject *) line->channel);
-  
-  pthread_mutex_unlock(application_mutex);
-  
-  /* find ports */
-  pthread_mutex_lock(channel_mutex);
-  
-  recall_start =
-    recall = ags_recall_get_by_effect(line->channel->play,
-				      filename,
-				      effect);
-
-  if(recall == NULL){
-    pthread_mutex_unlock(channel_mutex);
-    
-    return(NULL);
-  }
-  
-  recall = g_list_last(recall);
-  port = AGS_RECALL(recall->data)->port;
-
-  g_list_free(recall_start);
-
-  recall_start = 
-    recall = ags_recall_get_by_effect(line->channel->recall,
-				      filename,
-				      effect);
-  recall = g_list_last(recall);
-
-  recall_port = AGS_RECALL(recall->data)->port;
-  g_list_free(recall_start);
-
-  pthread_mutex_unlock(channel_mutex);
+  /* add separator */
+  separator = gtk_hseparator_new();
+  gtk_widget_set_size_request(separator,
+			      120, -1);
+  g_object_set_data(separator,
+		    AGS_LINE_SEPARATOR_FILENAME,
+		    filename);
+  g_object_set_data(separator,
+		    AGS_LINE_SEPARATOR_EFFECT,
+		    effect);
+  ags_expander_add(line->expander,
+		   (GtkWidget *) separator,
+		   0, y,
+		   AGS_LINE_COLUMNS_COUNT, 1);
+  gtk_widget_show(separator);
+
+  y++;
   
   /* load ports */
   port_descriptor = AGS_BASE_PLUGIN(lv2_plugin)->port;
@@ -1063,8 +1083,7 @@ ags_line_add_lv2_effect(AgsLine *line,
   port_count = g_list_length(port_descriptor);
   k = 0;
   
-  while(port_descriptor != NULL &&
-	port != NULL){
+  while(port_descriptor != NULL){
     if((AGS_PORT_DESCRIPTOR_CONTROL & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
       GtkWidget *child_widget;
 
@@ -1073,11 +1092,24 @@ ags_line_add_lv2_effect(AgsLine *line,
       GType widget_type;
 
       guint step_count;
+      gboolean disable_seemless;
+
+      disable_seemless = FALSE;
       
       if((AGS_PORT_DESCRIPTOR_TOGGLED & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
-	widget_type = GTK_TYPE_TOGGLE_BUTTON;
+	disable_seemless = TRUE;
+	
+      	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  widget_type = AGS_TYPE_LED;
+	}else{
+	  widget_type = GTK_TYPE_TOGGLE_BUTTON;
+	}
       }else{
-	widget_type = AGS_TYPE_DIAL;
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  widget_type = AGS_TYPE_HINDICATOR;
+	}else{
+	  widget_type = AGS_TYPE_DIAL;
+	}
       }
 
       if(control_type_name != NULL){
@@ -1090,6 +1122,8 @@ ags_line_add_lv2_effect(AgsLine *line,
 
       if((AGS_PORT_DESCRIPTOR_INTEGER & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
 	step_count = AGS_PORT_DESCRIPTOR(port_descriptor->data)->scale_steps;
+
+	disable_seemless = TRUE;
       }
 
       /* add line member */
@@ -1138,6 +1172,10 @@ ags_line_add_lv2_effect(AgsLine *line,
 	
 	dial = (AgsDial *) child_widget;
 
+	if(disable_seemless){
+	  dial->flags &= (~AGS_DIAL_SEEMLESS_MODE);
+	}
+	
 	/* add controls of ports and apply range  */
 	lower_bound = g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->lower_value);
 	upper_bound = g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->upper_value);
@@ -1163,6 +1201,12 @@ ags_line_add_lv2_effect(AgsLine *line,
 				 upper_bound);
 	gtk_adjustment_set_value(adjustment,
 				 g_value_get_float(AGS_PORT_DESCRIPTOR(port_descriptor->data)->default_value));
+      }else if(AGS_IS_INDICATOR(child_widget)){
+	g_hash_table_insert(ags_line_indicator_queue_draw,
+			    child_widget, ags_line_indicator_queue_draw_timeout);
+	line->queued_drawing = g_list_prepend(line->queued_drawing,
+					      child_widget);
+	g_timeout_add(1000 / 30, (GSourceFunc) ags_line_indicator_queue_draw_timeout, (gpointer) child_widget);
       }
 
 #ifdef AGS_DEBUG
@@ -1171,13 +1215,17 @@ ags_line_add_lv2_effect(AgsLine *line,
 
       ags_expander_add(line->expander,
 		       (GtkWidget *) line_member,
-		       x, y,
+		       x % AGS_LINE_COLUMNS_COUNT, y,
 		       1, 1);      
       ags_connectable_connect(AGS_CONNECTABLE(line_member));
       gtk_widget_show_all((GtkWidget *) line_member);
 
-      port = port->next;
+      //      port = port->next;
       x++;
+
+      if(x % AGS_LINE_COLUMNS_COUNT == 0){
+	y++;
+      }
     }
 
     port_descriptor = port_descriptor->next;
@@ -1275,11 +1323,12 @@ ags_line_real_remove_effect(AgsLine *line,
   
   AgsMutexManager *mutex_manager;
 
-  GList *control;
+  GList *control, *control_start;
   GList *recall;
   GList *port;
 
   gchar **remove_specifier;
+  gchar *filename, *effect;
   
   guint nth_effect, n_bulk;
   guint i;
@@ -1336,6 +1385,39 @@ ags_line_real_remove_effect(AgsLine *line,
   }
   
   nth_effect--;
+
+  /* destroy separator */
+  filename = NULL;
+  effect = NULL;
+  
+  if(AGS_IS_RECALL_LV2(recall->data)){
+    filename = AGS_RECALL_LV2(recall->data)->filename;
+    effect = AGS_RECALL_LV2(recall->data)->effect;
+  }else if(AGS_IS_RECALL_LADSPA(recall->data)){
+    filename = AGS_RECALL_LADSPA(recall->data)->filename;
+    effect = AGS_RECALL_LADSPA(recall->data)->effect;
+  }
+  
+  control_start =
+    control = gtk_container_get_children((GtkContainer *) line->expander->table);
+
+  while(control != NULL){
+    if(GTK_IS_SEPARATOR(control->data) &&
+       !strcmp(filename,
+	       g_object_get_data(control->data,
+				 AGS_LINE_SEPARATOR_FILENAME)) &&
+       !strcmp(effect,
+	       g_object_get_data(control->data,
+				 AGS_LINE_SEPARATOR_EFFECT))){
+      gtk_widget_destroy(control->data);
+      
+      break;
+    }
+
+    control->next;
+  }
+  
+  g_list_free(control_start);
   
   /* destroy controls */
   port = AGS_RECALL(recall->data)->port;
@@ -1343,11 +1425,16 @@ ags_line_real_remove_effect(AgsLine *line,
   i = 0;
   
   while(port != NULL){
-    control = gtk_container_get_children((GtkContainer *) line->expander->table);
+    control_start =
+      control = gtk_container_get_children((GtkContainer *) line->expander->table);
       
     while(control != NULL){
       if(AGS_IS_LINE_MEMBER(control->data) &&
 	 AGS_LINE_MEMBER(control->data)->port == port->data){
+	GtkWidget *child_widget;
+	
+	child_widget = gtk_bin_get_child(control->data);
+
 	/* collect specifier */
 	if(remove_specifier == NULL){
 	  remove_specifier = (gchar **) malloc(2 * sizeof(gchar *));
@@ -1360,6 +1447,12 @@ ags_line_real_remove_effect(AgsLine *line,
 	i++;
 
 	/* remove widget */
+	if(AGS_IS_LED(child_widget) ||
+	   AGS_IS_INDICATOR(child_widget)){
+	  g_hash_table_remove(ags_line_indicator_queue_draw,
+			      child_widget);
+	}
+	
 	ags_expander_remove(line->expander,
 			    control->data);
 
@@ -1368,7 +1461,9 @@ ags_line_real_remove_effect(AgsLine *line,
 	
       control = control->next;
     }
-      
+
+    g_list_free(control_start);
+    
     port = port->next;
   }
 
@@ -1544,8 +1639,156 @@ ags_line_find_next_grouped(GList *line)
 gboolean
 ags_line_indicator_queue_draw_timeout(GtkWidget *widget)
 {
-  if(g_hash_table_lookup(ags_indicator_queue_draw,
-			 widget) != NULL){
+  AgsLine *line;
+
+  if(g_hash_table_lookup(ags_line_indicator_queue_draw,
+			 widget) != NULL){      
+    GList *list, *list_start;
+    
+    line = gtk_widget_get_ancestor(widget,
+				   AGS_TYPE_LINE);
+  
+    list_start = 
+      list = gtk_container_get_children((GtkContainer *) AGS_LINE(line)->expander->table);
+    
+    /* check members */
+    while(list != NULL){
+      if(AGS_IS_LINE_MEMBER(list->data) &&
+	 (AGS_LINE_MEMBER(list->data)->widget_type == AGS_TYPE_VINDICATOR ||
+	  AGS_LINE_MEMBER(list->data)->widget_type == AGS_TYPE_HINDICATOR ||
+	  AGS_LINE_MEMBER(list->data)->widget_type == AGS_TYPE_LED)){
+	AgsLineMember *line_member;
+	GtkAdjustment *adjustment;
+	GtkWidget *child;
+
+	AgsPort *current;
+	
+	gdouble average_peak;
+	gdouble lower, upper;
+	gdouble range;
+	gdouble peak;
+
+	GValue value = {0,};
+
+	line_member = AGS_LINE_MEMBER(list->data);
+	child = GTK_BIN(line_member)->child;
+      
+	average_peak = 0.0;
+      
+	/* play port */
+	current = line_member->port;
+
+	if(current == NULL){
+	  list = list->next;
+	
+	  continue;
+	}
+	
+	/* check if output port and specifier matches */
+	pthread_mutex_lock(current->mutex);
+      
+	if((AGS_PORT_IS_OUTPUT & (current->flags)) == 0 ||
+	   current->port_descriptor == NULL ||
+	   g_ascii_strcasecmp(current->specifier,
+			      line_member->specifier)){
+	  pthread_mutex_unlock(current->mutex);
+	
+	  list = list->next;
+	
+	  continue;
+	}
+
+	/* lower and upper */
+	lower = g_value_get_float(AGS_PORT_DESCRIPTOR(current->port_descriptor)->lower_value);
+	upper = g_value_get_float(AGS_PORT_DESCRIPTOR(current->port_descriptor)->upper_value);
+      
+	pthread_mutex_unlock(current->mutex);
+
+	/* get range */
+	if(line_member->conversion != NULL){
+	  lower = ags_conversion_convert(line_member->conversion,
+					 lower,
+					 TRUE);
+
+	  upper = ags_conversion_convert(line_member->conversion,
+					 upper,
+					 TRUE);
+	}
+      
+	range = upper - lower;
+      
+	/* play port - read value */
+	g_value_init(&value, G_TYPE_FLOAT);
+	ags_port_safe_read(current,
+			   &value);
+      
+	peak = g_value_get_float(&value);
+	g_value_unset(&value);
+
+	if(line_member->conversion != NULL){
+	  peak = ags_conversion_convert(line_member->conversion,
+					peak,
+					TRUE);
+	}
+      
+	/* calculate peak */
+	if(range == 0.0 ||
+	   current->port_value_type == G_TYPE_BOOLEAN){
+	  if(peak != 0.0){
+	    average_peak = 10.0;
+	  }
+	}else{
+	  average_peak += ((1.0 / (range / peak)) * 10.0);
+	}
+
+	/* recall port */
+	current = line_member->recall_port;
+
+	/* recall port - read value */
+	g_value_init(&value, G_TYPE_FLOAT);
+	ags_port_safe_read(current,
+			   &value);
+      
+	peak = g_value_get_float(&value);
+	g_value_unset(&value);
+
+	if(line_member->conversion != NULL){
+	  peak = ags_conversion_convert(line_member->conversion,
+					peak,
+					TRUE);
+	}
+
+	/* calculate peak */
+	if(range == 0.0 ||
+	   current->port_value_type == G_TYPE_BOOLEAN){
+	  if(peak != 0.0){
+	    average_peak = 10.0;
+	  }
+	}else{
+	  average_peak += ((1.0 / (range / peak)) * 10.0);
+	}
+      
+	/* apply */
+	if(AGS_IS_LED(child)){
+	  if(average_peak != 0.0){
+	    ags_led_set_active(child);
+	  }
+	}else{
+	  g_object_get(child,
+		       "adjustment\0", &adjustment,
+		       NULL);
+	
+	  gtk_adjustment_set_value(adjustment,
+				   average_peak);
+	}
+      }
+    
+      list = list->next;
+    }
+
+    g_list_free(list_start);
+
+    /* queue draw */
     gtk_widget_queue_draw(widget);
     
     return(TRUE);
diff --git a/ags/X/ags_line.h b/ags/X/ags_line.h
index a78041f..3285639 100644
--- a/ags/X/ags_line.h
+++ b/ags/X/ags_line.h
@@ -37,7 +37,10 @@
 
 #define AGS_LINE_DEFAULT_VERSION "0.7.0\0"
 #define AGS_LINE_DEFAULT_BUILD_ID "CEST 31-10-2015 19:49\0"
+
 #define AGS_LINE_COLUMNS_COUNT (2)
+#define AGS_LINE_SEPARATOR_FILENAME "ags-line-separator-filename\0"
+#define AGS_LINE_SEPARATOR_EFFECT "ags-line-separator-effect\0"
 
 typedef struct _AgsLine AgsLine;
 typedef struct _AgsLineClass AgsLineClass;
@@ -72,6 +75,8 @@ struct _AgsLine
   AgsExpander *expander;
 
   GtkWidget *indicator;
+
+  GList *queued_drawing;
 };
 
 struct _AgsLineClass
diff --git a/ags/X/ags_line_callbacks.c b/ags/X/ags_line_callbacks.c
index 59a7040..45e5172 100644
--- a/ags/X/ags_line_callbacks.c
+++ b/ags/X/ags_line_callbacks.c
@@ -23,7 +23,8 @@
 #include <ags/object/ags_soundcard.h>
 
 #include <ags/thread/ags_mutex_manager.h>
-#include <ags/thread/ags_task_thread.h>
+
+#include <ags/plugin/ags_base_plugin.h>
 
 #include <ags/audio/ags_playback.h>
 #include <ags/audio/ags_recall.h>
@@ -41,8 +42,10 @@
 #include <ags/audio/recall/ags_copy_pattern_channel.h>
 #include <ags/audio/recall/ags_copy_pattern_channel_run.h>
 
+#include <ags/widget/ags_led.h>
 #include <ags/widget/ags_indicator.h>
 #include <ags/widget/ags_vindicator.h>
+#include <ags/widget/ags_hindicator.h>
 
 #include <ags/X/ags_window.h>
 #include <ags/X/ags_machine.h>
@@ -58,7 +61,7 @@
 #include <ags/X/ags_dssi_browser.h>
 #include <ags/X/ags_lv2_browser.h>
 
-#include <ags/X/task/ags_change_indicator.h>
+#include <ags/X/thread/ags_gui_thread.h>
 
 int
 ags_line_parent_set_callback(GtkWidget *widget, GtkObject *old_parent, AgsLine *line)
@@ -86,7 +89,7 @@ ags_line_remove_recall_callback(AgsRecall *recall, AgsLine *line)
   }
 }
 
-int
+void
 ags_line_group_clicked_callback(GtkWidget *widget, AgsLine *line)
 {
   AgsPad *pad;
@@ -112,7 +115,8 @@ ags_line_group_clicked_callback(GtkWidget *widget, AgsLine *line)
 
       if(!gtk_toggle_button_get_active(current->group)){
 	g_list_free(list_start);
-	return(0);
+
+	return;
       }
 
       list = list->next;
@@ -131,7 +135,8 @@ ags_line_group_clicked_callback(GtkWidget *widget, AgsLine *line)
 	if(gtk_toggle_button_get_active(current->group)){
 	  ags_line_group_changed(line);
 	  g_list_free(list_start);
-	  return(0);
+
+	  return;
 	}
 
 	list = list->next;
@@ -143,7 +148,7 @@ ags_line_group_clicked_callback(GtkWidget *widget, AgsLine *line)
 
   g_list_free(list_start);
 
-  return(0);
+  return;
 }
 
 void
@@ -152,18 +157,49 @@ ags_line_add_effect_callback(AgsChannel *channel,
 			     gchar *effect,
 			     AgsLine *line)
 {
+  AgsWindow *window;
   AgsMachine *machine;
   AgsMachineEditor *machine_editor;
   AgsLineMemberEditor *line_member_editor;
   AgsPluginBrowser *plugin_browser;
+
+  AgsGuiThread *gui_thread;
+
+  AgsMutexManager *mutex_manager;
+  AgsThread *main_loop;
+
+  AgsApplicationContext *application_context;
   
   GList *pad_editor, *pad_editor_start;
   GList *line_editor, *line_editor_start;
   GList *control_type_name;
   
+  pthread_mutex_t *application_mutex;
+
   /* lock gdk threads */
   gdk_threads_enter();
 
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) line);
+
+  application_context = (AgsApplicationContext *) window->application_context;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* get audio loop */
+  pthread_mutex_lock(application_mutex);
+
+  main_loop = (AgsAudioLoop *) application_context->main_loop;
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* get task thread */
+  gui_thread = (AgsGuiThread *) ags_thread_find_type((AgsThread *) main_loop,
+						      AGS_TYPE_GUI_THREAD);
+
+  /*  */
+  gdk_threads_enter();
+
   /* get machine and machine editor */
   machine = (AgsMachine *) gtk_widget_get_ancestor((GtkWidget *) line,
 						   AGS_TYPE_MACHINE);
@@ -231,8 +267,23 @@ ags_line_add_effect_callback(AgsChannel *channel,
 	      controls = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(port_control->data));
 
 	      if(!g_ascii_strncasecmp(controls,
-				      "spin button\0",
-				      12)){
+				      "led\0",
+				      4)){
+		control_type_name = g_list_prepend(control_type_name,
+						   "AgsLed\0");
+	      }else if(!g_ascii_strncasecmp(controls,
+					    "vertical indicator\0",
+					    19)){
+		control_type_name = g_list_prepend(control_type_name,
+						   "AgsVIndicator\0");
+	      }else if(!g_ascii_strncasecmp(controls,
+					    "horizontal indicator\0",
+					    19)){
+		control_type_name = g_list_prepend(control_type_name,
+						   "AgsHIndicator\0");
+	      }else if(!g_ascii_strncasecmp(controls,
+					    "spin button\0",
+					    12)){
 		control_type_name = g_list_prepend(control_type_name,
 						   "GtkSpinButton\0");
 	      }else if(!g_ascii_strncasecmp(controls,
@@ -268,8 +319,8 @@ ags_line_add_effect_callback(AgsChannel *channel,
 	  }
 
 	  /* free lists */
-	g_list_free(description_start);
-	g_list_free(port_control_start);
+	  g_list_free(description_start);
+	  g_list_free(port_control_start);
 	}
       }
       
@@ -289,6 +340,8 @@ ags_line_add_effect_callback(AgsChannel *channel,
   g_list_free(pad_editor_start);
   g_list_free(line_editor_start);
 
+  gdk_threads_leave();
+
   /* unlock gdk threads */
   gdk_threads_leave();
 }
@@ -298,12 +351,46 @@ ags_line_remove_effect_callback(AgsChannel *channel,
 				guint nth,
 				AgsLine *line)
 {
+  AgsWindow *window;
+
+  AgsGuiThread *gui_thread;
+
+  AgsMutexManager *mutex_manager;
+  AgsThread *main_loop;
+
+  AgsApplicationContext *application_context;
+
+  pthread_mutex_t *application_mutex;
+
+  gdk_threads_enter();
+
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) line);
+
+  application_context = (AgsApplicationContext *) window->application_context;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* get audio loop */
+  pthread_mutex_lock(application_mutex);
+
+  main_loop = (AgsAudioLoop *) application_context->main_loop;
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* get task thread */
+  gui_thread = (AgsGuiThread *) ags_thread_find_type((AgsThread *) main_loop,
+						      AGS_TYPE_GUI_THREAD);
+
+  /*  */
   gdk_threads_enter();
 
   ags_line_remove_effect(line,
 			 nth);
 
   gdk_threads_leave();
+
+  gdk_threads_leave();
 }
 
 void
@@ -339,111 +426,69 @@ ags_line_volume_callback(GtkRange *range,
 }
 
 void
-ags_line_peak_run_post_callback(AgsRecall *peak_channel_run,
-				AgsLine *line)
+ags_line_channel_done_callback(AgsChannel *source, AgsRecallID *recall_id,
+			       AgsLine *line)
 {
-  GtkWidget *child;
-
-  AgsPort *port;
+  AgsChannel *channel;
+  AgsPlayback *playback;
+  AgsChannel *next_pad;
+  AgsRecallID *match_recall_id;
 
   AgsMutexManager *mutex_manager;
-  AgsTaskThread *task_thread;
-
-  GList *list, *list_start;
 
-  gdouble peak;
-
-  GValue value = {0,};
+  gboolean all_done;
 
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *channel_mutex;
 
-  /* lock gdk threads */
-  gdk_threads_enter();
-
   mutex_manager = ags_mutex_manager_get_instance();
   application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
-  
-  list_start = 
-    list = gtk_container_get_children((GtkContainer *) AGS_LINE(line)->expander->table);
-
-  while(list != NULL){
-    if(AGS_IS_LINE_MEMBER(list->data) &&
-       AGS_LINE_MEMBER(list->data)->widget_type == AGS_TYPE_VINDICATOR){
-      GtkAdjustment *adjustment;
-
-      child = GTK_BIN(list->data)->child;
-
-      /* get port */
-      pthread_mutex_lock(application_mutex);
 
-      channel_mutex = ags_mutex_manager_lookup(mutex_manager,
-					       (GObject *) line->channel);
-      
-      pthread_mutex_unlock(application_mutex);
-
-      pthread_mutex_lock(channel_mutex);
-      
-      port = AGS_PEAK_CHANNEL(AGS_RECALL_CHANNEL_RUN(peak_channel_run)->recall_channel)->peak;
-
-      pthread_mutex_unlock(channel_mutex);
-
-      /* get peak */
-      g_value_init(&value, G_TYPE_DOUBLE);
-      ags_port_safe_read(port,
-			 &value);
-
-      peak = g_value_get_double(&value);
-      g_value_unset(&value);
-
-      /* apply */
-      g_object_get(child,
-		   "adjustment\0", &adjustment,
-		   NULL);
-
-      gtk_adjustment_set_value(adjustment,
-			       peak);
-
-      break;
-    }
-    
-    list = list->next;
-  }
+  gdk_threads_enter();
+  
+  /* retrieve channel */
+  channel = AGS_PAD(AGS_LINE(line)->pad)->channel;
 
-  g_list_free(list_start);
+  /* retrieve channel mutex */
+  pthread_mutex_lock(application_mutex);
 
-  /* unlock gdk threads */
-  gdk_threads_leave();
-}
+  channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+					   (GObject *) channel);
 
-void
-ags_line_channel_done_callback(AgsChannel *source, AgsRecallID *recall_id,
-			       AgsLine *line)
-{
-  AgsChannel *channel;
-  AgsPlayback *playback;
-  AgsChannel *next_pad;
+  pthread_mutex_unlock(application_mutex);
 
-  gboolean all_done;
+  /* get next pad */
+  pthread_mutex_lock(channel_mutex);
 
-  gdk_threads_enter();
-  
-  channel = AGS_PAD(AGS_LINE(line)->pad)->channel;
   next_pad = channel->next_pad;
 
+  pthread_mutex_unlock(channel_mutex);
+
   all_done = TRUE;
 
   while(channel != next_pad){
+    pthread_mutex_lock(channel_mutex);
+
     playback = AGS_PLAYBACK(channel->playback);
-    
-    if(playback->recall_id[0] != NULL){
+    match_recall_id = playback->recall_id[0];
+		
+    pthread_mutex_unlock(channel_mutex);
+
+    /* check if pending */
+    if(match_recall_id != NULL){
       all_done = FALSE;
       break;
     }
-    
+
+    /* iterate */
+    pthread_mutex_lock(channel_mutex);
+
     channel = channel->next;
+
+    pthread_mutex_unlock(channel_mutex);
   }
 
+  /* toggle play button if all playback done */
   if(all_done){
     AgsPad *pad;
 
diff --git a/ags/X/ags_line_callbacks.h b/ags/X/ags_line_callbacks.h
index b1cfba4..866722d 100644
--- a/ags/X/ags_line_callbacks.h
+++ b/ags/X/ags_line_callbacks.h
@@ -30,7 +30,7 @@ int ags_line_parent_set_callback(GtkWidget *widget, GtkObject *old_parent, AgsLi
 
 void ags_line_remove_recall_callback(AgsRecall *recall, AgsLine *line);
 
-int ags_line_group_clicked_callback(GtkWidget *widget, AgsLine *line);
+void ags_line_group_clicked_callback(GtkWidget *widget, AgsLine *line);
 
 void ags_line_add_effect_callback(AgsChannel *channel,
 				  gchar *filename,
@@ -45,9 +45,6 @@ void ags_line_volume_callback(GtkRange *range,
 			      AgsLine *line);
 
 /* AgsRecall - recall */
-void ags_line_peak_run_post_callback(AgsRecall *peak_channel,
-				     AgsLine *line);
-
 void ags_line_copy_pattern_done(AgsRecall *recall,
 				AgsLine *line);
 void ags_line_copy_pattern_cancel(AgsRecall *recall,
diff --git a/ags/X/ags_line_editor.c b/ags/X/ags_line_editor.c
index 81f33a8..42c9e48 100644
--- a/ags/X/ags_line_editor.c
+++ b/ags/X/ags_line_editor.c
@@ -123,7 +123,7 @@ ags_line_editor_class_init(AgsLineEditorClass *line_editor)
    */
   param_spec = g_param_spec_object("channel\0",
 				   "assigned channel\0",
-				   "The channel which this pad editor is assigned with\0",
+				   "The channel which this line editor is assigned with\0",
 				   AGS_TYPE_CHANNEL,
 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
@@ -196,7 +196,9 @@ ags_line_editor_get_property(GObject *gobject,
 
   switch(prop_id){
   case PROP_CHANNEL:
-    g_value_set_object(value, line_editor->channel);
+    {
+      g_value_set_object(value, line_editor->channel);
+    }
     break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
@@ -219,9 +221,18 @@ ags_line_editor_connect(AgsConnectable *connectable)
   
   g_signal_connect(G_OBJECT(line_editor), "show\0",
   		   G_CALLBACK(ags_line_editor_show_callback), (gpointer) line_editor);
-
-  ags_connectable_connect(AGS_CONNECTABLE(line_editor->link_editor));
-  ags_connectable_connect(AGS_CONNECTABLE(line_editor->member_editor));
+  
+  if(line_editor->link_editor != NULL){
+    ags_connectable_connect(AGS_CONNECTABLE(line_editor->link_editor));
+  }
+  
+  if(line_editor->output_editor != NULL){
+    ags_connectable_connect(AGS_CONNECTABLE(line_editor->output_editor));
+  }
+  
+  if(line_editor->member_editor != NULL){
+    ags_connectable_connect(AGS_CONNECTABLE(line_editor->member_editor));
+  }
 }
 
 void
@@ -243,8 +254,17 @@ ags_line_editor_disconnect(AgsConnectable *connectable)
 		      (gpointer) line_editor,
 		      NULL);
 
-  ags_connectable_disconnect(AGS_CONNECTABLE(line_editor->link_editor));
-  ags_connectable_disconnect(AGS_CONNECTABLE(line_editor->member_editor));
+  if(line_editor->link_editor != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(line_editor->link_editor));
+  }
+  
+  if(line_editor->output_editor != NULL){
+    ags_connectable_connect(AGS_CONNECTABLE(line_editor->output_editor));
+  }
+  
+  if(line_editor->member_editor != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(line_editor->member_editor));
+  }
 }
 
 void
@@ -269,6 +289,10 @@ ags_line_editor_apply(AgsApplicable *applicable)
   if(line_editor->link_editor != NULL){
     ags_applicable_apply(AGS_APPLICABLE(line_editor->link_editor));
   }
+
+  if(line_editor->output_editor != NULL){
+    ags_applicable_apply(AGS_APPLICABLE(line_editor->output_editor));
+  }
 }
 
 void
@@ -282,6 +306,10 @@ ags_line_editor_reset(AgsApplicable *applicable)
     ags_applicable_reset(AGS_APPLICABLE(line_editor->link_editor));
   }
 
+  if(line_editor->output_editor != NULL){
+    ags_applicable_reset(AGS_APPLICABLE(line_editor->output_editor));
+  }
+
   if(line_editor->member_editor != NULL){
     ags_applicable_reset(AGS_APPLICABLE(line_editor->member_editor));
   }
@@ -303,25 +331,43 @@ ags_line_editor_set_channel(AgsLineEditor *line_editor,
   if(line_editor->link_editor != NULL){
     line_editor->link_editor = NULL;
     gtk_widget_destroy(GTK_WIDGET(line_editor->link_editor));
+    gtk_widget_destroy(GTK_WIDGET(line_editor->output_editor));
     gtk_widget_destroy(GTK_WIDGET(line_editor->member_editor));
   }
 
   line_editor->channel = channel;
 
   if(channel != NULL){
-    /* link */
-    line_editor->link_editor = ags_link_editor_new();
-    gtk_box_pack_start(GTK_BOX(line_editor),
-		       GTK_WIDGET(line_editor->link_editor),
-		       FALSE, FALSE,
-		       0);
-
-    /* recall */
-    line_editor->member_editor = ags_line_member_editor_new();
-    gtk_box_pack_start(GTK_BOX(line_editor),
-		       GTK_WIDGET(line_editor->member_editor),
-		       FALSE, FALSE,
-		       0);
+    guint i;
+
+    for(i = 0; i < line_editor->editor_type_count; i++){
+      /* link */
+      if(line_editor->editor_type[i] == AGS_TYPE_LINK_EDITOR){
+	line_editor->link_editor = ags_link_editor_new();
+	gtk_box_pack_start(GTK_BOX(line_editor),
+			   GTK_WIDGET(line_editor->link_editor),
+			   FALSE, FALSE,
+			   0);
+      }
+
+      /* recall */
+      if(line_editor->editor_type[i] == AGS_TYPE_OUTPUT_EDITOR){
+	line_editor->output_editor = ags_output_editor_new();
+	gtk_box_pack_start(GTK_BOX(line_editor),
+			   GTK_WIDGET(line_editor->output_editor),
+			   FALSE, FALSE,
+			   0);
+      }
+      
+      /* recall */
+      if(line_editor->editor_type[i] == AGS_TYPE_LINE_MEMBER_EDITOR){
+	line_editor->member_editor = ags_line_member_editor_new();
+	gtk_box_pack_start(GTK_BOX(line_editor),
+			   GTK_WIDGET(line_editor->member_editor),
+			   FALSE, FALSE,
+			   0);
+      }
+    }
   }
 }
 
diff --git a/ags/X/ags_line_editor.h b/ags/X/ags_line_editor.h
index 4c72165..c32932b 100644
--- a/ags/X/ags_line_editor.h
+++ b/ags/X/ags_line_editor.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -27,6 +27,7 @@
 #include <ags/audio/ags_channel.h>
 
 #include <ags/X/ags_link_editor.h>
+#include <ags/X/ags_output_editor.h>
 #include <ags/X/ags_line_member_editor.h>
 
 #define AGS_TYPE_LINE_EDITOR                (ags_line_editor_get_type())
@@ -57,7 +58,11 @@ struct _AgsLineEditor
 
   AgsChannel *channel;
 
+  guint editor_type_count;
+  GType *editor_type;
+
   AgsLinkEditor *link_editor;
+  AgsOutputEditor *output_editor;
   AgsLineMemberEditor *member_editor;
 };
 
diff --git a/ags/X/ags_line_editor_callbacks.c b/ags/X/ags_line_editor_callbacks.c
index 7dc0381..57081a2 100644
--- a/ags/X/ags_line_editor_callbacks.c
+++ b/ags/X/ags_line_editor_callbacks.c
@@ -27,20 +27,41 @@
 int
 ags_line_editor_parent_set_callback(GtkWidget *widget, GtkObject *old_parent, AgsLineEditor *line_editor)
 {
-  if(old_parent != NULL)
+  if(old_parent != NULL){
     return(0);
+  }
 
-  gtk_box_pack_start((GtkBox *) line_editor,
-		     (GtkWidget *) line_editor->link_editor,
-		     FALSE, FALSE, 0);
+  if(line_editor->link_editor != NULL){
+    gtk_box_pack_start((GtkBox *) line_editor,
+		       (GtkWidget *) line_editor->link_editor,
+		       FALSE, FALSE,
+		       0);
+  }
+
+  if(line_editor->output_editor != NULL){
+    gtk_box_pack_start((GtkBox *) line_editor,
+		       (GtkWidget *) line_editor->output_editor,
+		       FALSE, FALSE,
+		       0);
+  }
+    
   return(0);
 }
 
 int
 ags_line_editor_show_callback(GtkWidget *widget, AgsLineEditor *line_editor)
 {
-  gtk_widget_show((GtkWidget *) line_editor->link_editor);
-  gtk_widget_show((GtkWidget *) line_editor->member_editor);
+  if(line_editor->link_editor != NULL){
+    gtk_widget_show((GtkWidget *) line_editor->link_editor);
+  }
+  
+  if(line_editor->output_editor != NULL){
+    gtk_widget_show((GtkWidget *) line_editor->output_editor);
+  }
 
+  if(line_editor->member_editor != NULL){
+    gtk_widget_show((GtkWidget *) line_editor->member_editor);
+  }
+  
   return(0);
 }
diff --git a/ags/X/ags_line_member.c b/ags/X/ags_line_member.c
index 187f9e4..90d4eca 100644
--- a/ags/X/ags_line_member.c
+++ b/ags/X/ags_line_member.c
@@ -32,6 +32,8 @@
 
 #include <ags/audio/thread/ags_audio_loop.h>
 
+#include <ags/widget/ags_led.h>
+#include <ags/widget/ags_hindicator.h>
 #include <ags/widget/ags_dial.h>
 
 #include <ags/X/ags_window.h>
@@ -423,9 +425,6 @@ ags_line_member_init(AgsLineMember *line_member)
   dial = (AgsDial *) g_object_new(AGS_TYPE_DIAL,
 				  "adjustment\0", gtk_adjustment_new(0.0, 0.0, 1.0, 0.1, 0.1, 0.0),
 				  NULL);
-  gtk_widget_set_size_request((GtkWidget *) dial,
-			      2 * (dial->radius + dial->outline_strength + dial->button_width + 4),
-			      2 * (dial->radius + dial->outline_strength + 1));
   
   gtk_container_add(GTK_CONTAINER(line_member),
 		    (GtkWidget *) dial);
@@ -553,7 +552,10 @@ ags_line_member_set_property(GObject *gobject,
 	gtk_toggle_button_set_active((GtkToggleButton *) new_child,
 				     active);
       }else{
-	g_warning("ags_line_member_set_property() - unknown child type %s\0", g_type_name(widget_type));
+	if(!(AGS_IS_INDICATOR(new_child) ||
+	     AGS_IS_LED(new_child))){
+	  g_warning("ags_line_member_set_property() - unknown child type %s\0", g_type_name(widget_type));
+	}
       }
 
       /* add */
@@ -692,6 +694,18 @@ ags_line_member_set_property(GObject *gobject,
 
       if(port != NULL){
 	g_object_ref(port);
+
+	if((AGS_PORT_INFINITE_RANGE & (port->flags)) != 0){
+	  GtkWidget *child;
+
+	  child = gtk_bin_get_child(GTK_BIN(line_member));
+
+	  //TODO:JK: add more types
+
+	  if(AGS_IS_DIAL(child)){
+	    AGS_DIAL(child)->flags |= AGS_DIAL_SEEMLESS_MODE;
+	  }
+	}
       }
 
       line_member->port = port;
@@ -936,7 +950,8 @@ ags_line_member_disconnect(AgsConnectable *connectable)
 void
 ags_line_member_finalize(GObject *gobject)
 {
-  /* empty */
+  /* call parent */
+  G_OBJECT_CLASS(ags_line_member_parent_class)->finalize(gobject);  
 }
 
 GtkWidget*
@@ -1016,9 +1031,17 @@ ags_line_member_real_change_port(AgsLineMember *line_member,
 			   ((guint *) port_data)[0]);
       }else if(port->port_value_type == G_TYPE_FLOAT){
 	gfloat val;
-	  
-	val = ((gdouble *) port_data)[0];
-	  
+	
+	if(GTK_IS_TOGGLE_BUTTON(gtk_bin_get_child((GtkBin *) line_member))){
+	  if(((gboolean *) port_data)[0]){
+	    val = 1.0;
+	  }else{
+	    val = 0.0;
+	  }
+	}else{
+	  val = ((gdouble *) port_data)[0];
+	}
+
 	if(line_member->conversion != NULL){
 	  gfloat upper, lower, range, step;
 	  gfloat c_upper, c_lower, c_range;
@@ -1081,14 +1104,21 @@ ags_line_member_real_change_port(AgsLineMember *line_member,
 
 	g_value_init(&value,
 		     G_TYPE_FLOAT);
-
 	g_value_set_float(&value,
-			  (gfloat) ((gdouble *) port_data)[0]);
+			  (gfloat) val);
       }else if(port->port_value_type == G_TYPE_DOUBLE){
 	gdouble val;
-	  
-	val = ((gdouble *) port_data)[0];
-	  
+
+	if(GTK_IS_TOGGLE_BUTTON(gtk_bin_get_child((GtkBin *) line_member))){
+	  if(((gboolean *) port_data)[0]){
+	    val = 1.0;
+	  }else{
+	    val = 0.0;
+	  }
+	}else{
+	  val = ((gdouble *) port_data)[0];
+	}
+	
 	if(line_member->conversion != NULL){
 	  gdouble upper, lower, range, step;
 	  gdouble c_upper, c_lower, c_range;
@@ -1154,7 +1184,7 @@ ags_line_member_real_change_port(AgsLineMember *line_member,
 		     G_TYPE_DOUBLE);
 
 	g_value_set_double(&value,
-			   ((gdouble *) port_data)[0]);
+			   val);
       }
     }else{
       if(port->port_value_type == G_TYPE_OBJECT){
diff --git a/ags/X/ags_link_editor.c b/ags/X/ags_link_editor.c
index bbd0259..eb0ff2e 100644
--- a/ags/X/ags_link_editor.c
+++ b/ags/X/ags_link_editor.c
@@ -151,7 +151,8 @@ ags_link_editor_init(AgsLinkEditor *link_editor)
   link_editor->combo = (GtkComboBox *) gtk_combo_box_new();
   gtk_box_pack_start(GTK_BOX(link_editor),
 		     GTK_WIDGET(link_editor->combo),
-		     FALSE, FALSE, 0);
+		     FALSE, FALSE,
+		     0);
   
   cell_renderer = gtk_cell_renderer_text_new();
   gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(link_editor->combo),
@@ -166,7 +167,8 @@ ags_link_editor_init(AgsLinkEditor *link_editor)
   link_editor->spin_button = (GtkSpinButton *) gtk_spin_button_new_with_range(0.0, 0.0, 1.0);
   gtk_box_pack_start(GTK_BOX(link_editor),
 		     GTK_WIDGET(link_editor->spin_button),
-		     FALSE, FALSE, 0);
+		     FALSE, FALSE,
+		     0);
 
   link_editor->audio_file = NULL;
 
@@ -400,7 +402,9 @@ void
 ags_link_editor_reset(AgsApplicable *applicable)
 {
   AgsLinkEditor *link_editor;
+
   GtkTreeModel *model;
+
   GtkTreeIter iter;
 
   link_editor = AGS_LINK_EDITOR(applicable);
diff --git a/ags/X/ags_link_editor_callbacks.c b/ags/X/ags_link_editor_callbacks.c
index 972b1fd..8ccff1c 100644
--- a/ags/X/ags_link_editor_callbacks.c
+++ b/ags/X/ags_link_editor_callbacks.c
@@ -20,6 +20,9 @@
 #include <ags/X/ags_link_editor_callbacks.h>
 
 #include <ags/object/ags_soundcard.h>
+
+#include <ags/audio/ags_audio.h>
+#include <ags/audio/ags_channel.h>
 #include <ags/audio/ags_output.h>
 #include <ags/audio/ags_input.h>
 
@@ -28,6 +31,7 @@
 #include <ags/audio/recall/ags_play_audio_file.h>
 
 #include <ags/X/ags_window.h>
+#include <ags/X/ags_machine.h>
 #include <ags/X/ags_machine_editor.h>
 #include <ags/X/ags_line_editor.h>
 
@@ -45,52 +49,59 @@ ags_link_editor_parent_set_callback(GtkWidget *widget, GtkObject *old_parent, Ag
   AgsMachine *machine;
   AgsLineEditor *line_editor;
 
+  AgsAudio *audio;
   AgsChannel *channel;
 
   GtkTreeModel *model;
 
-  if(old_parent != NULL)
+  if(old_parent != NULL){
     return(0);
+  }
 
+  //TODO:JK: missing mutex
   line_editor = (AgsLineEditor *) gtk_widget_get_ancestor(widget, AGS_TYPE_LINE_EDITOR);
-  channel = line_editor->channel;
+
+  if(line_editor != NULL){
+    channel = line_editor->channel;
   
-  machine = AGS_MACHINE(AGS_AUDIO(channel->audio)->machine);
+    if(channel != NULL){
+      GtkTreeIter iter;
+      
+      audio = AGS_AUDIO(channel->audio);
 
-  model = GTK_TREE_MODEL(ags_machine_get_possible_links(machine));
+      if(audio != NULL){
+	machine = AGS_MACHINE(audio->machine);
     
-  if(line_editor != NULL &&
-     channel != NULL &&
-     AGS_IS_INPUT(channel) &&
-     channel->audio != NULL &&
-     AGS_AUDIO(channel->audio)->machine != NULL){
-    GtkTreeIter iter;
+	model = GTK_TREE_MODEL(ags_machine_get_possible_links(machine));
+  
+	if(AGS_IS_INPUT(line_editor->channel) &&
+	   (AGS_MACHINE_TAKES_FILE_INPUT & (machine->flags)) != 0 &&
+	   ((AGS_MACHINE_ACCEPT_WAV & (machine->file_input_flags)) != 0 ||
+	    ((AGS_MACHINE_ACCEPT_OGG & (machine->file_input_flags)) != 0))){
+	  gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+
+	  if(AGS_INPUT(channel)->file_link != NULL){
+	    gtk_list_store_set(GTK_LIST_STORE(model), &iter,
+			       0, g_strdup_printf("file://%s\0", AGS_FILE_LINK(AGS_INPUT(channel)->file_link)->filename),
+			       1, NULL,
+			       -1);
+	    gtk_combo_box_set_active_iter(link_editor->combo,
+					  &iter);
+	  }else{
+	    gtk_list_store_set(GTK_LIST_STORE(model), &iter,
+			       0, "file://\0",
+			       1, NULL,
+			       -1);
+	  }
 
-    if((AGS_MACHINE_TAKES_FILE_INPUT & (machine->flags)) != 0 &&
-       ((AGS_MACHINE_ACCEPT_WAV & (machine->file_input_flags)) != 0 ||
-	((AGS_MACHINE_ACCEPT_OGG & (machine->file_input_flags)) != 0))){
-      gtk_list_store_append(GTK_LIST_STORE(model), &iter);
-
-      if(AGS_INPUT(channel)->file_link != NULL){
-	gtk_list_store_set(GTK_LIST_STORE(model), &iter,
-			   0, g_strdup_printf("file://%s\0", AGS_FILE_LINK(AGS_INPUT(channel)->file_link)->filename),
-			   1, NULL,
-			   -1);
-	gtk_combo_box_set_active_iter(link_editor->combo,
-				      &iter);
-      }else{
-	gtk_list_store_set(GTK_LIST_STORE(model), &iter,
-			   0, "file://\0",
-			   1, NULL,
-			   -1);
+	}
+
+	gtk_combo_box_set_model(link_editor->combo,
+				model);
       }
     }
-
   }
-
-  gtk_combo_box_set_model(link_editor->combo,
-			  model);
-
+  
   return(0);
 }
 
diff --git a/ags/X/ags_listing_editor.c b/ags/X/ags_listing_editor.c
index a37da78..9ee19a5 100644
--- a/ags/X/ags_listing_editor.c
+++ b/ags/X/ags_listing_editor.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -23,11 +23,16 @@
 #include <ags/object/ags_connectable.h>
 #include <ags/object/ags_applicable.h>
 
+#include <ags/thread/ags_mutex_manager.h>
+
 #include <ags/audio/ags_channel.h>
 #include <ags/audio/ags_output.h>
 
 #include <ags/X/ags_machine_editor.h>
 #include <ags/X/ags_pad_editor.h>
+#include <ags/X/ags_line_editor.h>
+#include <ags/X/ags_link_editor.h>
+#include <ags/X/ags_line_member_editor.h>
 
 void ags_listing_editor_class_init(AgsListingEditorClass *listing_editor);
 void ags_listing_editor_connectable_interface_init(AgsConnectableInterface *connectable);
@@ -38,8 +43,6 @@ void ags_listing_editor_disconnect(AgsConnectable *connectable);
 void ags_listing_editor_set_update(AgsApplicable *applicable, gboolean update);
 void ags_listing_editor_apply(AgsApplicable *applicable);
 void ags_listing_editor_reset(AgsApplicable *applicable);
-void ags_listing_editor_destroy(GtkObject *object);
-void ags_listing_editor_show(GtkWidget *widget);
 
 /**
  * SECTION:ags_listing_editor
@@ -131,6 +134,8 @@ ags_listing_editor_init(AgsListingEditor *listing_editor)
   g_signal_connect_after(G_OBJECT(listing_editor), "parent_set\0",
 			 G_CALLBACK(ags_listing_editor_parent_set_callback), listing_editor);
 
+  listing_editor->channel_type = G_TYPE_NONE;
+
   listing_editor->child = NULL;
 }
 
@@ -177,6 +182,7 @@ ags_listing_editor_disconnect(AgsConnectable *connectable)
 {
   AgsMachineEditor *machine_editor;
   AgsListingEditor *listing_editor;
+
   GList *pad_editor, *pad_editor_start;
 
   ags_listing_editor_parent_connectable_interface->connect(connectable);
@@ -214,6 +220,7 @@ void
 ags_listing_editor_set_update(AgsApplicable *applicable, gboolean update)
 {
   AgsListingEditor *listing_editor;
+
   GList *pad_editor, *pad_editor_start;
 
   listing_editor = AGS_LISTING_EDITOR(applicable);
@@ -235,12 +242,14 @@ ags_listing_editor_apply(AgsApplicable *applicable)
 {
 
   AgsListingEditor *listing_editor;
+
   GList *pad_editor, *pad_editor_start;
 
   listing_editor = AGS_LISTING_EDITOR(applicable);
 
-  if((AGS_PROPERTY_EDITOR_ENABLED & (AGS_PROPERTY_EDITOR(listing_editor)->flags)) == 0)
+  if((AGS_PROPERTY_EDITOR_ENABLED & (AGS_PROPERTY_EDITOR(listing_editor)->flags)) == 0){
     return;
+  }
 
   pad_editor_start = 
     pad_editor = gtk_container_get_children(GTK_CONTAINER(listing_editor->child));
@@ -258,6 +267,7 @@ void
 ags_listing_editor_reset(AgsApplicable *applicable)
 {
   AgsListingEditor *listing_editor;
+
   GList *pad_editor, *pad_editor_start;
 
   listing_editor = AGS_LISTING_EDITOR(applicable);
@@ -274,18 +284,6 @@ ags_listing_editor_reset(AgsApplicable *applicable)
   g_list_free(pad_editor_start);
 }
 
-void
-ags_listing_editor_destroy(GtkObject *object)
-{
-  /* empty */
-}
-
-void
-ags_listing_editor_show(GtkWidget *widget)
-{
-  /* empty */
-}
-
 /**
  * ags_listing_editor_add_children:
  * @listing_editor: the #AgsListingEditor
@@ -304,8 +302,15 @@ ags_listing_editor_add_children(AgsListingEditor *listing_editor,
 {
   AgsPadEditor *pad_editor;
   GtkVBox *vbox;
+
   AgsChannel *channel;
 
+  AgsMutexManager *mutex_manager;
+
+  pthread_mutex_t *application_mutex;
+  pthread_mutex_t *audio_mutex;
+  pthread_mutex_t *channel_mutex;
+
   if(nth_channel == 0 &&
      listing_editor->child != NULL){
     vbox = listing_editor->child;
@@ -313,9 +318,22 @@ ags_listing_editor_add_children(AgsListingEditor *listing_editor,
     gtk_widget_destroy(GTK_WIDGET(vbox));
   }
 
-  if(audio == NULL)
+  if(audio == NULL){
     return;
+  }
   
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* lookup audio mutex */
+  pthread_mutex_lock(application_mutex);
+  
+  audio_mutex = ags_mutex_manager_lookup(mutex_manager,
+					 audio);
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* instantiate pad editor vbox */
   if(nth_channel == 0){
     listing_editor->child = (GtkVBox *) gtk_vbox_new(FALSE, 0);
     gtk_box_pack_start(GTK_BOX(listing_editor),
@@ -324,13 +342,48 @@ ags_listing_editor_add_children(AgsListingEditor *listing_editor,
 		       0);
   }
 
-  if(listing_editor->channel_type == AGS_TYPE_OUTPUT)
-    channel = ags_channel_nth(audio->output, nth_channel);
-  else
-    channel = ags_channel_nth(audio->input, nth_channel);
+  /* get current channel */
+  if(listing_editor->channel_type == AGS_TYPE_OUTPUT){
+    pthread_mutex_lock(audio_mutex);
+
+    channel = audio->output;
 
+    pthread_mutex_unlock(audio_mutex);
+
+    channel = ags_channel_nth(channel,
+			      nth_channel);
+  }else{
+    pthread_mutex_lock(audio_mutex);
+
+    channel = audio->input;
+
+    pthread_mutex_unlock(audio_mutex);
+    
+    channel = ags_channel_nth(channel,
+			      nth_channel);
+  }
+  
   while(channel != NULL){
-    pad_editor = ags_pad_editor_new(channel);
+    /* lookup channel mutex */
+    pthread_mutex_lock(application_mutex);
+
+    channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+					     channel);
+    
+    pthread_mutex_unlock(application_mutex);
+
+    /* instantiate pad editor */
+    pad_editor = ags_pad_editor_new(NULL);
+
+    pad_editor->editor_type_count = 2;
+    pad_editor->editor_type = (GType *) malloc(pad_editor->editor_type_count * sizeof(GType));
+    pad_editor->editor_type[0] = AGS_TYPE_LINK_EDITOR;
+    pad_editor->editor_type[1] = AGS_TYPE_LINE_MEMBER_EDITOR;
+
+    g_object_set(pad_editor,
+		 "channel\0", channel,
+		 NULL);
+    
     gtk_box_pack_start(GTK_BOX(listing_editor->child),
 		       GTK_WIDGET(pad_editor),
 		       FALSE, FALSE,
@@ -341,7 +394,12 @@ ags_listing_editor_add_children(AgsListingEditor *listing_editor,
       gtk_widget_show_all(GTK_WIDGET(pad_editor));
     }
 
+    /* iterate */
+    pthread_mutex_lock(channel_mutex);
+      
     channel = channel->next_pad;
+
+    pthread_mutex_unlock(channel_mutex);
   }
 }
 
diff --git a/ags/X/ags_listing_editor_callbacks.c b/ags/X/ags_listing_editor_callbacks.c
index 48e25e3..771e300 100644
--- a/ags/X/ags_listing_editor_callbacks.c
+++ b/ags/X/ags_listing_editor_callbacks.c
@@ -19,6 +19,11 @@
 
 #include <ags/X/ags_listing_editor_callbacks.h>
 
+#include <ags/thread/ags_mutex_manager.h>
+
+#include <ags/X/ags_machine.h>
+#include <ags/X/ags_machine_editor.h>
+
 int
 ags_listing_editor_parent_set_callback(GtkWidget *widget,
 				       GtkObject *old_parent,
@@ -32,11 +37,12 @@ ags_listing_editor_parent_set_callback(GtkWidget *widget,
   machine_editor = (AgsMachineEditor *) gtk_widget_get_ancestor(widget,
 								AGS_TYPE_MACHINE_EDITOR);
 
-  if(machine_editor->machine != NULL)
+  if(machine_editor->machine != NULL){
     ags_listing_editor_add_children(listing_editor,
 				    machine_editor->machine->audio, 0,
 				    FALSE);
-
+  }
+  
   return(0);
 }
 
@@ -45,13 +51,39 @@ ags_listing_editor_set_pads_callback(AgsAudio *audio, GType channel_type,
 				     guint pads, guint pads_old,
 				     AgsListingEditor *listing_editor)
 {
-  if(channel_type != listing_editor->channel_type)
+  if(channel_type != listing_editor->channel_type){
     return;
+  }
 
   if(pads_old < pads){
+    AgsMutexManager *mutex_manager;
+
+    guint audio_channels;
     guint nth_channel;
+
+    pthread_mutex_t *application_mutex;
+    pthread_mutex_t *audio_mutex;
+    
+    mutex_manager = ags_mutex_manager_get_instance();
+    application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+    /* lookup audio mutex */
+    pthread_mutex_lock(application_mutex);
   
-    nth_channel = pads_old * audio->audio_channels;
+    audio_mutex = ags_mutex_manager_lookup(mutex_manager,
+					   audio);
+  
+    pthread_mutex_unlock(application_mutex);
+
+    /* get some audio fields */
+    pthread_mutex_lock(audio_mutex);
+
+    audio_channels = audio->audio_channels;
+
+    pthread_mutex_unlock(audio_mutex);
+
+    /* add children */
+    nth_channel = pads_old * audio_channels;
     
     ags_listing_editor_add_children(listing_editor,
 				    audio, nth_channel,
diff --git a/ags/X/ags_listing_editor_callbacks.h b/ags/X/ags_listing_editor_callbacks.h
index 1b2e151..6682772 100644
--- a/ags/X/ags_listing_editor_callbacks.h
+++ b/ags/X/ags_listing_editor_callbacks.h
@@ -24,10 +24,9 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
-#include <ags/X/ags_listing_editor.h>
+#include <ags/audio/ags_audio.h>
 
-#include <ags/X/ags_machine.h>
-#include <ags/X/ags_machine_editor.h>
+#include <ags/X/ags_listing_editor.h>
 
 int ags_listing_editor_parent_set_callback(GtkWidget *widget,
 					   GtkObject *old_parent,
diff --git a/ags/X/ags_lv2_browser.c b/ags/X/ags_lv2_browser.c
index 3494c7c..849309e 100644
--- a/ags/X/ags_lv2_browser.c
+++ b/ags/X/ags_lv2_browser.c
@@ -355,6 +355,58 @@ ags_lv2_browser_get_plugin_effect(AgsLv2Browser *lv2_browser)
 }
 
 /**
+ * ags_lv2_browser_combo_box_output_boolean_controls_new:
+ *
+ * Creates a #GtkComboBox containing suitable widgets as controls.
+ *
+ * Returns: a new #GtkComboBox
+ *
+ * Since: 0.7.128
+ */
+GtkWidget*
+ags_lv2_browser_combo_box_output_boolean_controls_new()
+{
+  GtkComboBoxText *combo_box;
+
+  combo_box = (GtkComboBoxText *) gtk_combo_box_text_new();
+
+  gtk_combo_box_text_append_text(combo_box,
+				 "led\0");
+
+  gtk_combo_box_set_active((GtkComboBox *) combo_box,
+			   1);
+
+  return((GtkWidget *) combo_box);
+}
+
+/**
+ * ags_lv2_browser_combo_box_controls_new:
+ *
+ * Creates a #GtkComboBox containing suitable widgets as controls.
+ *
+ * Returns: a new #GtkComboBox
+ *
+ * Since: 0.7.128
+ */
+GtkWidget*
+ags_lv2_browser_combo_box_output_controls_new()
+{
+  GtkComboBoxText *combo_box;
+
+  combo_box = (GtkComboBoxText *) gtk_combo_box_text_new();
+
+  gtk_combo_box_text_append_text(combo_box,
+				 "vertical indicator\0");
+  gtk_combo_box_text_append_text(combo_box,
+				 "horizontal indicator\0");
+
+  gtk_combo_box_set_active((GtkComboBox *) combo_box,
+			   1);
+
+  return((GtkWidget *) combo_box);
+}
+
+/**
  * ags_lv2_browser_combo_box_boolean_controls_new:
  *
  * Creates a #GtkComboBox containing suitable widgets as controls.
diff --git a/ags/X/ags_lv2_browser.h b/ags/X/ags_lv2_browser.h
index 6d18c62..d2f125c 100644
--- a/ags/X/ags_lv2_browser.h
+++ b/ags/X/ags_lv2_browser.h
@@ -56,8 +56,12 @@ GType ags_lv2_browser_get_type(void);
 gchar* ags_lv2_browser_get_plugin_filename(AgsLv2Browser *lv2_browser);
 gchar* ags_lv2_browser_get_plugin_effect(AgsLv2Browser *lv2_browser);
 
+GtkWidget* ags_lv2_browser_combo_box_output_boolean_controls_new();
+GtkWidget* ags_lv2_browser_combo_box_output_controls_new();
+
 GtkWidget* ags_lv2_browser_combo_box_boolean_controls_new();
 GtkWidget* ags_lv2_browser_combo_box_controls_new();
+
 GtkWidget* ags_lv2_browser_preview_new();
 
 AgsLv2Browser* ags_lv2_browser_new();
diff --git a/ags/X/ags_lv2_browser_callbacks.c b/ags/X/ags_lv2_browser_callbacks.c
index f656250..5d9b667 100644
--- a/ags/X/ags_lv2_browser_callbacks.c
+++ b/ags/X/ags_lv2_browser_callbacks.c
@@ -160,15 +160,29 @@ ags_lv2_browser_plugin_uri_callback(GtkComboBoxText *combo_box,
 				y, y + 1);
       
       if((AGS_PORT_DESCRIPTOR_TOGGLED & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
-	gtk_table_attach_defaults(table,
-				  GTK_WIDGET(ags_lv2_browser_combo_box_boolean_controls_new()),
-				  1, 2,
-				  y, y + 1);
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  gtk_table_attach_defaults(table,
+				    GTK_WIDGET(ags_lv2_browser_combo_box_output_boolean_controls_new()),
+				    1, 2,
+				    y, y + 1);
+	}else{
+	  gtk_table_attach_defaults(table,
+				    GTK_WIDGET(ags_lv2_browser_combo_box_boolean_controls_new()),
+				    1, 2,
+				    y, y + 1);
+	}
       }else{
-	gtk_table_attach_defaults(table,
-				  GTK_WIDGET(ags_lv2_browser_combo_box_controls_new()),
-				  1, 2,
-				  y, y + 1);
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  gtk_table_attach_defaults(table,
+				    GTK_WIDGET(ags_lv2_browser_combo_box_output_controls_new()),
+				    1, 2,
+				    y, y + 1);
+	}else{
+	  gtk_table_attach_defaults(table,
+				    GTK_WIDGET(ags_lv2_browser_combo_box_controls_new()),
+				    1, 2,
+				    y, y + 1);
+	}
       }
 	
       y++;
diff --git a/ags/X/ags_machine.c b/ags/X/ags_machine.c
index 9b8d083..6591c73 100644
--- a/ags/X/ags_machine.c
+++ b/ags/X/ags_machine.c
@@ -313,7 +313,6 @@ ags_machine_init(AgsMachine *machine)
 {
   GtkVBox *vbox;
   GtkFrame *frame;
-  GtkMenuToolButton *menu_tool_button;
 
   machine->name = NULL;
 
@@ -340,6 +339,8 @@ ags_machine_init(AgsMachine *machine)
 
   machine->audio = ags_audio_new(NULL);
   g_object_ref(G_OBJECT(machine->audio));
+
+  machine->audio->flags |= AGS_AUDIO_CAN_NEXT_ACTIVE;
   machine->audio->machine = (GObject *) machine;
 
   /* AgsAudio */
@@ -365,12 +366,12 @@ ags_machine_init(AgsMachine *machine)
   machine->popup = ags_machine_popup_new(machine);
   g_object_ref(machine->popup);
   
-  menu_tool_button = (GtkMenuToolButton *) g_object_new(GTK_TYPE_MENU_TOOL_BUTTON,
-							"label\0", "machine\0",
-							"menu\0", machine->popup,
-							NULL);
+  machine->menu_tool_button = (GtkMenuToolButton *) g_object_new(GTK_TYPE_MENU_TOOL_BUTTON,
+								 "label\0", "machine\0",
+								 "menu\0", machine->popup,
+								 NULL);
   gtk_frame_set_label_widget(frame,
-			     (GtkWidget *) menu_tool_button);
+			     (GtkWidget *) machine->menu_tool_button);
   machine->properties = NULL;
   machine->rename = NULL;
   machine->connection_editor = NULL;
@@ -625,7 +626,8 @@ void
 ags_machine_connect(AgsConnectable *connectable)
 {
   AgsMachine *machine;
-  GList *pad_list;
+
+  GList *list_start, *list;
 
   /* AgsMachine */
   machine = AGS_MACHINE(connectable);
@@ -664,24 +666,30 @@ ags_machine_connect(AgsConnectable *connectable)
 
   /* AgsPad - input */
   if(machine->input != NULL){
-    pad_list = gtk_container_get_children(GTK_CONTAINER(machine->input));
+    list_start =
+      list = gtk_container_get_children(GTK_CONTAINER(machine->input));
 
-    while(pad_list != NULL){
-      ags_connectable_connect(AGS_CONNECTABLE(pad_list->data));
+    while(list != NULL){
+      ags_connectable_connect(AGS_CONNECTABLE(list->data));
       
-      pad_list = pad_list->next;
+      list = list->next;
     }
+
+    g_list_free(list_start);
   }
 
   /* AgsPad - output */
   if(machine->output != NULL){
-    pad_list = gtk_container_get_children(GTK_CONTAINER(machine->output));
+    list_start =
+      list = gtk_container_get_children(GTK_CONTAINER(machine->output));
     
-    while(pad_list != NULL){
-      ags_connectable_connect(AGS_CONNECTABLE(pad_list->data));
+    while(list != NULL){
+      ags_connectable_connect(AGS_CONNECTABLE(list->data));
       
-      pad_list = pad_list->next;
+      list = list->next;
     }
+
+    g_list_free(list_start);
   }
 
   /* audio */
@@ -695,7 +703,54 @@ ags_machine_connect(AgsConnectable *connectable)
 void
 ags_machine_disconnect(AgsConnectable *connectable)
 {
+  AgsMachine *machine;
+
+  GList *list_start, *list;
+
+  /* AgsMachine */
+  machine = AGS_MACHINE(connectable);
+
+  if((AGS_MACHINE_CONNECTED & (machine->flags)) == 0){
+    return;
+  }
+
+  machine->flags &= (~AGS_MACHINE_CONNECTED);
+
+  if(machine->bridge != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(machine->bridge));
+  }
+
+  /* AgsPad - input */
+  if(machine->input != NULL){
+    list_start =
+      list = gtk_container_get_children(GTK_CONTAINER(machine->input));
+
+    while(list != NULL){
+      ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
+      
+      list = list->next;
+    }
+
+    g_list_free(list_start);
+  }
+
+  /* AgsPad - output */
+  if(machine->output != NULL){
+    list_start =
+      list = gtk_container_get_children(GTK_CONTAINER(machine->output));
+    
+    while(list != NULL){
+      ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
+      
+      list = list->next;
+    }
+
+    g_list_free(list_start);
+  }
+
   //TODO:JK: implement me
+  g_signal_handlers_disconnect_by_data(machine->audio,
+				       machine);
 }
 
 
@@ -1056,7 +1111,7 @@ ags_machine_real_resize_audio_channels(AgsMachine *machine,
 
 	gtk_widget_destroy(GTK_WIDGET(list_input_pad->data));
 
-	list_input_pad->next = list_input_pad_next;
+	list_input_pad = list_input_pad_next;
       }
 
       /* AgsOutput */
@@ -1065,7 +1120,7 @@ ags_machine_real_resize_audio_channels(AgsMachine *machine,
 
 	gtk_widget_destroy(GTK_WIDGET(list_output_pad->data));
 
-	list_output_pad->next = list_output_pad_next;
+	list_output_pad = list_output_pad_next;
       }
     }else{
       /* AgsInput */
@@ -1261,27 +1316,31 @@ ags_machine_real_resize_pads(AgsMachine *machine, GType type,
     GList *list, *list_next;
 
     /* input - destroy AgsPad's */
-    list = gtk_container_get_children(GTK_CONTAINER(machine->input));
-    list = g_list_nth(list, pads);
+    if(type == AGS_TYPE_INPUT){
+      list = gtk_container_get_children(GTK_CONTAINER(machine->input));
+      list = g_list_nth(list, pads);
 
-    while(list != NULL){
-      list_next = list->next;
+      while(list != NULL){
+	list_next = list->next;
 
-      gtk_widget_destroy(GTK_WIDGET(list->data));
+	gtk_widget_destroy(GTK_WIDGET(list->data));
 
-      list = list_next;
+	list = list_next;
+      }
     }
-
+    
     /* output - destroy AgsPad's */
-    list = gtk_container_get_children(GTK_CONTAINER(machine->output));
-    list = g_list_nth(list, pads);
+    if(type == AGS_TYPE_OUTPUT){
+      list = gtk_container_get_children(GTK_CONTAINER(machine->output));
+      list = g_list_nth(list, pads);
 
-    while(list != NULL){
-      list_next = list->next;
+      while(list != NULL){
+	list_next = list->next;
 
-      gtk_widget_destroy(GTK_WIDGET(list->data));
+	gtk_widget_destroy(GTK_WIDGET(list->data));
 
-      list = list_next;
+	list = list_next;
+      }
     }
   }
 
@@ -1503,6 +1562,8 @@ ags_machine_set_run_extended(AgsMachine *machine,
   AgsTaskThread *task_thread;
 
   AgsApplicationContext *application_context;
+
+  gboolean no_soundcard;
   
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *audio_loop_mutex;
@@ -1513,12 +1574,28 @@ ags_machine_set_run_extended(AgsMachine *machine,
 
   mutex_manager = ags_mutex_manager_get_instance();
   application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  no_soundcard = FALSE;
   
+  pthread_mutex_lock(application_mutex);
+
+  if(ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context)) == NULL){
+    no_soundcard = TRUE;
+  }
+
+  pthread_mutex_unlock(application_mutex);
+
+  if(no_soundcard){
+    g_message("No soundcard available\0");
+    
+    return;
+  }
+
   /* get threads */
   pthread_mutex_lock(application_mutex);
 
   audio_loop = (AgsAudioLoop *) application_context->main_loop;
-
+  
   pthread_mutex_unlock(application_mutex);
 
   /* lookup audio loop mutex */
@@ -1575,13 +1652,9 @@ ags_machine_set_run_extended(AgsMachine *machine,
       AgsGuiThread *gui_thread;
       AgsTaskCompletion *task_completion;
 
-      pthread_mutex_lock(audio_loop_mutex);
-      
       gui_thread = (AgsGuiThread *) ags_thread_find_type((AgsThread *) audio_loop,
 							 AGS_TYPE_GUI_THREAD);
 
-      pthread_mutex_unlock(audio_loop_mutex);
-
       /* start soundcard */
       start_soundcard = ags_start_soundcard_new(window->application_context);
       list = g_list_prepend(list, start_soundcard);
@@ -2130,6 +2203,8 @@ ags_machine_popup_add_edit_options(AgsMachine *machine, guint edit_options)
 
     gtk_widget_show((GtkWidget *) item);
   }
+
+  gtk_widget_show_all(machine->popup);
 }
 
 /**
@@ -2178,4 +2253,6 @@ ags_machine_popup_add_connection_options(AgsMachine *machine, guint connection_o
 
     gtk_widget_show((GtkWidget *) item);
   }
+
+  gtk_widget_show_all(machine->popup);
 }
diff --git a/ags/X/ags_machine.h b/ags/X/ags_machine.h
index 058eb8e..f5a7a5b 100644
--- a/ags/X/ags_machine.h
+++ b/ags/X/ags_machine.h
@@ -117,7 +117,9 @@ struct _AgsMachine
   GList *port;
   gchar **automation_port;
 
+  GtkMenuToolButton *menu_tool_button;
   GtkMenu *popup;
+  
   GtkDialog *properties;
   GtkDialog *rename;
   GtkDialog *connection_editor;
diff --git a/ags/X/ags_machine_callbacks.c b/ags/X/ags_machine_callbacks.c
index bd71105..9aef6cb 100644
--- a/ags/X/ags_machine_callbacks.c
+++ b/ags/X/ags_machine_callbacks.c
@@ -39,6 +39,7 @@
 
 #include <ags/X/ags_window.h>
 #include <ags/X/ags_pad.h>
+#include <ags/X/ags_automation_editor.h>
 #include <ags/X/ags_editor.h>
 #include <ags/X/ags_machine_editor.h>
 #include <ags/X/ags_connection_editor.h>
@@ -47,6 +48,8 @@
 #include <ags/X/editor/ags_machine_radio_button.h>
 #include <ags/X/editor/ags_file_selection.h>
 
+#include <ags/X/thread/ags_gui_thread.h>
+
 #define AGS_RENAME_ENTRY "AgsRenameEntry\0"
 
 int ags_machine_popup_rename_response_callback(GtkWidget *widget, gint response, AgsMachine *machine);
@@ -54,6 +57,7 @@ int ags_machine_popup_properties_destroy_callback(GtkWidget *widget, AgsMachine
 void ags_machine_connection_editor_delete_event_callback(GtkWidget *dialog, gint response, AgsMachine *machine);
 void ags_machine_midi_dialog_delete_event_callback(GtkWidget *dialog, gint response, AgsMachine *machine);
 void ags_machine_start_complete_response(GtkWidget *dialog, gint response, AgsMachine *machine);
+void ags_machine_remove_audio_launch_callback(AgsTask *task, AgsMachine *machine);
 
 int
 ags_machine_button_press_callback(GtkWidget *handle_box, GdkEventButton *event, AgsMachine *machine)
@@ -132,52 +136,30 @@ ags_machine_popup_show_activate_callback(GtkWidget *widget, AgsMachine *machine)
 }
 
 void
-ags_machine_popup_destroy_activate_callback(GtkWidget *widget, AgsMachine *machine)
+ags_machine_remove_audio_launch_callback(AgsTask *task, AgsMachine *machine)
 {
   AgsWindow *window;
-  AgsRemoveAudio *remove_audio;
-
-  AgsMutexManager *mutex_manager;
-  AgsAudioLoop *audio_loop;
-  AgsTaskThread *task_thread;
-
-  AgsApplicationContext *application_context;
 
   GList *list, *list_start;
 
-  pthread_mutex_t *application_mutex;
+  gdk_threads_enter();
   
   window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) machine);
-
-  application_context = (AgsApplicationContext *) window->application_context;
-
-  mutex_manager = ags_mutex_manager_get_instance();
-  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
   
-  /* get audio loop */
-  pthread_mutex_lock(application_mutex);
-
-  audio_loop = (AgsAudioLoop *) application_context->main_loop;
-  
-  pthread_mutex_unlock(application_mutex);
-
-  /* get task thread */
-  task_thread = (AgsTaskThread *) ags_thread_find_type((AgsThread *) audio_loop,
-						       AGS_TYPE_TASK_THREAD);
-
-  g_object_ref(machine->audio);
-  remove_audio = ags_remove_audio_new(window->soundcard,
-				      machine->audio);
-  ags_task_thread_append_task(task_thread,
-			      AGS_TASK(remove_audio));
-
-  ags_connectable_disconnect(AGS_CONNECTABLE(machine));
-
   /* destroy editor */
   list = window->editor->editor_child;
 
   while(list != NULL){
     if(AGS_EDITOR_CHILD(list->data)->machine == machine){
+      //TODO:JK: remove work-around
+      g_signal_handlers_disconnect_by_data(machine->audio,
+					   AGS_EDITOR_CHILD(list->data)->notebook);
+      g_signal_handlers_disconnect_by_data(machine->audio,
+					   AGS_EDITOR_CHILD(list->data)->edit_widget);
+      
+      ags_connectable_disconnect(AGS_CONNECTABLE(AGS_EDITOR_CHILD(list->data)->notebook));
+      ags_connectable_disconnect(AGS_CONNECTABLE(AGS_EDITOR_CHILD(list->data)->edit_widget));
+      
       gtk_widget_destroy((GtkWidget *) AGS_EDITOR_CHILD(list->data)->notebook);
       gtk_widget_destroy((GtkWidget *) AGS_EDITOR_CHILD(list->data)->meter);
       gtk_widget_destroy((GtkWidget *) AGS_EDITOR_CHILD(list->data)->edit_widget);
@@ -186,7 +168,7 @@ ags_machine_popup_destroy_activate_callback(GtkWidget *widget, AgsMachine *machi
 
     list = list->next;
   }
-  
+
   list =
     list_start = gtk_container_get_children((GtkContainer *) window->editor->machine_selector);
 
@@ -203,8 +185,99 @@ ags_machine_popup_destroy_activate_callback(GtkWidget *widget, AgsMachine *machi
 
   g_list_free(list_start);
 
+  /* destroy automation editor */
+  list = window->automation_window->automation_editor->automation_editor_child;
+
+  while(list != NULL){
+    if(AGS_AUTOMATION_EDITOR_CHILD(list->data)->machine == machine){
+      //TODO:JK: remove work-around
+      g_signal_handlers_disconnect_by_data(machine->audio,
+					   AGS_AUTOMATION_EDITOR_CHILD(list->data)->output_notebook);
+      g_signal_handlers_disconnect_by_data(machine->audio,
+					   AGS_AUTOMATION_EDITOR_CHILD(list->data)->input_notebook);
+      
+      ags_connectable_disconnect(AGS_CONNECTABLE(AGS_AUTOMATION_EDITOR_CHILD(list->data)->output_notebook));
+      ags_connectable_disconnect(AGS_CONNECTABLE(AGS_AUTOMATION_EDITOR_CHILD(list->data)->input_notebook));
+      
+      gtk_widget_destroy((GtkWidget *) AGS_AUTOMATION_EDITOR_CHILD(list->data)->audio_scale);
+      gtk_widget_destroy((GtkWidget *) AGS_AUTOMATION_EDITOR_CHILD(list->data)->audio_automation_edit);
+
+      gtk_widget_destroy((GtkWidget *) AGS_AUTOMATION_EDITOR_CHILD(list->data)->output_scale);
+      gtk_widget_destroy((GtkWidget *) AGS_AUTOMATION_EDITOR_CHILD(list->data)->output_notebook);
+      gtk_widget_destroy((GtkWidget *) AGS_AUTOMATION_EDITOR_CHILD(list->data)->output_automation_edit);
+
+      gtk_widget_destroy((GtkWidget *) AGS_AUTOMATION_EDITOR_CHILD(list->data)->input_scale);
+      gtk_widget_destroy((GtkWidget *) AGS_AUTOMATION_EDITOR_CHILD(list->data)->input_notebook);
+      gtk_widget_destroy((GtkWidget *) AGS_AUTOMATION_EDITOR_CHILD(list->data)->input_automation_edit);
+
+      break;
+    }
+
+    list = list->next;
+  }
+  
+  list =
+    list_start = gtk_container_get_children((GtkContainer *) window->automation_window->automation_editor->machine_selector);
+
+  list = list->next;
+
+  while(list != NULL){
+    if(AGS_IS_MACHINE_RADIO_BUTTON(list->data) && AGS_MACHINE_RADIO_BUTTON(list->data)->machine == machine){
+      gtk_widget_destroy(list->data);
+      break;
+    }
+    
+    list = list->next;
+  }
+
+  g_list_free(list_start);
+
   /* destroy machine */
+  ags_connectable_disconnect(AGS_CONNECTABLE(machine));
   gtk_widget_destroy((GtkWidget *) machine);
+
+  gdk_threads_leave();
+}
+
+void
+ags_machine_popup_destroy_activate_callback(GtkWidget *widget, AgsMachine *machine)
+{
+  AgsWindow *window;
+  AgsRemoveAudio *remove_audio;
+
+  AgsMutexManager *mutex_manager;
+  AgsAudioLoop *audio_loop;
+  AgsTaskThread *task_thread;
+
+  AgsApplicationContext *application_context;
+
+  pthread_mutex_t *application_mutex;
+  
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) machine);
+
+  application_context = (AgsApplicationContext *) window->application_context;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+  
+  /* get audio loop */
+  pthread_mutex_lock(application_mutex);
+
+  audio_loop = (AgsAudioLoop *) application_context->main_loop;
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* get task thread */
+  task_thread = (AgsTaskThread *) ags_thread_find_type((AgsThread *) audio_loop,
+						       AGS_TYPE_TASK_THREAD);
+
+  g_object_ref(machine->audio);
+  remove_audio = ags_remove_audio_new(window->soundcard,
+				      machine->audio);
+  g_signal_connect(remove_audio, "launch\0",
+		   G_CALLBACK(ags_machine_remove_audio_launch_callback), machine);
+  ags_task_thread_append_task(task_thread,
+			      AGS_TASK(remove_audio));
 }
 
 int
@@ -258,10 +331,12 @@ ags_machine_popup_rename_response_callback(GtkWidget *widget, gint response, Ags
     gtk_menu_tool_button_set_menu((GtkMenuToolButton *) gtk_frame_get_label_widget((GtkFrame *) gtk_bin_get_child((GtkBin *) machine)),
 				  NULL);
     gtk_widget_destroy(gtk_frame_get_label_widget((GtkFrame *) gtk_bin_get_child((GtkBin *) machine)));
-    menu_tool_button = g_object_new(GTK_TYPE_MENU_TOOL_BUTTON,
-				    "label\0", g_strconcat(G_OBJECT_TYPE_NAME(machine), ": \0", text, NULL),
-				    "menu\0", machine->popup,
-				    NULL);
+
+    menu_tool_button = 
+      machine->menu_tool_button = g_object_new(GTK_TYPE_MENU_TOOL_BUTTON,
+					       "label\0", g_strconcat(G_OBJECT_TYPE_NAME(machine), ": \0", text, NULL),
+					       "menu\0", machine->popup,
+					       NULL);
     gtk_frame_set_label_widget((GtkFrame *) gtk_bin_get_child((GtkBin *) machine),
 			       (GtkWidget *) menu_tool_button);
     gtk_widget_show_all((GtkWidget *) menu_tool_button);
@@ -620,11 +695,18 @@ ags_machine_set_audio_channels_callback(AgsAudio *audio,
 					guint audio_channels, guint audio_channels_old,
 					AgsMachine *machine)
 {
+  AgsWindow *window;
+
   GList *pad_list;
   GList *line_list;
   
   guint i;
   
+  gdk_threads_enter();
+
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) machine);
+
+  /* resize */
   ags_machine_resize_audio_channels(machine,
 				    audio_channels, audio_channels_old);
 
@@ -667,6 +749,8 @@ ags_machine_set_audio_channels_callback(AgsAudio *audio,
       }
     }
   }
+
+  gdk_threads_leave();
 }
 
 void
@@ -674,8 +758,15 @@ ags_machine_set_pads_callback(AgsAudio *audio, GType channel_type,
 			      guint pads, guint pads_old,
 			      AgsMachine *machine)
 {
+  AgsWindow *window;
+
   GList *pad_list;
   
+  gdk_threads_enter();
+
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) machine);
+
+  /* resize */
   ags_machine_resize_pads(machine,
 			  channel_type,
 			  pads, pads_old);
@@ -709,6 +800,8 @@ ags_machine_set_pads_callback(AgsAudio *audio, GType channel_type,
       }
     }
   }
+
+  gdk_threads_leave();
 }
 
 void
@@ -752,11 +845,32 @@ ags_machine_start_complete_callback(AgsTaskCompletion *task_completion,
   
   AgsSoundcardThread *soundcard_thread;
 
+  AgsMutexManager *mutex_manager;
+  AgsAudioLoop *audio_loop;
+
+  AgsApplicationContext *application_context;
+
+  pthread_mutex_t *application_mutex;
+
   gdk_threads_enter();
 
   window = (AgsWindow *) gtk_widget_get_ancestor((GtkWidget *) machine,
 						 AGS_TYPE_WINDOW);
-  soundcard_thread = (AgsSoundcardThread *) ags_thread_find_type((AgsThread *) AGS_APPLICATION_CONTEXT(window->application_context)->main_loop,
+
+  application_context = (AgsApplicationContext *) window->application_context;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+  
+  /* get audio loop */
+  pthread_mutex_lock(application_mutex);
+
+  audio_loop = (AgsAudioLoop *) application_context->main_loop;
+
+  pthread_mutex_unlock(application_mutex);
+
+  /* get soundcard thread */
+  soundcard_thread = (AgsSoundcardThread *) ags_thread_find_type((AgsThread *) audio_loop,
 								 AGS_TYPE_SOUNDCARD_THREAD);
 
   if(soundcard_thread->error != NULL){
diff --git a/ags/X/ags_navigation.c b/ags/X/ags_navigation.c
index 318c8a4..3801586 100644
--- a/ags/X/ags_navigation.c
+++ b/ags/X/ags_navigation.c
@@ -202,6 +202,8 @@ ags_navigation_init(AgsNavigation *navigation)
   gtk_box_pack_start((GtkBox *) navigation, (GtkWidget *) hbox, FALSE, FALSE, 2);
 
   navigation->expander = (GtkToggleButton *) gtk_toggle_button_new();
+  gtk_widget_set_name(navigation->expander,
+		      "ags-navigation-expander\0");
   gtk_box_pack_start((GtkBox*) hbox, (GtkWidget *) navigation->expander, FALSE, FALSE, 2);
   gtk_container_add((GtkContainer *) navigation->expander,
 		    (GtkWidget *) gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_NONE));
@@ -294,11 +296,13 @@ ags_navigation_init(AgsNavigation *navigation)
   gtk_box_pack_start((GtkBox *) hbox, (GtkWidget *) navigation->loop_right_tact, FALSE, FALSE, 2);
 
   navigation->scroll = NULL;
+  /*
   navigation->scroll = (GtkCheckButton *) gtk_check_button_new_with_label("auto-scroll\0");
   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(navigation->scroll),
 			       FALSE);
   gtk_box_pack_start((GtkBox *) hbox, (GtkWidget *) navigation->scroll, FALSE, FALSE, 2);
-
+  */
+  
   navigation->exclude_sequencer = (GtkCheckButton *) gtk_check_button_new_with_label("exclude sequencers\0");
   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(navigation->exclude_sequencer),
 			       TRUE);
@@ -750,6 +754,8 @@ gboolean
 ags_navigation_duration_time_queue_draw(GtkWidget *widget)
 {
   AgsNavigation *navigation;
+
+  gchar *str;
   
   gdk_threads_enter();
 
@@ -760,10 +766,13 @@ ags_navigation_duration_time_queue_draw(GtkWidget *widget)
     
     return(TRUE);
   }
-  
+
+  str = ags_soundcard_get_uptime(AGS_SOUNDCARD(navigation->soundcard));
   g_object_set(navigation->duration_time,
-	       "label\0", ags_soundcard_get_uptime(AGS_SOUNDCARD(navigation->soundcard)),
+	       "label\0", str,
 	       NULL);
+  g_free(str);
+  
   gtk_widget_queue_draw((GtkWidget *) navigation->duration_time);
 
   gdk_threads_leave();
diff --git a/ags/X/ags_output_collection_editor.c b/ags/X/ags_output_collection_editor.c
new file mode 100644
index 0000000..4e28259
--- /dev/null
+++ b/ags/X/ags_output_collection_editor.c
@@ -0,0 +1,589 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2015 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/X/ags_output_collection_editor.h>
+#include <ags/X/ags_output_collection_editor_callbacks.h>
+
+#include <ags/object/ags_application_context.h>
+#include <ags/object/ags_connectable.h>
+#include <ags/object/ags_soundcard.h>
+#include <ags/object/ags_applicable.h>
+
+#include <ags/thread/ags_mutex_manager.h>
+#include <ags/thread/ags_task_thread.h>
+
+#include <ags/audio/ags_audio.h>
+#include <ags/audio/ags_input.h>
+
+#include <ags/audio/task/ags_reset_audio_connection.h>
+
+#include <ags/audio/thread/ags_audio_loop.h>
+
+#include <ags/X/ags_window.h>
+#include <ags/X/ags_machine.h>
+#include <ags/X/ags_connection_editor.h>
+
+void ags_output_collection_editor_class_init(AgsOutputCollectionEditorClass *output_collection_editor);
+void ags_output_collection_editor_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_output_collection_editor_applicable_interface_init(AgsApplicableInterface *applicable);
+void ags_output_collection_editor_init(AgsOutputCollectionEditor *output_collection_editor);
+void ags_output_collection_editor_set_property(GObject *gobject,
+					       guint prop_id,
+					       const GValue *value,
+					       GParamSpec *param_spec);
+void ags_output_collection_editor_get_property(GObject *gobject,
+					       guint prop_id,
+					       GValue *value,
+					       GParamSpec *param_spec);
+void ags_output_collection_editor_connect(AgsConnectable *connectable);
+void ags_output_collection_editor_disconnect(AgsConnectable *connectable);
+void ags_output_collection_editor_set_update(AgsApplicable *applicable, gboolean update);
+void ags_output_collection_editor_apply(AgsApplicable *applicable);
+void ags_output_collection_editor_reset(AgsApplicable *applicable);
+
+/**
+ * SECTION:ags_output_collection_editor
+ * @short_description: edit audio connections in bulk mode.
+ * @title: AgsOutputCollectionEditor
+ * @section_id:
+ * @include: ags/X/ags_output_collection_editor.h
+ *
+ * #AgsOutputCollectionEditor is a composite widget to modify audio connections. A output collection
+ * editor should be packed by a #AgsConnectionEditor.
+ */
+
+static gpointer ags_output_collection_editor_parent_class = NULL;
+
+enum{
+  PROP_0,
+  PROP_CHANNEL_TYPE,
+};
+
+GType
+ags_output_collection_editor_get_type(void)
+{
+  static GType ags_type_output_collection_editor = 0;
+
+  if(!ags_type_output_collection_editor){
+    static const GTypeInfo ags_output_collection_editor_info = {
+      sizeof (AgsOutputCollectionEditorClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_output_collection_editor_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof (AgsOutputCollectionEditor),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_output_collection_editor_init,
+    };
+
+    static const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_output_collection_editor_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    static const GInterfaceInfo ags_applicable_interface_info = {
+      (GInterfaceInitFunc) ags_output_collection_editor_applicable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    ags_type_output_collection_editor = g_type_register_static(GTK_TYPE_TABLE,
+							       "AgsOutputCollectionEditor\0",
+							       &ags_output_collection_editor_info,
+							       0);
+    
+    g_type_add_interface_static(ags_type_output_collection_editor,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+
+    g_type_add_interface_static(ags_type_output_collection_editor,
+				AGS_TYPE_APPLICABLE,
+				&ags_applicable_interface_info);
+  }
+
+  return(ags_type_output_collection_editor);
+}
+
+void
+ags_output_collection_editor_class_init(AgsOutputCollectionEditorClass *output_collection_editor)
+{
+  GObjectClass *gobject;
+  GParamSpec *param_spec;
+
+  ags_output_collection_editor_parent_class = g_type_class_peek_parent(output_collection_editor);
+
+  /* GObjectClass */
+  gobject = (GObjectClass *) output_collection_editor;
+
+  gobject->set_property = ags_output_collection_editor_set_property;
+  gobject->get_property = ags_output_collection_editor_get_property;
+  
+  /* properties */
+  /**
+   * AgsOutputCollectionEditor:channel-type:
+   *
+   * The channel type to apply to. Either %AGS_TYPE_INPUT or %AGS_TYPE_OUTPUT.
+   * 
+   * Since: 0.7.65
+   */
+  param_spec = g_param_spec_gtype("channel-type\0",
+				  "assigned channel type\0",
+				  "The channel type which this channel output collection editor is assigned with\0",
+				  G_TYPE_NONE,
+				  G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_CHANNEL_TYPE,
+				  param_spec);
+}
+
+void
+ags_output_collection_editor_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  connectable->connect = ags_output_collection_editor_connect;
+  connectable->disconnect = ags_output_collection_editor_disconnect;
+}
+
+void
+ags_output_collection_editor_applicable_interface_init(AgsApplicableInterface *applicable)
+{
+  applicable->set_update = ags_output_collection_editor_set_update;
+  applicable->apply = ags_output_collection_editor_apply;
+  applicable->reset = ags_output_collection_editor_reset;
+}
+
+void
+ags_output_collection_editor_init(AgsOutputCollectionEditor *output_collection_editor)
+{
+  GtkAlignment *alignment;
+  GtkLabel *label;
+  
+  g_signal_connect_after(GTK_WIDGET(output_collection_editor), "parent-set\0",
+			 G_CALLBACK(ags_output_collection_editor_parent_set_callback), output_collection_editor);
+
+  output_collection_editor->channel_type = G_TYPE_NONE;
+  
+  gtk_table_resize(GTK_TABLE(output_collection_editor),
+		   4, 2);
+  gtk_table_set_row_spacings(GTK_TABLE(output_collection_editor),
+			     4);
+  gtk_table_set_col_spacings(GTK_TABLE(output_collection_editor),
+			     2);
+
+  /* first line */
+  alignment = (GtkAlignment *) gtk_alignment_new(0.0, 0.5,
+						 0.0, 0.0);
+  gtk_table_attach(GTK_TABLE(output_collection_editor),
+		   GTK_WIDGET(alignment),
+		   0, 1,
+		   0, 1,
+		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
+		   0, 0);
+
+  label = (GtkLabel *) gtk_label_new("first line\0");
+  gtk_container_add(GTK_CONTAINER(alignment),
+		    GTK_WIDGET(label));
+
+  output_collection_editor->first_line = (GtkSpinButton *) gtk_spin_button_new_with_range(-1.0,
+											  -1.0,
+											  1.0);
+  gtk_table_attach(GTK_TABLE(output_collection_editor),
+		   GTK_WIDGET(output_collection_editor->first_line),
+		   1, 2,
+		   0, 1,
+		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
+		   0, 0);
+
+  /* count */
+  alignment = (GtkAlignment *) gtk_alignment_new(0.0, 0.5,
+						 0.0, 0.0);
+  gtk_table_attach(GTK_TABLE(output_collection_editor),
+		   GTK_WIDGET(alignment),
+		   0, 1,
+		   1, 2,
+		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
+		   0, 0);
+
+  label = (GtkLabel *) gtk_label_new("count\0");
+  gtk_container_add(GTK_CONTAINER(alignment),
+		    GTK_WIDGET(label));
+
+  output_collection_editor->count = (GtkSpinButton *) gtk_spin_button_new_with_range(-1.0,
+										     -1.0,
+										     1.0);
+  gtk_table_attach(GTK_TABLE(output_collection_editor),
+		   GTK_WIDGET(output_collection_editor->count),
+		   1, 2,
+		   1, 2,
+		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
+		   0, 0);
+
+  /* soundcard */
+  alignment = (GtkAlignment *) gtk_alignment_new(0.0, 0.5,
+						 0.0, 0.0);
+  gtk_table_attach(GTK_TABLE(output_collection_editor),
+		   GTK_WIDGET(alignment),
+		   0, 1,
+		   2, 3,
+		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
+		   0, 0);
+
+  label = (GtkLabel *) gtk_label_new("soundcard\0");
+  gtk_container_add(GTK_CONTAINER(alignment),
+		    GTK_WIDGET(label));
+
+  output_collection_editor->soundcard = (GtkComboBoxText *) gtk_combo_box_text_new();
+  gtk_table_attach(GTK_TABLE(output_collection_editor),
+		   GTK_WIDGET(output_collection_editor->soundcard),
+		   1, 2,
+		   2, 3,
+		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
+		   0, 0);
+
+  /* audio channel */
+  alignment = (GtkAlignment *) gtk_alignment_new(0.0, 0.5,
+						 0.0, 0.0);
+  gtk_table_attach(GTK_TABLE(output_collection_editor),
+		   GTK_WIDGET(alignment),
+		   0, 1,
+		   3, 4,
+		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
+		   0, 0);
+
+  label = (GtkLabel *) gtk_label_new("audio channel\0");
+  gtk_container_add(GTK_CONTAINER(alignment),
+		    GTK_WIDGET(label));
+
+  output_collection_editor->audio_channel = (GtkSpinButton *) gtk_spin_button_new_with_range(-1.0,
+											     -1.0,
+											     1.0);
+  gtk_table_attach(GTK_TABLE(output_collection_editor),
+		   GTK_WIDGET(output_collection_editor->audio_channel),
+		   1, 2,
+		   3, 4,
+		   GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
+		   0, 0);
+}
+
+
+void
+ags_output_collection_editor_set_property(GObject *gobject,
+					  guint prop_id,
+					  const GValue *value,
+					  GParamSpec *param_spec)
+{
+  AgsOutputCollectionEditor *output_collection_editor;
+
+  output_collection_editor = AGS_OUTPUT_COLLECTION_EDITOR(gobject);
+
+  switch(prop_id){
+  case PROP_CHANNEL_TYPE:
+    output_collection_editor->channel_type = g_value_get_gtype(value);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  }
+}
+
+void
+ags_output_collection_editor_get_property(GObject *gobject,
+					  guint prop_id,
+					  GValue *value,
+					  GParamSpec *param_spec)
+{
+  AgsOutputCollectionEditor *output_collection_editor;
+
+  output_collection_editor = AGS_OUTPUT_COLLECTION_EDITOR(gobject);
+
+  switch(prop_id){
+  case PROP_CHANNEL_TYPE:
+    g_value_set_gtype(value, output_collection_editor->channel_type);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  }
+}
+
+void
+ags_output_collection_editor_connect(AgsConnectable *connectable)
+{
+  AgsOutputCollectionEditor *output_collection_editor;
+
+  /* AgsOutputCollectionEditor */
+  output_collection_editor = AGS_OUTPUT_COLLECTION_EDITOR(connectable);
+
+  g_signal_connect_after(G_OBJECT(output_collection_editor->soundcard), "changed\0",
+			 G_CALLBACK(ags_output_collection_editor_soundcard_callback), output_collection_editor);
+}
+
+void
+ags_output_collection_editor_disconnect(AgsConnectable *connectable)
+{
+  AgsOutputCollectionEditor *output_collection_editor;
+
+  /* AgsOutputCollectionEditor */
+  output_collection_editor = AGS_OUTPUT_COLLECTION_EDITOR(connectable);
+
+  g_object_disconnect(G_OBJECT(output_collection_editor->soundcard),
+		      "changed\0",
+		      G_CALLBACK(ags_output_collection_editor_soundcard_callback),
+		      output_collection_editor,
+		      NULL);
+}
+
+void
+ags_output_collection_editor_set_update(AgsApplicable *applicable, gboolean update)
+{
+  /* empty */
+}
+
+void
+ags_output_collection_editor_apply(AgsApplicable *applicable)
+{
+  AgsOutputCollectionEditor *output_collection_editor;
+  GtkTreeIter iter;
+
+  output_collection_editor = AGS_OUTPUT_COLLECTION_EDITOR(applicable);
+
+  if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(output_collection_editor->soundcard),
+				   &iter)){
+    AgsWindow *window;
+    AgsMachine *machine;
+    AgsConnectionEditor *connection_editor;
+
+    AgsAudio *audio;
+
+    AgsResetAudioConnection *reset_audio_connection;
+    
+    AgsMutexManager *mutex_manager;
+    AgsAudioLoop *audio_loop;
+    AgsTaskThread *task_thread;
+
+    AgsApplicationContext *application_context;
+    GObject *soundcard;
+
+    GtkTreeModel *model;
+
+    GList *task;
+    
+    guint audio_channels;
+    guint first_line, count;
+    guint audio_channel;
+    guint i;
+    
+    pthread_mutex_t *application_mutex;
+    pthread_mutex_t *audio_mutex;
+
+    connection_editor = AGS_CONNECTION_EDITOR(gtk_widget_get_ancestor(GTK_WIDGET(output_collection_editor),
+								      AGS_TYPE_CONNECTION_EDITOR));
+    machine = connection_editor->machine;
+    audio = machine->audio;
+
+    /* get window and application_context  */
+    window = (AgsWindow *) gtk_widget_get_toplevel(GTK_WIDGET(machine));
+  
+    application_context = (AgsApplicationContext *) window->application_context;
+    
+    mutex_manager = ags_mutex_manager_get_instance();
+    application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+    
+    /* get audio loop */
+    pthread_mutex_lock(application_mutex);
+
+    audio_loop = (AgsAudioLoop *) application_context->main_loop;
+
+    pthread_mutex_unlock(application_mutex);
+
+    /* lookup audio mutex */
+    pthread_mutex_lock(application_mutex);
+
+    audio_mutex = ags_mutex_manager_lookup(mutex_manager,
+					   audio);
+
+    pthread_mutex_unlock(application_mutex);
+
+    /* get audio fields */
+    pthread_mutex_lock(audio_mutex);
+
+    audio_channels = audio->audio_channels;
+    
+    pthread_mutex_unlock(audio_mutex);
+
+    /* get task and soundcard thread */
+    task_thread = (AgsTaskThread *) ags_thread_find_type((AgsThread *) audio_loop,
+							 AGS_TYPE_TASK_THREAD);
+
+    /* get mapping and soundcard */
+    first_line = (guint) gtk_spin_button_get_value_as_int(output_collection_editor->first_line);
+    count = (guint) gtk_spin_button_get_value_as_int(output_collection_editor->count);
+
+    audio_channel = (guint) gtk_spin_button_get_value_as_int(output_collection_editor->audio_channel);
+
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(output_collection_editor->soundcard));
+    gtk_tree_model_get(model,
+		       &iter,
+		       1, &soundcard,
+		       -1);
+
+    /* create task */
+    task = NULL;
+    
+    for(i = 0; i < count; i++){
+      reset_audio_connection = ags_reset_audio_connection_new(soundcard,
+							      audio,
+							      output_collection_editor->channel_type,
+							      floor((double) (first_line + i) / (double) audio_channels),
+							      (first_line + i) % audio_channels,
+							      audio_channel + i);
+      task = g_list_prepend(task,
+			    reset_audio_connection);
+    }
+    
+    ags_task_thread_append_tasks(task_thread,
+				 (AgsTask *) task);
+  }
+}
+
+void
+ags_output_collection_editor_reset(AgsApplicable *applicable)
+{
+  /* empty */
+}
+
+/**
+ * ags_output_collection_editor_check:
+ * @output_collection_editor: the #AgsOutputCollectionEditor
+ *
+ * Checks for possible channels to output. And modifies its ranges.
+ * 
+ * Since: 0.7.65
+ */
+void
+ags_output_collection_editor_check(AgsOutputCollectionEditor *output_collection_editor)
+{
+  AgsConnectionEditor *connection_editor;
+
+  AgsAudio *audio;
+
+  AgsMutexManager *mutex_manager;
+  
+  GtkTreeIter iter;
+  
+  guint count;
+  
+  pthread_mutex_t *application_mutex;
+  pthread_mutex_t *audio_mutex;
+
+  connection_editor = AGS_CONNECTION_EDITOR(gtk_widget_get_ancestor(GTK_WIDGET(output_collection_editor),
+								    AGS_TYPE_CONNECTION_EDITOR));
+  audio = connection_editor->machine->audio;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* lookup audio mutex */
+  pthread_mutex_lock(application_mutex);
+
+  audio_mutex = (AgsAudioLoop *) ags_mutex_manager_lookup(mutex_manager,
+							  audio);
+
+  pthread_mutex_unlock(application_mutex);
+
+  /* get audio fields */
+  if(output_collection_editor->channel_type == AGS_TYPE_INPUT){
+    pthread_mutex_lock(audio_mutex);
+
+    count = audio->input_lines;
+    
+    pthread_mutex_unlock(audio_mutex);
+  }else{
+    pthread_mutex_lock(audio_mutex);
+    
+    count = audio->output_lines;
+    
+    pthread_mutex_unlock(audio_mutex);
+  }
+
+  gtk_spin_button_set_range(output_collection_editor->first_line,
+			    0.0,
+			    count - 1.0);
+  gtk_spin_button_set_range(output_collection_editor->count,
+			    0.0,
+			    count);
+
+  if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(output_collection_editor->soundcard),
+				   &iter)){    
+    GObject *soundcard;
+    
+    GtkTreeModel *model;
+
+    guint audio_channels;
+    
+    /* soundcard connection */
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(output_collection_editor->soundcard));
+    gtk_tree_model_get(model,
+		       &iter,
+		       1, &soundcard,
+		       -1);
+
+    ags_soundcard_get_presets(AGS_SOUNDCARD(soundcard),
+			      &audio_channels,
+			      NULL,
+			      NULL,
+			      NULL);
+
+    gtk_spin_button_set_range(output_collection_editor->audio_channel,
+			      0.0,
+			      audio_channels - 1.0);
+
+    if(audio_channels < count){
+      gtk_spin_button_set_range(output_collection_editor->count,
+				0.0,
+				audio_channels);
+    }
+  }else{
+    gtk_spin_button_set_range(output_collection_editor->audio_channel,
+			      -1.0, -1.0);
+  }
+}
+
+/**
+ * ags_output_collection_editor_new:
+ * @channel_type: either %AGS_TYPE_INPUT or %AGS_TYPE_OUTPUT
+ *
+ * Creates an #AgsOutputCollectionEditor
+ *
+ * Returns: a new #AgsOutputCollectionEditor
+ *
+ * Since: 0.7.65
+ */
+AgsOutputCollectionEditor*
+ags_output_collection_editor_new(GType channel_type)
+{
+  AgsOutputCollectionEditor *output_collection_editor;
+  
+  output_collection_editor = (AgsOutputCollectionEditor *) g_object_new(AGS_TYPE_OUTPUT_COLLECTION_EDITOR,
+									"channel_type\0", channel_type,
+									NULL);
+  
+  return(output_collection_editor);
+}
diff --git a/ags/X/ags_output_collection_editor.h b/ags/X/ags_output_collection_editor.h
new file mode 100644
index 0000000..054ee07
--- /dev/null
+++ b/ags/X/ags_output_collection_editor.h
@@ -0,0 +1,62 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2015 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_OUTPUT_COLLECTION_EDITOR_H__
+#define __AGS_OUTPUT_COLLECTION_EDITOR_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+#define AGS_TYPE_OUTPUT_COLLECTION_EDITOR                (ags_output_collection_editor_get_type())
+#define AGS_OUTPUT_COLLECTION_EDITOR(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_OUTPUT_COLLECTION_EDITOR, AgsOutputCollectionEditor))
+#define AGS_OUTPUT_COLLECTION_EDITOR_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_OUTPUT_COLLECTION_EDITOR, AgsOutputCollectionEditorClass))
+#define AGS_IS_OUTPUT_COLLECTION_EDITOR(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_OUTPUT_COLLECTION_EDITOR))
+#define AGS_IS_OUTPUT_COLLECTION_EDITOR_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_OUTPUT_COLLECTION_EDITOR))
+#define AGS_OUTPUT_COLLECTION_EDITOR_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_OUTPUT_COLLECTION_EDITOR, AgsOutputCollectionEditorClass))
+
+typedef struct _AgsOutputCollectionEditor AgsOutputCollectionEditor;
+typedef struct _AgsOutputCollectionEditorClass AgsOutputCollectionEditorClass;
+
+struct _AgsOutputCollectionEditor
+{
+  GtkTable table;
+
+  GType channel_type;
+
+  GtkSpinButton *first_line;
+  GtkSpinButton *count;
+  
+  GtkComboBoxText *soundcard;
+  GtkSpinButton *audio_channel;
+};
+
+struct _AgsOutputCollectionEditorClass
+{
+  GtkTableClass table;
+};
+
+GType ags_output_collection_editor_get_type();
+
+void ags_output_collection_editor_check(AgsOutputCollectionEditor *output_collection_editor);
+
+AgsOutputCollectionEditor* ags_output_collection_editor_new(GType channel_type);
+
+#endif /*__AGS_OUTPUT_COLLECTION_EDITOR_H__*/
diff --git a/ags/X/ags_audio_connection_collection_editor_callbacks.c b/ags/X/ags_output_collection_editor_callbacks.c
similarity index 63%
rename from ags/X/ags_audio_connection_collection_editor_callbacks.c
rename to ags/X/ags_output_collection_editor_callbacks.c
index c7e0402..e6ab3d6 100644
--- a/ags/X/ags_audio_connection_collection_editor_callbacks.c
+++ b/ags/X/ags_output_collection_editor_callbacks.c
@@ -17,34 +17,37 @@
  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <ags/X/ags_audio_connection_collection_editor_callbacks.h>
+#include <ags/X/ags_output_collection_editor_callbacks.h>
 
 #include <ags/X/ags_connection_editor.h>
 
 int
-ags_audio_connection_collection_editor_parent_set_callback(GtkWidget *widget, GtkObject *old_parent,
-							   AgsAudioConnectionCollectionEditor *audio_connection_collection_editor)
+ags_output_collection_editor_parent_set_callback(GtkWidget *widget, GtkObject *old_parent,
+						 AgsOutputCollectionEditor *output_collection_editor)
 {
   AgsConnectionEditor *connection_editor;
 
-  if(old_parent != NULL)
+  if(old_parent != NULL){
     return(0);
+  }
 
   connection_editor = (AgsConnectionEditor *) gtk_widget_get_ancestor(widget, 
 								      AGS_TYPE_CONNECTION_EDITOR);
 
   if(connection_editor != NULL &&
      connection_editor->machine != NULL){
-    gtk_combo_box_set_model(GTK_COMBO_BOX(audio_connection_collection_editor->soundcard),
+    gtk_combo_box_set_model(GTK_COMBO_BOX(output_collection_editor->soundcard),
 			    GTK_TREE_MODEL(ags_machine_get_possible_audio_output_connections(connection_editor->machine)));
 
-    ags_audio_connection_collection_editor_check(audio_connection_collection_editor);
+    ags_output_collection_editor_check(output_collection_editor);
   }
+
+  return(0);
 }
 
 void
-ags_audio_connection_collection_editor_soundcard_callback(GtkWidget *combo_box,
-							  AgsAudioConnectionCollectionEditor *audio_connection_collection_editor)
+ags_output_collection_editor_soundcard_callback(GtkWidget *combo_box,
+						AgsOutputCollectionEditor *output_collection_editor)
 {
-  ags_audio_connection_collection_editor_check(audio_connection_collection_editor);
+  ags_output_collection_editor_check(output_collection_editor);
 }
diff --git a/ags/X/ags_plugin_browser_callbacks.h b/ags/X/ags_output_collection_editor_callbacks.h
similarity index 62%
copy from ags/X/ags_plugin_browser_callbacks.h
copy to ags/X/ags_output_collection_editor_callbacks.h
index 9f63a22..f06e40c 100644
--- a/ags/X/ags_plugin_browser_callbacks.h
+++ b/ags/X/ags_output_collection_editor_callbacks.h
@@ -17,20 +17,20 @@
  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __AGS_PLUGIN_BROWSER_CALLBACKS_H__
-#define __AGS_PLUGIN_BROWSER_CALLBACKS_H__
+#ifndef __AGS_OUTPUT_COLLECTION_EDITOR_CALLBACKS_H__
+#define __AGS_OUTPUT_COLLECTION_EDITOR_CALLBACKS_H__
 
 #include <glib.h>
 #include <glib-object.h>
+
 #include <gtk/gtk.h>
 
-#include <ags/X/ags_plugin_browser.h>
-void ags_plugin_browser_plugin_type_changed_callback(GtkWidget *combo_box,
-						     AgsPluginBrowser *plugin_browser);
+#include <ags/X/ags_output_collection_editor.h>
+
+int ags_output_collection_editor_parent_set_callback(GtkWidget *widget, GtkObject *old_parent,
+						     AgsOutputCollectionEditor *output_collection_editor);
 
-void ags_plugin_browser_ok_callback(GtkWidget *button,
-				    AgsPluginBrowser *plugin_browser);
-void ags_plugin_browser_cancel_callback(GtkWidget *button,
-					AgsPluginBrowser *plugin_browser);
+void ags_output_collection_editor_soundcard_callback(GtkWidget *combo_box,
+						     AgsOutputCollectionEditor *output_collection_editor);
 
-#endif /*__AGS_PLUGIN_BROWSER_CALLBACKS_H__*/
+#endif /*__AGS_OUTPUT_COLLECTION_EDITOR_CALLBACKS_H__*/
diff --git a/ags/X/ags_output_editor.c b/ags/X/ags_output_editor.c
new file mode 100644
index 0000000..655b057
--- /dev/null
+++ b/ags/X/ags_output_editor.c
@@ -0,0 +1,477 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2015 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/X/ags_output_editor.h>
+#include <ags/X/ags_output_editor_callbacks.h>
+
+#include <ags/object/ags_connectable.h>
+#include <ags/object/ags_applicable.h>
+
+#include <ags/thread/ags_mutex_manager.h>
+#include <ags/thread/ags_task_thread.h>
+
+#include <ags/audio/ags_audio.h>
+#include <ags/audio/ags_audio_connection.h>
+#include <ags/audio/ags_input.h>
+
+#include <ags/audio/task/ags_reset_audio_connection.h>
+
+#include <ags/audio/thread/ags_audio_loop.h>
+
+#include <ags/X/ags_window.h>
+#include <ags/X/ags_machine.h>
+#include <ags/X/ags_connection_editor.h>
+#include <ags/X/ags_line_editor.h>
+
+void ags_output_editor_class_init(AgsOutputEditorClass *output_editor);
+void ags_output_editor_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_output_editor_applicable_interface_init(AgsApplicableInterface *applicable);
+void ags_output_editor_init(AgsOutputEditor *output_editor);
+void ags_output_editor_connect(AgsConnectable *connectable);
+void ags_output_editor_disconnect(AgsConnectable *connectable);
+void ags_output_editor_set_update(AgsApplicable *applicable, gboolean update);
+void ags_output_editor_apply(AgsApplicable *applicable);
+void ags_output_editor_reset(AgsApplicable *applicable);
+
+/**
+ * SECTION:ags_output_editor
+ * @short_description: A composite widget to edit #AgsChannel
+ * @title: AgsOutputEditor
+ * @section_id:
+ * @include: ags/X/ags_output_editor.h
+ *
+ * #AgsOutputEditor is a composite widget to edit #AgsChannel.
+ */
+
+static gpointer ags_output_editor_parent_class = NULL;
+
+GType
+ags_output_editor_get_type(void)
+{
+  static GType ags_type_output_editor = 0;
+
+  if(!ags_type_output_editor){
+    static const GTypeInfo ags_output_editor_info = {
+      sizeof (AgsOutputEditorClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_output_editor_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof (AgsOutputEditor),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_output_editor_init,
+    };
+
+    static const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_output_editor_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    static const GInterfaceInfo ags_applicable_interface_info = {
+      (GInterfaceInitFunc) ags_output_editor_applicable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    ags_type_output_editor = g_type_register_static(GTK_TYPE_HBOX,
+						    "AgsOutputEditor\0", &ags_output_editor_info,
+						    0);
+
+    g_type_add_interface_static(ags_type_output_editor,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+
+    g_type_add_interface_static(ags_type_output_editor,
+				AGS_TYPE_APPLICABLE,
+				&ags_applicable_interface_info);
+  }
+  
+  return(ags_type_output_editor);
+}
+
+void
+ags_output_editor_class_init(AgsOutputEditorClass *output_editor)
+{
+  ags_output_editor_parent_class = g_type_class_peek_parent(output_editor);
+}
+
+void
+ags_output_editor_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  connectable->is_ready = NULL;
+  connectable->is_connected = NULL;
+  connectable->connect = ags_output_editor_connect;
+  connectable->disconnect = ags_output_editor_disconnect;
+}
+
+void
+ags_output_editor_applicable_interface_init(AgsApplicableInterface *applicable)
+{
+  applicable->set_update = ags_output_editor_set_update;
+  applicable->apply = ags_output_editor_apply;
+  applicable->reset = ags_output_editor_reset;
+}
+
+void
+ags_output_editor_init(AgsOutputEditor *output_editor)
+{
+  g_signal_connect_after((GObject *) output_editor, "parent_set\0",
+			 G_CALLBACK(ags_output_editor_parent_set_callback), (gpointer) output_editor);
+
+  output_editor->flags = 0;
+
+  output_editor->version = AGS_OUTPUT_EDITOR_DEFAULT_VERSION;
+  output_editor->build_id = AGS_OUTPUT_EDITOR_DEFAULT_BUILD_ID;
+
+  /* connecting soundcard */
+  output_editor->soundcard = (GtkComboBoxText *) gtk_combo_box_text_new();
+  gtk_box_pack_start(GTK_BOX(output_editor),
+		     GTK_WIDGET(output_editor->soundcard),
+		     FALSE, FALSE,
+		     0);
+
+  /* connect with line */
+  output_editor->audio_channel = (GtkSpinButton *) gtk_spin_button_new_with_range(0.0, 0.0, 1.0);
+  gtk_box_pack_start(GTK_BOX(output_editor),
+		     GTK_WIDGET(output_editor->audio_channel),
+		     FALSE, FALSE,
+		     0);
+}
+
+void
+ags_output_editor_connect(AgsConnectable *connectable)
+{
+  AgsOutputEditor *output_editor;
+
+  output_editor = AGS_OUTPUT_EDITOR(connectable);
+
+  if((AGS_OUTPUT_EDITOR_CONNECTED & (output_editor->flags)) != 0){
+    return;
+  }
+
+  output_editor->flags |= AGS_OUTPUT_EDITOR_CONNECTED;
+
+  g_signal_connect(G_OBJECT(output_editor->soundcard), "changed\0",
+		   G_CALLBACK(ags_output_editor_soundcard_callback), output_editor);
+}
+
+void
+ags_output_editor_disconnect(AgsConnectable *connectable)
+{
+  AgsOutputEditor *output_editor;
+
+  output_editor = AGS_OUTPUT_EDITOR(connectable);
+
+  if((AGS_OUTPUT_EDITOR_CONNECTED & (output_editor->flags)) == 0){
+    return;
+  }
+
+  output_editor->flags &= (~AGS_OUTPUT_EDITOR_CONNECTED);
+
+  g_object_disconnect(G_OBJECT(output_editor->soundcard),
+		      "changed\0",
+		      G_CALLBACK(ags_output_editor_soundcard_callback),
+		      output_editor,
+		      NULL);
+}
+
+void
+ags_output_editor_set_update(AgsApplicable *applicable, gboolean update)
+{
+  //TODO:JK: implement me
+}
+
+void
+ags_output_editor_apply(AgsApplicable *applicable)
+{
+  AgsOutputEditor *output_editor;
+  AgsLineEditor *line_editor;
+
+  GtkTreeIter iter;
+
+  output_editor = AGS_OUTPUT_EDITOR(applicable);
+
+  if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(output_editor->soundcard),
+				   &iter)){
+    AgsWindow *window;
+    AgsMachine *machine;
+    AgsConnectionEditor *connection_editor;
+
+    AgsAudio *audio;
+    AgsChannel *channel;
+
+    AgsResetAudioConnection *reset_audio_connection;
+    
+    AgsMutexManager *mutex_manager;
+    AgsAudioLoop *audio_loop;
+    AgsTaskThread *task_thread;
+
+    AgsApplicationContext *application_context;
+    GObject *soundcard;
+
+    GtkTreeModel *model;
+
+    guint soundcard_channel;
+    guint pad, audio_channel;
+    
+    pthread_mutex_t *application_mutex;
+    pthread_mutex_t *channel_mutex;
+
+    connection_editor = AGS_CONNECTION_EDITOR(gtk_widget_get_ancestor(GTK_WIDGET(output_editor),
+								      AGS_TYPE_CONNECTION_EDITOR));
+    line_editor = AGS_LINE_EDITOR(gtk_widget_get_ancestor(GTK_WIDGET(output_editor),
+							  AGS_TYPE_LINE_EDITOR));
+
+    machine = connection_editor->machine;
+    audio = machine->audio;
+    channel = line_editor->channel;
+    
+    /* get window and application_context  */
+    window = (AgsWindow *) gtk_widget_get_toplevel(GTK_WIDGET(machine));
+  
+    application_context = (AgsApplicationContext *) window->application_context;
+    
+    mutex_manager = ags_mutex_manager_get_instance();
+    application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+    
+    /* get audio loop */
+    pthread_mutex_lock(application_mutex);
+
+    audio_loop = (AgsAudioLoop *) application_context->main_loop;
+
+    pthread_mutex_unlock(application_mutex);
+
+    /* lookup channel mutex */
+    pthread_mutex_lock(application_mutex);
+
+    channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+					     channel);
+
+    pthread_mutex_unlock(application_mutex);
+
+    /* get audio fields */
+    pthread_mutex_lock(channel_mutex);
+
+    pad = channel->pad;
+    audio_channel = channel->audio_channel;
+    
+    pthread_mutex_unlock(channel_mutex);
+
+    /* get task and soundcard thread */
+    task_thread = (AgsTaskThread *) ags_thread_find_type((AgsThread *) audio_loop,
+							 AGS_TYPE_TASK_THREAD);
+
+    /* get mapping and soundcard */
+    soundcard_channel = (guint) gtk_spin_button_get_value_as_int(output_editor->audio_channel);
+
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(output_editor->soundcard));
+    gtk_tree_model_get(model,
+		       &iter,
+		       1, &soundcard,
+		       -1);
+
+    /* create task */
+    reset_audio_connection = ags_reset_audio_connection_new(soundcard,
+							    audio,
+							    G_OBJECT_TYPE(channel),
+							    pad,
+							    audio_channel,
+							    soundcard_channel);
+    
+    ags_task_thread_append_task(task_thread,
+				(AgsTask *) reset_audio_connection);
+  }
+}
+
+void
+ags_output_editor_reset(AgsApplicable *applicable)
+{
+  AgsOutputEditor *output_editor;
+
+  GtkTreeModel *model;
+
+  GtkTreeIter iter;
+
+  output_editor = AGS_OUTPUT_EDITOR(applicable);
+
+  model = gtk_combo_box_get_model(output_editor->soundcard);
+
+  if(gtk_tree_model_get_iter_first(model,
+				   &iter)){
+    AgsLineEditor *line_editor;
+    
+    AgsAudio *audio;
+    AgsAudioConnection *audio_connection;
+    AgsChannel *channel;
+    
+    GObject *soundcard, *current;
+
+    GList *list;
+    
+    gint i;
+    gboolean found;
+
+    line_editor = AGS_LINE_EDITOR(gtk_widget_get_ancestor(GTK_WIDGET(output_editor),
+							  AGS_TYPE_LINE_EDITOR));
+
+    soundcard = NULL;
+    audio = NULL;
+    channel = line_editor->channel;
+    
+    if(channel != NULL){
+      soundcard = channel->soundcard;
+      audio = AGS_AUDIO(channel->audio);
+    }
+    
+    i = 0;
+    found = FALSE;
+
+    if(soundcard != NULL){
+      do{
+	gtk_tree_model_get(model,
+			   &iter,
+			   1, &current,
+			   -1);
+
+	if(soundcard == current){
+	  found = TRUE;
+	  break;
+	}
+
+	i++;
+      }while(gtk_tree_model_iter_next(model,
+				      &iter));
+    }
+
+    if(found &&
+       audio != NULL){      
+      /* set channel link */
+      gtk_combo_box_set_active(output_editor->soundcard,
+			       i);
+
+      /*  */
+      audio_connection = NULL;
+      
+      list = audio->audio_connection;
+	  
+      while((list = ags_audio_connection_find(list,
+					      AGS_TYPE_INPUT,
+					      channel->pad,
+					      channel->audio_channel)) != NULL){
+	GObject *data_object;
+
+	g_object_get(G_OBJECT(list->data),
+		     "data-object\0", &data_object,
+		     NULL);
+	
+	if(AGS_IS_SOUNDCARD(data_object)){
+	  audio_connection = list->data;
+	  
+	  break;
+	}
+
+	list = list->next;
+      }
+
+      if(audio_connection != NULL){
+	gtk_spin_button_set_value(output_editor->audio_channel,
+				  audio_connection->mapped_line);
+      }else{
+	gtk_spin_button_set_value(output_editor->audio_channel,
+				  0);
+      }
+    }else{
+      gtk_combo_box_set_active(output_editor->soundcard,
+			       0);
+    }
+  }
+}
+
+/**
+ * ags_output_editor_check:
+ * @output_editor: the #AgsOutputEditor
+ *
+ * Checks for possible channels to output. And modifies its ranges.
+ * 
+ * Since: 0.7.131
+ */
+void
+ags_output_editor_check(AgsOutputEditor *output_editor)
+{
+  AgsConnectionEditor *connection_editor;
+  AgsLineEditor *line_editor;
+  
+  GtkTreeIter iter;
+
+  connection_editor = AGS_CONNECTION_EDITOR(gtk_widget_get_ancestor(GTK_WIDGET(output_editor),
+								    AGS_TYPE_CONNECTION_EDITOR));
+  line_editor = AGS_LINE_EDITOR(gtk_widget_get_ancestor(GTK_WIDGET(output_editor),
+							AGS_TYPE_LINE_EDITOR));
+
+  if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(output_editor->soundcard),
+				   &iter)){    
+    GObject *soundcard;
+    
+    GtkTreeModel *model;
+
+    guint audio_channels;
+    
+    /* soundcard connection */
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(output_editor->soundcard));
+    gtk_tree_model_get(model,
+		       &iter,
+		       1, &soundcard,
+		       -1);
+
+    ags_soundcard_get_presets(AGS_SOUNDCARD(soundcard),
+ 			      &audio_channels,
+			      NULL,
+			      NULL,
+			      NULL);
+
+    gtk_spin_button_set_range(output_editor->audio_channel,
+			      0.0,
+			      audio_channels - 1.0);
+  }else{
+    gtk_spin_button_set_range(output_editor->audio_channel,
+			      -1.0, -1.0);
+  }
+}
+
+/**
+ * ags_output_editor_new:
+ *
+ * Creates an #AgsOutputEditor
+ *
+ * Returns: a new #AgsOutputEditor
+ *
+ * Since: 0.7.131
+ */
+AgsOutputEditor*
+ags_output_editor_new()
+{
+  AgsOutputEditor *output_editor;
+
+  output_editor = (AgsOutputEditor *) g_object_new(AGS_TYPE_OUTPUT_EDITOR,
+						   NULL);
+
+  return(output_editor);
+}
diff --git a/ags/X/ags_output_editor.h b/ags/X/ags_output_editor.h
new file mode 100644
index 0000000..152a40f
--- /dev/null
+++ b/ags/X/ags_output_editor.h
@@ -0,0 +1,69 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_OUTPUT_EDITOR_H__
+#define __AGS_OUTPUT_EDITOR_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+#define AGS_TYPE_OUTPUT_EDITOR                (ags_output_editor_get_type())
+#define AGS_OUTPUT_EDITOR(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_OUTPUT_EDITOR, AgsOutputEditor))
+#define AGS_OUTPUT_EDITOR_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_OUTPUT_EDITOR, AgsOutputEditorClass))
+#define AGS_IS_OUTPUT_EDITOR(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_OUTPUT_EDITOR))
+#define AGS_IS_OUTPUT_EDITOR_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_OUTPUT_EDITOR))
+#define AGS_OUTPUT_EDITOR_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_OUTPUT_EDITOR, AgsOutputEditorClass))
+
+#define AGS_OUTPUT_EDITOR_DEFAULT_VERSION "0.7.131\0"
+#define AGS_OUTPUT_EDITOR_DEFAULT_BUILD_ID "CEST 2017 18-02-2014 04:53\0"
+
+typedef struct _AgsOutputEditor AgsOutputEditor;
+typedef struct _AgsOutputEditorClass AgsOutputEditorClass;
+
+typedef enum{
+  AGS_OUTPUT_EDITOR_CONNECTED    = 1,
+}AgsOutputEditorFlags;
+
+struct _AgsOutputEditor
+{
+  GtkHBox hbox;
+
+  guint flags;
+  
+  gchar *version;
+  gchar *build_id;
+
+  GtkComboBoxText *soundcard;
+  GtkSpinButton *audio_channel;
+};
+
+struct _AgsOutputEditorClass
+{
+  GtkHBoxClass hbox;
+};
+
+GType ags_output_editor_get_type(void);
+
+void ags_output_editor_check(AgsOutputEditor *output_editor);
+
+AgsOutputEditor* ags_output_editor_new();
+
+#endif /*__AGS_OUTPUT_EDITOR_H__*/
diff --git a/ags/X/ags_output_editor_callbacks.c b/ags/X/ags_output_editor_callbacks.c
new file mode 100644
index 0000000..c20be83
--- /dev/null
+++ b/ags/X/ags_output_editor_callbacks.c
@@ -0,0 +1,71 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/X/ags_output_editor_callbacks.h>
+
+#include <ags/audio/ags_audio.h>
+#include <ags/audio/ags_channel.h>
+
+#include <ags/X/ags_machine.h>
+#include <ags/X/ags_connection_editor.h>
+#include <ags/X/ags_line_editor.h>
+
+int
+ags_output_editor_parent_set_callback(GtkWidget *widget, GtkObject *old_parent, AgsOutputEditor *output_editor)
+{
+  AgsMachine *machine;
+  AgsLineEditor *line_editor;
+
+  AgsAudio *audio;
+  AgsChannel *channel;
+
+  if(old_parent != NULL){
+    return(0);
+  }
+
+  //TODO:JK: missing mutex
+  line_editor = (AgsLineEditor *) gtk_widget_get_ancestor(widget, AGS_TYPE_LINE_EDITOR);
+
+  if(line_editor != NULL){
+    channel = line_editor->channel;
+  
+    if(channel != NULL){
+      GtkTreeIter iter;
+
+      audio = AGS_AUDIO(channel->audio);
+
+      if(audio != NULL){
+	machine = AGS_MACHINE(audio->machine);
+	
+	gtk_combo_box_set_model(GTK_COMBO_BOX(output_editor->soundcard),
+				GTK_TREE_MODEL(ags_machine_get_possible_audio_output_connections(machine)));
+	
+	ags_output_editor_check(output_editor);
+      }
+    }
+  }
+  
+  return(0);
+}
+
+void
+ags_output_editor_soundcard_callback(GtkComboBoxText *combo_text, AgsOutputEditor *output_editor)
+{
+  ags_output_editor_check(output_editor);
+}
diff --git a/ags/X/machine/ags_ladspa_bridge_callbacks.h b/ags/X/ags_output_editor_callbacks.h
similarity index 64%
copy from ags/X/machine/ags_ladspa_bridge_callbacks.h
copy to ags/X/ags_output_editor_callbacks.h
index 45f845e..281516a 100644
--- a/ags/X/machine/ags_ladspa_bridge_callbacks.h
+++ b/ags/X/ags_output_editor_callbacks.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -17,15 +17,17 @@
  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __AGS_LADSPA_BRIDGE_CALLBACKS_H__
-#define __AGS_LADSPA_BRIDGE_CALLBACKS_H__
+#ifndef __AGS_OUTPUT_EDITOR_CALLBACKS_H__
+#define __AGS_OUTPUT_EDITOR_CALLBACKS_H__
 
 #include <glib.h>
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
-#include <ags/X/machine/ags_ladspa_bridge.h>
+#include <ags/X/ags_output_editor.h>
 
+int ags_output_editor_parent_set_callback(GtkWidget *widget, GtkObject *old_parent, AgsOutputEditor *output_editor);
 
+void ags_output_editor_soundcard_callback(GtkComboBoxText *combo_box, AgsOutputEditor *output_editor);
 
-#endif /*__AGS_LADSPA_BRIDGE_CALLBACKS_H__*/
+#endif /*__AGS_OUTPUT_EDITOR_CALLBACKS_H__*/
diff --git a/ags/X/ags_output_listing_editor.c b/ags/X/ags_output_listing_editor.c
new file mode 100644
index 0000000..c23e4d0
--- /dev/null
+++ b/ags/X/ags_output_listing_editor.c
@@ -0,0 +1,427 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/X/ags_output_listing_editor.h>
+#include <ags/X/ags_output_listing_editor_callbacks.h>
+
+#include <ags/object/ags_connectable.h>
+#include <ags/object/ags_applicable.h>
+
+#include <ags/thread/ags_mutex_manager.h>
+
+#include <ags/audio/ags_channel.h>
+#include <ags/audio/ags_output.h>
+
+#include <ags/X/ags_connection_editor.h>
+#include <ags/X/ags_pad_editor.h>
+#include <ags/X/ags_line_editor.h>
+#include <ags/X/ags_output_editor.h>
+
+void ags_output_listing_editor_class_init(AgsOutputListingEditorClass *output_listing_editor);
+void ags_output_listing_editor_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_output_listing_editor_applicable_interface_init(AgsApplicableInterface *applicable);
+void ags_output_listing_editor_init(AgsOutputListingEditor *output_listing_editor);
+void ags_output_listing_editor_connect(AgsConnectable *connectable);
+void ags_output_listing_editor_disconnect(AgsConnectable *connectable);
+void ags_output_listing_editor_set_update(AgsApplicable *applicable, gboolean update);
+void ags_output_listing_editor_apply(AgsApplicable *applicable);
+void ags_output_listing_editor_reset(AgsApplicable *applicable);
+void ags_output_listing_editor_destroy(GtkObject *object);
+void ags_output_listing_editor_show(GtkWidget *widget);
+
+/**
+ * SECTION:ags_output_listing_editor
+ * @short_description: pack output editors
+ * @title: AgsOutputListingEditor
+ * @section_id:
+ * @include: ags/X/ags_output_listing_editor.h
+ *
+ * #AgsOutputListingEditor is a composite widget to pack #AgsOutputEditor.
+ */
+
+static gpointer ags_output_listing_editor_parent_class = NULL;
+static AgsConnectableInterface* ags_output_listing_editor_parent_connectable_interface;
+
+GType
+ags_output_listing_editor_get_type(void)
+{
+  static GType ags_type_output_listing_editor = 0;
+
+  if(!ags_type_output_listing_editor){
+    static const GTypeInfo ags_output_listing_editor_info = {
+      sizeof (AgsOutputListingEditorClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_output_listing_editor_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof (AgsOutputListingEditor),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_output_listing_editor_init,
+    };
+
+    static const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_output_listing_editor_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    static const GInterfaceInfo ags_applicable_interface_info = {
+      (GInterfaceInitFunc) ags_output_listing_editor_applicable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    ags_type_output_listing_editor = g_type_register_static(AGS_TYPE_PROPERTY_LISTING_EDITOR,
+							    "AgsOutputListingEditor\0",
+							    &ags_output_listing_editor_info,
+							    0);
+    
+    g_type_add_interface_static(ags_type_output_listing_editor,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+
+    g_type_add_interface_static(ags_type_output_listing_editor,
+				AGS_TYPE_APPLICABLE,
+				&ags_applicable_interface_info);
+  }
+
+  return(ags_type_output_listing_editor);
+}
+
+void
+ags_output_listing_editor_class_init(AgsOutputListingEditorClass *output_listing_editor)
+{
+}
+
+void
+ags_output_listing_editor_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  ags_output_listing_editor_parent_connectable_interface = g_type_interface_peek_parent(connectable);
+
+  connectable->is_ready = NULL;
+  connectable->is_connected = NULL;
+  connectable->connect = ags_output_listing_editor_connect;
+  connectable->disconnect = ags_output_listing_editor_disconnect;
+}
+
+void
+ags_output_listing_editor_applicable_interface_init(AgsApplicableInterface *applicable)
+{
+  applicable->set_update = ags_output_listing_editor_set_update;
+  applicable->apply = ags_output_listing_editor_apply;
+  applicable->reset = ags_output_listing_editor_reset;
+}
+
+void
+ags_output_listing_editor_init(AgsOutputListingEditor *output_listing_editor)
+{
+  g_signal_connect_after(G_OBJECT(output_listing_editor), "parent_set\0",
+			 G_CALLBACK(ags_output_listing_editor_parent_set_callback), output_listing_editor);
+
+  output_listing_editor->channel_type = G_TYPE_NONE;
+
+  output_listing_editor->child = NULL;
+}
+
+void
+ags_output_listing_editor_connect(AgsConnectable *connectable)
+{
+  AgsConnectionEditor *connection_editor;
+  AgsOutputListingEditor *output_listing_editor;
+
+  GList *pad_editor, *pad_editor_start;
+
+  ags_output_listing_editor_parent_connectable_interface->connect(connectable);
+
+  output_listing_editor = AGS_OUTPUT_LISTING_EDITOR(connectable);
+
+  connection_editor = (AgsConnectionEditor *) gtk_widget_get_ancestor(GTK_WIDGET(output_listing_editor),
+								      AGS_TYPE_CONNECTION_EDITOR);
+
+  if(connection_editor != NULL &&
+     connection_editor->machine != NULL){
+    AgsAudio *audio;
+
+    /* AgsAudio */
+    audio = connection_editor->machine->audio;
+
+    output_listing_editor->set_pads_handler = g_signal_connect_after(G_OBJECT(audio), "set_pads\0",
+								     G_CALLBACK(ags_output_listing_editor_set_pads_callback), output_listing_editor);
+  }
+
+  /* AgsPadEditor */
+  pad_editor_start = 
+    pad_editor = gtk_container_get_children(GTK_CONTAINER(output_listing_editor->child));
+
+  while(pad_editor != NULL){
+    ags_connectable_connect(AGS_CONNECTABLE(pad_editor->data));
+
+    pad_editor = pad_editor->next;
+  }
+  
+  g_list_free(pad_editor_start);
+}
+
+void
+ags_output_listing_editor_disconnect(AgsConnectable *connectable)
+{
+  AgsConnectionEditor *connection_editor;
+  AgsOutputListingEditor *output_listing_editor;
+
+  GList *pad_editor, *pad_editor_start;
+
+  ags_output_listing_editor_parent_connectable_interface->connect(connectable);
+
+  output_listing_editor = AGS_OUTPUT_LISTING_EDITOR(connectable);
+
+  connection_editor = (AgsConnectionEditor *) gtk_widget_get_ancestor(GTK_WIDGET(output_listing_editor),
+								      AGS_TYPE_CONNECTION_EDITOR);
+
+  if(connection_editor != NULL &&
+     connection_editor->machine != NULL){
+    AgsAudio *audio;
+
+    /* AgsAudio */
+    audio = connection_editor->machine->audio;
+
+    g_signal_handler_disconnect(audio,
+				output_listing_editor->set_pads_handler);
+  }
+
+  /* AgsPadEditor */
+  pad_editor_start = 
+    pad_editor = gtk_container_get_children(GTK_CONTAINER(output_listing_editor->child));
+
+  while(pad_editor != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(pad_editor->data));
+
+    pad_editor = pad_editor->next;
+  }
+  
+  g_list_free(pad_editor_start);
+}
+
+void
+ags_output_listing_editor_set_update(AgsApplicable *applicable, gboolean update)
+{
+  AgsOutputListingEditor *output_listing_editor;
+
+  GList *pad_editor, *pad_editor_start;
+
+  output_listing_editor = AGS_OUTPUT_LISTING_EDITOR(applicable);
+
+  pad_editor_start = 
+    pad_editor = gtk_container_get_children(GTK_CONTAINER(output_listing_editor->child));
+
+  while(pad_editor != NULL){
+    ags_applicable_set_update(AGS_APPLICABLE(pad_editor->data), update);
+
+    pad_editor = pad_editor->next;
+  }
+
+  g_list_free(pad_editor_start);
+}
+
+void
+ags_output_listing_editor_apply(AgsApplicable *applicable)
+{
+  AgsOutputListingEditor *output_listing_editor;
+
+  GList *pad_editor, *pad_editor_start;
+
+  output_listing_editor = AGS_OUTPUT_LISTING_EDITOR(applicable);
+
+  if((AGS_PROPERTY_EDITOR_ENABLED & (AGS_PROPERTY_EDITOR(output_listing_editor)->flags)) == 0){
+    return;
+  }
+
+  pad_editor_start = 
+    pad_editor = gtk_container_get_children(GTK_CONTAINER(output_listing_editor->child));
+
+  while(pad_editor != NULL){
+    ags_applicable_apply(AGS_APPLICABLE(pad_editor->data));
+
+    pad_editor = pad_editor->next;
+  }
+  
+  g_list_free(pad_editor_start);
+}
+
+void
+ags_output_listing_editor_reset(AgsApplicable *applicable)
+{
+  AgsOutputListingEditor *output_listing_editor;
+
+  GList *pad_editor, *pad_editor_start;
+
+  output_listing_editor = AGS_OUTPUT_LISTING_EDITOR(applicable);
+
+  pad_editor_start = 
+    pad_editor = gtk_container_get_children(GTK_CONTAINER(output_listing_editor->child));
+
+  while(pad_editor != NULL){
+    ags_applicable_reset(AGS_APPLICABLE(pad_editor->data));
+
+    pad_editor = pad_editor->next;
+  }
+
+  g_list_free(pad_editor_start);
+}
+
+/**
+ * ags_output_listing_editor_add_children:
+ * @output_listing_editor: the #AgsOutputListingEditor
+ * @audio: the #AgsAudio to use
+ * @nth_channel: nth channel to start creation until end
+ * @connect: if %TRUE widget is connected and shown
+ *
+ * Creates new pad editors or destroys them.
+ *
+ * Since: 0.7.131
+ */
+void
+ags_output_listing_editor_add_children(AgsOutputListingEditor *output_listing_editor,
+				       AgsAudio *audio, guint nth_channel,
+				       gboolean connect)
+{
+  AgsPadEditor *pad_editor;
+  GtkVBox *vbox;
+
+  AgsChannel *channel;
+
+  AgsMutexManager *mutex_manager;
+
+  pthread_mutex_t *application_mutex;
+  pthread_mutex_t *audio_mutex;
+  pthread_mutex_t *channel_mutex;
+
+  if(nth_channel == 0 &&
+     output_listing_editor->child != NULL){
+    vbox = output_listing_editor->child;
+    output_listing_editor->child = NULL;
+    gtk_widget_destroy(GTK_WIDGET(vbox));
+  }
+
+  if(audio == NULL){
+    return;
+  }
+  
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* lookup audio mutex */
+  pthread_mutex_lock(application_mutex);
+  
+  audio_mutex = ags_mutex_manager_lookup(mutex_manager,
+					 audio);
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* instantiate pad editor vbox */
+  if(nth_channel == 0){
+    output_listing_editor->child = (GtkVBox *) gtk_vbox_new(FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(output_listing_editor),
+		       GTK_WIDGET(output_listing_editor->child),
+		       FALSE, FALSE,
+		       0);
+  }
+
+  /* get current channel */
+  if(output_listing_editor->channel_type == AGS_TYPE_OUTPUT){
+    pthread_mutex_lock(audio_mutex);
+
+    channel = audio->output;
+
+    pthread_mutex_unlock(audio_mutex);
+
+    channel = ags_channel_nth(channel,
+			      nth_channel);
+  }else{
+    pthread_mutex_lock(audio_mutex);
+
+    channel = audio->input;
+
+    pthread_mutex_unlock(audio_mutex);
+    
+    channel = ags_channel_nth(channel,
+			      nth_channel);
+  }
+  
+  while(channel != NULL){
+    /* lookup channel mutex */
+    pthread_mutex_lock(application_mutex);
+
+    channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+					     channel);
+    
+    pthread_mutex_unlock(application_mutex);
+
+    /* instantiate pad editor */
+    pad_editor = ags_pad_editor_new(NULL);
+
+    pad_editor->editor_type_count = 1;
+      pad_editor->editor_type = (GType *) malloc(pad_editor->editor_type_count * sizeof(GType));
+    pad_editor->editor_type[0] = AGS_TYPE_OUTPUT_EDITOR;
+
+    g_object_set(pad_editor,
+		 "channel\0", channel,
+		 NULL);
+    
+    gtk_box_pack_start(GTK_BOX(output_listing_editor->child),
+		       GTK_WIDGET(pad_editor),
+		       FALSE, FALSE,
+		       0);
+
+    if(connect){
+      ags_connectable_connect(AGS_CONNECTABLE(pad_editor));
+      gtk_widget_show_all(GTK_WIDGET(pad_editor));
+    }
+
+    /* iterate */
+    pthread_mutex_lock(channel_mutex);
+      
+    channel = channel->next_pad;
+
+    pthread_mutex_unlock(channel_mutex);
+  }
+}
+
+/**
+ * ags_output_listing_editor_new:
+ * @channel_type: the channel type to represent
+ *
+ * Creates an #AgsOutputListingEditor
+ *
+ * Returns: a new #AgsOutputListingEditor
+ *
+ * Since: 0.7.131
+ */
+AgsOutputListingEditor*
+ags_output_listing_editor_new(GType channel_type)
+{
+  AgsOutputListingEditor *output_listing_editor;
+
+  output_listing_editor = (AgsOutputListingEditor *) g_object_new(AGS_TYPE_OUTPUT_LISTING_EDITOR,
+								  NULL);
+  
+  output_listing_editor->channel_type = channel_type;
+
+  return(output_listing_editor);
+}
diff --git a/ags/X/ags_output_listing_editor.h b/ags/X/ags_output_listing_editor.h
new file mode 100644
index 0000000..bfdbfd4
--- /dev/null
+++ b/ags/X/ags_output_listing_editor.h
@@ -0,0 +1,65 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_OUTPUT_LISTING_EDITOR_H__
+#define __AGS_OUTPUT_LISTING_EDITOR_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+#include <ags/X/ags_property_listing_editor.h>
+
+#include <ags/audio/ags_audio.h>
+
+#define AGS_TYPE_OUTPUT_LISTING_EDITOR                (ags_output_listing_editor_get_type())
+#define AGS_OUTPUT_LISTING_EDITOR(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_OUTPUT_LISTING_EDITOR, AgsOutputListingEditor))
+#define AGS_OUTPUT_LISTING_EDITOR_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_OUTPUT_LISTING_EDITOR, AgsOutputListingEditorClass))
+#define AGS_IS_OUTPUT_LISTING_EDITOR(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_OUTPUT_LISTING_EDITOR))
+#define AGS_IS_OUTPUT_LISTING_EDITOR_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_OUTPUT_LISTING_EDITOR))
+#define AGS_OUTPUT_LISTING_EDITOR_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_OUTPUT_LISTING_EDITOR, AgsOutputListingEditorClass))
+
+  typedef struct _AgsOutputListingEditor AgsOutputListingEditor;
+typedef struct _AgsOutputListingEditorClass AgsOutputListingEditorClass;
+
+struct _AgsOutputListingEditor
+{
+  AgsPropertyListingEditor property_listing_editor;
+
+  GType channel_type;
+
+  GtkVBox *child;
+
+  gulong set_pads_handler;
+};
+
+struct _AgsOutputListingEditorClass
+{
+  AgsPropertyListingEditorClass property_listing_editor;
+};
+
+GType ags_output_listing_editor_get_type();
+
+void ags_output_listing_editor_add_children(AgsOutputListingEditor *listing_editor,
+					    AgsAudio *audio, guint nth_channel,
+					    gboolean connect);
+AgsOutputListingEditor* ags_output_listing_editor_new(GType channel_type);
+
+#endif /*__AGS_OUTPUT_LISTING_EDITOR_H__*/
diff --git a/ags/X/ags_output_listing_editor_callbacks.c b/ags/X/ags_output_listing_editor_callbacks.c
new file mode 100644
index 0000000..4b6d640
--- /dev/null
+++ b/ags/X/ags_output_listing_editor_callbacks.c
@@ -0,0 +1,110 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/X/ags_output_listing_editor_callbacks.h>
+
+#include <ags/thread/ags_mutex_manager.h>
+
+#include <ags/X/ags_machine.h>
+#include <ags/X/ags_connection_editor.h>
+
+int
+ags_output_listing_editor_parent_set_callback(GtkWidget *widget,
+					      GtkObject *old_parent,
+					      AgsOutputListingEditor *output_listing_editor)
+{
+  AgsConnectionEditor *connection_editor;
+
+  if(old_parent != NULL){
+    return(0);
+  }
+
+  connection_editor = (AgsConnectionEditor *) gtk_widget_get_ancestor(widget,
+								      AGS_TYPE_CONNECTION_EDITOR);
+
+  if(connection_editor != NULL &&
+     connection_editor->machine != NULL){
+    ags_output_listing_editor_add_children(output_listing_editor,
+					   connection_editor->machine->audio, 0,
+					   FALSE);
+  }
+  
+  return(0);
+}
+
+void
+ags_output_listing_editor_set_pads_callback(AgsAudio *audio, GType channel_type,
+					    guint pads, guint pads_old,
+					    AgsOutputListingEditor *output_listing_editor)
+{
+  if(channel_type != output_listing_editor->channel_type){
+    return;
+  }
+
+  if(pads_old < pads){
+    AgsMutexManager *mutex_manager;
+
+    guint audio_channels;
+    guint nth_channel;
+
+    pthread_mutex_t *application_mutex;
+    pthread_mutex_t *audio_mutex;
+    
+    mutex_manager = ags_mutex_manager_get_instance();
+    application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+    /* lookup audio mutex */
+    pthread_mutex_lock(application_mutex);
+  
+    audio_mutex = ags_mutex_manager_lookup(mutex_manager,
+					   audio);
+  
+    pthread_mutex_unlock(application_mutex);
+
+    /* get some audio fields */
+    pthread_mutex_lock(audio_mutex);
+
+    audio_channels = audio->audio_channels;
+
+    pthread_mutex_unlock(audio_mutex);
+
+    /* add children */
+    nth_channel = pads_old * audio_channels;
+    
+    ags_output_listing_editor_add_children(output_listing_editor,
+					   audio, nth_channel,
+					   TRUE);
+  }else{
+    GList *list, *list_next, *list_start;
+
+    list_start = 
+      list = gtk_container_get_children(GTK_CONTAINER(output_listing_editor->child));
+    list = g_list_nth(list, pads);
+    
+    while(list != NULL){
+      list_next = list->next;
+
+      gtk_widget_destroy(GTK_WIDGET(list->data));
+
+      list = list_next;
+    }
+
+    g_list_free(list_start);
+  }
+}
diff --git a/ags/X/ags_pad_editor_callbacks.h b/ags/X/ags_output_listing_editor_callbacks.h
similarity index 59%
copy from ags/X/ags_pad_editor_callbacks.h
copy to ags/X/ags_output_listing_editor_callbacks.h
index 523a4c3..5273153 100644
--- a/ags/X/ags_pad_editor_callbacks.h
+++ b/ags/X/ags_output_listing_editor_callbacks.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -17,8 +17,8 @@
  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __AGS_PAD_EDITOR_CALLBACKS_H__
-#define __AGS_PAD_EDITOR_CALLBACKS_H__
+#ifndef __AGS_OUTPUT_LISTING_EDITOR_CALLBACKS_H__
+#define __AGS_OUTPUT_LISTING_EDITOR_CALLBACKS_H__
 
 #include <glib.h>
 #include <glib-object.h>
@@ -26,12 +26,14 @@
 
 #include <ags/audio/ags_audio.h>
 
-#include <ags/X/ags_pad_editor.h>
+#include <ags/X/ags_output_listing_editor.h>
 
-int ags_pad_editor_parent_set_callback(GtkWidget *widget, GtkObject *old_parent, AgsPadEditor *pad_editor);
+int ags_output_listing_editor_parent_set_callback(GtkWidget *widget,
+						  GtkObject *old_parent,
+						  AgsOutputListingEditor *output_listing_editor);
 
-void ags_pad_editor_set_audio_channels_callback(AgsAudio *audio,
-						guint audio_channels, guint audio_channels_old,
-						AgsPadEditor *pad_editor);
+void ags_output_listing_editor_set_pads_callback(AgsAudio *audio, GType channel_type,
+						 guint pads, guint pads_old,
+						 AgsOutputListingEditor *output_listing_editor);
 
-#endif /*__AGS_PAD_EDITOR_CALLBACKS_H__*/
+#endif /*__AGS_OUTPUT_LISTING_EDITOR_CALLBACKS_H__*/
diff --git a/ags/X/ags_pad.c b/ags/X/ags_pad.c
index e08e14e..ddb08bb 100644
--- a/ags/X/ags_pad.c
+++ b/ags/X/ags_pad.c
@@ -30,6 +30,7 @@
 #include <ags/thread/ags_task_thread.h>
 #include <ags/thread/ags_task_completion.h>
 
+#include <ags/audio/ags_sound_provider.h>
 #include <ags/audio/ags_audio.h>
 #include <ags/audio/ags_input.h>
 #include <ags/audio/ags_output.h>
@@ -421,7 +422,32 @@ ags_pad_connect(AgsConnectable *connectable)
 void
 ags_pad_disconnect(AgsConnectable *connectable)
 {
-  //TODO:JK: implement me
+  AgsPad *pad;
+  GList *line_list, *line_list_start;
+
+  /* AgsPad */
+  pad = AGS_PAD(connectable);
+
+  if((AGS_PAD_CONNECTED & (pad->flags)) == 0){
+    return;
+  }
+  
+  pad->flags &= (~AGS_PAD_CONNECTED);
+
+  /* AgsLine */
+  line_list_start =  
+    line_list = gtk_container_get_children(GTK_CONTAINER(pad->expander_set));
+
+  while(line_list != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(line_list->data));
+
+    line_list = line_list->next;
+  }
+
+  g_list_free(line_list_start);
+
+  g_signal_handlers_disconnect_by_data(pad->channel,
+				       pad);
 }
 
 gchar*
@@ -770,6 +796,7 @@ ags_pad_play(AgsPad *pad)
   
   GList *tasks;
 
+  gboolean no_soundcard;
   gboolean play_all;
 
   pthread_mutex_t *application_mutex;
@@ -783,7 +810,23 @@ ags_pad_play(AgsPad *pad)
   
   mutex_manager = ags_mutex_manager_get_instance();
   application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  no_soundcard = FALSE;
   
+  pthread_mutex_lock(application_mutex);
+
+  if(ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context)) == NULL){
+    no_soundcard = TRUE;
+  }
+
+  pthread_mutex_unlock(application_mutex);
+
+  if(no_soundcard){
+    g_message("No soundcard available\0");
+    
+    return;
+  }
+
   /* get audio loop */
   pthread_mutex_lock(application_mutex);
 
diff --git a/ags/X/ags_pad_callbacks.c b/ags/X/ags_pad_callbacks.c
index aaebd78..a6c3e05 100644
--- a/ags/X/ags_pad_callbacks.c
+++ b/ags/X/ags_pad_callbacks.c
@@ -33,6 +33,7 @@
 #include <ags/audio/ags_playback.h>
 #include <ags/audio/ags_pattern.h>
 #include <ags/audio/ags_recall.h>
+#include <ags/audio/ags_recall_id.h>
 
 #include <ags/audio/thread/ags_audio_loop.h>
 #include <ags/audio/thread/ags_soundcard_thread.h>
@@ -51,7 +52,7 @@ void ags_pad_start_complete_response(GtkWidget *dialog,
 				     gint response,
 				     AgsPad *pad);
 
-int
+void
 ags_pad_group_clicked_callback(GtkWidget *widget, AgsPad *pad)
 {
   AgsLine *line;
@@ -85,7 +86,9 @@ ags_pad_group_clicked_callback(GtkWidget *widget, AgsPad *pad)
       line = AGS_LINE(list->data);
 
       if(!gtk_toggle_button_get_active(line->group)){
-	return(0);
+	g_list_free(list_start);
+	
+	return;
       }
 
       list = list->next;
@@ -94,11 +97,9 @@ ags_pad_group_clicked_callback(GtkWidget *widget, AgsPad *pad)
     g_list_free(list_start);
     gtk_toggle_button_set_active(pad->group, TRUE);
   }
-
-  return(0);
 }
 
-int
+void
 ags_pad_mute_clicked_callback(GtkWidget *widget, AgsPad *pad)
 {
   AgsWindow *window;
@@ -244,11 +245,9 @@ ags_pad_mute_clicked_callback(GtkWidget *widget, AgsPad *pad)
 
   ags_task_thread_append_tasks(task_thread,
 			       tasks);
-
-  return(0);
 }
 
-int
+void
 ags_pad_solo_clicked_callback(GtkWidget *widget, AgsPad *pad)
 {
   AgsMachine *machine;
@@ -280,10 +279,9 @@ ags_pad_solo_clicked_callback(GtkWidget *widget, AgsPad *pad)
 
     g_list_free(list_start);
     machine->flags |= (AGS_MACHINE_SOLO);
-  }else
+  }else{
     machine->flags &= ~(AGS_MACHINE_SOLO);
-
-  return(0);
+  }
 }
 
 void
@@ -325,6 +323,7 @@ void
 ags_pad_init_channel_launch_callback(AgsTask *task, AgsPad *input_pad)
 { 
   AgsSoundcard *soundcard;
+  AgsAudio *audio;
   AgsChannel *channel, *next_pad;
   AgsRecycling *recycling, *end_recycling;
 
@@ -338,11 +337,28 @@ ags_pad_init_channel_launch_callback(AgsTask *task, AgsPad *input_pad)
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *audio_mutex;
   pthread_mutex_t *channel_mutex;
+  pthread_mutex_t *recycling_mutex;
  
   mutex_manager = ags_mutex_manager_get_instance();
   application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
 
-  /* get audio loop and audio mutex */
+  /* get channel and its mutex */
+  channel = input_pad->channel;
+
+  pthread_mutex_lock(application_mutex);
+
+  channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+					   (GObject *) channel);
+
+  pthread_mutex_unlock(application_mutex);
+
+  /* get audio and its audio mutex */
+  pthread_mutex_lock(channel_mutex);
+
+  audio = AGS_AUDIO(channel->audio);
+  
+  pthread_mutex_unlock(channel_mutex);
+
   pthread_mutex_lock(application_mutex);
   
   audio_mutex = ags_mutex_manager_lookup(mutex_manager,
@@ -353,7 +369,7 @@ ags_pad_init_channel_launch_callback(AgsTask *task, AgsPad *input_pad)
   /* get soundcard */
   pthread_mutex_lock(audio_mutex);
   
-  soundcard = AGS_SOUNDCARD(AGS_AUDIO(input_pad->channel->audio)->soundcard);
+  soundcard = AGS_SOUNDCARD(audio->soundcard);
   
   pthread_mutex_unlock(audio_mutex);
 
@@ -361,16 +377,6 @@ ags_pad_init_channel_launch_callback(AgsTask *task, AgsPad *input_pad)
   list_start = 
     list = gtk_container_get_children((GtkContainer *) input_pad->expander_set);
 
-  /* get channel and its mutex */
-  channel = input_pad->channel;
-
-  pthread_mutex_lock(application_mutex);
-
-  channel_mutex = ags_mutex_manager_lookup(mutex_manager,
-					   (GObject *) channel);
-
-  pthread_mutex_unlock(application_mutex);
-
   /* get next pad */
   pthread_mutex_lock(channel_mutex);
   
@@ -407,6 +413,7 @@ ags_pad_init_channel_launch_callback(AgsTask *task, AgsPad *input_pad)
     
     if(recall != NULL){
       AgsAudioSignal *audio_signal;
+      AgsRecallID *current_recall_id;
       
       g_signal_connect_after(channel, "done\0",
 			     G_CALLBACK(ags_line_channel_done_callback), AGS_LINE(list->data));
@@ -416,13 +423,25 @@ ags_pad_init_channel_launch_callback(AgsTask *task, AgsPad *input_pad)
       
       recycling = channel->first_recycling;
       end_recycling = channel->last_recycling->next;
+
+      current_recall_id = AGS_RECALL(recall->data)->recall_id;
       
       pthread_mutex_unlock(channel_mutex);
 
       while(recycling != end_recycling){
+	/* get recycling mutex */
+	pthread_mutex_lock(application_mutex);
+  
+	recycling_mutex = ags_mutex_manager_lookup(mutex_manager,
+						   (GObject *) recycling);
+	
+	pthread_mutex_unlock(application_mutex);
+
+	/* instantiate audio signal */
 	audio_signal = ags_audio_signal_new((GObject *) soundcard,
 					    (GObject *) recycling,
-					    (GObject *) AGS_RECALL(recall->data)->recall_id);
+					    (GObject *) current_recall_id);
+	
 	/* add audio signal */
 	ags_recycling_create_audio_signal_with_defaults(recycling,
 							audio_signal,
@@ -436,7 +455,13 @@ ags_pad_init_channel_launch_callback(AgsTask *task, AgsPad *input_pad)
 	ags_recycling_add_audio_signal(recycling,
 				       audio_signal);
 
+
+	/* iterate recycling */
+	pthread_mutex_lock(recycling_mutex);
+
 	recycling = recycling->next;
+
+	pthread_mutex_unlock(recycling_mutex);
       }    
     }
 
diff --git a/ags/X/ags_pad_callbacks.h b/ags/X/ags_pad_callbacks.h
index 3e7aaec..12c4045 100644
--- a/ags/X/ags_pad_callbacks.h
+++ b/ags/X/ags_pad_callbacks.h
@@ -29,9 +29,9 @@
 #include <ags/thread/ags_task.h>
 #include <ags/thread/ags_task_completion.h>
 
-int ags_pad_group_clicked_callback(GtkWidget *widget, AgsPad *pad);
-int ags_pad_mute_clicked_callback(GtkWidget *widget, AgsPad *pad);
-int ags_pad_solo_clicked_callback(GtkWidget *widget, AgsPad *pad);
+void ags_pad_group_clicked_callback(GtkWidget *widget, AgsPad *pad);
+void ags_pad_mute_clicked_callback(GtkWidget *widget, AgsPad *pad);
+void ags_pad_solo_clicked_callback(GtkWidget *widget, AgsPad *pad);
 
 void ags_pad_start_complete_callback(AgsTaskCompletion *task_completion,
 				     AgsPad *pad);
diff --git a/ags/X/ags_pad_editor.c b/ags/X/ags_pad_editor.c
index 3f14504..afa2774 100644
--- a/ags/X/ags_pad_editor.c
+++ b/ags/X/ags_pad_editor.c
@@ -23,6 +23,8 @@
 #include <ags/object/ags_connectable.h>
 #include <ags/object/ags_applicable.h>
 
+#include <ags/thread/ags_mutex_manager.h>
+
 #include <ags/X/ags_line_editor.h>
 
 void ags_pad_editor_class_init(AgsPadEditorClass *pad_editor);
@@ -321,7 +323,7 @@ void
 ags_pad_editor_set_channel(AgsPadEditor *pad_editor, AgsChannel *channel)
 {
   GtkVBox *vbox;
-
+  
   if(pad_editor->line_editor != NULL){
     vbox = pad_editor->line_editor;
     pad_editor->line_editor = NULL;
@@ -332,25 +334,77 @@ ags_pad_editor_set_channel(AgsPadEditor *pad_editor, AgsChannel *channel)
   
   if(channel != NULL){
     AgsLineEditor *line_editor;
+    
     AgsChannel *next_pad;
 
+    AgsMutexManager *mutex_manager;
+
+    guint pad;
+    guint i;
+
+    pthread_mutex_t *application_mutex;
+    pthread_mutex_t *channel_mutex;
+    
+    mutex_manager = ags_mutex_manager_get_instance();
+    application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+    /* lookup channel mutex */
+    pthread_mutex_lock(application_mutex);
+
+    channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+					     channel);
+    
+    pthread_mutex_unlock(application_mutex);
+
+    /* get some channel fields */
+    pthread_mutex_lock(channel_mutex);
+    
+    next_pad = channel->next_pad;
+    pad = channel->pad;
+
+    pthread_mutex_unlock(channel_mutex);
+
+    /* set label */
     gtk_expander_set_label(pad_editor->line_editor_expander,
-			   g_strdup_printf("pad: %u\0", channel->pad));
+			   g_strdup_printf("pad: %u\0", pad));
 
     pad_editor->line_editor = (GtkVBox *) gtk_vbox_new(FALSE, 0);
     gtk_container_add(GTK_CONTAINER(pad_editor->line_editor_expander),
 		      GTK_WIDGET(pad_editor->line_editor));
 
-    next_pad = channel->next_pad;
-
     while(channel != next_pad){
-      line_editor = ags_line_editor_new(channel);
+      /* lookup channel mutex */
+      pthread_mutex_lock(application_mutex);
+
+      channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+					       channel);
+    
+      pthread_mutex_unlock(application_mutex);
+      
+      /* instantiate line editor */
+      line_editor = ags_line_editor_new(NULL);
+      line_editor->editor_type_count = pad_editor->editor_type_count;
+      line_editor->editor_type = (GType *) malloc(line_editor->editor_type_count * sizeof(GType));
+      
+      for(i = 0; i < line_editor->editor_type_count; i++){
+	line_editor->editor_type[i] = pad_editor->editor_type[i];
+      }
+
+      g_object_set(line_editor,
+		   "channel\0", channel,
+		   NULL);
+      
       gtk_box_pack_start(GTK_BOX(pad_editor->line_editor),
 			 GTK_WIDGET(line_editor),
 			 FALSE, FALSE,
 			 0);
 
+      /* iterate */
+      pthread_mutex_lock(channel_mutex);
+      
       channel = channel->next;
+
+      pthread_mutex_unlock(channel_mutex);
     }
   }else{
     gtk_expander_set_label(pad_editor->line_editor_expander,
diff --git a/ags/X/ags_pad_editor.h b/ags/X/ags_pad_editor.h
index 953832c..cbe33e9 100644
--- a/ags/X/ags_pad_editor.h
+++ b/ags/X/ags_pad_editor.h
@@ -48,6 +48,9 @@ struct _AgsPadEditor
   
   AgsChannel *pad;
 
+  guint editor_type_count;
+  GType *editor_type;
+  
   GtkExpander *line_editor_expander;
   GtkVBox *line_editor;
 
diff --git a/ags/X/ags_pad_editor_callbacks.c b/ags/X/ags_pad_editor_callbacks.c
index ab286b9..b8d6564 100644
--- a/ags/X/ags_pad_editor_callbacks.c
+++ b/ags/X/ags_pad_editor_callbacks.c
@@ -21,6 +21,8 @@
 
 #include <ags/object/ags_connectable.h>
 
+#include <ags/thread/ags_mutex_manager.h>
+
 #include <ags/audio/ags_channel.h>
 
 #include <ags/X/ags_machine.h>
@@ -40,13 +42,56 @@ ags_pad_editor_set_audio_channels_callback(AgsAudio *audio,
 {
   if(audio_channels > audio_channels_old){
     AgsLineEditor *line_editor;
+
     AgsChannel *channel, *next_pad;
 
-    channel = ags_channel_nth(pad_editor->pad, audio_channels_old);
+    AgsMutexManager *mutex_manager;
+
+    guint i;
+
+    pthread_mutex_t *application_mutex;
+    pthread_mutex_t *channel_mutex;
+    
+    mutex_manager = ags_mutex_manager_get_instance();
+    application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+    /* lookup channel mutex */
+    pthread_mutex_lock(application_mutex);
+
+    channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+					     pad_editor->pad);
+    
+    pthread_mutex_unlock(application_mutex);
+
+    /* get some channel fields */
+    pthread_mutex_lock(channel_mutex);
+
     next_pad = pad_editor->pad->next_pad;
 
+    pthread_mutex_unlock(channel_mutex);
+
+    /* get current last of pad */
+    channel = ags_channel_nth(pad_editor->pad,
+			      audio_channels_old);
+
     while(channel != next_pad){
+      /* lookup channel mutex */
+      pthread_mutex_lock(application_mutex);
+
+      channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+					       channel);
+    
+      pthread_mutex_unlock(application_mutex);
+
+      /* instantiate line editor */
       line_editor = ags_line_editor_new(channel);
+      line_editor->editor_type_count = pad_editor->editor_type_count;
+      line_editor->editor_type = (GType *) malloc(line_editor->editor_type_count * sizeof(GType));
+
+      for(i = 0; i < line_editor->editor_type_count; i++){
+	line_editor->editor_type[i] = pad_editor->editor_type[i];
+      }
+      
       gtk_box_pack_start(GTK_BOX(pad_editor->line_editor),
 			 GTK_WIDGET(line_editor),
 			 FALSE, FALSE,
@@ -54,14 +99,21 @@ ags_pad_editor_set_audio_channels_callback(AgsAudio *audio,
       ags_connectable_connect(AGS_CONNECTABLE(line_editor));
       gtk_widget_show_all(GTK_WIDGET(line_editor));
 
+      /* iterate */
+      pthread_mutex_lock(channel_mutex);
+      
       channel = channel->next;
+
+      pthread_mutex_unlock(channel_mutex);
     }
   }else{
     GList *list, *list_next, *list_start;
 
     list_start = 
       list = gtk_container_get_children(GTK_CONTAINER(pad_editor->line_editor));
-    list = g_list_nth(list, audio_channels);
+
+    list = g_list_nth(list,
+		      audio_channels);
 
     while(list != NULL){
       list_next = list->next;
diff --git a/ags/X/ags_performance_preferences.c b/ags/X/ags_performance_preferences.c
index 58f08a7..1541290 100644
--- a/ags/X/ags_performance_preferences.c
+++ b/ags/X/ags_performance_preferences.c
@@ -184,6 +184,27 @@ ags_performance_preferences_apply(AgsApplicable *applicable)
 
   config = ags_config_get_instance();
 
+  /* restore thread config */
+  ags_config_set_value(config,
+		       AGS_CONFIG_THREAD,
+		       "model\0",
+		       "super-threaded\0");
+  
+  ags_config_set_value(config,
+		       AGS_CONFIG_THREAD,
+		       "super-threaded-scope\0",
+		       "channel\0");
+
+  ags_config_set_value(config,
+		       AGS_CONFIG_THREAD,
+		       "lock-global\0",
+		       "ags-thread\0");
+  
+  ags_config_set_value(config,
+		       AGS_CONFIG_THREAD,
+		       "lock-parent\0",
+		       "ags-recycling-thread\0");
+
   /* auto-sense */
   str = g_strdup(((gtk_toggle_button_get_active((GtkToggleButton *) performance_preferences->stream_auto_sense)) ? "true\0": "false\0"));
   ags_config_set_value(config,
diff --git a/ags/X/ags_preferences.c b/ags/X/ags_preferences.c
index ea7ccd2..dc7a0a0 100644
--- a/ags/X/ags_preferences.c
+++ b/ags/X/ags_preferences.c
@@ -280,6 +280,8 @@ ags_preferences_apply(AgsApplicable *applicable)
   
   config = ags_config_get_instance();
 
+  ags_config_clear(config);
+
   ags_applicable_apply(AGS_APPLICABLE(preferences->generic_preferences));
   ags_applicable_apply(AGS_APPLICABLE(preferences->audio_preferences));
   ags_applicable_apply(AGS_APPLICABLE(preferences->midi_preferences));
diff --git a/ags/X/ags_soundcard_editor.c b/ags/X/ags_soundcard_editor.c
index 495cadb..876683c 100644
--- a/ags/X/ags_soundcard_editor.c
+++ b/ags/X/ags_soundcard_editor.c
@@ -826,12 +826,21 @@ ags_soundcard_editor_reset(AgsApplicable *applicable)
 			   &samplerate_min, &samplerate_max,
 			   &buffer_size_min, &buffer_size_max,
 			   &error);
+
+    if(error != NULL){
+      channels_min = 0.0;
+      channels_max = 24.0;
+      samplerate_min = 8000.0;
+      samplerate_max = 192000.0;
+      buffer_size_min = 2.0;
+      buffer_size_max = 65535.0;
+    }
   }else{
     channels_min = 0.0;
     channels_max = 24.0;
-    samplerate_min = 1.0;
+    samplerate_min = 8000.0;
     samplerate_max = 192000.0;
-    buffer_size_min = 1.0;
+    buffer_size_min = 2.0;
     buffer_size_max = 65535.0;
   }
   
diff --git a/ags/X/ags_soundcard_editor_callbacks.c b/ags/X/ags_soundcard_editor_callbacks.c
index cff8da4..b1ea7fd 100644
--- a/ags/X/ags_soundcard_editor_callbacks.c
+++ b/ags/X/ags_soundcard_editor_callbacks.c
@@ -355,7 +355,7 @@ ags_soundcard_editor_samplerate_changed_callback(GtkSpinButton *spin_button,
   
   window = AGS_WINDOW(AGS_PREFERENCES(gtk_widget_get_ancestor(GTK_WIDGET(soundcard_editor),
 							      AGS_TYPE_PREFERENCES))->window);
-  soundcard = window->soundcard;
+  soundcard = soundcard_editor->soundcard;
 
   application_context = (AgsApplicationContext *) window->application_context;
 
@@ -400,7 +400,7 @@ ags_soundcard_editor_buffer_size_changed_callback(GtkSpinButton *spin_button,
   
   window = AGS_WINDOW(AGS_PREFERENCES(gtk_widget_get_ancestor(GTK_WIDGET(soundcard_editor),
 							      AGS_TYPE_PREFERENCES))->window);
-  soundcard = window->soundcard;
+  soundcard = soundcard_editor->soundcard;
 
   application_context = (AgsApplicationContext *) window->application_context;
 
@@ -447,7 +447,7 @@ ags_soundcard_editor_format_changed_callback(GtkComboBox *combo_box,
   
   window = AGS_WINDOW(AGS_PREFERENCES(gtk_widget_get_ancestor(GTK_WIDGET(soundcard_editor),
 							      AGS_TYPE_PREFERENCES))->window);
-  soundcard = window->soundcard;
+  soundcard = soundcard_editor->soundcard;
 
   application_context = (AgsApplicationContext *) window->application_context;
 
diff --git a/ags/X/ags_xorg_application_context.c b/ags/X/ags_xorg_application_context.c
index 79a6c7d..b330051 100644
--- a/ags/X/ags_xorg_application_context.c
+++ b/ags/X/ags_xorg_application_context.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -41,10 +41,14 @@
 #include <ags/thread/ags_thread-posix.h>
 #include <ags/thread/ags_thread_pool.h>
 #include <ags/thread/ags_task_thread.h>
+#include <ags/thread/ags_destroy_worker.h>
 
 #include <ags/plugin/ags_ladspa_manager.h>
 #include <ags/plugin/ags_dssi_manager.h>
 #include <ags/plugin/ags_lv2_manager.h>
+#include <ags/plugin/ags_lv2_worker_manager.h>
+#include <ags/plugin/ags_lv2_worker.h>
+#include <ags/plugin/ags_lv2_urid_manager.h>
 
 #include <ags/audio/ags_sound_provider.h>
 #include <ags/audio/ags_devout.h>
@@ -63,6 +67,9 @@
 #include <ags/audio/jack/ags_jack_port.h>
 #include <ags/audio/jack/ags_jack_devout.h>
 
+#include <ags/audio/task/ags_cancel_audio.h>
+#include <ags/audio/task/ags_cancel_channel.h>
+
 #include <ags/audio/recall/ags_play_audio.h>
 #include <ags/audio/recall/ags_play_channel.h>
 #include <ags/audio/recall/ags_play_channel_run.h>
@@ -154,6 +161,9 @@ void ags_xorg_application_context_disconnect(AgsConnectable *connectable);
 AgsThread* ags_xorg_application_context_get_main_loop(AgsConcurrencyProvider *concurrency_provider);
 AgsThread* ags_xorg_application_context_get_task_thread(AgsConcurrencyProvider *concurrency_provider);
 AgsThreadPool* ags_xorg_application_context_get_thread_pool(AgsConcurrencyProvider *concurrency_provider);
+GList* ags_xorg_application_context_get_worker(AgsConcurrencyProvider *concurrency_provider);
+void ags_xorg_application_context_set_worker(AgsConcurrencyProvider *concurrency_provider,
+					     GList *worker);
 GList* ags_xorg_application_context_get_soundcard(AgsSoundProvider *sound_provider);
 void ags_xorg_application_context_set_soundcard(AgsSoundProvider *sound_provider,
 						GList *soundcard);
@@ -164,6 +174,7 @@ GList* ags_xorg_application_context_get_sequencer(AgsSoundProvider *sound_provid
 void ags_xorg_application_context_set_sequencer(AgsSoundProvider *sound_provider,
 						GList *sequencer);
 GList* ags_xorg_application_context_get_distributed_manager(AgsSoundProvider *sound_provider);
+void ags_xorg_application_context_dispose(GObject *gobject);
 void ags_xorg_application_context_finalize(GObject *gobject);
 
 void ags_xorg_application_context_load_config(AgsApplicationContext *application_context);
@@ -261,6 +272,7 @@ ags_xorg_application_context_class_init(AgsXorgApplicationContextClass *xorg_app
   gobject->set_property = ags_xorg_application_context_set_property;
   gobject->get_property = ags_xorg_application_context_get_property;
 
+  gobject->dispose = ags_xorg_application_context_dispose;
   gobject->finalize = ags_xorg_application_context_finalize;
   
   /**
@@ -307,6 +319,8 @@ ags_xorg_application_context_concurrency_provider_interface_init(AgsConcurrencyP
   concurrency_provider->get_main_loop = ags_xorg_application_context_get_main_loop;
   concurrency_provider->get_task_thread = ags_xorg_application_context_get_task_thread;
   concurrency_provider->get_thread_pool = ags_xorg_application_context_get_thread_pool;
+  concurrency_provider->get_worker = ags_xorg_application_context_get_worker;
+  concurrency_provider->set_worker = ags_xorg_application_context_set_worker;
 }
 
 void
@@ -336,7 +350,8 @@ ags_xorg_application_context_init(AgsXorgApplicationContext *xorg_application_co
   AgsThread *soundcard_thread;
   AgsThread *export_thread;
   AgsThread *sequencer_thread;
-
+  AgsDestroyWorker *destroy_worker;
+  
   AgsConfig *config;
 
   GList *list;  
@@ -348,12 +363,16 @@ ags_xorg_application_context_init(AgsXorgApplicationContext *xorg_application_co
 
   guint i;
   gboolean has_jack;
+
+  g_atomic_int_set(&(xorg_application_context->gui_ready),
+		   0);
   
   AGS_APPLICATION_CONTEXT(xorg_application_context)->log = NULL;
 
   /**/
   config = ags_config_get_instance();
   AGS_APPLICATION_CONTEXT(xorg_application_context)->config = config;
+  g_object_ref(config);
   g_object_set(config,
 	       "application-context\0", xorg_application_context,
 	       NULL);
@@ -634,10 +653,10 @@ ags_xorg_application_context_init(AgsXorgApplicationContext *xorg_application_co
   */
     
   /* AgsWindow */
-  window = ags_window_new((GObject *) xorg_application_context);
-  g_object_set(window,
-	       "soundcard\0", soundcard,
-	       NULL);
+  window = g_object_new(AGS_TYPE_WINDOW,
+			"soundcard\0", soundcard,
+			"application-context\0", xorg_application_context,
+			NULL);
   AGS_XORG_APPLICATION_CONTEXT(xorg_application_context)->window = window;
   g_object_ref(G_OBJECT(window));
 
@@ -676,7 +695,6 @@ ags_xorg_application_context_init(AgsXorgApplicationContext *xorg_application_co
 				TRUE, TRUE);
   g_signal_connect(AGS_APPLICATION_CONTEXT(xorg_application_context)->task_thread, "clear-cache\0",
 		   G_CALLBACK(ags_xorg_application_context_clear_cache), NULL);
-
   
   /* AgsSoundcardThread and AgsExportThread */
   xorg_application_context->soundcard_thread = NULL;
@@ -760,7 +778,20 @@ ags_xorg_application_context_init(AgsXorgApplicationContext *xorg_application_co
 				    TRUE, TRUE);
     }
   }
-  
+
+  /* AgsWorkerThread */
+  xorg_application_context->worker = NULL;
+
+  /* AgsDestroyWorker */
+  destroy_worker = ags_destroy_worker_new();
+  g_object_ref(destroy_worker);
+  ags_thread_add_child_extended(AGS_THREAD(audio_loop),
+				destroy_worker,
+				TRUE, TRUE);
+  xorg_application_context->worker = g_list_prepend(xorg_application_context->worker,
+						    destroy_worker);
+  ags_thread_start(destroy_worker);
+
   /* AgsThreadPool */
   xorg_application_context->thread_pool = AGS_TASK_THREAD(AGS_APPLICATION_CONTEXT(xorg_application_context)->task_thread)->thread_pool;
 
@@ -901,6 +932,19 @@ ags_xorg_application_context_get_thread_pool(AgsConcurrencyProvider *concurrency
 }
 
 GList*
+ags_xorg_application_context_get_worker(AgsConcurrencyProvider *concurrency_provider)
+{
+  return(AGS_XORG_APPLICATION_CONTEXT(concurrency_provider)->worker);
+}
+
+void
+ags_xorg_application_context_set_worker(AgsConcurrencyProvider *concurrency_provider,
+					GList *worker)
+{
+  AGS_XORG_APPLICATION_CONTEXT(concurrency_provider)->worker = worker;
+}
+
+GList*
 ags_xorg_application_context_get_soundcard(AgsSoundProvider *sound_provider)
 {
   return(AGS_XORG_APPLICATION_CONTEXT(sound_provider)->soundcard);
@@ -946,14 +990,187 @@ ags_xorg_application_context_get_distributed_manager(AgsSoundProvider *sound_pro
 }
 
 void
+ags_xorg_application_context_dispose(GObject *gobject)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  GList *list;
+
+  xorg_application_context = AGS_XORG_APPLICATION_CONTEXT(gobject);
+
+  /* thread pool */
+  if(xorg_application_context->thread_pool != NULL){
+    g_object_unref(xorg_application_context->thread_pool);
+    
+    xorg_application_context->thread_pool = NULL;
+  }
+
+  /* polling thread */
+  if(xorg_application_context->polling_thread != NULL){
+    g_object_unref(xorg_application_context->polling_thread);
+
+    xorg_application_context->polling_thread = NULL;
+  }
+
+  /* worker thread */
+  if(xorg_application_context->worker != NULL){
+    list = xorg_application_context->worker;
+
+    while(list != NULL){
+      g_object_run_dispose(list->data);
+      
+      list = list->next;
+    }
+    
+    g_list_free_full(xorg_application_context->worker,
+		     g_object_unref);
+
+    xorg_application_context->worker = NULL;
+  }
+  
+  /* soundcard and export thread */
+  if(xorg_application_context->soundcard_thread != NULL){
+    g_object_unref(xorg_application_context->soundcard_thread);
+
+    xorg_application_context->soundcard_thread = NULL;
+  }
+
+  if(xorg_application_context->export_thread != NULL){
+    g_object_unref(xorg_application_context->export_thread);
+
+    xorg_application_context->export_thread = NULL;
+  }
+
+  /* server */
+  if(xorg_application_context->server != NULL){
+    g_object_set(xorg_application_context->server,
+		 "application-context\0", NULL,
+		 NULL);
+    
+    g_object_unref(xorg_application_context->server);
+
+    xorg_application_context->server = NULL;
+  }
+
+  /* soundcard and sequencer */
+  if(xorg_application_context->soundcard != NULL){
+    list = xorg_application_context->soundcard;
+
+    while(list != NULL){
+      g_object_set(list->data,
+		   "application-context\0", NULL,
+		   NULL);
+
+      list = list->next;
+    }
+    
+    g_list_free_full(xorg_application_context->soundcard,
+		     g_object_unref);
+
+    xorg_application_context->soundcard = NULL;
+  }
+
+  if(xorg_application_context->sequencer != NULL){
+    list = xorg_application_context->sequencer;
+
+    while(list != NULL){
+      g_object_set(list->data,
+		   "application-context\0", NULL,
+		   NULL);
+
+      list = list->next;
+    }
+
+    g_list_free_full(xorg_application_context->sequencer,
+		     g_object_unref);
+
+    xorg_application_context->sequencer = NULL;
+  }
+
+  /* distributed manager */
+  if(xorg_application_context->distributed_manager != NULL){
+    list = xorg_application_context->distributed_manager;
+
+    while(list != NULL){
+      g_object_set(list->data,
+		   "application-context\0", NULL,
+		   NULL);
+
+      list = list->next;
+    }
+
+    g_list_free_full(xorg_application_context->distributed_manager,
+		     g_object_unref);
+
+    xorg_application_context->distributed_manager = NULL;
+  }
+
+  /* window */
+  if(xorg_application_context->window != NULL){
+    g_object_set(xorg_application_context->window,
+		 "application-context\0", NULL,
+		 NULL);
+    
+    gtk_widget_destroy(xorg_application_context->window);
+
+    xorg_application_context->window = NULL;
+  }  
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_xorg_application_context_parent_class)->dispose(gobject);
+}
+
+void
 ags_xorg_application_context_finalize(GObject *gobject)
 {
   AgsXorgApplicationContext *xorg_application_context;
 
   xorg_application_context = AGS_XORG_APPLICATION_CONTEXT(gobject);
 
+  if(xorg_application_context->thread_pool != NULL){
+    g_object_unref(xorg_application_context->thread_pool);
+  }
+
+  if(xorg_application_context->polling_thread != NULL){
+    g_object_unref(xorg_application_context->polling_thread);
+  }
+
+  if(xorg_application_context->worker != NULL){
+    g_list_free_full(xorg_application_context->worker,
+		     g_object_unref);
+
+    xorg_application_context->worker = NULL;
+  }
+  
+  if(xorg_application_context->soundcard_thread != NULL){
+    g_object_unref(xorg_application_context->soundcard_thread);
+  }
+
+  if(xorg_application_context->export_thread != NULL){
+    g_object_unref(xorg_application_context->export_thread);
+  }
+
+  if(xorg_application_context->server != NULL){
+    g_object_unref(xorg_application_context->server);
+  }
+
+  if(xorg_application_context->soundcard != NULL){
+    g_list_free_full(xorg_application_context->soundcard,
+		     g_object_unref);
+  }
+
+  if(xorg_application_context->sequencer != NULL){
+    g_list_free_full(xorg_application_context->sequencer,
+		     g_object_unref);
+  }
+  
+  if(xorg_application_context->distributed_manager != NULL){
+    g_list_free_full(xorg_application_context->distributed_manager,
+		     g_object_unref);
+  }
+  
   if(xorg_application_context->window != NULL){
-    g_object_unref(xorg_application_context->window);
+    gtk_widget_destroy(xorg_application_context->window);
   }
   
   /* call parent */
@@ -972,6 +1189,12 @@ ags_xorg_application_context_register_types(AgsApplicationContext *application_c
   ags_gui_thread_get_type();
 
   /*  */
+  ags_lv2_manager_get_type();
+  ags_lv2_urid_manager_get_type();
+  ags_lv2_worker_manager_get_type();
+  ags_lv2_worker_get_type();
+  
+  /*  */
   ags_audio_loop_get_type();
   ags_soundcard_thread_get_type();
   ags_export_thread_get_type();
@@ -982,6 +1205,12 @@ ags_xorg_application_context_register_types(AgsApplicationContext *application_c
   /*  */
   ags_audio_file_get_type();
   ags_audio_file_link_get_type();
+
+  /* register tasks */
+  ags_cancel_audio_get_type();
+  ags_cancel_channel_get_type();
+  
+  //TODO:JK: extend me
   
   /* register recalls */
   ags_recall_channel_run_dummy_get_type();
@@ -1040,6 +1269,10 @@ ags_xorg_application_context_register_types(AgsApplicationContext *application_c
   
   /* gui */
   //TODO:JK: move me
+  ags_led_get_type();
+  ags_indicator_get_type();
+  ags_vindicator_get_type();
+  ags_hindicator_get_type();
   ags_dial_get_type();
 
   /* register machine */
@@ -1083,7 +1316,7 @@ ags_xorg_application_context_quit(AgsApplicationContext *application_context)
 {
   AgsLadspaManager *ladspa_manager;
   AgsDssiManager *dssi_manager;
-  AgsLv2Manager *lv2_manager;;
+  AgsLv2Manager *lv2_manager;
 
   AgsJackServer *jack_server;
 
diff --git a/ags/X/ags_xorg_application_context.h b/ags/X/ags_xorg_application_context.h
index 348fc04..0d5d744 100644
--- a/ags/X/ags_xorg_application_context.h
+++ b/ags/X/ags_xorg_application_context.h
@@ -56,8 +56,8 @@
 #define AGS_IS_XORG_APPLICATION_CONTEXT_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_XORG_APPLICATION_CONTEXT))
 #define AGS_XORG_APPLICATION_CONTEXT_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS(obj, AGS_TYPE_XORG_APPLICATION_CONTEXT, AgsXorgApplicationContextClass))
 
-#define AGS_XORG_VERSION "0.7.7\0"
-#define AGS_XORG_BUILD_ID "Fre Feb 26 18:08:25 CET 2016\0"
+#define AGS_XORG_VERSION "0.7.122.8\0"
+#define AGS_XORG_BUILD_ID "Tue Mar 21 20:03:29 CET 2017\0"
 
 typedef struct _AgsXorgApplicationContext AgsXorgApplicationContext;
 typedef struct _AgsXorgApplicationContextClass AgsXorgApplicationContextClass;
@@ -70,9 +70,13 @@ struct _AgsXorgApplicationContext
 {
   AgsApplicationContext application_context;
 
+  volatile gboolean gui_ready;
+  
   AgsThreadPool *thread_pool;
 
   AgsPollingThread *polling_thread;
+
+  GList *worker;
   
   AgsThread *soundcard_thread;
   AgsThread *export_thread;
diff --git a/ags/X/editor/ags_automation_area.c b/ags/X/editor/ags_automation_area.c
index a904a76..1ef3505 100644
--- a/ags/X/editor/ags_automation_area.c
+++ b/ags/X/editor/ags_automation_area.c
@@ -572,20 +572,33 @@ ags_automation_area_draw_strip(AgsAutomationArea *automation_area,
 			       cairo_t *cr,
 			       gdouble x_offset, gdouble y_offset)
 {
+  GtkStyle *automation_area_style;
+  
   gdouble y;
   gdouble width, height;
 
+  static const gdouble white_gc = 65535.0;
+
+  automation_area_style = gtk_widget_get_style(GTK_WIDGET(automation_area->drawing_area));
+
   y = (gdouble) automation_area->y - y_offset;
   
   width = (gdouble) GTK_WIDGET(automation_area->drawing_area)->allocation.width;
   height = (gdouble) automation_area->height;
 
   /* background */
-  cairo_set_source_rgb(cr, 0.5, 0.4, 0.0);
+  cairo_set_source_rgb(cr,
+		       automation_area_style->bg[0].red / white_gc,
+		       automation_area_style->bg[0].red / white_gc,
+		       automation_area_style->bg[0].red / white_gc);
   cairo_rectangle(cr, 0.0, y, width, height);
   cairo_fill(cr);
 
-  cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+  /* background border */
+  cairo_set_source_rgb(cr,
+		       automation_area_style->base[0].red / white_gc,
+		       automation_area_style->base[0].green / white_gc,
+		       automation_area_style->base[0].blue / white_gc);
   cairo_set_line_width(cr, 1.0);
   cairo_rectangle(cr, 0.0, y, width, height);
   cairo_stroke(cr);
@@ -614,6 +627,8 @@ ags_automation_area_draw_segment(AgsAutomationArea *automation_area,
   AgsAutomationEdit *automation_edit;
   GtkWidget *widget;
   
+  GtkStyle *automation_area_style;
+
   double tact;
   gdouble y;
   gdouble height;
@@ -621,7 +636,11 @@ ags_automation_area_draw_segment(AgsAutomationArea *automation_area,
   guint i, j;
   guint j_set;
   
+  static const gdouble white_gc = 65535.0;
+
   widget = (GtkWidget *) automation_area->drawing_area;
+  
+  automation_area_style = gtk_widget_get_style(widget);
 
   automation_edit = (AgsAutomationEdit *) gtk_widget_get_ancestor(GTK_WIDGET(automation_area->drawing_area),
 								  AGS_TYPE_AUTOMATION_EDIT);
@@ -644,7 +663,10 @@ ags_automation_area_draw_segment(AgsAutomationArea *automation_area,
      tact > 1.0 ){
     j_set = ((guint) x_offset / control_width + 1) % ((guint) tact);
 
-    cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
+    cairo_set_source_rgb(cr,
+			 automation_area_style->mid[0].red / white_gc,
+			 automation_area_style->mid[0].green / white_gc,
+			 automation_area_style->mid[0].blue / white_gc);
 
     if(j_set != 0){
       j = j_set;
@@ -653,7 +675,10 @@ ags_automation_area_draw_segment(AgsAutomationArea *automation_area,
   }
 
   for(; i < widget->allocation.width; ){
-    cairo_set_source_rgb(cr, 1.0, 1.0, 0.0);
+    cairo_set_source_rgb(cr,
+			 automation_area_style->fg[0].red / white_gc,
+			 automation_area_style->fg[0].blue / white_gc,
+			 automation_area_style->fg[0].green / white_gc);
     
     cairo_move_to(cr, (double) i, y);
     cairo_line_to(cr, (double) i, y + height);
@@ -661,7 +686,10 @@ ags_automation_area_draw_segment(AgsAutomationArea *automation_area,
     
     i += control_width;
     
-    cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
+    cairo_set_source_rgb(cr,
+			 automation_area_style->mid[0].red / white_gc,
+			 automation_area_style->mid[0].green / white_gc,
+			 automation_area_style->mid[0].blue / white_gc);
     
     for(j = 1; i < widget->allocation.width && j < tact; j++){
     ags_automation_area_draw_segment0:
@@ -690,6 +718,8 @@ ags_automation_area_draw_scale(AgsAutomationArea *automation_area,
 			       cairo_t *cr,
 			       gdouble x_offset, gdouble y_offset)
 {
+  GtkStyle *automation_area_style;
+
   gdouble y;
   gdouble width, height;
   gdouble translated_ground;
@@ -698,6 +728,10 @@ ags_automation_area_draw_scale(AgsAutomationArea *automation_area,
     0.25,
   };
 
+  static const gdouble white_gc = 65535.0;
+
+  automation_area_style = gtk_widget_get_style(GTK_WIDGET(automation_area->drawing_area));
+
   y = (gdouble) automation_area->y - y_offset;
   
   width = (gdouble) GTK_WIDGET(automation_area->drawing_area)->allocation.width;
@@ -705,7 +739,10 @@ ags_automation_area_draw_scale(AgsAutomationArea *automation_area,
 
   cairo_save(cr);
 
-  cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+  cairo_set_source_rgb(cr,
+		       automation_area_style->bg[0].red / white_gc,
+		       automation_area_style->bg[0].green / white_gc,
+		       automation_area_style->bg[0].blue / white_gc);
 
   /* middle */
   cairo_move_to(cr,
@@ -715,7 +752,10 @@ ags_automation_area_draw_scale(AgsAutomationArea *automation_area,
   cairo_stroke(cr);
 
   /* set dash */
-  cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+  cairo_set_source_rgb(cr,
+		       automation_area_style->bg[0].red / white_gc,
+		       automation_area_style->bg[0].green / white_gc,
+		       automation_area_style->bg[0].blue / white_gc);
   cairo_set_dash(cr,
 		 &dashes,
 		 1,
@@ -784,6 +824,8 @@ ags_automation_area_draw_automation(AgsAutomationArea *automation_area,
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *audio_mutex;
 
+  static const gdouble white_gc = 65535.0;
+
   auto gboolean ags_automation_area_draw_automation_find_tab(gdouble x, gdouble y, gdouble prev_x, gdouble prev_y);
 
   gboolean ags_automation_area_draw_automation_find_tab(gdouble x, gdouble y, gdouble prev_x, gdouble prev_y){
@@ -1120,6 +1162,8 @@ ags_automation_area_draw_surface(AgsAutomationArea *automation_area, cairo_t *cr
   AgsAutomationEditor *automation_editor;
   AgsAutomationEdit *automation_edit;
 
+  GtkStyle *automation_area_style;
+
   GList *list;
 
   double tact_factor, zoom_factor;
@@ -1127,11 +1171,15 @@ ags_automation_area_draw_surface(AgsAutomationArea *automation_area, cairo_t *cr
   gdouble width, height;
   gdouble pos_x, pos_y;
   
+  static const gdouble white_gc = 65535.0;
+
   automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor((GtkWidget *) automation_area->drawing_area,
 								      AGS_TYPE_AUTOMATION_EDITOR);
   automation_edit = (AgsAutomationEdit *) gtk_widget_get_ancestor((GtkWidget *) automation_area->drawing_area,
 								  AGS_TYPE_AUTOMATION_EDIT);
   
+  automation_area_style = gtk_widget_get_style(GTK_WIDGET(automation_area->drawing_area));
+
   zoom_factor = 1.0 / 4.0;
 
   tact_factor = exp2(6.0 - (double) gtk_combo_box_get_active(automation_editor->automation_toolbar->zoom));
@@ -1173,7 +1221,11 @@ ags_automation_area_draw_surface(AgsAutomationArea *automation_area, cairo_t *cr
   }
   
   /*  */
-  cairo_set_source_rgba(cr, 1.0, 1.0, 0.0, 0.2);
+  cairo_set_source_rgba(cr,
+			automation_area_style->light[0].red / white_gc,
+			automation_area_style->light[0].green / white_gc,
+			automation_area_style->light[0].blue / white_gc,
+			0.4);
 
   /* area */
   cairo_rectangle(cr,
diff --git a/ags/X/editor/ags_automation_edit.c b/ags/X/editor/ags_automation_edit.c
index 2102566..4586ec6 100644
--- a/ags/X/editor/ags_automation_edit.c
+++ b/ags/X/editor/ags_automation_edit.c
@@ -261,6 +261,7 @@ ags_automation_edit_init(AgsAutomationEdit *automation_edit)
 void
 ags_automation_edit_connect(AgsConnectable *connectable)
 {
+  AgsAutomationEditor *automation_editor;
   AgsAutomationEdit *automation_edit;
 
   automation_edit = AGS_AUTOMATION_EDIT(connectable);
@@ -270,6 +271,18 @@ ags_automation_edit_connect(AgsConnectable *connectable)
   }
   
   automation_edit->flags |= AGS_AUTOMATION_EDIT_CONNECTED;
+
+  automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor(GTK_WIDGET(automation_edit),
+								      AGS_TYPE_AUTOMATION_EDITOR);
+
+  if(automation_editor != NULL && automation_editor->selected_machine != NULL){
+    g_signal_connect_after(automation_editor->selected_machine->audio, "set-audio-channels\0",
+			   G_CALLBACK(ags_automation_edit_set_audio_channels_callback), automation_edit);
+
+    g_signal_connect_after(automation_editor->selected_machine->audio, "set-pads\0",
+			   G_CALLBACK(ags_automation_edit_set_pads_callback), automation_edit);
+  }
+
   
   /*  */
   g_signal_connect_after((GObject *) automation_edit->drawing_area, "expose_event\0",
diff --git a/ags/X/editor/ags_automation_edit_callbacks.c b/ags/X/editor/ags_automation_edit_callbacks.c
index 9cdff56..16c520e 100644
--- a/ags/X/editor/ags_automation_edit_callbacks.c
+++ b/ags/X/editor/ags_automation_edit_callbacks.c
@@ -19,12 +19,16 @@
 
 #include <ags/X/editor/ags_automation_edit_callbacks.h>
 
+#include <ags/object/ags_application_context.h>
+
 #include <ags/thread/ags_mutex_manager.h>
+#include <ags/thread/ags_thread-posix.h>
 
 #include <ags/audio/ags_audio.h>
 #include <ags/audio/ags_output.h>
 #include <ags/audio/ags_input.h>
 
+#include <ags/X/ags_window.h>
 #include <ags/X/ags_automation_editor.h>
 
 #include <ags/X/editor/ags_notebook.h>
@@ -37,9 +41,177 @@
 #include <ags/X/machine/ags_synth.h>
 #include <ags/X/machine/ags_ffplayer.h>
 
+#include <ags/X/thread/ags_gui_thread.h>
+
 #include <math.h>
 #include <gdk/gdkkeysyms.h>
 
+void
+ags_automation_edit_set_audio_channels_callback(AgsAudio *audio,
+						guint audio_channels, guint audio_channels_old,
+						AgsAutomationEdit *automation_edit)
+{
+  AgsWindow *window;
+  AgsAutomationEditor *automation_editor;
+  AgsAutomationEditorChild *editor_child;
+  AgsNotebook *notebook;
+
+  GList *list;
+
+  guint pads;
+  guint i, j;
+  gboolean is_output;
+
+  gdk_threads_enter();
+
+  window = (AgsWindow *) AGS_AUTOMATION_WINDOW(gtk_widget_get_toplevel((GtkWidget *) automation_edit))->parent_window;
+  
+  automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor(GTK_WIDGET(automation_edit),
+								      AGS_TYPE_AUTOMATION_EDITOR);
+
+  editor_child = NULL;
+  list = automation_editor->automation_editor_child;
+  
+  while(list != NULL){
+    if(AGS_AUTOMATION_EDITOR_CHILD(list->data)->audio_automation_edit == (GtkWidget *) automation_edit){
+      gdk_threads_leave();
+    
+      return;
+    }else if(AGS_AUTOMATION_EDITOR_CHILD(list->data)->output_automation_edit == (GtkWidget *) automation_edit){
+      editor_child = AGS_AUTOMATION_EDITOR_CHILD(list->data);
+
+      notebook = editor_child->output_notebook;
+
+      pads = audio->output_pads;
+      is_output = TRUE;
+
+      break;
+    }else if(AGS_AUTOMATION_EDITOR_CHILD(list->data)->input_automation_edit == (GtkWidget *) automation_edit){
+      editor_child = AGS_AUTOMATION_EDITOR_CHILD(list->data);
+
+      notebook = editor_child->input_notebook;
+
+      pads = audio->input_pads;
+      is_output = FALSE;
+
+      break;
+    }
+    
+    list = list->next;
+  }
+
+  if(editor_child == NULL){    
+    gdk_threads_leave();
+    
+    return;
+  }
+
+  if(audio_channels_old < audio_channels){
+    for(j = 0; j < pads; j++){
+      for(i = audio_channels_old; i < audio_channels; i++){
+	ags_notebook_insert_tab(notebook,
+				j * audio_channels + i);
+      }
+    }
+    
+    gtk_widget_show_all((GtkWidget *) notebook);
+  }else if(audio_channels_old > audio_channels){
+    for(j = 0; j < pads; j++){
+      for(i = audio_channels; i < audio_channels_old; i++){
+	ags_notebook_remove_tab(notebook,
+				j * audio_channels + i);
+      }
+    }
+  }
+
+  gdk_threads_leave();
+}
+
+void
+ags_automation_edit_set_pads_callback(AgsAudio *audio,
+				      GType channel_type,
+				      guint pads, guint pads_old,
+				      AgsAutomationEdit *automation_edit)
+{
+  AgsWindow *window;
+  AgsAutomationEditor *automation_editor;
+  AgsAutomationEditorChild *editor_child;
+  AgsNotebook *notebook;
+
+  GList *list;
+
+  guint audio_channels;
+  guint i, j;
+  gboolean is_output;
+  
+  gdk_threads_enter();
+
+  window = (AgsWindow *) AGS_AUTOMATION_WINDOW(gtk_widget_get_toplevel((GtkWidget *) automation_edit))->parent_window;
+
+  automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor(GTK_WIDGET(automation_edit),
+								      AGS_TYPE_AUTOMATION_EDITOR);
+
+  automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor(GTK_WIDGET(automation_edit),
+								      AGS_TYPE_AUTOMATION_EDITOR);
+
+  editor_child = NULL;
+  list = automation_editor->automation_editor_child;
+
+  audio_channels = audio->audio_channels;
+  
+  while(list != NULL){
+    if(AGS_AUTOMATION_EDITOR_CHILD(list->data)->audio_automation_edit == (GtkWidget *) automation_edit){
+      gdk_threads_leave();
+    
+      return;
+    }else if(AGS_AUTOMATION_EDITOR_CHILD(list->data)->output_automation_edit == (GtkWidget *) automation_edit){
+      editor_child = AGS_AUTOMATION_EDITOR_CHILD(list->data);
+
+      notebook = editor_child->output_notebook;
+      
+      is_output = TRUE;
+
+      break;
+    }else if(AGS_AUTOMATION_EDITOR_CHILD(list->data)->input_automation_edit == (GtkWidget *) automation_edit){
+      editor_child = AGS_AUTOMATION_EDITOR_CHILD(list->data);
+
+      notebook = editor_child->input_notebook;
+ 
+      is_output = FALSE;
+
+      break;
+    }
+    
+    list = list->next;
+  }
+
+  if(editor_child == NULL){    
+    gdk_threads_leave();
+    
+    return;
+  }
+
+  if(pads_old < pads){
+    for(j = pads_old; j < pads; j++){
+      for(i = 0; i < audio_channels; i++){
+	ags_notebook_insert_tab(notebook,
+				j * audio_channels + i);
+      }
+    }
+    
+    gtk_widget_show_all((GtkWidget *) notebook);
+  }else if(pads_old > pads){
+    for(j = pads; j < pads_old; j++){
+      for(i = 0; i < audio_channels; i++){
+	ags_notebook_remove_tab(notebook,
+				j * audio_channels + i);
+      }
+    }
+  }
+
+  gdk_threads_leave();
+}
+
 gboolean
 ags_automation_edit_drawing_area_expose_event(GtkWidget *widget, GdkEventExpose *event,
 					      AgsAutomationEdit *automation_edit)
diff --git a/ags/X/editor/ags_automation_edit_callbacks.h b/ags/X/editor/ags_automation_edit_callbacks.h
index e816791..d94bd91 100644
--- a/ags/X/editor/ags_automation_edit_callbacks.h
+++ b/ags/X/editor/ags_automation_edit_callbacks.h
@@ -26,6 +26,15 @@
 
 #include <ags/X/editor/ags_automation_edit.h>
 
+
+void ags_automation_edit_set_audio_channels_callback(AgsAudio *audio,
+						     guint audio_channels, guint audio_channels_old,
+						     AgsAutomationEdit *automation_edit);
+void ags_automation_edit_set_pads_callback(AgsAudio *audio,
+					   GType channel_type,
+					   guint pads, guint pads_old,
+					   AgsAutomationEdit *automation_edit);
+
 gboolean ags_automation_edit_drawing_area_expose_event(GtkWidget *widget, GdkEventExpose *event,
 						       AgsAutomationEdit *automation_edit);
 gboolean ags_automation_edit_drawing_area_configure_event(GtkWidget *widget, GdkEventConfigure *event,
diff --git a/ags/X/editor/ags_machine_selector.c b/ags/X/editor/ags_machine_selector.c
index a205e06..961fc08 100644
--- a/ags/X/editor/ags_machine_selector.c
+++ b/ags/X/editor/ags_machine_selector.c
@@ -25,6 +25,7 @@
 #include <ags/audio/ags_notation.h>
 
 #include <ags/X/ags_editor.h>
+#include <ags/X/ags_automation_editor.h>
 
 #include <ags/X/editor/ags_machine_radio_button.h>
 
@@ -225,10 +226,7 @@ ags_machine_selector_remove_index(AgsMachineSelector *machine_selector,
   
   GList *list, *list_start;
 
-  editor = (AgsEditor *) gtk_widget_get_ancestor((GtkWidget *) machine_selector,
-						 AGS_TYPE_EDITOR);
-
-  /* emit changed */
+  /* get machine radio button */
   machine_radio_button = NULL;
 
   list_start = 
@@ -243,28 +241,106 @@ ags_machine_selector_remove_index(AgsMachineSelector *machine_selector,
   }
   
   g_list_free(list_start);
+
+  if(machine_radio_button == NULL){
+    return;
+  }
   
-  /* destroy edit widgets */
-  if(machine_radio_button != NULL){
+  /*  */
+  editor = (AgsEditor *) gtk_widget_get_ancestor((GtkWidget *) machine_selector,
+						 AGS_TYPE_EDITOR);
+
+  if(editor != NULL){  
+    /* destroy edit widgets */
     if(machine_radio_button->machine != NULL){
+      AgsEditorChild *editor_child;
+
+      editor_child = NULL;
+      
       list = editor->editor_child;
 
       while(list != NULL){
 	if(AGS_EDITOR_CHILD(list->data)->machine == machine_radio_button->machine){
-	  gtk_widget_destroy((GtkWidget *) AGS_EDITOR_CHILD(list->data)->notebook);
-	  gtk_widget_destroy((GtkWidget *) AGS_EDITOR_CHILD(list->data)->meter);
-	  gtk_widget_destroy((GtkWidget *) AGS_EDITOR_CHILD(list->data)->edit_widget);
-	
+	  editor_child = AGS_EDITOR_CHILD(list->data);
+	  
+	  gtk_widget_destroy((GtkWidget *) editor_child->notebook);
+	  gtk_widget_destroy((GtkWidget *) editor_child->meter);
+	  gtk_widget_destroy((GtkWidget *) editor_child->edit_widget);
+
+	  editor->current_notebook = NULL;
+	  editor->current_meter = NULL;
+	  editor->current_edit_widget = NULL;
+	  
 	  break;
 	}
     
 	list = list->next;
       }
+
+      if(editor_child != NULL){
+	editor->editor_child = g_list_remove(editor->editor_child,
+					     editor_child);
+	free(editor_child);
+      }
+    }
+  }else{
+    AgsAutomationEditor *automation_editor;
+    
+    automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor((GtkWidget *) machine_selector,
+									AGS_TYPE_AUTOMATION_EDITOR);
+
+    if(automation_editor != NULL){
+      /* destroy edit widgets */
+      if(machine_radio_button->machine != NULL){
+	AgsAutomationEditorChild *automation_editor_child;
+
+	automation_editor_child = NULL;
+	
+	list = automation_editor->automation_editor_child;
+
+	while(list != NULL){
+	  if(AGS_AUTOMATION_EDITOR_CHILD(list->data)->machine == machine_radio_button->machine){
+	    automation_editor_child = AGS_AUTOMATION_EDITOR_CHILD(list->data);
+	    
+	    gtk_widget_destroy((GtkWidget *) automation_editor_child->audio_scale);
+	    gtk_widget_destroy((GtkWidget *) automation_editor_child->audio_automation_edit);
+	    
+	    gtk_widget_destroy((GtkWidget *) automation_editor_child->output_scale);
+	    gtk_widget_destroy((GtkWidget *) automation_editor_child->output_notebook);
+	    gtk_widget_destroy((GtkWidget *) automation_editor_child->output_automation_edit);
+
+	    gtk_widget_destroy((GtkWidget *) automation_editor_child->input_scale);
+	    gtk_widget_destroy((GtkWidget *) automation_editor_child->input_notebook);
+	    gtk_widget_destroy((GtkWidget *) automation_editor_child->input_automation_edit);
+
+	    automation_editor->current_audio_scale = NULL;
+	    automation_editor->current_audio_automation_edit = NULL;
+
+	    automation_editor->current_output_notebook = NULL;
+	    automation_editor->current_output_scale = NULL;
+	    automation_editor->current_output_automation_edit = NULL;
+
+	    automation_editor->current_input_notebook = NULL;
+	    automation_editor->current_input_scale = NULL;
+	    automation_editor->current_input_automation_edit = NULL;
+
+	    break;
+	  }
+    
+	  list = list->next;
+	}
+
+	if(automation_editor_child != NULL){
+	  automation_editor->automation_editor_child = g_list_remove(automation_editor->automation_editor_child,
+								     automation_editor_child);
+	  free(automation_editor_child);
+	}
+      }
     }
-  
-    /**/
-    gtk_widget_destroy(GTK_WIDGET(machine_radio_button));
   }
+  
+  /**/
+  gtk_widget_destroy(GTK_WIDGET(machine_radio_button));
 }
 
 void
diff --git a/ags/X/editor/ags_note_edit.c b/ags/X/editor/ags_note_edit.c
index 4757e3d..a0ede45 100644
--- a/ags/X/editor/ags_note_edit.c
+++ b/ags/X/editor/ags_note_edit.c
@@ -331,6 +331,14 @@ ags_note_edit_connect(AgsConnectable *connectable)
 void
 ags_note_edit_disconnect(AgsConnectable *connectable)
 {
+  AgsEditor *editor;
+  AgsNoteEdit *note_edit;
+
+  note_edit = AGS_NOTE_EDIT(connectable);
+
+  editor = (AgsEditor *) gtk_widget_get_ancestor(GTK_WIDGET(note_edit),
+						 AGS_TYPE_EDITOR);
+
   //TODO:JK: implement me
 }
 
diff --git a/ags/X/editor/ags_note_edit_callbacks.c b/ags/X/editor/ags_note_edit_callbacks.c
index 3d7fcd6..a9742a2 100644
--- a/ags/X/editor/ags_note_edit_callbacks.c
+++ b/ags/X/editor/ags_note_edit_callbacks.c
@@ -27,6 +27,7 @@
 #include <ags/thread/ags_mutex_manager.h>
 #include <ags/thread/ags_task_thread.h>
 
+#include <ags/audio/ags_sound_provider.h>
 #include <ags/audio/ags_audio.h>
 #include <ags/audio/ags_channel.h>
 #include <ags/audio/ags_output.h>
@@ -46,6 +47,7 @@
 #include <ags/audio/task/ags_append_recall.h>
 #include <ags/audio/task/ags_add_audio_signal.h>
 
+#include <ags/X/ags_window.h>
 #include <ags/X/ags_editor.h>
 
 #include <ags/X/machine/ags_panel.h>
@@ -57,6 +59,8 @@
 #include <ags/X/machine/ags_dssi_bridge.h>
 #include <ags/X/machine/ags_lv2_bridge.h>
 
+#include <ags/X/thread/ags_gui_thread.h>
+
 #include <gdk/gdkkeysyms.h>
 
 void ags_note_edit_init_channel_launch_callback(AgsTask *task, AgsNote *note);
@@ -66,14 +70,21 @@ ags_note_edit_set_audio_channels_callback(AgsAudio *audio,
 					  guint audio_channels, guint audio_channels_old,
 					  AgsNoteEdit *note_edit)
 {
+  AgsWindow *window;
   AgsEditor *editor;
   AgsEditorChild *editor_child;
 
   GList *list;
   GList *tabs;
   GList *notation;
+
   guint i;
 
+  /*  */
+  gdk_threads_enter();
+
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) note_edit);
+
   editor = (AgsEditor *) gtk_widget_get_ancestor(GTK_WIDGET(note_edit),
 						 AGS_TYPE_EDITOR);
 
@@ -88,6 +99,12 @@ ags_note_edit_set_audio_channels_callback(AgsAudio *audio,
     
     list = list->next;
   }
+
+  if(editor_child == NULL){    
+    gdk_threads_leave();
+    
+    return;
+  }
   
   if(audio_channels_old < audio_channels){
     notation = g_list_nth(audio->notation,
@@ -110,6 +127,8 @@ ags_note_edit_set_audio_channels_callback(AgsAudio *audio,
 			      i);
     }
   }
+
+  gdk_threads_leave();
 }
 
 void
@@ -118,11 +137,9 @@ ags_note_edit_set_pads_callback(AgsAudio *audio,
 				guint pads, guint pads_old,
 				AgsNoteEdit *note_edit)
 {
+  AgsWindow *window;
   AgsEditor *editor;
 
-  editor = (AgsEditor *) gtk_widget_get_ancestor(GTK_WIDGET(note_edit),
-						 AGS_TYPE_EDITOR);
-
   if((AGS_AUDIO_NOTATION_DEFAULT & (audio->flags)) != 0){
     if(!g_type_is_a(channel_type, AGS_TYPE_INPUT)){
       return;
@@ -132,16 +149,25 @@ ags_note_edit_set_pads_callback(AgsAudio *audio,
       return;
     }
   }
+  /*  */
+  gdk_threads_enter();
+  
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) note_edit);
+
+  editor = (AgsEditor *) gtk_widget_get_ancestor(GTK_WIDGET(note_edit),
+						 AGS_TYPE_EDITOR);
 
   if(AGS_IS_NOTE_EDIT(note_edit)){
     ags_note_edit_set_map_height(note_edit,
-			       pads * note_edit->control_height);
+				 pads * note_edit->control_height);
   }else if(AGS_IS_NOTE_EDIT(note_edit)){
     ags_note_edit_set_map_height(AGS_NOTE_EDIT(note_edit),
-				    pads * AGS_NOTE_EDIT(note_edit)->control_height);
+				 pads * AGS_NOTE_EDIT(note_edit)->control_height);
   }
 
   gtk_widget_queue_draw((GtkWidget *) editor->current_meter);
+
+  gdk_threads_leave();
 }
 
 gboolean
@@ -1210,6 +1236,8 @@ ags_note_edit_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *eve
   auto void ags_note_edit_drawing_area_key_release_event_play_channel(AgsChannel *channel, AgsNote *note);
 
   void ags_note_edit_drawing_area_key_release_event_play_channel(AgsChannel *channel, AgsNote *note){
+    AgsWindow *window;
+    
     GObject *soundcard;
     AgsAudio *audio;
 
@@ -1226,13 +1254,35 @@ ags_note_edit_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *eve
     
     GList *tasks;
 
+    gboolean no_soundcard;
+    
     pthread_mutex_t *application_mutex;
     pthread_mutex_t *soundcard_mutex;
     pthread_mutex_t *audio_mutex;
     pthread_mutex_t *channel_mutex;
 
+    window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) note_edit);
+
+    application_context = (AgsApplicationContext *) window->application_context;
+
     mutex_manager = ags_mutex_manager_get_instance();
     application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+    
+    no_soundcard = FALSE;
+
+    pthread_mutex_lock(application_mutex);
+
+    if(ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context)) == NULL){
+      no_soundcard = TRUE;
+    }
+
+    pthread_mutex_unlock(application_mutex);
+
+    if(no_soundcard){
+      g_message("No soundcard available\0");
+      
+      return;
+    }
 
     /* lookup channel mutex */
     pthread_mutex_lock(application_mutex);
@@ -1272,13 +1322,6 @@ ags_note_edit_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *eve
 
     pthread_mutex_unlock(application_mutex);
 
-    /* get application_context */
-    pthread_mutex_lock(soundcard_mutex);
-
-    application_context = (AgsApplicationContext *) ags_soundcard_get_application_context(AGS_SOUNDCARD(soundcard));
-
-    pthread_mutex_unlock(soundcard_mutex);
-
     /* get threads */
     pthread_mutex_lock(application_mutex);
 
diff --git a/ags/X/editor/ags_notebook.c b/ags/X/editor/ags_notebook.c
index d1df894..f16df5c 100644
--- a/ags/X/editor/ags_notebook.c
+++ b/ags/X/editor/ags_notebook.c
@@ -531,10 +531,12 @@ ags_notebook_remove_tab(AgsNotebook *notebook,
   tab = g_list_nth_data(notebook->tabs,
 			length - nth - 1);
 
-  notebook->tabs = g_list_remove(notebook->tabs,
-				 tab);
-  gtk_widget_destroy(GTK_WIDGET(tab->toggle));
-  free(tab);
+  if(tab != NULL){
+    notebook->tabs = g_list_remove(notebook->tabs,
+				   tab);
+    gtk_widget_destroy(GTK_WIDGET(tab->toggle));
+    free(tab);
+  }
 }
 
 void
diff --git a/ags/X/editor/ags_pattern_edit_callbacks.c b/ags/X/editor/ags_pattern_edit_callbacks.c
index 40624cf..18dfac6 100644
--- a/ags/X/editor/ags_pattern_edit_callbacks.c
+++ b/ags/X/editor/ags_pattern_edit_callbacks.c
@@ -27,6 +27,7 @@
 #include <ags/thread/ags_mutex_manager.h>
 #include <ags/thread/ags_task_thread.h>
 
+#include <ags/audio/ags_sound_provider.h>
 #include <ags/audio/ags_audio.h>
 #include <ags/audio/ags_channel.h>
 #include <ags/audio/ags_output.h>
@@ -44,6 +45,7 @@
 #include <ags/audio/task/ags_append_recall.h>
 #include <ags/audio/task/ags_add_audio_signal.h>
 
+#include <ags/X/ags_window.h>
 #include <ags/X/ags_editor.h>
 
 #include <ags/X/machine/ags_panel.h>
@@ -53,6 +55,8 @@
 #include <ags/X/machine/ags_synth.h>
 #include <ags/X/machine/ags_ffplayer.h>
 
+#include <ags/X/thread/ags_gui_thread.h>
+
 #include <gdk/gdkkeysyms.h>
 
 void ags_pattern_edit_init_channel_launch_callback(AgsTask *task, gpointer data);
@@ -62,14 +66,20 @@ ags_pattern_edit_set_audio_channels_callback(AgsAudio *audio,
 					     guint audio_channels, guint audio_channels_old,
 					     AgsPatternEdit *pattern_edit)
 {
+  AgsWindow *window;
   AgsEditor *editor;
   AgsEditorChild *editor_child;
 
   GList *list;
   GList *tabs;
   GList *notation;
+
   guint i;
 
+  gdk_threads_enter();
+  
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) pattern_edit);
+
   editor = (AgsEditor *) gtk_widget_get_ancestor(GTK_WIDGET(pattern_edit),
 						 AGS_TYPE_EDITOR);
 
@@ -85,6 +95,12 @@ ags_pattern_edit_set_audio_channels_callback(AgsAudio *audio,
     list = list->next;
   }
   
+  if(editor_child == NULL){
+    gdk_threads_leave();
+    
+    return;
+  }
+
   if(audio_channels_old < audio_channels){
     notation = g_list_nth(audio->notation,
 			  audio_channels_old - 1);
@@ -106,6 +122,8 @@ ags_pattern_edit_set_audio_channels_callback(AgsAudio *audio,
 			      i);
     }
   }
+
+  gdk_threads_leave();
 }
 
 void
@@ -114,11 +132,9 @@ ags_pattern_edit_set_pads_callback(AgsAudio *audio,
 				   guint pads, guint pads_old,
 				   AgsPatternEdit *pattern_edit)
 {
+  AgsWindow *window;
   AgsEditor *editor;
 
-  editor = (AgsEditor *) gtk_widget_get_ancestor(GTK_WIDGET(pattern_edit),
-						 AGS_TYPE_EDITOR);
-
   if((AGS_AUDIO_NOTATION_DEFAULT & (audio->flags)) != 0){
     if(!g_type_is_a(channel_type, AGS_TYPE_INPUT)){
       return;
@@ -129,6 +145,13 @@ ags_pattern_edit_set_pads_callback(AgsAudio *audio,
     }
   }
 
+  gdk_threads_enter();
+
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) pattern_edit);
+
+  editor = (AgsEditor *) gtk_widget_get_ancestor(GTK_WIDGET(pattern_edit),
+						 AGS_TYPE_EDITOR);
+
   if(AGS_IS_PATTERN_EDIT(pattern_edit)){
     ags_pattern_edit_set_map_height(pattern_edit,
 				    pads * pattern_edit->control_height);
@@ -138,6 +161,8 @@ ags_pattern_edit_set_pads_callback(AgsAudio *audio,
   }
   
   gtk_widget_queue_draw((GtkWidget *) editor->current_meter);
+
+  gdk_threads_leave();
 }
 
 gboolean
@@ -1154,6 +1179,8 @@ ags_pattern_edit_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *
   auto void ags_pattern_edit_drawing_area_key_release_event_play_channel(AgsChannel *channel);
 
   void ags_pattern_edit_drawing_area_key_release_event_play_channel(AgsChannel *channel){
+    AgsWindow *window;
+    
     GObject *soundcard;
     AgsAudio *audio;
 
@@ -1171,14 +1198,36 @@ ags_pattern_edit_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *
     
     GList *tasks;
 
+    gboolean no_soundcard;
+    
     pthread_mutex_t *application_mutex;
     pthread_mutex_t *soundcard_mutex;
     pthread_mutex_t *audio_mutex;
     pthread_mutex_t *channel_mutex;
 
+    window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) pattern_edit);
+
+    application_context = (AgsApplicationContext *) window->application_context;
+
     mutex_manager = ags_mutex_manager_get_instance();
     application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
 
+    no_soundcard = FALSE;
+
+    pthread_mutex_lock(application_mutex);
+
+    if(ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context)) == NULL){
+      no_soundcard = TRUE;
+    }
+
+    pthread_mutex_unlock(application_mutex);
+
+    if(no_soundcard){
+      g_message("No soundcard available\0");
+      
+      return;
+    }
+
     /* lookup channel mutex */
     pthread_mutex_lock(application_mutex);
   
@@ -1217,13 +1266,6 @@ ags_pattern_edit_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *
   
     pthread_mutex_unlock(application_mutex);
 
-    /* get application_context */
-    pthread_mutex_lock(soundcard_mutex);
-
-    application_context = (AgsApplicationContext *) ags_soundcard_get_application_context(AGS_SOUNDCARD(soundcard));
-
-    pthread_mutex_unlock(soundcard_mutex);
-
     /* get threads */
     pthread_mutex_lock(application_mutex);
 
diff --git a/ags/X/file/ags_gui_file_xml.c b/ags/X/file/ags_gui_file_xml.c
index 50cd5d2..c792ac1 100644
--- a/ags/X/file/ags_gui_file_xml.c
+++ b/ags/X/file/ags_gui_file_xml.c
@@ -2075,53 +2075,6 @@ ags_file_read_line_member_resolve_port(AgsFileLookup *file_lookup,
 		   NULL);
     }
   }
-
-  child_widget = (GtkWidget *) gtk_bin_get_child(GTK_BIN(line_member));
-
-  if(AGS_IS_VINDICATOR(child_widget)){
-    AgsLine *line;
-    AgsChannel *source;
-    
-    AgsPeakChannelRun *recall_peak_channel_run, *play_peak_channel_run;
-    AgsRecallHandler *recall_handler;
-    GList *list;
-
-    line = (AgsLine *) gtk_widget_get_ancestor((GtkWidget *) line_member,
-					       AGS_TYPE_LINE);
-    source = line->channel;
-    
-    /* play - connect run_post */
-    list = ags_recall_template_find_type(source->play,
-					 AGS_TYPE_PEAK_CHANNEL_RUN);
-
-    if(list != NULL){
-      play_peak_channel_run = AGS_PEAK_CHANNEL_RUN(list->data);
-
-      recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
-
-      recall_handler->signal_name = "run-post\0";
-      recall_handler->callback = G_CALLBACK(ags_line_peak_run_post_callback);
-      recall_handler->data = (gpointer) line;
-
-      ags_recall_add_handler(AGS_RECALL(play_peak_channel_run), recall_handler);
-    }
-
-    /* recall - connect run_post */
-    list = ags_recall_template_find_type(source->recall,
-					 AGS_TYPE_PEAK_CHANNEL_RUN);
-
-    if(list != NULL){
-      recall_peak_channel_run = AGS_PEAK_CHANNEL_RUN(list->data);
-
-      recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
-
-      recall_handler->signal_name = "run-post\0";
-      recall_handler->callback = G_CALLBACK(ags_line_peak_run_post_callback);
-      recall_handler->data = (gpointer) line;
-
-      ags_recall_add_handler(AGS_RECALL(recall_peak_channel_run), recall_handler);
-    }
-  }
 }
 
 xmlNode*
diff --git a/ags/X/file/ags_simple_file.c b/ags/X/file/ags_simple_file.c
index 427235e..bf15741 100644
--- a/ags/X/file/ags_simple_file.c
+++ b/ags/X/file/ags_simple_file.c
@@ -1136,15 +1136,21 @@ ags_simple_file_real_read(AgsSimpleFile *simple_file)
 {
   AgsApplicationContext *application_context;
 
-  xmlNode *root_node, *child;
+  AgsGuiThread *gui_thread;
 
+  xmlNode *root_node, *child;
+  
   application_context = (AgsApplicationContext *) simple_file->application_context;
 
+  gui_thread = ags_thread_find_type(application_context->main_loop,
+				    AGS_TYPE_GUI_THREAD);
+
   root_node = simple_file->root_node;
 
   /* child elements */
   child = root_node->children;
 
+  /*  */
   ags_application_context_register_types(application_context);
   
   while(child != NULL){
@@ -1181,6 +1187,10 @@ ags_simple_file_real_read(AgsSimpleFile *simple_file)
 
   /* start */
   ags_simple_file_read_start(simple_file);
+
+  g_atomic_int_set(&(AGS_XORG_APPLICATION_CONTEXT(application_context)->gui_ready),
+		     1);
+    
 }
 
 void
@@ -1625,7 +1635,10 @@ ags_simple_file_read_machine_list(AgsSimpleFile *simple_file, xmlNode *node, GLi
 
 	  iter = g_list_nth(*machine,
 			    i);
-	  current = iter->data;
+
+	  if(iter != NULL){
+	    current = iter->data;
+	  }
 	}
 	
 	ags_simple_file_read_machine(simple_file, child, &current);
@@ -1692,6 +1705,14 @@ ags_simple_file_read_machine(AgsSimpleFile *simple_file, xmlNode *node, AgsMachi
 					  "reference\0", gobject,
 					  NULL));
 
+  /* set name if available */
+  str = xmlGetProp(node,
+		   AGS_FILE_NAME_PROP);
+
+  if(str != NULL){
+    gobject->name = g_strdup(str);
+  }
+  
   /* retrieve window */  
   window = AGS_XORG_APPLICATION_CONTEXT(simple_file->application_context)->window;
 
@@ -1782,6 +1803,9 @@ ags_simple_file_read_machine(AgsSimpleFile *simple_file, xmlNode *node, AgsMachi
 				AGS_AUDIO_NOTATION_DEFAULT);
       gobject->flags |= (AGS_MACHINE_IS_SYNTHESIZER |
 			 AGS_MACHINE_REVERSE_NOTATION);
+
+      ags_machine_popup_add_connection_options((AgsMachine *) gobject,
+					       (AGS_MACHINE_POPUP_MIDI_DIALOG));
     }
 
     g_object_set(gobject,
@@ -2128,6 +2152,7 @@ ags_simple_file_read_machine_launch(AgsFileLaunch *file_launch,
   auto void ags_simple_file_read_matrix_launch(AgsSimpleFile *simpleFile, xmlNode *node, AgsMatrix *matrix);
   auto void ags_simple_file_read_ffplayer_launch(AgsSimpleFile *simpleFile, xmlNode *node, AgsFFPlayer *ffplayer);
   auto void ags_simple_file_read_dssi_bridge_launch(AgsSimpleFile *simpleFile, xmlNode *node, AgsDssiBridge *dssi_bridge);
+  auto void ags_simple_file_read_lv2_bridge_launch(AgsSimpleFile *simpleFile, xmlNode *node, AgsLv2Bridge *lv2_bridge);
 
   auto void ags_simple_file_read_effect_bridge_launch(AgsSimpleFile *simple_file, xmlNode *node, AgsEffectBridge *effect_bridge);
   auto void ags_simple_file_read_effect_bulk_launch(AgsSimpleFile *simple_file, xmlNode *node, AgsEffectBulk *effect_bulk);
@@ -2255,7 +2280,8 @@ ags_simple_file_read_machine_launch(AgsFileLaunch *file_launch,
     ags_ffplayer_open_filename(ffplayer,
 			       str);
 
-    if(ffplayer->ipatch->base == NULL){
+    if(ffplayer->ipatch == NULL ||
+       ffplayer->ipatch->base == NULL){
       return;
     }
     
@@ -2344,6 +2370,44 @@ ags_simple_file_read_machine_launch(AgsFileLaunch *file_launch,
     }
   }
 
+  void ags_simple_file_read_lv2_bridge_launch(AgsSimpleFile *simpleFile, xmlNode *node, AgsLv2Bridge *lv2_bridge){
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+
+    xmlChar *str;
+    gchar *value;
+
+    if(lv2_bridge->preset == NULL){
+      return;
+    }
+    
+    /* program */
+    //NOTE:JK: work-around
+    gtk_combo_box_set_active((GtkComboBox *) lv2_bridge->preset,
+			     0);
+
+    model = gtk_combo_box_get_model((GtkComboBox *) lv2_bridge->preset);
+
+    str = xmlGetProp(node,
+		     "preset\0");
+
+    if(gtk_tree_model_get_iter_first(model, &iter)){
+      do{
+	gtk_tree_model_get(model, &iter,
+			   0, &value,
+			   -1);
+
+	if(!g_strcmp0(str,
+		      value)){
+	  gtk_combo_box_set_active_iter((GtkComboBox *) lv2_bridge->preset,
+					&iter);
+	  break;
+	}
+      }while(gtk_tree_model_iter_next(model,
+				      &iter));
+    }
+  }
+
   void ags_simple_file_read_effect_bridge_launch(AgsSimpleFile *simple_file, xmlNode *node, AgsEffectBridge *effect_bridge){
     AgsEffectBulk *effect_bulk;
     
@@ -2498,6 +2562,8 @@ ags_simple_file_read_machine_launch(AgsFileLaunch *file_launch,
     ags_simple_file_read_ffplayer_launch((AgsSimpleFile *) file_launch->file, file_launch->node, (AgsFFPlayer *) machine);
   }else if(AGS_IS_DSSI_BRIDGE(machine)){
     ags_simple_file_read_dssi_bridge_launch((AgsSimpleFile *) file_launch->file, file_launch->node, (AgsDssiBridge *) machine);
+  }else if(AGS_IS_LV2_BRIDGE(machine)){
+    ags_simple_file_read_lv2_bridge_launch((AgsSimpleFile *) file_launch->file, file_launch->node, (AgsLv2Bridge *) machine);
   }
   
   /* children */
@@ -2566,7 +2632,10 @@ ags_simple_file_read_pad_list(AgsSimpleFile *simple_file, xmlNode *node, GList *
 
 	  iter = g_list_nth(*pad,
 			    i);
-	  current = iter->data;
+
+	  if(iter != NULL){
+	    current = iter->data;
+	  }
 	}
 	
 	ags_simple_file_read_pad(simple_file, child, &current);
@@ -2684,6 +2753,8 @@ ags_simple_file_read_pad(AgsSimpleFile *simple_file, xmlNode *node, AgsPad **pad
     child = child->next;
   }
 
+  ags_connectable_connect(AGS_CONNECTABLE(gobject));
+
   /* launch AgsPad */
   file_launch = (AgsFileLaunch *) g_object_new(AGS_TYPE_FILE_LAUNCH,
 					       "node\0", node,
@@ -2786,7 +2857,10 @@ ags_simple_file_read_line_list(AgsSimpleFile *simple_file, xmlNode *node, GList
 
 	  iter = g_list_nth(*line,
 			    i);
-	  current = iter->data;
+	  
+	  if(iter != NULL){
+	    current = iter->data;
+	  }
 	}
 	
 	ags_simple_file_read_line(simple_file, child, &current);
@@ -3225,6 +3299,8 @@ ags_simple_file_read_line(AgsSimpleFile *simple_file, xmlNode *node, AgsLine **l
     child = child->next;
   }
 
+  ags_connectable_connect(AGS_CONNECTABLE(gobject));
+  
   /* launch AgsLine */
   if(AGS_IS_LINE(gobject)){
     file_launch = (AgsFileLaunch *) g_object_new(AGS_TYPE_FILE_LAUNCH,
@@ -3675,7 +3751,10 @@ ags_simple_file_read_effect_line_list(AgsSimpleFile *simple_file, xmlNode *node,
 
 	  iter = g_list_nth(*effect_line,
 			    i);
-	  current = iter->data;
+
+	  if(iter != NULL){
+	    current = iter->data;
+	  }
 	}
 	
 	ags_simple_file_read_effect_line(simple_file, child, &current);
@@ -4186,7 +4265,10 @@ ags_simple_file_read_notation_list(AgsSimpleFile *simple_file, xmlNode *node, GL
 
 	  iter = g_list_nth(*notation,
 			    i);
-	  current = iter->data;
+
+	  if(iter != NULL){
+	    current = iter->data;
+	  }
 	}
 	
 	ags_simple_file_read_notation(simple_file, child, &current);
@@ -4375,12 +4457,15 @@ ags_simple_file_read_automation_list(AgsSimpleFile *simple_file, xmlNode *node,
 
 	  iter = g_list_nth(*automation,
 			    i);
-	  current = iter->data;
+
+	  if(iter != NULL){
+	    current = iter->data;
+	  }
 	}
-	
+
 	ags_simple_file_read_automation(simple_file, child, &current);
 	list = g_list_prepend(list, current);
-
+	
 	i++;
       }
     }
@@ -5016,7 +5101,11 @@ ags_simple_file_write_machine(AgsSimpleFile *simple_file, xmlNode *parent, AgsMa
   xmlNewProp(node,
 	     (xmlChar *) AGS_FILE_TYPE_PROP,
 	     (xmlChar *) G_OBJECT_TYPE_NAME(machine));
-  
+
+  xmlNewProp(node,
+	     (xmlChar *) AGS_FILE_NAME_PROP,
+	     (xmlChar *) machine->name);
+
   ags_simple_file_add_id_ref(simple_file,
 			     g_object_new(AGS_TYPE_FILE_ID_REF,
 					  "application-context\0", simple_file->application_context,
@@ -5174,6 +5263,12 @@ ags_simple_file_write_machine(AgsSimpleFile *simple_file, xmlNode *parent, AgsMa
     xmlNewProp(node,
 	       "effect\0",
 	       lv2_bridge->effect);
+
+    if(lv2_bridge->preset != NULL){
+      xmlNewProp(node,
+		 "preset\0",
+		 gtk_combo_box_text_get_active_text(lv2_bridge->preset));
+    }
   }
   
   /* input */
diff --git a/ags/X/machine/ags_cell_pattern.c b/ags/X/machine/ags_cell_pattern.c
index 549790a..6391cd9 100644
--- a/ags/X/machine/ags_cell_pattern.c
+++ b/ags/X/machine/ags_cell_pattern.c
@@ -36,8 +36,6 @@
 
 #include <ags/audio/thread/ags_audio_loop.h>
 
-#include <ags/widget/ags_led.h>
-
 #include <ags/X/ags_window.h>
 #include <ags/X/ags_machine.h>
 
@@ -278,23 +276,19 @@ ags_cell_pattern_init(AgsCellPattern *cell_pattern)
   /* led */
   cell_pattern->active_led = 0;
 
-  cell_pattern->led = (GtkHBox *) gtk_hbox_new(FALSE, 0);
+  cell_pattern->hled_array = (GtkHBox *) ags_hled_array_new();
+  g_object_set(cell_pattern->hled_array,
+	       "led-width\0", cell_pattern->cell_width,
+	       "led-height\0", AGS_CELL_PATTERN_DEFAULT_CELL_HEIGHT,
+	       "led-count\0", cell_pattern->n_cols,
+	       NULL);
   gtk_table_attach((GtkTable *) cell_pattern,
-		   (GtkWidget *) cell_pattern->led,
+		   (GtkWidget *) cell_pattern->hled_array,
 		   0, 1,
 		   2, 3,
 		   GTK_FILL, GTK_FILL,
 		   0, 0);
-  
-  for(i = 0; i < 32; i++){
-    led = ags_led_new();
-    gtk_widget_set_size_request((GtkWidget *) led,
-				cell_pattern->cell_width, cell_pattern->cell_height);
-    gtk_box_pack_start((GtkBox *) cell_pattern->led,
-		       (GtkWidget *) led,
-		       FALSE, FALSE,
-		       0);
-  }
+  gtk_widget_show_all(cell_pattern->hled_array);
 
   if(ags_cell_pattern_led_queue_draw == NULL){
     ags_cell_pattern_led_queue_draw = g_hash_table_new_full(g_direct_hash, g_direct_equal,
@@ -305,7 +299,6 @@ ags_cell_pattern_init(AgsCellPattern *cell_pattern)
   g_hash_table_insert(ags_cell_pattern_led_queue_draw,
 		      cell_pattern, ags_cell_pattern_led_queue_draw_timeout);
   g_timeout_add(1000 / 30, (GSourceFunc) ags_cell_pattern_led_queue_draw_timeout, (gpointer) cell_pattern);
-
 }
 
 void
@@ -641,22 +634,26 @@ ags_cell_pattern_draw_gutter(AgsCellPattern *cell_pattern)
 {
   AgsMachine *machine;
   
-  AgsChannel *channel;
+  AgsChannel *start_channel, *channel;
 
   AgsMutexManager *mutex_manager;
 
+  guint input_pads;
   guint gutter;
+  guint current_gutter;
   int i, j;
 
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *audio_mutex;
+  pthread_mutex_t *channel_mutex;
 
   machine = (AgsMachine *) gtk_widget_get_ancestor((GtkWidget *) cell_pattern,
 						   AGS_TYPE_MACHINE);
   
   mutex_manager = ags_mutex_manager_get_instance();
   application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
-  
+
+  /* get audio mutex */
   pthread_mutex_lock(application_mutex);
   
   audio_mutex = ags_mutex_manager_lookup(mutex_manager,
@@ -664,52 +661,75 @@ ags_cell_pattern_draw_gutter(AgsCellPattern *cell_pattern)
   
   pthread_mutex_unlock(application_mutex);
 
+  /* retrieve some audio fields */
   pthread_mutex_lock(audio_mutex);
 
+  start_channel = machine->audio->input;
+  
+  input_pads = machine->audio->input_pads;
+  
+  pthread_mutex_unlock(audio_mutex);
+
+  if(input_pads == 0){
+    return;
+  }
+  
+  if(input_pads > AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
+    gutter = AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY;
+  }else{
+    gutter = input_pads;
+  }
+
+  current_gutter = (guint) GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value;
+  
+  /* clear bg */
   gdk_draw_rectangle(GTK_WIDGET(cell_pattern->drawing_area)->window,
 		     GTK_WIDGET(cell_pattern->drawing_area)->style->bg_gc[0],
 		     TRUE,
 		     0, 0,
-		     288, 80);
-
-  if(machine->audio->input_lines - ((guint) GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value + AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY) - 1 > AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
-    channel = ags_channel_nth(machine->audio->input,
-			      machine->audio->input_lines - ((guint) GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value + AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY) - 1);
-  }else if(machine->audio->input_lines > AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
-    channel = ags_channel_nth(machine->audio->input,
-			      AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY - 1);
+		     AGS_CELL_PATTERN_DEFAULT_CELL_WIDTH * AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_HORIZONTALLY, gutter * AGS_CELL_PATTERN_DEFAULT_CELL_HEIGHT);
+
+  if(input_pads - ((guint) current_gutter + AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY) > AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
+    channel = ags_channel_nth(start_channel,
+			      input_pads - (current_gutter + AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY));
+  }else if(input_pads > AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
+    channel = ags_channel_nth(start_channel,
+			      AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY);
   }else{
-    channel = ags_channel_nth(machine->audio->input,
-			      machine->audio->input_lines - 1);
+    channel = ags_channel_nth(start_channel,
+			      input_pads - 1);
   }
   
   if(channel == NULL){
-    pthread_mutex_unlock(audio_mutex);
-    
     return;
   }
-  
-  if(machine->audio->input_pads > AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
-    gutter = AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY;
-  }else{
-    gutter = machine->audio->input_pads;
-  }
 
   for (i = 0; channel != NULL && i < gutter; i++){
+    /* get channel mutex */
+    pthread_mutex_lock(application_mutex);
+  
+    channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+					     (GObject *) channel);
+  
+    pthread_mutex_unlock(application_mutex);
+    
     for (j = 0; j < 32; j++){
       gdk_draw_rectangle(GTK_WIDGET(cell_pattern->drawing_area)->window,
 			 GTK_WIDGET(cell_pattern->drawing_area)->style->fg_gc[0],
 			 FALSE,
-			 j * 12, i * 10,
-			 12, 10);
+			 j * AGS_CELL_PATTERN_DEFAULT_CELL_WIDTH, i * AGS_CELL_PATTERN_DEFAULT_CELL_HEIGHT,
+			 AGS_CELL_PATTERN_DEFAULT_CELL_WIDTH, AGS_CELL_PATTERN_DEFAULT_CELL_HEIGHT);
 
       ags_cell_pattern_redraw_gutter_point(cell_pattern, channel, j, i);
     }
 
-    channel = channel->prev;
-  }
+    /* iterate */
+    pthread_mutex_lock(channel_mutex);
+    
+    channel = channel->prev_pad;
 
-  pthread_mutex_unlock(audio_mutex);
+    pthread_mutex_unlock(channel_mutex);
+  }
 }
 
 void
@@ -717,22 +737,26 @@ ags_cell_pattern_draw_matrix(AgsCellPattern *cell_pattern)
 {
   AgsMachine *machine;
 
-  AgsChannel *channel;
+  AgsChannel *start_channel, *channel;
 
   AgsMutexManager *mutex_manager;
 
+  guint input_pads;
   guint gutter;
+  guint current_gutter;
   int i, j;
 
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *audio_mutex;
+  pthread_mutex_t *channel_mutex;
 
   machine = (AgsMachine *) gtk_widget_get_ancestor((GtkWidget *) cell_pattern,
 						   AGS_TYPE_MACHINE);
 
   mutex_manager = ags_mutex_manager_get_instance();
   application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
-  
+
+  /* get audio mutex */
   pthread_mutex_lock(application_mutex);
   
   audio_mutex = ags_mutex_manager_lookup(mutex_manager,
@@ -740,30 +764,49 @@ ags_cell_pattern_draw_matrix(AgsCellPattern *cell_pattern)
   
   pthread_mutex_unlock(application_mutex);
 
+  /* get some audio fields */
   pthread_mutex_lock(audio_mutex);
 
-  if(machine->audio->input_pads > AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
+  start_channel = machine->audio->input;
+
+  input_pads = machine->audio->input_pads;
+  
+  pthread_mutex_unlock(audio_mutex);
+
+  if(input_pads > AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
     gutter = AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY;
   }else{
-    gutter = machine->audio->input_pads;
+    gutter = input_pads;
   }
 
-  channel = ags_channel_nth(machine->audio->input, machine->audio->input_pads - (guint) GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value - 1);
+  current_gutter = (guint) GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value;
+
+  channel = ags_channel_nth(start_channel, input_pads - current_gutter - 1);
 
   if(channel == NULL){
-    pthread_mutex_unlock(audio_mutex);
-    
     return;
   }
 
   for (i = 0; channel != NULL && i < gutter; i++){
-    for (j = 0; j < 32; j++)
+    /* get channel mutex */
+    pthread_mutex_lock(application_mutex);
+  
+    channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+					     (GObject *) channel);
+  
+    pthread_mutex_unlock(application_mutex);
+
+    for(j = 0; j < AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_HORIZONTALLY; j++){
       ags_cell_pattern_redraw_gutter_point(cell_pattern, channel, j, i);
+    }
+    
+    /* iterate */
+    pthread_mutex_lock(channel_mutex);
+    
+    channel = channel->prev_pad;
 
-    channel = channel->prev;
+    pthread_mutex_unlock(channel_mutex);
   }
-
-  pthread_mutex_unlock(audio_mutex);
 }
 
 void
@@ -812,7 +855,7 @@ ags_cell_pattern_highlight_gutter_point(AgsCellPattern *cell_pattern, guint j, g
 		     GTK_WIDGET(cell_pattern->drawing_area)->style->fg_gc[0],
 		     TRUE,
 		     j * cell_pattern->cell_width + 1, i * cell_pattern->cell_height + 1,
-		     11, 9);
+		     AGS_CELL_PATTERN_DEFAULT_CELL_WIDTH - 1, AGS_CELL_PATTERN_DEFAULT_CELL_HEIGHT - 1);
 }
 
 void
@@ -822,7 +865,7 @@ ags_cell_pattern_unpaint_gutter_point(AgsCellPattern *cell_pattern, guint j, gui
 		     GTK_WIDGET(cell_pattern->drawing_area)->style->bg_gc[0],
 		     TRUE,
 		     j * cell_pattern->cell_width + 1, i * cell_pattern->cell_height +1,
-		     11, 9);
+		     AGS_CELL_PATTERN_DEFAULT_CELL_WIDTH - 1, AGS_CELL_PATTERN_DEFAULT_CELL_HEIGHT - 1);
 }
 
 void*
@@ -908,10 +951,10 @@ ags_cell_pattern_led_queue_draw_timeout(AgsCellPattern *cell_pattern)
 
     AgsMutexManager *mutex_manager;
 
-    GList *list, *active;
+    GList *list_start, *list;
+    
     guint offset;
     guint active_led_new;
-    guint i;
     
     pthread_mutex_t *application_mutex;
     pthread_mutex_t *audio_mutex;
@@ -945,36 +988,44 @@ ags_cell_pattern_led_queue_draw_timeout(AgsCellPattern *cell_pattern)
     recall_id = ags_recall_id_find_parent_recycling_context(audio->recall_id,
 							    NULL);
 
+    pthread_mutex_unlock(audio_mutex);
+    
     if(recall_id == NULL){
-      pthread_mutex_unlock(audio_mutex);
-      
       gdk_threads_leave();
       
       return(TRUE);
     }
+
+    g_object_get(audio,
+		 "play\0", &list_start,
+		 NULL);
     
     play_count_beats_audio = NULL;
     play_count_beats_audio_run = NULL;
 
-    list = ags_recall_find_type(audio->play,
+    pthread_mutex_lock(audio->play_mutex);
+    
+    list = ags_recall_find_type(list_start,
 				AGS_TYPE_COUNT_BEATS_AUDIO);
     
     if(list != NULL){
       play_count_beats_audio = AGS_COUNT_BEATS_AUDIO(list->data);
     }
     
-    list = ags_recall_find_type_with_recycling_context(audio->play,
+    list = ags_recall_find_type_with_recycling_context(list_start,
 						       AGS_TYPE_COUNT_BEATS_AUDIO_RUN,
 						       (GObject *) recall_id->recycling_context);
     
     if(list != NULL){
       play_count_beats_audio_run = AGS_COUNT_BEATS_AUDIO_RUN(list->data);
     }
+
+    pthread_mutex_unlock(audio->play_mutex);
+
+    g_list_free(list_start);  
     
     if(play_count_beats_audio == NULL ||
        play_count_beats_audio_run == NULL){
-      pthread_mutex_unlock(audio_mutex);
-      
       gdk_threads_leave();
       
       return(TRUE);
@@ -982,32 +1033,11 @@ ags_cell_pattern_led_queue_draw_timeout(AgsCellPattern *cell_pattern)
 
     /* active led */
     active_led_new = (guint) play_count_beats_audio_run->sequencer_counter;
-    cell_pattern->active_led = (guint) active_led_new;
-      
-    pthread_mutex_unlock(audio_mutex);
 
-    /* led */
-    list = gtk_container_get_children((GtkContainer *) cell_pattern->led);
-    active = NULL;
-    
-    for(i = 0; list != NULL; i++){
-      if(i == active_led_new){
-	active = list;
-	list = list->next;
-	
-	continue;
-      }
-      
-      ags_led_unset_active(AGS_LED(list->data));
-      
-      list = list->next;
-    }
-
-    if(active != NULL){
-      ags_led_set_active(AGS_LED(active->data));
-    }
-    
-    g_list_free(list);
+    cell_pattern->active_led = (guint) active_led_new;
+    ags_led_array_unset_all(cell_pattern->hled_array);
+    ags_led_array_set_nth(cell_pattern->hled_array,
+			  active_led_new);
     
     gdk_threads_leave();
     
diff --git a/ags/X/machine/ags_cell_pattern.h b/ags/X/machine/ags_cell_pattern.h
index dde3727..e7e7fae 100644
--- a/ags/X/machine/ags_cell_pattern.h
+++ b/ags/X/machine/ags_cell_pattern.h
@@ -26,6 +26,8 @@
 
 #include <ags/audio/ags_channel.h>
 
+#include <ags/widget/ags_hled_array.h>
+
 #define AGS_TYPE_CELL_PATTERN                (ags_cell_pattern_get_type())
 #define AGS_CELL_PATTERN(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_CELL_PATTERN, AgsCellPattern))
 #define AGS_CELL_PATTERN_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_CELL_PATTERN, AgsCellPatternClass))
@@ -87,7 +89,7 @@ struct _AgsCellPattern
   GtkHScrollbar *hscrollbar;
 
   guint active_led;
-  GtkHBox *led;
+  AgsHLedArray *hled_array;
 };
 
 struct _AgsCellPatternClass
diff --git a/ags/X/machine/ags_cell_pattern_callbacks.c b/ags/X/machine/ags_cell_pattern_callbacks.c
index de8e28e..7ed27fd 100644
--- a/ags/X/machine/ags_cell_pattern_callbacks.c
+++ b/ags/X/machine/ags_cell_pattern_callbacks.c
@@ -26,6 +26,7 @@
 #include <ags/thread/ags_mutex_manager.h>
 #include <ags/thread/ags_task_thread.h>
 
+#include <ags/audio/ags_sound_provider.h>
 #include <ags/audio/ags_playback.h>
 
 #include <ags/audio/thread/ags_audio_loop.h>
@@ -208,6 +209,8 @@ ags_cell_pattern_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *
     
     GList *tasks;
 
+    gboolean no_soundcard;
+
     pthread_mutex_t *application_mutex;
     pthread_mutex_t *audio_mutex;
     pthread_mutex_t *channel_mutex;
@@ -217,6 +220,22 @@ ags_cell_pattern_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *
     mutex_manager = ags_mutex_manager_get_instance();
     application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
 
+    no_soundcard = FALSE;
+
+    pthread_mutex_lock(application_mutex);
+
+    if(ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context)) == NULL){
+      no_soundcard = TRUE;
+    }
+
+    pthread_mutex_unlock(application_mutex);
+
+    if(no_soundcard){
+      g_message("No soundcard available\0");
+      
+      return;
+    }
+
     /* lookup channel mutex */
     pthread_mutex_lock(application_mutex);
 
@@ -412,7 +431,7 @@ ags_cell_pattern_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *
 void
 ags_cell_pattern_adjustment_value_changed_callback(GtkWidget *widget, AgsCellPattern *cell_pattern)
 {
-  ags_cell_pattern_draw_matrix(cell_pattern);
+  ags_cell_pattern_paint(cell_pattern);
 }
 
 void
@@ -479,7 +498,9 @@ ags_cell_pattern_init_channel_launch_callback(AgsTask *task, gpointer data)
   task_thread = (AgsTaskThread *) ags_thread_find_type(main_loop,
 						       AGS_TYPE_TASK_THREAD);
 
+#ifdef AGS_DEBUG
   g_message("launch\0");
+#endif
   
   if(AGS_PLAYBACK(channel->playback) == NULL ||
      AGS_PLAYBACK(channel->playback)->recall_id[0] == NULL){    
diff --git a/ags/X/machine/ags_drum_callbacks.c b/ags/X/machine/ags_drum_callbacks.c
index 8a84832..aa1fea0 100644
--- a/ags/X/machine/ags_drum_callbacks.c
+++ b/ags/X/machine/ags_drum_callbacks.c
@@ -116,6 +116,10 @@ ags_drum_open_callback(GtkWidget *toggle_button, AgsDrum *drum)
   GtkFileChooserDialog *file_chooser;
   GtkCheckButton *check_button;
 
+  if(drum->open_dialog != NULL){
+    return;
+  }
+  
   file_chooser = (GtkFileChooserDialog *) gtk_file_chooser_dialog_new(g_strdup("open audio files\0"),
 								      (GtkWindow *) gtk_widget_get_toplevel((GtkWidget *) drum),
 								      GTK_FILE_CHOOSER_ACTION_OPEN,
@@ -412,8 +416,6 @@ ags_drum_done_callback(AgsAudio *audio,
   GList *playback;
   gboolean all_done;
 
-  gdk_threads_enter();
-  
   playback = AGS_PLAYBACK_DOMAIN(audio->playback_domain)->playback;
 
   /* check unset */
@@ -427,21 +429,11 @@ ags_drum_done_callback(AgsAudio *audio,
 
     playback = playback->next;
   }
+  
+  gdk_threads_enter();  
 
   if(all_done){
-    GList *list, *list_start;
-
-    /* unset led */
-    list_start = 
-      list = gtk_container_get_children(GTK_CONTAINER(drum->pattern_box->led));
-
-    while(list != NULL){
-      ags_led_unset_active(AGS_LED(list->data));
-	
-      list = list->next;
-    }
-
-    g_list_free(list_start);
+    ags_led_array_unset_all(drum->pattern_box->hled_array);
   }
   
   gdk_threads_leave();
diff --git a/ags/X/machine/ags_drum_input_line.c b/ags/X/machine/ags_drum_input_line.c
index aff0d2b..c543a4f 100644
--- a/ags/X/machine/ags_drum_input_line.c
+++ b/ags/X/machine/ags_drum_input_line.c
@@ -101,7 +101,7 @@ void ags_drum_input_line_map_recall(AgsLine *line,
 static gpointer ags_drum_input_line_parent_class = NULL;
 static AgsConnectableInterface *ags_drum_input_line_parent_connectable_interface;
 
-extern GHashTable *ags_indicator_queue_draw;
+extern GHashTable *ags_line_indicator_queue_draw;
 
 GType
 ags_drum_input_line_get_type()
@@ -211,7 +211,7 @@ ags_drum_input_line_init(AgsDrumInputLine *drum_input_line)
 		   1, 1);
   widget = gtk_bin_get_child(GTK_BIN(line_member));
   AGS_LINE(drum_input_line)->indicator = widget;
-  g_hash_table_insert(ags_indicator_queue_draw,
+  g_hash_table_insert(ags_line_indicator_queue_draw,
 		      widget, ags_line_indicator_queue_draw_timeout);
   g_timeout_add(1000 / 30, (GSourceFunc) ags_line_indicator_queue_draw_timeout, (gpointer) widget);
 
@@ -436,38 +436,6 @@ ags_drum_input_line_map_recall(AgsLine *line,
 			     AGS_RECALL_FACTORY_ADD),
 			    0);
 
-  /* play - connect run_post */
-  list = ags_recall_template_find_type(source->play,
-				       AGS_TYPE_PEAK_CHANNEL_RUN);
-
-  if(list != NULL){
-    play_peak_channel_run = AGS_PEAK_CHANNEL_RUN(list->data);
-
-    recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
-
-    recall_handler->signal_name = "run-post\0";
-    recall_handler->callback = G_CALLBACK(ags_line_peak_run_post_callback);
-    recall_handler->data = (gpointer) line;
-
-    ags_recall_add_handler(AGS_RECALL(play_peak_channel_run), recall_handler);
-  }
-
-  /* recall - connect run_post */
-  list = ags_recall_template_find_type(source->recall,
-				       AGS_TYPE_PEAK_CHANNEL_RUN);
-
-  if(list != NULL){
-    recall_peak_channel_run = AGS_PEAK_CHANNEL_RUN(list->data);
-
-    recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
-
-    recall_handler->signal_name = "run-post\0";
-    recall_handler->callback = G_CALLBACK(ags_line_peak_run_post_callback);
-    recall_handler->data = (gpointer) line;
-
-    ags_recall_add_handler(AGS_RECALL(recall_peak_channel_run), recall_handler);
-  }
-
   /* ags-copy-pattern */
   ags_recall_factory_create(audio,
 			    NULL, NULL,
diff --git a/ags/X/machine/ags_drum_output_line.c b/ags/X/machine/ags_drum_output_line.c
index ff39d16..f7ed446 100644
--- a/ags/X/machine/ags_drum_output_line.c
+++ b/ags/X/machine/ags_drum_output_line.c
@@ -24,6 +24,7 @@
 
 #include <ags/object/ags_connectable.h>
 #include <ags/object/ags_plugin.h>
+#include <ags/object/ags_config.h>
 
 #include <ags/thread/ags_mutex_manager.h>
 
@@ -188,7 +189,7 @@ ags_drum_output_line_connect(AgsConnectable *connectable)
   ags_drum_output_line_parent_connectable_interface->connect(connectable);
 
   g_signal_connect_after((GObject *) AGS_LINE(drum_output_line)->channel->audio, "set-pads\0",
-			 G_CALLBACK(ags_drum_output_line_set_pads_callback), NULL);
+			 G_CALLBACK(ags_drum_output_line_set_pads_callback), drum_output_line);
 
   /* empty */
 }
@@ -196,9 +197,20 @@ ags_drum_output_line_connect(AgsConnectable *connectable)
 void
 ags_drum_output_line_disconnect(AgsConnectable *connectable)
 {
+  AgsDrumOutputLine *drum_output_line;
+
+  drum_output_line = AGS_DRUM_OUTPUT_LINE(connectable);
+
+  if((AGS_LINE_CONNECTED & (AGS_LINE(drum_output_line)->flags)) == 0){
+    return;
+  }
+
   ags_drum_output_line_parent_connectable_interface->disconnect(connectable);
 
-  /* empty */
+  if(AGS_LINE(drum_output_line)->channel != NULL){
+    g_signal_handlers_disconnect_by_data(AGS_LINE(drum_output_line)->channel->audio,
+					 drum_output_line);
+  }
 }
 
 gchar*
@@ -294,9 +306,14 @@ ags_drum_output_line_map_recall(AgsLine *line,
 				guint output_pad_start)
 {
   AgsAudio *audio;
-
   AgsChannel *output, *input;
 
+  AgsConfig *config;
+  
+  gchar *str;
+
+  gboolean performance_mode;
+  
   if((AGS_LINE_MAPPED_RECALL & (line->flags)) != 0 ||
      (AGS_LINE_PREMAPPED_RECALL & (line->flags)) != 0){
     return;
@@ -304,37 +321,71 @@ ags_drum_output_line_map_recall(AgsLine *line,
 
   output = line->channel;
   audio = AGS_AUDIO(output->audio);
+
+  config = ags_config_get_instance();
   
   /* remap for input */
-  input = audio->input;
-
-  while(input != NULL){
+  str = ags_config_get_value(config,
+			     AGS_CONFIG_GENERIC,
+			     "engine-mode\0");
+  performance_mode = FALSE;
+  
+  if(str != NULL &&
+     !g_ascii_strncasecmp(str,
+			  "performance\0",
+			  12)){    
+    input = audio->input;
+
+    while(input != NULL){
+      /* ags-copy */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-copy\0",
+				0, audio->audio_channels, 
+				input->pad, input->pad + 1,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      input = input->next_pad;
+    }
+
+    /* set performance mode */
+    performance_mode = TRUE;
+  }else{
     /* ags-buffer */
+    input = audio->input;
+
+    while(input != NULL){
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-buffer\0",
+				0, audio->audio_channels, 
+				input->pad, input->pad + 1,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      input = input->next_pad;
+    }
+  }
+  
+  if(!performance_mode){
+    /* ags-stream */
     ags_recall_factory_create(audio,
 			      NULL, NULL,
-			      "ags-buffer\0",
-			      0, audio->audio_channels, 
-			      input->pad, input->pad + 1,
-			      (AGS_RECALL_FACTORY_INPUT |
-			       AGS_RECALL_FACTORY_RECALL |
+			      "ags-stream\0",
+			      output->audio_channel, output->audio_channel + 1,
+			      output->pad, output->pad + 1,
+			      (AGS_RECALL_FACTORY_OUTPUT |
+			       AGS_RECALL_FACTORY_PLAY |
+			       AGS_RECALL_FACTORY_RECALL | 
 			       AGS_RECALL_FACTORY_ADD),
 			      0);
-
-    input = input->next_pad;
   }
   
-  /* ags-stream */
-  ags_recall_factory_create(audio,
-			    NULL, NULL,
-			    "ags-stream\0",
-			    output->audio_channel, output->audio_channel + 1,
-			    output->pad, output->pad + 1,
-			    (AGS_RECALL_FACTORY_OUTPUT |
-			     AGS_RECALL_FACTORY_PLAY |
-			     AGS_RECALL_FACTORY_RECALL | 
-			     AGS_RECALL_FACTORY_ADD),
-			    0);
-
   AGS_LINE_CLASS(ags_drum_output_line_parent_class)->map_recall(line,
 								output_pad_start);
 }
diff --git a/ags/X/machine/ags_drum_output_line_callbacks.c b/ags/X/machine/ags_drum_output_line_callbacks.c
index 6e40c44..4ef4782 100644
--- a/ags/X/machine/ags_drum_output_line_callbacks.c
+++ b/ags/X/machine/ags_drum_output_line_callbacks.c
@@ -21,6 +21,8 @@
 
 #include <ags/X/machine/ags_drum.h>
 
+#include <ags/object/ags_config.h>
+
 #include <ags/audio/ags_channel.h>
 #include <ags/audio/ags_input.h>
 #include <ags/audio/ags_audio_signal.h>
@@ -73,6 +75,19 @@ ags_drum_output_line_set_pads_callback(AgsAudio *audio, GType channel_type,
 				       guint pads_new, guint pads_old,
 				       AgsDrumOutputLine *output_line)
 {
+  AgsConfig *config;
+
+  gchar *str;
+
+  gboolean performance_mode;
+
+  config = ags_config_get_instance();
+  
+  str = ags_config_get_value(config,
+			     AGS_CONFIG_GENERIC,
+			     "engine-mode\0");
+  performance_mode = FALSE;
+
   if(channel_type == AGS_TYPE_INPUT){
     if(pads_new > pads_old){
       AgsChannel *input;
@@ -80,19 +95,42 @@ ags_drum_output_line_set_pads_callback(AgsAudio *audio, GType channel_type,
       input = ags_channel_pad_nth(audio->input,
 				  pads_old);
 
-      while(input != NULL){
-	/* ags-buffer */
-	ags_recall_factory_create(audio,
-				  NULL, NULL,
-				  "ags-buffer\0",
-				  0, audio->audio_channels, 
-				  input->pad, input->pad + 1,
-				  (AGS_RECALL_FACTORY_INPUT |
-				   AGS_RECALL_FACTORY_RECALL |
-				   AGS_RECALL_FACTORY_ADD),
-				  0);
-
-	input = input->next_pad;
+      if(str != NULL &&
+	 !g_ascii_strncasecmp(str,
+			      "performance\0",
+			      12)){
+	while(input != NULL){
+	  /* ags-copy */
+	  ags_recall_factory_create(audio,
+				    NULL, NULL,
+				    "ags-copy\0",
+				    0, audio->audio_channels, 
+				    input->pad, input->pad + 1,
+				    (AGS_RECALL_FACTORY_INPUT |
+				     AGS_RECALL_FACTORY_RECALL |
+				     AGS_RECALL_FACTORY_ADD),
+				    0);
+
+	  input = input->next_pad;
+	}
+	
+	/* set performance mode */
+	performance_mode = TRUE;
+      }else{
+	while(input != NULL){
+	  /* ags-buffer */
+	  ags_recall_factory_create(audio,
+				    NULL, NULL,
+				    "ags-buffer\0",
+				    0, audio->audio_channels, 
+				    input->pad, input->pad + 1,
+				    (AGS_RECALL_FACTORY_INPUT |
+				     AGS_RECALL_FACTORY_RECALL |
+				     AGS_RECALL_FACTORY_ADD),
+				    0);
+
+	  input = input->next_pad;
+	}
       }
     }
   }
diff --git a/ags/X/machine/ags_dssi_bridge.c b/ags/X/machine/ags_dssi_bridge.c
index 13f1b66..e0b1aab 100644
--- a/ags/X/machine/ags_dssi_bridge.c
+++ b/ags/X/machine/ags_dssi_bridge.c
@@ -336,6 +336,7 @@ ags_dssi_bridge_init(AgsDssiBridge *dssi_bridge)
   gtk_container_add((GtkContainer *) gtk_bin_get_child((GtkBin *) dssi_bridge),
 		    (GtkWidget *) vbox);
 
+  /* program */
   hbox = (GtkHBox *) gtk_hbox_new(FALSE, 0);
   gtk_box_pack_start((GtkBox *) vbox,
 		     (GtkWidget *) hbox,
@@ -354,12 +355,12 @@ ags_dssi_bridge_init(AgsDssiBridge *dssi_bridge)
 		     FALSE, FALSE,
 		     0);
 
+  /* effect bridge */
   AGS_MACHINE(dssi_bridge)->bridge = (GtkContainer *) ags_effect_bridge_new(audio);
   gtk_box_pack_start((GtkBox *) vbox,
 		     (GtkWidget *) AGS_MACHINE(dssi_bridge)->bridge,
 		     FALSE, FALSE,
 		     0);
-
   
   table = (GtkTable *) gtk_table_new(1, 2, FALSE);
   gtk_box_pack_start((GtkBox *) AGS_EFFECT_BRIDGE(AGS_MACHINE(dssi_bridge)->bridge),
@@ -1132,8 +1133,14 @@ ags_dssi_bridge_input_map_recall(AgsDssiBridge *dssi_bridge, guint audio_channel
   AgsAudio *audio;
   AgsChannel *source, *current;
   
+  AgsConfig *config;
+
   GList *list;
 
+  gchar *str;
+
+  gboolean performance_mode;
+
   audio = AGS_MACHINE(dssi_bridge)->audio;
 
   if(dssi_bridge->mapped_input_pad > input_pad_start){
@@ -1143,22 +1150,54 @@ ags_dssi_bridge_input_map_recall(AgsDssiBridge *dssi_bridge, guint audio_channel
   source = ags_channel_nth(audio->input,
 			   audio_channel_start + input_pad_start * audio->audio_channels);
 
+  config = ags_config_get_instance();
+
   /* map dependending on output */
-  current = source;
+  str = ags_config_get_value(config,
+			     AGS_CONFIG_GENERIC,
+			     "engine-mode\0");
+  performance_mode = FALSE;
+  
+  if(str != NULL &&
+     !g_ascii_strncasecmp(str,
+			  "performance\0",
+			  12)){
+    current = source;
+
+    while(current != NULL){
+      /* ags-copy */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-copy\0",
+				audio_channel_start, audio->audio_channels, 
+				current->pad, current->pad + 1,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      current = current->next_pad;
+    }
 
-  while(current != NULL){
-    /* ags-buffer */
-    ags_recall_factory_create(audio,
-			      NULL, NULL,
-			      "ags-buffer\0",
-			      audio_channel_start, audio->audio_channels, 
-			      current->pad, current->pad + 1,
-			      (AGS_RECALL_FACTORY_INPUT |
-			       AGS_RECALL_FACTORY_RECALL |
-			       AGS_RECALL_FACTORY_ADD),
-			      0);
+    /* set performance mode */
+    performance_mode = TRUE;
+  }else{    
+    current = source;
+
+    while(current != NULL){
+      /* ags-buffer */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-buffer\0",
+				audio_channel_start, audio->audio_channels, 
+				current->pad, current->pad + 1,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
     
-    current = current->next_pad;
+      current = current->next_pad;
+    }
   }
   
   /*  */
@@ -1197,7 +1236,7 @@ ags_dssi_bridge_input_map_recall(AgsDssiBridge *dssi_bridge, guint audio_channel
 
     current = current->next_pad;
   }
-
+  
   dssi_bridge->mapped_input_pad = audio->input_pads;
 }
 
@@ -1210,51 +1249,92 @@ ags_dssi_bridge_output_map_recall(AgsDssiBridge *dssi_bridge, guint audio_channe
   AgsDelayAudio *recall_delay_audio;
   AgsCountBeatsAudioRun *recall_count_beats_audio_run;
 
+  AgsConfig *config;
+
   GList *list;
 
+  gchar *str;
+
+  gboolean performance_mode;
+
   audio = AGS_MACHINE(dssi_bridge)->audio;
 
   if(dssi_bridge->mapped_output_pad > output_pad_start){
     return;
   }
 
+  config = ags_config_get_instance();
+
+  /* map dependending on output */
+  str = ags_config_get_value(config,
+			     AGS_CONFIG_GENERIC,
+			     "engine-mode\0");
+  performance_mode = FALSE;
+
   /* remap for input */
-  input = audio->input;
+  if(str != NULL &&
+     !g_ascii_strncasecmp(str,
+			  "performance\0",
+			  12)){
+    input = audio->input;
+
+    while(input != NULL){
+      /* ags-copy */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-copy\0",
+				audio_channel_start, audio->audio_channels, 
+				input->pad, input->pad + 1,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_REMAP),
+				0);
+    
+      input = input->next_pad;
+    }
 
-  while(input != NULL){
-    /* ags-buffer */
-    ags_recall_factory_create(audio,
-			      NULL, NULL,
-			      "ags-buffer\0",
-			      audio_channel_start, audio->audio_channels, 
-			      input->pad, input->pad + 1,
-			      (AGS_RECALL_FACTORY_INPUT |
-			       AGS_RECALL_FACTORY_RECALL |
-			       AGS_RECALL_FACTORY_REMAP),
-			      0);
+    /* set performance mode */
+    performance_mode = TRUE;
+  }else{      
+    input = audio->input;
+
+    while(input != NULL){
+      /* ags-buffer */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-buffer\0",
+				audio_channel_start, audio->audio_channels, 
+				input->pad, input->pad + 1,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_REMAP),
+				0);
     
-    input = input->next_pad;
+      input = input->next_pad;
+    }
   }
-
-  current = ags_channel_nth(audio->output,
-			    audio_channel_start + output_pad_start * audio->audio_channels);
-
-  while(current != NULL){
-    /* ags-stream */
-    ags_recall_factory_create(audio,
-			      NULL, NULL,
-			      "ags-stream\0",
-			      audio_channel_start, audio->audio_channels,
-			      current->pad, current->pad + 1,
-			      (AGS_RECALL_FACTORY_OUTPUT |
-			       AGS_RECALL_FACTORY_PLAY |
-			       AGS_RECALL_FACTORY_RECALL | 
-			       AGS_RECALL_FACTORY_ADD),
-			      0);
-
-    current = current->next_pad;
+    
+  if(!performance_mode){
+    current = ags_channel_nth(audio->output,
+			      audio_channel_start + output_pad_start * audio->audio_channels);
+
+    while(current != NULL){
+      /* ags-stream */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-stream\0",
+				audio_channel_start, audio->audio_channels,
+				current->pad, current->pad + 1,
+				(AGS_RECALL_FACTORY_OUTPUT |
+				 AGS_RECALL_FACTORY_PLAY |
+				 AGS_RECALL_FACTORY_RECALL | 
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      current = current->next_pad;
+    }
   }
-
+  
   dssi_bridge->mapped_output_pad = audio->output_pads;
 }
 
diff --git a/ags/X/machine/ags_ffplayer.c b/ags/X/machine/ags_ffplayer.c
index 0d8ffab..26e1b0e 100644
--- a/ags/X/machine/ags_ffplayer.c
+++ b/ags/X/machine/ags_ffplayer.c
@@ -23,6 +23,7 @@
 #include <ags/util/ags_id_generator.h>
 
 #include <ags/object/ags_application_context.h>
+#include <ags/object/ags_config.h>
 #include <ags/object/ags_connectable.h>
 #include <ags/object/ags_soundcard.h>
 #include <ags/object/ags_plugin.h>
@@ -251,10 +252,10 @@ ags_ffplayer_init(AgsFFPlayer *ffplayer)
   					   (AGS_MACHINE_POPUP_MIDI_DIALOG));
 
   g_signal_connect_after(G_OBJECT(ffplayer->machine.audio), "set_audio_channels\0",
-			 G_CALLBACK(ags_ffplayer_set_audio_channels), NULL);
+			 G_CALLBACK(ags_ffplayer_set_audio_channels), ffplayer);
 
   g_signal_connect_after(G_OBJECT(ffplayer->machine.audio), "set_pads\0",
-			 G_CALLBACK(ags_ffplayer_set_pads), NULL);
+			 G_CALLBACK(ags_ffplayer_set_pads), ffplayer);
 
   ffplayer->flags = 0;
   
@@ -603,6 +604,8 @@ ags_ffplayer_disconnect(AgsConnectable *connectable)
     return;
   }
 
+  ags_ffplayer_parent_connectable_interface->disconnect(connectable);
+
   ffplayer = AGS_FFPLAYER(connectable);
 
   g_object_disconnect((GObject *) ffplayer,
@@ -630,7 +633,6 @@ ags_ffplayer_disconnect(AgsConnectable *connectable)
 		      (gpointer) ffplayer,
 		      NULL);
 
-
   g_object_disconnect((GObject *) ffplayer->drawing_area,
 		      "expose_event\0",
 		      G_CALLBACK(ags_ffplayer_drawing_area_expose_callback),
@@ -648,8 +650,6 @@ ags_ffplayer_disconnect(AgsConnectable *connectable)
 		      G_CALLBACK(ags_ffplayer_hscrollbar_value_changed),
 		      (gpointer) ffplayer,
 		      NULL);
-
-  ags_ffplayer_parent_connectable_interface->disconnect(connectable);
 }
 
 void
@@ -785,6 +785,10 @@ ags_ffplayer_launch_task(AgsFileLaunch *file_launch, AgsFFPlayer *ffplayer)
   filename = xmlGetProp(node,
 			"filename\0");
 
+  if(filename == NULL){
+    return;
+  }
+
   if(g_str_has_suffix(filename, ".sf2\0")){
     AgsIpatch *ipatch;
     AgsPlayable *playable;
@@ -961,19 +965,51 @@ ags_ffplayer_set_audio_channels(AgsAudio *audio,
 				guint audio_channels, guint audio_channels_old,
 				gpointer data)
 {
-  if(audio_channels > audio_channels_old){
-    /* AgsInput */
-    /* ags-buffer */
-    ags_recall_factory_create(audio,
-			      NULL, NULL,
-			      "ags-buffer\0",
-			      audio_channels_old, audio_channels,
-			      0, audio->input_pads,
-			      (AGS_RECALL_FACTORY_INPUT |
-			       AGS_RECALL_FACTORY_RECALL |
-			       AGS_RECALL_FACTORY_ADD),
-			      0);
+  AgsConfig *config;
+
+  gchar *str;
 
+  gboolean performance_mode;
+
+  config = ags_config_get_instance();
+
+  if(audio_channels > audio_channels_old){
+    /* map dependending on output */
+    str = ags_config_get_value(config,
+			       AGS_CONFIG_GENERIC,
+			       "engine-mode\0");
+    performance_mode = FALSE;
+  
+    if(str != NULL &&
+       !g_ascii_strncasecmp(str,
+			    "performance\0",
+			    12)){
+      /* ags-copy */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-copy\0",
+				audio_channels_old, audio_channels,
+				0, audio->input_pads,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      /* set performance mode */
+      performance_mode = TRUE;
+    }else{    
+      /* ags-buffer */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-buffer\0",
+				audio_channels_old, audio_channels,
+				0, audio->input_pads,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+    }
+    
     /* ags-play */
     ags_recall_factory_create(audio,
 			      NULL, NULL,
@@ -999,15 +1035,17 @@ ags_ffplayer_set_audio_channels(AgsAudio *audio,
 
     /* AgsOutput */
     /* ags-stream */
-    ags_recall_factory_create(audio,
-			      NULL, NULL,
-			      "ags-stream\0",
-			      audio_channels_old, audio_channels,
-			      0, audio->output_pads,
-			      (AGS_RECALL_FACTORY_OUTPUT |
-			       AGS_RECALL_FACTORY_PLAY |
-			       AGS_RECALL_FACTORY_ADD),
-			      0);
+    if(!performance_mode){
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-stream\0",
+				audio_channels_old, audio_channels,
+				0, audio->output_pads,
+				(AGS_RECALL_FACTORY_OUTPUT |
+				 AGS_RECALL_FACTORY_PLAY |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+    }
   }
 }
 
@@ -1058,35 +1096,74 @@ ags_ffplayer_input_map_recall(AgsFFPlayer *ffplayer, guint input_pad_start)
   AgsAudio *audio;
   AgsChannel *source, *current;
 
+  AgsConfig *config;
+
   GList *list;
 
+  gchar *str;
+
+  gboolean performance_mode;
+
   audio = AGS_MACHINE(ffplayer)->audio;
 
   if(ffplayer->mapped_input_pad > input_pad_start){
     return;
   }
 
+  config = ags_config_get_instance();
+
   source = ags_channel_nth(audio->input,
 			   input_pad_start * audio->audio_channels);
 
   /* map dependending on output */
-  current = source;
-
-  while(current != NULL){
-    /* ags-buffer */
-    ags_recall_factory_create(audio,
-			      NULL, NULL,
-			      "ags-buffer\0",
-			      0, audio->audio_channels, 
-			      current->pad, current->pad + 1,
-			      (AGS_RECALL_FACTORY_INPUT |
-			       AGS_RECALL_FACTORY_RECALL |
-			       AGS_RECALL_FACTORY_ADD),
-			      0);
-
-    current = current->next_pad;
+  str = ags_config_get_value(config,
+			     AGS_CONFIG_GENERIC,
+			     "engine-mode\0");
+  performance_mode = FALSE;
+  
+  /* remap for input */
+  if(str != NULL &&
+     !g_ascii_strncasecmp(str,
+			  "performance\0",
+			  12)){
+    current = source;
+
+    while(current != NULL){
+      /* ags-copy */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-copy\0",
+				0, audio->audio_channels, 
+				current->pad, current->pad + 1,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      current = current->next_pad;
+    }
+    
+    /* set performance mode */
+    performance_mode = TRUE;
+  }else{    
+    current = source;
+
+    while(current != NULL){
+      /* ags-buffer */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-buffer\0",
+				0, audio->audio_channels, 
+				current->pad, current->pad + 1,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      current = current->next_pad;
+    }
   }
-
+  
   /*  */
   current = source;
 
@@ -1142,7 +1219,7 @@ ags_ffplayer_input_map_recall(AgsFFPlayer *ffplayer, guint input_pad_start)
 
     current = current->next_pad;
   }
-
+  
   ffplayer->mapped_input_pad = audio->input_pads;
 }
 
@@ -1152,51 +1229,92 @@ ags_ffplayer_output_map_recall(AgsFFPlayer *ffplayer, guint output_pad_start)
   AgsAudio *audio;
   AgsChannel *source, *input, *current;
 
+  AgsConfig *config;
+
+  gchar *str;
+
+  gboolean performance_mode;
+
   audio = AGS_MACHINE(ffplayer)->audio;
 
   if(ffplayer->mapped_output_pad > output_pad_start){
     return;
   }
+
+  config = ags_config_get_instance();
   
   source = ags_channel_nth(audio->output,
 			   output_pad_start * audio->audio_channels);
 
   
-  /* remap for input */
-  input = audio->input;
-
-  while(input != NULL){
-    /* ags-buffer */
-    ags_recall_factory_create(audio,
-			      NULL, NULL,
-			      "ags-buffer\0",
-			      0, audio->audio_channels, 
-			      input->pad, input->pad + 1,
-			      (AGS_RECALL_FACTORY_INPUT |
-			       AGS_RECALL_FACTORY_RECALL |
-			       AGS_RECALL_FACTORY_ADD),
-			      0);
+  /* map dependending on output */
+  str = ags_config_get_value(config,
+			     AGS_CONFIG_GENERIC,
+			     "engine-mode\0");
+  performance_mode = FALSE;
 
-    input = input->next_pad;
+  /* remap for input */
+  if(str != NULL &&
+     !g_ascii_strncasecmp(str,
+			  "performance\0",
+			  12)){
+    input = audio->input;
+
+    while(input != NULL){
+      /* ags-copy */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-copy\0",
+				0, audio->audio_channels, 
+				input->pad, input->pad + 1,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      input = input->next_pad;
+    }
+    
+    /* set performance mode */
+    performance_mode = TRUE;
+  }else{    
+    input = audio->input;
+
+    while(input != NULL){
+      /* ags-buffer */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-buffer\0",
+				0, audio->audio_channels, 
+				input->pad, input->pad + 1,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      input = input->next_pad;
+    }
   }
 
-  current = source;
-
-  while(current != NULL){
-    /* ags-stream */
-    ags_recall_factory_create(audio,
-			      NULL, NULL,
-			      "ags-stream\0",
-			      0, audio->audio_channels,
-			      current->pad, current->pad + 1,
-			      (AGS_RECALL_FACTORY_OUTPUT |
-			       AGS_RECALL_FACTORY_PLAY |
-			       AGS_RECALL_FACTORY_ADD),
-			      0);
-
-    current = current->next_pad;
+  if(!performance_mode){
+    current = source;
+
+    while(current != NULL){
+      /* ags-stream */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-stream\0",
+				0, audio->audio_channels,
+				current->pad, current->pad + 1,
+				(AGS_RECALL_FACTORY_OUTPUT |
+				 AGS_RECALL_FACTORY_PLAY |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      current = current->next_pad;
+    }
   }
-
+  
   ffplayer->mapped_output_pad = audio->output_pads;
 }
 
@@ -1341,6 +1459,10 @@ void
 ags_ffplayer_open_filename(AgsFFPlayer *ffplayer,
 			   gchar *filename)
 {
+  if(filename == NULL){
+    return;
+  }
+  
   if(g_str_has_suffix(filename, ".sf2\0")){
     AgsWindow *window;
     
diff --git a/ags/X/machine/ags_ffplayer_bridge.c b/ags/X/machine/ags_ffplayer_bridge.c
index 8d52c51..ebb7abd 100644
--- a/ags/X/machine/ags_ffplayer_bridge.c
+++ b/ags/X/machine/ags_ffplayer_bridge.c
@@ -185,7 +185,7 @@ ags_ffplayer_bridge_disconnect(AgsConnectable *connectable)
     return;
   }
 
-  ags_ffplayer_bridge_parent_connectable_interface->connect(connectable);
+  ags_ffplayer_bridge_parent_connectable_interface->disconnect(connectable);
 
   //TODO:JK: implement me
 }
diff --git a/ags/X/machine/ags_ffplayer_bulk_input.c b/ags/X/machine/ags_ffplayer_bulk_input.c
index 4127afb..2431ec6 100644
--- a/ags/X/machine/ags_ffplayer_bulk_input.c
+++ b/ags/X/machine/ags_ffplayer_bulk_input.c
@@ -146,7 +146,7 @@ ags_ffplayer_bulk_input_disconnect(AgsConnectable *connectable)
     return;
   }
 
-  ags_ffplayer_bulk_input_parent_connectable_interface->connect(connectable);
+  ags_ffplayer_bulk_input_parent_connectable_interface->disconnect(connectable);
 
   //TODO:JK: implement me
 }
diff --git a/ags/X/machine/ags_ffplayer_input_line.c b/ags/X/machine/ags_ffplayer_input_line.c
index da66f92..12ea50c 100644
--- a/ags/X/machine/ags_ffplayer_input_line.c
+++ b/ags/X/machine/ags_ffplayer_input_line.c
@@ -177,12 +177,6 @@ ags_ffplayer_input_line_disconnect(AgsConnectable *connectable)
 void
 ags_ffplayer_input_line_finalize(GObject *gobject)
 {
-  g_object_disconnect(gobject,
-		      "notify::channel\0",
-		      G_CALLBACK(ags_ffplayer_input_line_notify_channel_callback),
-		      NULL,
-		      NULL);
-
   G_OBJECT_CLASS(ags_ffplayer_input_line_parent_class)->finalize(gobject);
 }
 
diff --git a/ags/X/machine/ags_lv2_bridge.c b/ags/X/machine/ags_lv2_bridge.c
index 49912af..165c3b5 100644
--- a/ags/X/machine/ags_lv2_bridge.c
+++ b/ags/X/machine/ags_lv2_bridge.c
@@ -42,7 +42,10 @@
 
 #include <ags/plugin/ags_lv2_manager.h>
 #include <ags/plugin/ags_lv2ui_manager.h>
+#include <ags/plugin/ags_base_plugin.h>
 #include <ags/plugin/ags_lv2_plugin.h>
+#include <ags/plugin/ags_lv2_preset.h>
+#include <ags/plugin/ags_lv2ui_plugin.h>
 
 #include <ags/audio/ags_input.h>
 #include <ags/audio/ags_recall_factory.h>
@@ -68,13 +71,6 @@
 #include <ags/X/ags_effect_bulk.h>
 #include <ags/X/ags_bulk_member.h>
 
-#include <dlfcn.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-
 void ags_lv2_bridge_class_init(AgsLv2BridgeClass *lv2_bridge);
 void ags_lv2_bridge_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_lv2_bridge_plugin_interface_init(AgsPluginInterface *plugin);
@@ -87,6 +83,7 @@ void ags_lv2_bridge_get_property(GObject *gobject,
 				 guint prop_id,
 				 GValue *value,
 				 GParamSpec *param_spec);
+void ags_lv2_bridge_finalize(GObject *gobject);
 void ags_lv2_bridge_connect(AgsConnectable *connectable);
 void ags_lv2_bridge_disconnect(AgsConnectable *connectable);
 gchar* ags_lv2_bridge_get_version(AgsPlugin *plugin);
@@ -135,6 +132,8 @@ static gpointer ags_lv2_bridge_parent_class = NULL;
 static AgsConnectableInterface* ags_lv2_bridge_parent_connectable_interface;
 static AgsPluginInterface* ags_lv2_bridge_parent_plugin_interface;
 
+GHashTable *ags_lv2_bridge_lv2ui_idle = NULL;
+
 GType
 ags_lv2_bridge_get_type(void)
 {
@@ -196,6 +195,8 @@ ags_lv2_bridge_class_init(AgsLv2BridgeClass *lv2_bridge)
   gobject->set_property = ags_lv2_bridge_set_property;
   gobject->get_property = ags_lv2_bridge_get_property;
 
+  gobject->finalize = ags_lv2_bridge_finalize;
+  
   /* properties */
   /**
    * AgsRecallLv2:filename:
@@ -371,8 +372,12 @@ ags_lv2_bridge_init(AgsLv2Bridge *lv2_bridge)
 
   AgsAudio *audio;
 
-  gchar *str;
-  
+  if(ags_lv2_bridge_lv2ui_idle == NULL){
+    ags_lv2_bridge_lv2ui_idle = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+						      NULL,
+						      NULL);
+  }
+
   audio = AGS_MACHINE(lv2_bridge)->audio;
   audio->flags |= (AGS_AUDIO_SYNC);
 
@@ -401,9 +406,18 @@ ags_lv2_bridge_init(AgsLv2Bridge *lv2_bridge)
 
   lv2_bridge->has_midi = FALSE;
 
-  AGS_MACHINE(lv2_bridge)->bridge = (GtkContainer *) ags_effect_bridge_new(audio);
+  lv2_bridge->vbox = (GtkVBox *) gtk_vbox_new(FALSE, 0);
   gtk_container_add((GtkContainer *) gtk_bin_get_child((GtkBin *) lv2_bridge),
-		    (GtkWidget *) AGS_MACHINE(lv2_bridge)->bridge);
+		    (GtkWidget *) lv2_bridge->vbox);
+
+  lv2_bridge->preset = NULL;
+  
+  /* effect bridge */  
+  AGS_MACHINE(lv2_bridge)->bridge = (GtkContainer *) ags_effect_bridge_new(audio);
+  gtk_box_pack_start((GtkBox *) lv2_bridge->vbox,
+		     (GtkWidget *) AGS_MACHINE(lv2_bridge)->bridge,
+		     FALSE, FALSE,
+		     0);
 
   table = (GtkTable *) gtk_table_new(1, 2, FALSE);
   gtk_box_pack_start((GtkBox *) AGS_EFFECT_BRIDGE(AGS_MACHINE(lv2_bridge)->bridge),
@@ -426,35 +440,26 @@ ags_lv2_bridge_init(AgsLv2Bridge *lv2_bridge)
   lv2_bridge->has_gui = FALSE;
   lv2_bridge->gui_filename = NULL;
   lv2_bridge->gui_uri = NULL;
+
+  lv2_bridge->ui_handle = NULL;
   
   lv2_bridge->lv2_gui = NULL;
 
   /* lv2 menu */
-  str = ags_config_get_value(ags_config_get_instance(),
-			     AGS_CONFIG_GENERIC,
-			     "disable-feature\0");
-  
-  if(str == NULL ||
-     !g_ascii_strncasecmp(str,
-			  "experimental\0",
-			  13)){
-    g_message("lv2 ui disabled\0");
-  }else{
-    item = (GtkImageMenuItem *) gtk_image_menu_item_new_with_label("Lv2\0");
-    gtk_menu_shell_append((GtkMenuShell *) AGS_MACHINE(lv2_bridge)->popup,
-			  (GtkWidget *) item);
-    gtk_widget_show((GtkWidget *) item);
+  item = (GtkImageMenuItem *) gtk_image_menu_item_new_with_label("Lv2\0");
+  gtk_menu_shell_append((GtkMenuShell *) AGS_MACHINE(lv2_bridge)->popup,
+			(GtkWidget *) item);
+  gtk_widget_show((GtkWidget *) item);
   
-    lv2_bridge->lv2_menu = (GtkMenu *) gtk_menu_new();
-    gtk_menu_item_set_submenu((GtkMenuItem *) item,
-			      (GtkWidget *) lv2_bridge->lv2_menu);
+  lv2_bridge->lv2_menu = (GtkMenu *) gtk_menu_new();
+  gtk_menu_item_set_submenu((GtkMenuItem *) item,
+			    (GtkWidget *) lv2_bridge->lv2_menu);
 
-    item = (GtkImageMenuItem *) gtk_image_menu_item_new_with_label("show GUI\0");
-    gtk_menu_shell_append((GtkMenuShell *) lv2_bridge->lv2_menu,
-			  (GtkWidget *) item);
+  item = (GtkImageMenuItem *) gtk_image_menu_item_new_with_label("show GUI\0");
+  gtk_menu_shell_append((GtkMenuShell *) lv2_bridge->lv2_menu,
+			(GtkWidget *) item);
 
-    gtk_widget_show_all((GtkWidget *) lv2_bridge->lv2_menu);
-  }
+  gtk_widget_show_all((GtkWidget *) lv2_bridge->lv2_menu);
 }
 
 void
@@ -570,15 +575,6 @@ ags_lv2_bridge_set_property(GObject *gobject,
       }
 
       lv2_bridge->has_gui = has_gui;
-
-      if(has_gui){
-	lv2_bridge->lv2_gui = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-	g_signal_connect(G_OBJECT(lv2_bridge->lv2_gui), "delete-event\0",
-			 G_CALLBACK(ags_lv2_bridge_delete_event_callback), lv2_bridge);
-      }else{
-	gtk_widget_destroy(lv2_bridge->lv2_gui);
-	lv2_bridge->lv2_gui = NULL;
-      }
     }
     break;
   case PROP_GUI_FILENAME:
@@ -588,92 +584,12 @@ ags_lv2_bridge_set_property(GObject *gobject,
       gchar *gui_filename;
 
       gui_filename = g_value_get_string(value);
-/*
 
       if(lv2_bridge->gui_filename == gui_filename){
 	return;
       }
 
-      if(lv2_bridge->gui_filename != NULL){
-	gtk_widget_destroy(gtk_bin_get_child((GtkBin *) lv2_bridge->lv2_gui));
-	free(lv2_bridge->gui_filename);
-      }
-
       lv2_bridge->gui_filename = g_strdup(gui_filename);
-
-      /* load GUI * /
-      if(gui_filename != NULL &&
-	 lv2_bridge->lv2_gui != NULL){
-	GtkWidget *widget;
-	AgsLv2uiPlugin *lv2ui_plugin;
-
-	gchar *uri;
-	
-	LV2UI_DescriptorFunction lv2ui_descriptor;
-	LV2UI_Descriptor *ui_descriptor;
-	
-	uint32_t ui_index;
-
-	static const LV2_Feature **feature = {
-	  NULL,
-	};
-	lv2ui_plugin = ags_lv2ui_manager_find_lv2ui_plugin(ags_lv2ui_manager_get_instance(),
-							   gui_filename);
-
-	if(AGS_BASE_PLUGIN(lv2ui_plugin)->plugin_so == NULL){
-	  AGS_BASE_PLUGIN(lv2ui_plugin)->plugin_so = dlopen(AGS_BASE_PLUGIN(lv2ui_plugin)->filename,
-							    RTLD_NOW);
-	}
-
-	if(AGS_BASE_PLUGIN(lv2ui_plugin)->plugin_so){
-	  lv2ui_descriptor = (LV2UI_Descriptor *) dlsym(AGS_BASE_PLUGIN(lv2ui_plugin)->plugin_so,
-							"lv2ui_descriptor\0");
-	  
-	  if(dlerror() == NULL && lv2ui_descriptor){
-	    ui_index = ags_lv2ui_manager_uri_index(ags_lv2ui_manager_get_instance(),
-						   gui_filename,
-						   lv2_bridge->gui_uri);
-
-	    if(ui_index != -1){
-	      GtkVBox *vbox;
-	      GtkAlignment *alignment;
-
-	      gchar *bundle_path;
-
-	      ui_descriptor = lv2ui_descriptor(ui_index);
-
-	      vbox = (GtkVBox *) gtk_vbox_new(FALSE,
-					      0);
-	      gtk_container_add((GtkContainer *) lv2_bridge->lv2_gui,
-				(GtkWidget *) vbox);
-	      
-	      alignment = gtk_alignment_new(0.5, 0.5, 1.0, 1.0);
-	      gtk_box_pack_start(GTK_BOX(vbox),
-				 (GtkWidget *) alignment,
-				 TRUE, TRUE,
-				 0);
-	      
-	      /* instantiate and pack ui * /
-	      bundle_path = g_strndup(gui_filename,
-				      rindex(gui_filename, '/') - gui_filename);
-	      widget = NULL;
-	      lv2_bridge->ui_handle = ui_descriptor->instantiate(ui_descriptor,
-								 lv2_bridge->uri,
-								 bundle_path,
-								 ags_lv2_bridge_lv2ui_write_function,
-								 lv2_bridge,
-								 &widget,
-								 feature);
-	      lv2_bridge->ui_widget = widget;
-	      gtk_container_add((GtkContainer *) alignment,
-				widget);
-	      
-	      gtk_widget_show_all((GtkWidget *) vbox);
-	    }
-	  }
-	}
-      }
-*/
     }
     break;
   case PROP_GUI_URI:
@@ -757,13 +673,26 @@ ags_lv2_bridge_get_property(GObject *gobject,
 }
 
 void
+ags_lv2_bridge_finalize(GObject *gobject)
+{
+  AgsLv2Bridge *lv2_bridge;
+
+  lv2_bridge = AGS_LV2_BRIDGE(gobject);
+  
+  if(lv2_bridge->ui_handle != NULL){
+    g_hash_table_remove(ags_lv2_bridge_lv2ui_idle,
+			lv2_bridge);
+  }
+  
+  G_OBJECT_CLASS(ags_lv2_bridge_parent_class)->finalize(gobject);
+}
+
+void
 ags_lv2_bridge_connect(AgsConnectable *connectable)
 {
   AgsLv2Bridge *lv2_bridge;
 
   GList *list;
-
-  gchar *str;
   
   if((AGS_MACHINE_CONNECTED & (AGS_MACHINE(connectable)->flags)) != 0){
     return;
@@ -774,19 +703,10 @@ ags_lv2_bridge_connect(AgsConnectable *connectable)
   lv2_bridge = AGS_LV2_BRIDGE(connectable);
 
   /* menu */
-  str = ags_config_get_value(ags_config_get_instance(),
-			     AGS_CONFIG_GENERIC,
-			     "disable-feature\0");
-  
-  if(str != NULL &&
-     g_ascii_strncasecmp(str,
-			 "experimental\0",
-			 13)){
-    list = gtk_container_get_children((GtkContainer *) lv2_bridge->lv2_menu);
-
-    g_signal_connect(G_OBJECT(list->data), "activate\0",
-		     G_CALLBACK(ags_lv2_bridge_show_gui_callback), lv2_bridge);
-  }
+  list = gtk_container_get_children((GtkContainer *) lv2_bridge->lv2_menu);
+
+  g_signal_connect(G_OBJECT(list->data), "activate\0",
+		   G_CALLBACK(ags_lv2_bridge_show_gui_callback), lv2_bridge);
 }
 
 void
@@ -1349,8 +1269,14 @@ ags_lv2_bridge_input_map_recall(AgsLv2Bridge *lv2_bridge, guint audio_channel_st
   AgsAudio *audio;
   AgsChannel *source, *current;
   
+  AgsConfig *config;
+  
   GList *list;
 
+  gchar *str;
+
+  gboolean performance_mode;
+
   audio = AGS_MACHINE(lv2_bridge)->audio;
 
   if(lv2_bridge->mapped_input_pad > input_pad_start){
@@ -1360,23 +1286,55 @@ ags_lv2_bridge_input_map_recall(AgsLv2Bridge *lv2_bridge, guint audio_channel_st
   source = ags_channel_nth(audio->input,
 			   audio_channel_start + input_pad_start * audio->audio_channels);
 
+  config = ags_config_get_instance();
+
   if((AGS_MACHINE_IS_SYNTHESIZER & (AGS_MACHINE(lv2_bridge)->flags)) != 0){
     /* map dependending on output */
-    current = source;
+    str = ags_config_get_value(config,
+			       AGS_CONFIG_GENERIC,
+			       "engine-mode\0");
+    performance_mode = FALSE;
+  
+    if(str != NULL &&
+       !g_ascii_strncasecmp(str,
+			    "performance\0",
+			    12)){
+      current = source;
+
+      while(current != NULL){
+	/* ags-copy */
+	ags_recall_factory_create(audio,
+				  NULL, NULL,
+				  "ags-copy\0",
+				  audio_channel_start, audio->audio_channels, 
+				  current->pad, current->pad + 1,
+				  (AGS_RECALL_FACTORY_INPUT |
+				   AGS_RECALL_FACTORY_RECALL |
+				   AGS_RECALL_FACTORY_ADD),
+				  0);
+
+	current = current->next_pad;
+      }
 
-    while(current != NULL){
-      /* ags-buffer */
-      ags_recall_factory_create(audio,
-				NULL, NULL,
-				"ags-buffer\0",
-				audio_channel_start, audio->audio_channels, 
-				current->pad, current->pad + 1,
-				(AGS_RECALL_FACTORY_INPUT |
-				 AGS_RECALL_FACTORY_RECALL |
-				 AGS_RECALL_FACTORY_ADD),
-				0);
+      /* set performance mode */
+      performance_mode = TRUE;
+    }else{    
+      current = source;
+
+      while(current != NULL){
+	/* ags-buffer */
+	ags_recall_factory_create(audio,
+				  NULL, NULL,
+				  "ags-buffer\0",
+				  audio_channel_start, audio->audio_channels, 
+				  current->pad, current->pad + 1,
+				  (AGS_RECALL_FACTORY_INPUT |
+				   AGS_RECALL_FACTORY_RECALL |
+				   AGS_RECALL_FACTORY_ADD),
+				  0);
     
-      current = current->next_pad;
+	current = current->next_pad;
+      }
     }
   
     /*  */
@@ -1429,50 +1387,92 @@ ags_lv2_bridge_output_map_recall(AgsLv2Bridge *lv2_bridge, guint audio_channel_s
   AgsDelayAudio *recall_delay_audio;
   AgsCountBeatsAudioRun *recall_count_beats_audio_run;
 
+  AgsConfig *config;
+
   GList *list;
 
+  gchar *str;
+
+  gboolean performance_mode;
+
   audio = AGS_MACHINE(lv2_bridge)->audio;
 
   if(lv2_bridge->mapped_output_pad > output_pad_start){
     return;
   }
 
+  config = ags_config_get_instance();
+
   if((AGS_MACHINE_IS_SYNTHESIZER & (AGS_MACHINE(lv2_bridge)->flags)) != 0){
+    /* map dependending on output */
+    str = ags_config_get_value(config,
+			       AGS_CONFIG_GENERIC,
+			       "engine-mode\0");
+    performance_mode = FALSE;
+  
     /* remap for input */
-    input = audio->input;
+    if(str != NULL &&
+       !g_ascii_strncasecmp(str,
+			    "performance\0",
+			    12)){
+      input = audio->input;
+
+      while(input != NULL){
+	/* ags-copy */
+	ags_recall_factory_create(audio,
+				  NULL, NULL,
+				  "ags-copy\0",
+				  audio_channel_start, audio->audio_channels, 
+				  input->pad, input->pad + 1,
+				  (AGS_RECALL_FACTORY_INPUT |
+				   AGS_RECALL_FACTORY_RECALL |
+				   AGS_RECALL_FACTORY_REMAP),
+				  0);
+    
+	input = input->next_pad;
+      }
 
-    while(input != NULL){
-      /* ags-buffer */
-      ags_recall_factory_create(audio,
-				NULL, NULL,
-				"ags-buffer\0",
-				audio_channel_start, audio->audio_channels, 
-				input->pad, input->pad + 1,
-				(AGS_RECALL_FACTORY_INPUT |
-				 AGS_RECALL_FACTORY_RECALL |
-				 AGS_RECALL_FACTORY_REMAP),
-				0);
+      /* set performance mode */
+      performance_mode = TRUE;
+    }else{    
+      input = audio->input;
+
+      while(input != NULL){
+	/* ags-buffer */
+	ags_recall_factory_create(audio,
+				  NULL, NULL,
+				  "ags-buffer\0",
+				  audio_channel_start, audio->audio_channels, 
+				  input->pad, input->pad + 1,
+				  (AGS_RECALL_FACTORY_INPUT |
+				   AGS_RECALL_FACTORY_RECALL |
+				   AGS_RECALL_FACTORY_REMAP),
+				  0);
     
-      input = input->next_pad;
+	input = input->next_pad;
+      }
     }
-
-    current = ags_channel_nth(audio->output,
-			      audio_channel_start + output_pad_start * audio->audio_channels);
-
-    while(current != NULL){
-      /* ags-stream */
-      ags_recall_factory_create(audio,
-				NULL, NULL,
-				"ags-stream\0",
-				audio_channel_start, audio->audio_channels,
-				current->pad, current->pad + 1,
-				(AGS_RECALL_FACTORY_OUTPUT |
-				 AGS_RECALL_FACTORY_PLAY |
-				 AGS_RECALL_FACTORY_RECALL | 
-				 AGS_RECALL_FACTORY_ADD),
-				0);
-
-      current = current->next_pad;
+    
+    /*  */
+    if(!performance_mode){
+      current = ags_channel_nth(audio->output,
+				audio_channel_start + output_pad_start * audio->audio_channels);
+
+      while(current != NULL){
+	/* ags-stream */
+	ags_recall_factory_create(audio,
+				  NULL, NULL,
+				  "ags-stream\0",
+				  audio_channel_start, audio->audio_channels,
+				  current->pad, current->pad + 1,
+				  (AGS_RECALL_FACTORY_OUTPUT |
+				   AGS_RECALL_FACTORY_PLAY |
+				   AGS_RECALL_FACTORY_RECALL | 
+				   AGS_RECALL_FACTORY_ADD),
+				  0);
+
+	current = current->next_pad;
+      }
     }
   }
   
@@ -1480,87 +1480,110 @@ ags_lv2_bridge_output_map_recall(AgsLv2Bridge *lv2_bridge, guint audio_channel_s
 }
 
 void
-ags_lv2_bridge_load_gui(AgsLv2Bridge *lv2_bridge)
+ags_lv2_bridge_load_preset(AgsLv2Bridge *lv2_bridge)
 {
+  GtkHBox *hbox;
+  GtkLabel *label;
+  
   AgsLv2Plugin *lv2_plugin;
-  AgsLv2uiPlugin *lv2ui_plugin;
 
-  GList *gtkui_list;
-  GList *binary_list;
+  GList *list;  
+  
+  /* program */
+  hbox = (GtkHBox *) gtk_hbox_new(FALSE, 0);
+  gtk_box_pack_start((GtkBox *) lv2_bridge->vbox,
+		     (GtkWidget *) hbox,
+		     FALSE, FALSE,
+		     0);
+  gtk_box_reorder_child(GTK_BOX(lv2_bridge->vbox),
+  			GTK_WIDGET(hbox),
+  			0);
+  
+  label = (GtkLabel *) gtk_label_new("preset\0");
+  gtk_box_pack_start((GtkBox *) hbox,
+		     (GtkWidget *) label,
+		     FALSE, FALSE,
+		     0);
 
-  gchar *str;
-  gchar *plugin_path;
-  gchar *filename;
-  gchar *gui_uri;
+  lv2_bridge->preset = gtk_combo_box_text_new();
+  gtk_box_pack_start((GtkBox *) hbox,
+		     (GtkWidget *) lv2_bridge->preset,
+		     FALSE, FALSE,
+		     0);
   
-  /* check if works with Gtk+ */
+  /* retrieve lv2 plugin */
   lv2_plugin = ags_lv2_manager_find_lv2_plugin(ags_lv2_manager_get_instance(),
 					       lv2_bridge->filename,
 					       lv2_bridge->effect);
 
-  if(lv2_plugin == NULL){
-    return;
-  }
+  /* preset */
+  list = lv2_plugin->preset;
 
-  gtkui_list = ags_turtle_find_xpath(lv2_plugin->turtle,
-				     "//rdf-triple//rdf-verb[@verb='a']/following-sibling::*[self::rdf-object-list]//rdf-pname-ln[substring(text(), string-length(text()) - string-length(':GtkUI') + 1) = ':GtkUI']\0");
+  while(list != NULL){
+    gtk_combo_box_text_append_text(lv2_bridge->preset,
+				   AGS_LV2_PRESET(list->data)->preset_label);
 
-  if(gtkui_list == NULL){
-    return;
+    list = list->next;
   }
-  
-  /* read ui binary from turtle */
-  binary_list = ags_turtle_find_xpath(lv2_plugin->turtle,
-				      "//rdf-triple//rdf-verb//rdf-pname-ln[text()='uiext:binary']/ancestor::*[self::rdf-verb][1]/following-sibling::*[self::rdf-object-list][1]//rdf-iriref\0");
 
-  if(binary_list == NULL){
+  gtk_widget_show_all(hbox);
+
+  /* connect preset */
+  g_signal_connect_after(G_OBJECT(lv2_bridge->preset), "changed\0",
+			 G_CALLBACK(ags_lv2_bridge_preset_changed_callback), lv2_bridge);
+}
+
+void
+ags_lv2_bridge_load_midi(AgsLv2Bridge *lv2_bridge)
+{
+  //TODO:JK: implement me
+}
+
+void
+ags_lv2_bridge_load_gui(AgsLv2Bridge *lv2_bridge)
+{
+  AgsLv2Plugin *lv2_plugin;
+  AgsLv2uiPlugin *lv2ui_plugin;
+
+  GList *list;
+  
+  /* retrieve lv2 plugin */
+  lv2_plugin = ags_lv2_manager_find_lv2_plugin(ags_lv2_manager_get_instance(),
+					       lv2_bridge->filename,
+					       lv2_bridge->effect);
+  
+  if(lv2_plugin == NULL ||
+     lv2_plugin->ui_uri == NULL){
     return;
   }
 
-  str = xmlNodeGetContent(binary_list->data);
+  /* retrieve lv2ui plugin */
+  list = ags_lv2ui_plugin_find_gui_uri(ags_lv2ui_manager_get_instance()->lv2ui_plugin,
+				       lv2_plugin->ui_uri);
 
-  if(strlen(str) < 2){
+  if(list == NULL){
     return;
   }
 
-  plugin_path = g_strndup(lv2_bridge->filename,
-			  rindex(lv2_bridge->filename, '/') - lv2_bridge->filename);
+  lv2ui_plugin = list->data;
   
-  str = g_strndup(&(str[1]),
-		  strlen(str) - 2);
-  filename = g_strdup_printf("%s/%s\0",
-			     plugin_path,
-			     str);
-  free(str);
-
 #ifdef AGS_DEBUG
-  g_message("plugin path - %s\0", plugin_path);
+  g_message("ui filename - %s\0", AGS_BASE_PLUGIN(lv2ui_plugin)->ui_filename);
 #endif
 
-  /*
-  gui_uri = ags_lv2ui_manager_find_uri(ags_lv2ui_manager_get_instance(),
-				       filename,
-				       lv2_bridge->effect);
-
-  /* apply ui * /
+  /* apply ui */
   g_object_set(lv2_bridge,
 	       "has-gui\0", TRUE,
-	       "gui-uri\0", gui_uri,
-	       "gui-filename\0", filename,
+	       "gui-uri\0", lv2_plugin->ui_uri,
+	       "gui-filename\0", AGS_BASE_PLUGIN(lv2ui_plugin)->ui_filename,
 	       NULL);
-  */
 }
 
 void
 ags_lv2_bridge_load(AgsLv2Bridge *lv2_bridge)
 {
   AgsLv2Plugin *lv2_plugin;
-  
-  gchar *uri;
-
-  if((AGS_MACHINE_IS_SYNTHESIZER & (AGS_MACHINE(lv2_bridge)->flags)) != 0){
-  }
-  
+    
   lv2_plugin = ags_lv2_manager_find_lv2_plugin(ags_lv2_manager_get_instance(),
 					       lv2_bridge->filename,
 					       lv2_bridge->effect);
@@ -1568,15 +1591,52 @@ ags_lv2_bridge_load(AgsLv2Bridge *lv2_bridge)
   if(lv2_plugin == NULL){
     return;
   }
-  
+
+  /* URI */
   g_object_set(lv2_bridge,
 	       "uri\0", lv2_plugin->uri,
 	       NULL);
-  
+
+  /* preset */
+  if(lv2_plugin->preset != NULL){
+    ags_lv2_bridge_load_preset(lv2_bridge);
+  }
+
+  /* load gui */
   ags_lv2_bridge_load_gui(lv2_bridge);
 }
 
 /**
+ * ags_lv2_bridge_lv2ui_idle_timeout:
+ * @widget: the #AgsLv2Bridge
+ *
+ * Idle lv2 ui.
+ *
+ * Returns: %TRUE if proceed with redraw, otherwise %FALSE
+ *
+ * Since: 0.7.127
+ */
+gboolean
+ags_lv2_bridge_lv2ui_idle_timeout(GtkWidget *widget)
+{
+  if(g_hash_table_lookup(ags_lv2_bridge_lv2ui_idle,
+			 widget) != NULL){
+    AgsLv2Bridge *lv2_bridge;
+    
+    lv2_bridge = AGS_LV2_BRIDGE(widget);
+    
+    if(lv2_bridge->ui_feature != NULL &&
+       lv2_bridge->ui_feature[0]->data != NULL){
+      ((struct _LV2UI_Idle_Interface *) lv2_bridge->ui_feature[0]->data)->idle(lv2_bridge->ui_handle);
+    }
+    
+    return(TRUE);
+  }else{
+    return(FALSE);
+  }
+}
+
+/**
  * ags_lv2_bridge_new:
  * @soundcard: the assigned soundcard.
  * @filename: the plugin.so
diff --git a/ags/X/machine/ags_lv2_bridge.h b/ags/X/machine/ags_lv2_bridge.h
index 4cb6db1..94876e2 100644
--- a/ags/X/machine/ags_lv2_bridge.h
+++ b/ags/X/machine/ags_lv2_bridge.h
@@ -78,8 +78,13 @@ struct _AgsLv2Bridge
   gchar *gui_filename;
   gchar *gui_uri;
 
-  LV2UI_Handle ui_handle;
+  GtkVBox *vbox;
   
+  GtkComboBoxText *preset;
+
+  LV2_Feature **ui_feature;
+  LV2UI_Handle ui_handle;
+
   GtkWidget *lv2_gui;
   GtkWidget *ui_widget;
 
@@ -96,10 +101,13 @@ GType ags_lv2_bridge_get_type(void);
 void ags_lv2_bridge_input_map_recall(AgsLv2Bridge *lv2_bridge, guint audio_channel_start, guint input_pad_start);
 void ags_lv2_bridge_output_map_recall(AgsLv2Bridge *lv2_bridge, guint audio_channel_start, guint output_pad_start);
 
+void ags_lv2_bridge_load_preset(AgsLv2Bridge *lv2_bridge);
 void ags_lv2_bridge_load_midi(AgsLv2Bridge *lv2_bridge);
 void ags_lv2_bridge_load_gui(AgsLv2Bridge *lv2_bridge);
 void ags_lv2_bridge_load(AgsLv2Bridge *lv2_bridge);
 
+gboolean ags_lv2_bridge_lv2ui_idle_timeout(GtkWidget *widget);
+
 AgsLv2Bridge* ags_lv2_bridge_new(GObject *soundcard,
 				 gchar *filename,
 				 gchar *effect);
diff --git a/ags/X/machine/ags_lv2_bridge_callbacks.c b/ags/X/machine/ags_lv2_bridge_callbacks.c
index 71d172b..22fca8d 100644
--- a/ags/X/machine/ags_lv2_bridge_callbacks.c
+++ b/ags/X/machine/ags_lv2_bridge_callbacks.c
@@ -19,22 +19,144 @@
 
 #include <ags/X/machine/ags_lv2_bridge_callbacks.h>
 
+#include <ags/plugin/ags_lv2_manager.h>
+#include <ags/plugin/ags_lv2ui_manager.h>
+#include <ags/plugin/ags_base_plugin.h>
+#include <ags/plugin/ags_lv2_conversion.h>
+#include <ags/plugin/ags_lv2_plugin.h>
+#include <ags/plugin/ags_lv2_preset.h>
+#include <ags/plugin/ags_lv2ui_plugin.h>
+
+#include <ags/audio/ags_audio.h>
 #include <ags/audio/ags_channel.h>
 #include <ags/audio/ags_recall.h>
 #include <ags/audio/ags_recall_lv2.h>
 #include <ags/audio/ags_port.h>
 
+#include <ags/widget/ags_dial.h>
+
+#include <ags/X/ags_window.h>
+#include <ags/X/ags_machine.h>
+#include <ags/X/ags_effect_bridge.h>
+#include <ags/X/ags_effect_bulk.h>
+#include <ags/X/ags_bulk_member.h>
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+extern GHashTable *ags_lv2_bridge_lv2ui_idle;
+
 void
 ags_lv2_bridge_show_gui_callback(GtkMenuItem *item, AgsLv2Bridge *lv2_bridge)
 {
-  gtk_widget_show_all(lv2_bridge->lv2_gui);
-  gtk_widget_show_all(gtk_bin_get_child((GtkBin *) lv2_bridge->lv2_gui));
+  AgsWindow *window;
+  GtkWidget *plugin_widget;
+  
+  AgsLv2uiPlugin *lv2ui_plugin;
+  
+  GList *list;
+  
+  gchar *uri;
+  
+  LV2UI_DescriptorFunction lv2ui_descriptor;
+  LV2UI_Descriptor *ui_descriptor;
+  
+  uint32_t ui_index;
+
+  static const LV2_Feature **feature = {
+    NULL,
+  };
+
+  window = gtk_widget_get_ancestor(lv2_bridge,
+				   AGS_TYPE_WINDOW);
+  
+  if(lv2_bridge->gui_uri == NULL){
+    return;
+  }
+  
+  list = ags_lv2ui_plugin_find_gui_uri(ags_lv2ui_manager_get_instance()->lv2ui_plugin,
+				       lv2_bridge->gui_uri);
+  
+  if(list == NULL){
+    return;
+  }
+
+  lv2ui_plugin = list->data;
+
+  if(lv2_bridge->ui_handle == NULL){
+    gchar *ui_filename;
+    gchar *bundle_path;	
+
+    LV2_Feature **feature;
+
+    /* feature array */
+    lv2_bridge->ui_feature = 
+      feature = (LV2_Feature **) malloc(3 * sizeof(LV2_Feature *));
+
+    /* idle interface */
+    feature[0] = (LV2_Feature *) malloc(sizeof(LV2_Feature));    
+    feature[0]->URI = LV2_UI__idleInterface;
+    feature[0]->data = NULL;
+    
+    /* show interface */
+    feature[1] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
+    feature[1]->URI = LV2_UI__showInterface;
+    feature[1]->data = NULL;
+
+    feature[2] = NULL;
+    
+    if(AGS_BASE_PLUGIN(lv2ui_plugin)->plugin_so == NULL){
+      AGS_BASE_PLUGIN(lv2ui_plugin)->plugin_so = dlopen(AGS_BASE_PLUGIN(lv2ui_plugin)->ui_filename,
+							RTLD_NOW);
+    }
+    
+    if(AGS_BASE_PLUGIN(lv2ui_plugin)->plugin_so){
+      lv2ui_descriptor = (LV2UI_Descriptor *) dlsym(AGS_BASE_PLUGIN(lv2ui_plugin)->plugin_so,
+						    "lv2ui_descriptor\0");
+      
+      if(dlerror() == NULL && lv2ui_descriptor){
+	ui_descriptor = lv2ui_descriptor(AGS_BASE_PLUGIN(lv2ui_plugin)->ui_effect_index);
+	ui_filename = AGS_BASE_PLUGIN(lv2ui_plugin)->ui_filename;
+	
+	/* instantiate */
+	plugin_widget = NULL;
+	
+	bundle_path = g_strndup(ui_filename,
+				rindex(ui_filename, '/') - ui_filename);
+
+	lv2_bridge->ui_handle = ui_descriptor->instantiate(ui_descriptor,
+							   lv2_bridge->uri,
+							   bundle_path,
+							   ags_lv2_bridge_lv2ui_write_function,
+							   lv2_bridge,
+							   &plugin_widget,
+							   feature);
+
+	if(ui_descriptor->extension_data != NULL){
+	  lv2_bridge->ui_feature[0]->data = ui_descriptor->extension_data(LV2_UI__idleInterface);
+	  lv2_bridge->ui_feature[1]->data = ui_descriptor->extension_data(LV2_UI__showInterface);
+
+	  g_hash_table_insert(ags_lv2_bridge_lv2ui_idle,
+			      lv2_bridge, ags_lv2_bridge_lv2ui_idle_timeout);
+	  g_timeout_add(1000 / 30, (GSourceFunc) ags_lv2_bridge_lv2ui_idle_timeout, (gpointer) lv2_bridge);
+	}	
+      }
+    }
+  }
+
+  if(lv2_bridge->ui_feature != NULL &&
+     lv2_bridge->ui_feature[1]->data != NULL){
+    ((struct _LV2UI_Show_Interface *) lv2_bridge->ui_feature[1]->data)->show(lv2_bridge->ui_handle);
+  }
 }
 
 gboolean
 ags_lv2_bridge_delete_event_callback(GtkWidget *widget, GdkEvent *event, AgsLv2Bridge *lv2_bridge)
 {
-  gtk_widget_hide(lv2_bridge->lv2_gui);
   
   return(TRUE);
 }
@@ -113,3 +235,98 @@ ags_lv2_bridge_lv2ui_write_function(LV2UI_Controller controller, uint32_t port_i
     channel = channel->next;
   }
 }
+
+void
+ags_lv2_bridge_preset_changed_callback(GtkComboBox *combo_box, AgsLv2Bridge *lv2_bridge)
+{
+  GtkContainer *container;
+  
+  AgsLv2Conversion *lv2_conversion;
+  AgsLv2Plugin *lv2_plugin;
+  AgsLv2Preset *lv2_preset;
+    
+  GList *list, *list_start;
+  GList *port_preset;
+  GList *port_descriptor;
+
+  gchar *preset_label;
+  
+  gdouble value;
+  
+  preset_label = gtk_combo_box_text_get_active_text(combo_box);
+
+  /* retrieve lv2 plugin */
+  lv2_plugin = ags_lv2_manager_find_lv2_plugin(ags_lv2_manager_get_instance(),
+					       lv2_bridge->filename,
+					       lv2_bridge->effect);
+  
+  /* preset */
+  lv2_preset = NULL;
+  list = ags_lv2_preset_find_preset_label(lv2_plugin->preset,
+					  preset_label);
+  
+  if(list != NULL){
+    lv2_preset = list->data;
+  }
+
+  /* port preset */
+  if(lv2_preset == NULL){
+    return;
+  }
+
+  container = AGS_EFFECT_BULK(AGS_EFFECT_BRIDGE(AGS_MACHINE(lv2_bridge)->bridge)->bulk_input)->table;
+
+  port_preset = lv2_preset->port_preset;
+  
+  while(port_preset != NULL){
+    port_descriptor = ags_port_descriptor_find_symbol(AGS_BASE_PLUGIN(lv2_plugin)->port,
+						      AGS_LV2_PORT_PRESET(port_preset->data)->port_symbol);
+    value = (gdouble) g_value_get_float(AGS_LV2_PORT_PRESET(port_preset->data)->port_value);
+    
+    list_start = 
+      list = gtk_container_get_children(container);
+    
+    while(list != NULL){
+      if(!g_strcmp0(AGS_BULK_MEMBER(list->data)->specifier,
+		    AGS_PORT_DESCRIPTOR(port_descriptor->data)->port_name)){
+	GtkWidget *child_widget;
+
+	//	AGS_BULK_MEMBER(list->data)->flags |= AGS_BULK_MEMBER_NO_UPDATE;
+
+	child_widget = gtk_bin_get_child((GtkBin *) AGS_BULK_MEMBER(list->data));
+	  
+	lv2_conversion = (AgsLv2Conversion *) AGS_BULK_MEMBER(list->data)->conversion;
+	  
+	if(GTK_IS_TOGGLE_BUTTON(child_widget)){
+	  if(value == 0.0){
+	    gtk_toggle_button_set_active((GtkToggleButton *) child_widget,
+					 FALSE);
+	  }else{
+	    gtk_toggle_button_set_active((GtkToggleButton *) child_widget,
+					 TRUE);
+	  }
+	}else if(AGS_IS_DIAL(child_widget)){
+	    
+	  if(lv2_conversion != NULL){
+	    //	      val = ags_lv2_conversion_convert(lv2_conversion,
+	    //				  value,
+	    //				  TRUE);
+	  }
+	    
+	  gtk_adjustment_set_value(AGS_DIAL(child_widget)->adjustment,
+				   value);
+	  ags_dial_draw((AgsDial *) child_widget);
+	}
+	
+	//	AGS_BULK_MEMBER(list->data)->flags &= (~AGS_BULK_MEMBER_NO_UPDATE);
+	break;
+      }
+
+      list = list->next;
+    }
+
+    g_list_free(list_start);
+    
+    port_preset = port_preset->next;
+  }
+}
diff --git a/ags/X/machine/ags_lv2_bridge_callbacks.h b/ags/X/machine/ags_lv2_bridge_callbacks.h
index 5ef3557..b60f2c4 100644
--- a/ags/X/machine/ags_lv2_bridge_callbacks.h
+++ b/ags/X/machine/ags_lv2_bridge_callbacks.h
@@ -34,4 +34,6 @@ gboolean ags_lv2_bridge_delete_event_callback(GtkWidget *widget, GdkEvent *event
 
 void ags_lv2_bridge_lv2ui_write_function(LV2UI_Controller controller, uint32_t port_index, uint32_t buffer_size, uint32_t port_protocol, const void *buffer);
 
+void ags_lv2_bridge_preset_changed_callback(GtkComboBox *combo_box, AgsLv2Bridge *lv2_bridge);
+
 #endif /*__AGS_LV2_BRIDGE_CALLBACKS_H__*/
diff --git a/ags/X/machine/ags_matrix.c b/ags/X/machine/ags_matrix.c
index 68867f0..f702032 100644
--- a/ags/X/machine/ags_matrix.c
+++ b/ags/X/machine/ags_matrix.c
@@ -20,12 +20,11 @@
 #include <ags/X/machine/ags_matrix.h>
 #include <ags/X/machine/ags_matrix_callbacks.h>
 
-#include <ags/object/ags_application_context.h>
-
-#include <ags/object/ags_connectable.h>
-
 #include <ags/util/ags_id_generator.h>
 
+#include <ags/object/ags_application_context.h>
+#include <ags/object/ags_config.h>
+#include <ags/object/ags_connectable.h>
 #include <ags/object/ags_portlet.h>
 #include <ags/object/ags_plugin.h>
 #include <ags/object/ags_seekable.h>
@@ -75,6 +74,8 @@
 
 #include <ags/X/file/ags_gui_file_xml.h>
 
+#include <ags/X/thread/ags_gui_thread.h>
+
 #include <math.h>
 
 #define AGS_MATRIX_INPUT_LINE_MAPPED_KEY "AGS_MATRIX_INPUT_LINE_MAPPED_KEY"
@@ -252,10 +253,10 @@ ags_matrix_init(AgsMatrix *matrix)
   AGS_MACHINE(matrix)->output_line_type = G_TYPE_NONE;
 
   g_signal_connect_after(G_OBJECT(audio), "set_audio_channels\0",
-			 G_CALLBACK(ags_matrix_set_audio_channels), NULL);
+			 G_CALLBACK(ags_matrix_set_audio_channels), matrix);
 
   g_signal_connect_after(G_OBJECT(audio), "set_pads\0",
-			 G_CALLBACK(ags_matrix_set_pads), NULL);
+			 G_CALLBACK(ags_matrix_set_pads), matrix);
 
   /*  */
   AGS_MACHINE(matrix)->flags |= (AGS_MACHINE_IS_SEQUENCER |
@@ -464,6 +465,7 @@ ags_matrix_set_pads(AgsAudio *audio, GType type,
 		    guint pads, guint pads_old,
 		    gpointer data)
 {
+  AgsWindow *window;
   AgsMachine *machine;
   AgsMatrix *matrix;
 
@@ -471,7 +473,10 @@ ags_matrix_set_pads(AgsAudio *audio, GType type,
   AgsAudioSignal *audio_signal;
 
   AgsMutexManager *mutex_manager;
+  AgsThread *main_loop;
 
+  AgsApplicationContext *application_context;
+  
   guint i, j;
   gboolean grow;
 
@@ -502,25 +507,39 @@ ags_matrix_set_pads(AgsAudio *audio, GType type,
 
   pthread_mutex_unlock(audio_mutex);
 
+  gdk_threads_enter();
+  
   machine = AGS_MACHINE(matrix);
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) machine);
+
+  application_context = window->application_context;
+  
+  /* get main loop */
+  pthread_mutex_lock(application_mutex);
+
+  main_loop = (AgsThread *) application_context->main_loop;
+  
+  pthread_mutex_unlock(application_mutex);
 
   /* set size request if needed */
   if(g_type_is_a(type, AGS_TYPE_INPUT)){
     gtk_adjustment_set_upper(GTK_RANGE(matrix->cell_pattern->vscrollbar)->adjustment,
-			     (double) pads - 1.0);
+			     (double) pads);
 
     
     if(pads < AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
-      gtk_widget_set_size_request((GtkWidget *) matrix->cell_pattern,
-				  -1,
-				  pads * matrix->cell_pattern->cell_height + 1);
+      //      gtk_widget_set_size_request((GtkWidget *) matrix->cell_pattern,
+      //			  -1,
+      //			  pads * matrix->cell_pattern->cell_height + AGS_LED_DEFAULT_HEIGHT + 2);
     }else if(pads_old < AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
-      gtk_widget_set_size_request((GtkWidget *) matrix->cell_pattern,
-				  -1,
-				  AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY * matrix->cell_pattern->cell_height + 1);
+      //      gtk_widget_set_size_request((GtkWidget *) matrix->cell_pattern,
+      //				  -1,
+      //				  AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY * matrix->cell_pattern->cell_height + AGS_LED_DEFAULT_HEIGHT + 2);
     }
   }
 
+  gdk_threads_leave();
+  
   if(pads_old < pads){
     grow = TRUE;
   }else{
@@ -845,34 +864,73 @@ ags_matrix_input_map_recall(AgsMatrix *matrix, guint input_pad_start)
 {
   AgsAudio *audio;
   AgsChannel *source, *current;
+
+  AgsConfig *config;
   
   GList *list;
 
+  gchar *str;
+
+  gboolean performance_mode;
+
   audio = AGS_MACHINE(matrix)->audio;
 
   if(matrix->mapped_input_pad > input_pad_start){
     return;
   }
 
+  config = ags_config_get_instance();
+
   source = ags_channel_nth(audio->input,
 			   input_pad_start * audio->audio_channels);
 
   /* map dependending on output */
-  current = source;
+  str = ags_config_get_value(config,
+			     AGS_CONFIG_GENERIC,
+			     "engine-mode\0");
+  performance_mode = FALSE;
 
-  while(current != NULL){
-    /* ags-buffer */
-    ags_recall_factory_create(audio,
-			      NULL, NULL,
-			      "ags-buffer\0",
-			      0, audio->audio_channels, 
-			      current->pad, current->pad + 1,
-			      (AGS_RECALL_FACTORY_INPUT |
-			       AGS_RECALL_FACTORY_RECALL |
-			       AGS_RECALL_FACTORY_ADD),
-			      0);
-
-    current = current->next_pad;
+  /* remap for input */
+  if(str != NULL &&
+     !g_ascii_strncasecmp(str,
+			  "performance\0",
+			  12)){
+    current = source;
+
+    while(current != NULL){
+      /* ags-copy */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-copy\0",
+				0, audio->audio_channels, 
+				current->pad, current->pad + 1,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      current = current->next_pad;
+    }
+    
+    /* set performance mode */
+    performance_mode = TRUE;
+  }else{    
+    current = source;
+
+    while(current != NULL){
+      /* ags-buffer */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-buffer\0",
+				0, audio->audio_channels, 
+				current->pad, current->pad + 1,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      current = current->next_pad;
+    }
   }
   
   /*  */
@@ -911,7 +969,7 @@ ags_matrix_input_map_recall(AgsMatrix *matrix, guint input_pad_start)
 
     current = current->next_pad;
   }
-
+  
   matrix->mapped_input_pad = audio->input_pads;
 }
 
@@ -921,48 +979,89 @@ ags_matrix_output_map_recall(AgsMatrix *matrix, guint output_pad_start)
   AgsAudio *audio;
   AgsChannel *input, *current;
 
+  AgsConfig *config;
+
+  gchar *str;
+
+  gboolean performance_mode;
+
   audio = AGS_MACHINE(matrix)->audio;
 
   if(matrix->mapped_output_pad > output_pad_start){
     return;
   }
 
-  /* remap for input */
-  input = audio->input;
+  config = ags_config_get_instance();
 
-  while(input != NULL){
-    /* ags-buffer */
-    ags_recall_factory_create(audio,
-			      NULL, NULL,
-			      "ags-buffer\0",
-			      0, audio->audio_channels, 
-			      input->pad, input->pad + 1,
-			      (AGS_RECALL_FACTORY_INPUT |
-			       AGS_RECALL_FACTORY_RECALL |
-			       AGS_RECALL_FACTORY_ADD),
-			      0);
+  /* map dependending on output */
+  str = ags_config_get_value(config,
+			     AGS_CONFIG_GENERIC,
+			     "engine-mode\0");
+  performance_mode = FALSE;
 
-    input = input->next_pad;
+  /* remap for input */
+  if(str != NULL &&
+     !g_ascii_strncasecmp(str,
+			  "performance\0",
+			  12)){
+    input = audio->input;
+
+    while(input != NULL){
+      /* ags-copy */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-copy\0",
+				0, audio->audio_channels, 
+				input->pad, input->pad + 1,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      input = input->next_pad;
+    }
+    
+    /* set performance mode */
+    performance_mode = TRUE;
+  }else{    
+    input = audio->input;
+
+    while(input != NULL){
+      /* ags-buffer */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-buffer\0",
+				0, audio->audio_channels, 
+				input->pad, input->pad + 1,
+				(AGS_RECALL_FACTORY_INPUT |
+				 AGS_RECALL_FACTORY_RECALL |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      input = input->next_pad;
+    }
   }
 
-  current = ags_channel_nth(audio->output,
-			    output_pad_start * audio->audio_channels);
-
-  while(current != NULL){
-    /* ags-stream */
-    ags_recall_factory_create(audio,
-			      NULL, NULL,
-			      "ags-stream\0",
-			      current->audio_channel, current->audio_channel + 1,
-			      current->pad, current->pad + 1,
-			      (AGS_RECALL_FACTORY_OUTPUT |
-			       AGS_RECALL_FACTORY_PLAY |
-			       AGS_RECALL_FACTORY_ADD),
-			      0);
-
-    current = current->next;
+  if(!performance_mode){
+    current = ags_channel_nth(audio->output,
+			      output_pad_start * audio->audio_channels);
+
+    while(current != NULL){
+      /* ags-stream */
+      ags_recall_factory_create(audio,
+				NULL, NULL,
+				"ags-stream\0",
+				current->audio_channel, current->audio_channel + 1,
+				current->pad, current->pad + 1,
+				(AGS_RECALL_FACTORY_OUTPUT |
+				 AGS_RECALL_FACTORY_PLAY |
+				 AGS_RECALL_FACTORY_ADD),
+				0);
+
+      current = current->next;
+    }
   }
-
+  
   matrix->mapped_output_pad = audio->output_pads;
 }
 
diff --git a/ags/X/machine/ags_matrix_callbacks.c b/ags/X/machine/ags_matrix_callbacks.c
index 56e7d5d..2c2234a 100644
--- a/ags/X/machine/ags_matrix_callbacks.c
+++ b/ags/X/machine/ags_matrix_callbacks.c
@@ -21,8 +21,6 @@
 
 #include <ags/object/ags_application_context.h>
 
-#include <ags/widget/ags_led.h>
-
 #include <ags/thread/ags_mutex_manager.h>
 #include <ags/thread/ags_task_thread.h>
 
@@ -94,7 +92,8 @@ ags_matrix_index_callback(GtkWidget *widget, AgsMatrix *matrix)
       gtk_toggle_button_set_active(toggle, FALSE);
 
       matrix->selected = (GtkToggleButton*) widget;
-      gtk_widget_queue_draw((GtkWidget *) matrix->cell_pattern);
+
+      ags_cell_pattern_paint(matrix->cell_pattern);
 
       /*  */
       AGS_MACHINE(matrix)->bank_1 = 
@@ -327,19 +326,11 @@ ags_matrix_done_callback(AgsAudio *audio,
     playback = playback->next;
   }
 
-  if(all_done){
-    GList *list, *list_start;
-    
-    /* unset led */
-    list_start = 
-      list = gtk_container_get_children(GTK_CONTAINER(matrix->cell_pattern->led));
-
-    while(list != NULL){
-      ags_led_unset_active(AGS_LED(list->data));
-	
-      list = list->next;
-    }
+  gdk_threads_enter();  
 
-    g_list_free(list_start);
+  if(all_done){
+    ags_led_array_unset_all(matrix->cell_pattern->hled_array);
   }
+
+  gdk_threads_leave();
 }
diff --git a/ags/X/machine/ags_mixer_input_line.c b/ags/X/machine/ags_mixer_input_line.c
index 341d57d..30bb4ac 100644
--- a/ags/X/machine/ags_mixer_input_line.c
+++ b/ags/X/machine/ags_mixer_input_line.c
@@ -62,7 +62,7 @@ void ags_mixer_input_line_map_recall(AgsLine *line,
 static gpointer ags_mixer_input_line_parent_class = NULL;
 static AgsConnectableInterface *ags_mixer_input_line_parent_connectable_interface;
 
-extern GHashTable *ags_indicator_queue_draw;
+extern GHashTable *ags_line_indicator_queue_draw;
 
 GType
 ags_mixer_input_line_get_type()
@@ -145,7 +145,7 @@ ags_mixer_input_line_init(AgsMixerInputLine *mixer_input_line)
 		   1, 1);
   widget = gtk_bin_get_child(GTK_BIN(line_member));
   AGS_LINE(mixer_input_line)->indicator = widget;
-  g_hash_table_insert(ags_indicator_queue_draw,
+  g_hash_table_insert(ags_line_indicator_queue_draw,
 		      widget, ags_line_indicator_queue_draw_timeout);
   g_timeout_add(1000 / 30, (GSourceFunc) ags_line_indicator_queue_draw_timeout, (gpointer) widget);
 
@@ -260,38 +260,6 @@ ags_mixer_input_line_map_recall(AgsLine *line,
 			     AGS_RECALL_FACTORY_ADD),
 			    0);
 
-  /* play - connect run_post */
-  list = ags_recall_template_find_type(source->play,
-				       AGS_TYPE_PEAK_CHANNEL_RUN);
-
-  if(list != NULL){
-    play_peak_channel_run = AGS_PEAK_CHANNEL_RUN(list->data);
-
-    recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
-
-    recall_handler->signal_name = "run-post\0";
-    recall_handler->callback = G_CALLBACK(ags_line_peak_run_post_callback);
-    recall_handler->data = (gpointer) line;
-
-    ags_recall_add_handler(AGS_RECALL(play_peak_channel_run), recall_handler);
-  }
-
-  /* recall - connect run_post */
-  list = ags_recall_template_find_type(source->recall,
-				       AGS_TYPE_PEAK_CHANNEL_RUN);
-
-  if(list != NULL){
-    recall_peak_channel_run = AGS_PEAK_CHANNEL_RUN(list->data);
-
-    recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
-
-    recall_handler->signal_name = "run-post\0";
-    recall_handler->callback = G_CALLBACK(ags_line_peak_run_post_callback);
-    recall_handler->data = (gpointer) line;
-
-    ags_recall_add_handler(AGS_RECALL(recall_peak_channel_run), recall_handler);
-  }
-
   /* ags-mute */
   ags_recall_factory_create(audio,
 			    NULL, NULL,
diff --git a/ags/X/machine/ags_oscillator.c b/ags/X/machine/ags_oscillator.c
index c66d172..862dfc7 100644
--- a/ags/X/machine/ags_oscillator.c
+++ b/ags/X/machine/ags_oscillator.c
@@ -190,7 +190,7 @@ ags_oscillator_init(AgsOscillator *oscillator)
   gtk_table_attach_defaults(table,
 			    (GtkWidget *) gtk_label_new("frequency\0"),
 			    2, 3, 1, 2);
-  oscillator->frequency = (GtkSpinButton *) gtk_spin_button_new_with_range(0.0, 100000.0, 1.0);
+  oscillator->frequency = (GtkSpinButton *) gtk_spin_button_new_with_range(8.0, 100000.0, 1.0);
   gtk_spin_button_set_digits(oscillator->frequency,
 			     3);
   oscillator->frequency->adjustment->value = 27.5;
diff --git a/ags/X/machine/ags_panel_input_line.c b/ags/X/machine/ags_panel_input_line.c
index c1c351e..d514c2a 100644
--- a/ags/X/machine/ags_panel_input_line.c
+++ b/ags/X/machine/ags_panel_input_line.c
@@ -264,7 +264,7 @@ ags_panel_input_line_show(GtkWidget *line)
 {
   GTK_WIDGET_CLASS(ags_panel_input_line_parent_class)->show(line);
 
-  gtk_widget_hide(GTK_WIDGET(AGS_LINE(line)->group));
+  //  gtk_widget_hide(GTK_WIDGET(AGS_LINE(line)->group));
 }
 
 void
@@ -272,7 +272,7 @@ ags_panel_input_line_show_all(GtkWidget *line)
 {
   GTK_WIDGET_CLASS(ags_panel_input_line_parent_class)->show_all(line);
 
-  gtk_widget_hide(GTK_WIDGET(AGS_LINE(line)->group));
+  //  gtk_widget_hide(GTK_WIDGET(AGS_LINE(line)->group));
 }
 
 void
diff --git a/ags/X/machine/ags_panel_input_line_callbacks.c b/ags/X/machine/ags_panel_input_line_callbacks.c
index f3ce4d8..e6844b0 100644
--- a/ags/X/machine/ags_panel_input_line_callbacks.c
+++ b/ags/X/machine/ags_panel_input_line_callbacks.c
@@ -31,7 +31,7 @@ ags_panel_input_line_notify_data_object_callback(GObject *audio_connection,
   gchar *str;
   
   str = g_strdup_printf("%s:%s[%d]\0",
-			G_OBJECT_TYPE_NAME(AGS_LINE(panel_input_line)->channel->soundcard),
+			G_OBJECT_TYPE_NAME(AGS_CONNECTION(audio_connection)->data_object),
 			ags_soundcard_get_device(AGS_SOUNDCARD(AGS_CONNECTION(audio_connection)->data_object)),
 			AGS_AUDIO_CONNECTION(audio_connection)->mapped_line);
   gtk_label_set_label(panel_input_line->soundcard_connection,
@@ -46,7 +46,7 @@ ags_panel_input_line_notify_mapped_line_callback(GObject *audio_connection,
   gchar *str;
   
   str = g_strdup_printf("%s:%s[%d]\0",
-			G_OBJECT_TYPE_NAME(AGS_LINE(panel_input_line)->channel->soundcard),
+			G_OBJECT_TYPE_NAME(AGS_CONNECTION(audio_connection)->data_object),
 			ags_soundcard_get_device(AGS_SOUNDCARD(AGS_CONNECTION(audio_connection)->data_object)),
 			AGS_AUDIO_CONNECTION(audio_connection)->mapped_line);
   gtk_label_set_label(panel_input_line->soundcard_connection,
diff --git a/ags/X/machine/ags_panel_input_pad.c b/ags/X/machine/ags_panel_input_pad.c
index 11a7cfa..2f3c6f0 100644
--- a/ags/X/machine/ags_panel_input_pad.c
+++ b/ags/X/machine/ags_panel_input_pad.c
@@ -225,9 +225,11 @@ ags_panel_input_pad_show(GtkWidget *pad)
 {
   GTK_WIDGET_CLASS(ags_panel_input_pad_parent_class)->show(pad);
 
+  /*
   gtk_widget_hide(GTK_WIDGET(AGS_PAD(pad)->group));
   gtk_widget_hide(GTK_WIDGET(AGS_PAD(pad)->mute));
   gtk_widget_hide(GTK_WIDGET(AGS_PAD(pad)->solo));
+  */
 }
 
 void
diff --git a/ags/X/machine/ags_pattern_box.c b/ags/X/machine/ags_pattern_box.c
index 160ac0f..5d6a41d 100644
--- a/ags/X/machine/ags_pattern_box.c
+++ b/ags/X/machine/ags_pattern_box.c
@@ -36,8 +36,6 @@
 
 #include <ags/audio/thread/ags_audio_loop.h>
 
-#include <ags/widget/ags_led.h>
-
 #include <ags/X/ags_window.h>
 #include <ags/X/ags_machine.h>
 #include <ags/X/ags_pad.h>
@@ -240,15 +238,22 @@ ags_pattern_box_init(AgsPatternBox *pattern_box)
   
   /* led */
   pattern_box->active_led = 0;
-
-  pattern_box->led = (GtkHBox *) gtk_hbox_new(FALSE, 16);
+  pattern_box->hled_array = (GtkHBox *) ags_hled_array_new();
+  g_object_set(pattern_box->hled_array,
+	       "led-width\0", AGS_PATTERN_BOX_LED_DEFAULT_WIDTH,
+	       "led-height\0", AGS_PATTERN_BOX_LED_DEFAULT_HEIGHT,
+	       "led-count\0", pattern_box->n_controls,
+	       NULL);
+  gtk_widget_set_size_request((GtkWidget *) pattern_box->hled_array,
+			      pattern_box->n_controls * AGS_PATTERN_BOX_DEFAULT_PAD_WIDTH, 10);
   gtk_table_attach((GtkTable *) pattern_box,
-		   (GtkWidget *) pattern_box->led,
+		   (GtkWidget *) pattern_box->hled_array,
 		   0, 1,
 		   0, 1,
 		   0, 0,
 		   0, 0);
-
+  gtk_widget_show_all(pattern_box->hled_array);
+  
   if(ags_pattern_box_led_queue_draw == NULL){
     ags_pattern_box_led_queue_draw = g_hash_table_new_full(g_direct_hash, g_direct_equal,
 							   NULL,
@@ -259,16 +264,6 @@ ags_pattern_box_init(AgsPatternBox *pattern_box)
 		      pattern_box, ags_pattern_box_led_queue_draw_timeout);
   g_timeout_add(1000 / 30, (GSourceFunc) ags_pattern_box_led_queue_draw_timeout, (gpointer) pattern_box);
 
-  for(i = 0; i < pattern_box->n_controls; i++){
-    led = (AgsLed *) ags_led_new();
-    gtk_widget_set_size_request((GtkWidget *) led,
-				AGS_PATTERN_BOX_LED_DEFAULT_WIDTH, AGS_PATTERN_BOX_LED_DEFAULT_HEIGHT);
-    gtk_box_pack_start((GtkBox *) pattern_box->led,
-		       (GtkWidget *) led,
-		       FALSE, FALSE,
-		       0);
-  }
-
   /* pattern */
   pattern_box->pattern = (GtkHBox *) gtk_hbox_new(FALSE, 0);
   gtk_table_attach((GtkTable *) pattern_box,
@@ -684,19 +679,30 @@ ags_pattern_box_set_pattern(AgsPatternBox *pattern_box)
 {
   AgsMachine *machine;
   AgsLine *selected_line;
+
+  AgsMutexManager *mutex_manager;
+
   GList *list, *list_start;
   GList *line, *line_start;
+
   guint index0, index1, offset;
+  gboolean is_active;
   gboolean set_active;
   guint i;
 
+  pthread_mutex_t *application_mutex;
+  pthread_mutex_t *channel_mutex;
+
   machine = (AgsMachine *) gtk_widget_get_ancestor((GtkWidget *) pattern_box,
 						   AGS_TYPE_MACHINE);
 
   if(machine->selected_input_pad == NULL){
     return;
   }
-    
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+  
   index0 = machine->bank_0;
   index1 = machine->bank_1;
 
@@ -725,7 +731,22 @@ ags_pattern_box_set_pattern(AgsPatternBox *pattern_box)
     while((line = ags_line_find_next_grouped(line)) != NULL){
       selected_line = AGS_LINE(line->data);
 
-      if(!ags_pattern_get_bit((AgsPattern *) selected_line->channel->pattern->data, index0, index1, offset + i)){
+      /* get channel mutex */
+      pthread_mutex_lock(application_mutex);
+      
+      channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+					       (GObject *) selected_line->channel);
+      
+      pthread_mutex_unlock(application_mutex);
+
+      /*  */
+      pthread_mutex_lock(channel_mutex);
+
+      is_active = ags_pattern_get_bit((AgsPattern *) selected_line->channel->pattern->data, index0, index1, offset + i);
+      
+      pthread_mutex_unlock(channel_mutex);
+      
+      if(!is_active){	
 	set_active = FALSE;
 	break;
       }
@@ -770,9 +791,8 @@ ags_pattern_box_led_queue_draw_timeout(AgsPatternBox *pattern_box)
 
     AgsMutexManager *mutex_manager;
 
-    GList *list, *active;
+    GList *list_start, *list;
     guint active_led_new;
-    guint i;
 
     pthread_mutex_t *application_mutex;
     pthread_mutex_t *audio_mutex;
@@ -806,82 +826,58 @@ ags_pattern_box_led_queue_draw_timeout(AgsPatternBox *pattern_box)
     recall_id = ags_recall_id_find_parent_recycling_context(audio->recall_id,
 							    NULL);
 
-    if(recall_id == NULL){
-      pthread_mutex_unlock(audio_mutex);
-      
+    pthread_mutex_unlock(audio_mutex);
+    
+    if(recall_id == NULL){      
       gdk_threads_leave();
       
       return(TRUE);
     }
 
+    g_object_get(audio,
+		 "play\0", &list_start,
+		 NULL);
+
     play_count_beats_audio = NULL;
     play_count_beats_audio_run = NULL;
     
-    list = ags_recall_find_type(audio->play,
+    pthread_mutex_lock(audio->play_mutex);
+
+    list = ags_recall_find_type(list_start,
 				AGS_TYPE_COUNT_BEATS_AUDIO);
     
     if(list != NULL){
       play_count_beats_audio = AGS_COUNT_BEATS_AUDIO(list->data);
     }
     
-    list = ags_recall_find_type_with_recycling_context(audio->play,
+    list = ags_recall_find_type_with_recycling_context(list_start,
 						       AGS_TYPE_COUNT_BEATS_AUDIO_RUN,
 						       (GObject *) recall_id->recycling_context);
     
     if(list != NULL){
       play_count_beats_audio_run = AGS_COUNT_BEATS_AUDIO_RUN(list->data);
     }
-    
+
+    pthread_mutex_unlock(audio->play_mutex);
+
+    g_list_free(list_start);  
+
     if(play_count_beats_audio == NULL ||
-       play_count_beats_audio_run == NULL){
-      pthread_mutex_unlock(audio_mutex);
-      
+       play_count_beats_audio_run == NULL){      
       gdk_threads_leave();
       
       return(TRUE);
     }
 
     /* active led */
-    active_led_new = (guint) play_count_beats_audio_run->sequencer_counter;
-    pattern_box->active_led = (guint) active_led_new;
-      
-    pthread_mutex_unlock(audio_mutex);
-    
-    /* offset */
-    list = gtk_container_get_children((GtkContainer *) pattern_box->offset);
-    
-    for(i = 0; list != NULL; i++){
-      if(gtk_toggle_button_get_active(list->data)){
-	break;
-      }
-
-      list = list->next;
-    }
-
-    g_list_free(list);
-
-    /* led */
-    list = gtk_container_get_children((GtkContainer *) pattern_box->led);
-    active = NULL;
-    
-    for(i = 0; list != NULL; i++){
-      if(i == active_led_new){
-	active = list;
-	list = list->next;
-	
-	continue;
-      }
+    active_led_new = (guint) play_count_beats_audio_run->sequencer_counter;      
 
-      ags_led_unset_active(AGS_LED(list->data));
-      
-      list = list->next;
-    }
+    pattern_box->active_led = (guint) active_led_new;
 
-    if(active != NULL){
-      ags_led_set_active(AGS_LED(active->data));
-    }
-    
-    g_list_free(list);
+    pattern_box->active_led = (guint) active_led_new;
+    ags_led_array_unset_all(pattern_box->hled_array);
+    ags_led_array_set_nth(pattern_box->hled_array,
+			  active_led_new);
         
     gdk_threads_leave();
     
diff --git a/ags/X/machine/ags_pattern_box.h b/ags/X/machine/ags_pattern_box.h
index 002358e..831fbdd 100644
--- a/ags/X/machine/ags_pattern_box.h
+++ b/ags/X/machine/ags_pattern_box.h
@@ -24,6 +24,8 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
+#include <ags/widget/ags_hled_array.h>
+
 #define AGS_TYPE_PATTERN_BOX                (ags_pattern_box_get_type())
 #define AGS_PATTERN_BOX(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_PATTERN_BOX, AgsPatternBox))
 #define AGS_PATTERN_BOX_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_PATTERN_BOX, AgsPatternBoxClass))
@@ -34,8 +36,8 @@
 #define AGS_PATTERN_BOX_DEFAULT_PAD_WIDTH   (24)
 #define AGS_PATTERN_BOX_DEFAULT_PAD_HEIGHT  (24)
 
-#define AGS_PATTERN_BOX_LED_DEFAULT_WIDTH (8)
-#define AGS_PATTERN_BOX_LED_DEFAULT_HEIGHT (4)
+#define AGS_PATTERN_BOX_LED_DEFAULT_WIDTH (10)
+#define AGS_PATTERN_BOX_LED_DEFAULT_HEIGHT (10)
 
 #define AGS_PATTERN_BOX_N_CONTROLS (16)
 #define AGS_PATTERN_BOX_N_INDICES (4)
@@ -77,8 +79,7 @@ struct _AgsPatternBox
   guint cursor_y;
   
   guint active_led;
-  
-  GtkHBox *led;
+  AgsHLedArray *hled_array;
 
   GtkHBox *pattern;
 
diff --git a/ags/X/machine/ags_pattern_box_callbacks.c b/ags/X/machine/ags_pattern_box_callbacks.c
index f9b5fbc..e9b8d45 100644
--- a/ags/X/machine/ags_pattern_box_callbacks.c
+++ b/ags/X/machine/ags_pattern_box_callbacks.c
@@ -36,7 +36,6 @@
 
 #include <gdk/gdkkeysyms.h>
 
-void ags_pattern_box_init_channel_launch_callback(AgsTask *task, AgsPatternBox *pattern_box);
 void ags_pattern_box_refresh_gui_callback(AgsTogglePatternBit *toggle_pattern_bit,
 					  AgsPatternBox *pattern_box);
 
diff --git a/ags/X/machine/ags_synth.c b/ags/X/machine/ags_synth.c
index 5296e62..ed60bdb 100644
--- a/ags/X/machine/ags_synth.c
+++ b/ags/X/machine/ags_synth.c
@@ -69,6 +69,8 @@
 
 #include <ags/X/ags_window.h>
 
+#include <ags/X/thread/ags_gui_thread.h>
+
 #include <math.h>
 
 void ags_synth_class_init(AgsSynthClass *synth);
@@ -607,7 +609,9 @@ ags_synth_update(AgsSynth *synth)
   pthread_mutex_t *audio_mutex;
   pthread_mutex_t *channel_mutex;
   pthread_mutex_t *application_mutex;
-    
+
+  gdk_threads_enter();
+  
   window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) synth);
   application_context = (AgsApplicationContext *) window->application_context;
 
@@ -634,7 +638,7 @@ ags_synth_update(AgsSynth *synth)
 					 (GObject *) audio);
   
   pthread_mutex_unlock(application_mutex);
-  
+
   /*  */
   start_frequency = (gdouble) gtk_spin_button_get_value_as_float(synth->lower);
 
@@ -731,6 +735,8 @@ ags_synth_update(AgsSynth *synth)
   }
   
   g_list_free(input_pad_start);
+
+  gdk_threads_leave();
 }
 
 /**
diff --git a/ags/X/machine/ags_synth_input_line.c b/ags/X/machine/ags_synth_input_line.c
index d80ad56..87de95d 100644
--- a/ags/X/machine/ags_synth_input_line.c
+++ b/ags/X/machine/ags_synth_input_line.c
@@ -195,14 +195,24 @@ ags_synth_input_line_connect(AgsConnectable *connectable)
   }
 
   ags_synth_input_line_parent_connectable_interface->connect(connectable);
+
+  ags_connectable_connect(AGS_CONNECTABLE(synth_input_line->oscillator));
 }
 
 void
 ags_synth_input_line_disconnect(AgsConnectable *connectable)
 {
+  AgsSynthInputLine *synth_input_line;
+
+  synth_input_line = AGS_SYNTH_INPUT_LINE(connectable);
+
+  if((AGS_LINE_CONNECTED & (AGS_LINE(synth_input_line)->flags)) == 0){
+    return;
+  }
+
   ags_synth_input_line_parent_connectable_interface->disconnect(connectable);
 
-  /* empty */
+  ags_connectable_disconnect(AGS_CONNECTABLE(synth_input_line->oscillator));
 }
 
 void
diff --git a/ags/X/task/ags_add_bulk_member.c b/ags/X/task/ags_add_bulk_member.c
index d2311bc..5cb5265 100644
--- a/ags/X/task/ags_add_bulk_member.c
+++ b/ags/X/task/ags_add_bulk_member.c
@@ -19,15 +19,21 @@
 
 #include <ags/X/task/ags_add_bulk_member.h>
 
+#include <ags/object/ags_application_context.h>
 #include <ags/object/ags_connectable.h>
 
+#include <ags/thread/ags_mutex_manager.h>
+
 #include <ags/audio/ags_audio.h>
 #include <ags/audio/ags_channel.h>
 
+#include <ags/X/ags_window.h>
 #include <ags/X/ags_effect_bridge.h>
 #include <ags/X/ags_effect_bulk.h>
 #include <ags/X/ags_bulk_member.h>
 
+#include <ags/X/thread/ags_gui_thread.h>
+
 void ags_add_bulk_member_class_init(AgsAddBulkMemberClass *add_bulk_member);
 void ags_add_bulk_member_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_add_bulk_member_init(AgsAddBulkMember *add_bulk_member);
@@ -153,15 +159,49 @@ ags_add_bulk_member_finalize(GObject *gobject)
 void
 ags_add_bulk_member_launch(AgsTask *task)
 {
+  AgsWindow *window;
+
   AgsEffectBridge *effect_bridge;
   AgsAddBulkMember *add_bulk_member;
 
+  AgsGuiThread *gui_thread;
+
+  AgsMutexManager *mutex_manager;
+  AgsThread *main_loop;
+
+  AgsApplicationContext *application_context;
+
   AgsChannel *channel;
 
   gboolean found_ports;
   
+  pthread_mutex_t *application_mutex;
+    
   add_bulk_member = AGS_ADD_BULK_MEMBER(task);
 
+  /* lock gdk threads */
+  gdk_threads_enter();
+
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) add_bulk_member->effect_bulk);
+
+  application_context = (AgsApplicationContext *) window->application_context;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* get audio loop */
+  pthread_mutex_lock(application_mutex);
+
+  main_loop = (AgsThread *) application_context->main_loop;
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* get task thread */
+  gui_thread = (AgsGuiThread *) ags_thread_find_type((AgsThread *) main_loop,
+						      AGS_TYPE_GUI_THREAD);
+  /*  */
+  gdk_threads_enter();
+
   gtk_table_attach(AGS_EFFECT_BULK(add_bulk_member->effect_bulk)->table,
 		   (GtkWidget *) add_bulk_member->bulk_member,
 		   add_bulk_member->x, add_bulk_member->x + add_bulk_member->width,
@@ -173,6 +213,11 @@ ags_add_bulk_member_launch(AgsTask *task)
 
   /* find ports */
   ags_bulk_member_find_port(add_bulk_member->bulk_member);
+
+  gdk_threads_leave();
+
+  /* unlock gdk threads */
+  gdk_threads_leave();
 }
 
 /**
diff --git a/ags/X/task/ags_add_sequencer_editor_jack.c b/ags/X/task/ags_add_sequencer_editor_jack.c
index e2ff3c0..deab877 100644
--- a/ags/X/task/ags_add_sequencer_editor_jack.c
+++ b/ags/X/task/ags_add_sequencer_editor_jack.c
@@ -19,14 +19,20 @@
 
 #include <ags/X/task/ags_add_sequencer_editor_jack.h>
 
+#include <ags/object/ags_application_context.h>
 #include <ags/object/ags_connectable.h>
 
+#include <ags/thread/ags_mutex_manager.h>
+
 #include <ags/audio/ags_audio.h>
 #include <ags/audio/ags_channel.h>
 
+#include <ags/X/ags_window.h>
 #include <ags/X/ags_effect_bridge.h>
 #include <ags/X/ags_effect_bulk.h>
 
+#include <ags/X/thread/ags_gui_thread.h>
+
 void ags_add_sequencer_editor_jack_class_init(AgsAddSequencerEditorJackClass *add_sequencer_editor_jack);
 void ags_add_sequencer_editor_jack_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_add_sequencer_editor_jack_init(AgsAddSequencerEditorJack *add_sequencer_editor_jack);
@@ -147,8 +153,47 @@ ags_add_sequencer_editor_jack_finalize(GObject *gobject)
 void
 ags_add_sequencer_editor_jack_launch(AgsTask *task)
 {
+  AgsWindow *window;
+
+  AgsGuiThread *gui_thread;
+
+  AgsMutexManager *mutex_manager;
+  AgsThread *main_loop;
+
+  AgsApplicationContext *application_context;
+  
+  pthread_mutex_t *application_mutex;
+  
+  /* lock gdk threads */
+  gdk_threads_enter();
+
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) AGS_ADD_SEQUENCER_EDITOR_JACK(task)->sequencer_editor);
+
+  application_context = (AgsApplicationContext *) window->application_context;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* get audio loop */
+  pthread_mutex_lock(application_mutex);
+
+  main_loop = (AgsThread *) application_context->main_loop;
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* get task thread */
+  gui_thread = (AgsGuiThread *) ags_thread_find_type((AgsThread *) main_loop,
+						      AGS_TYPE_GUI_THREAD);
+  /*  */
+  gdk_threads_enter();
+
   ags_sequencer_editor_add_jack(AGS_ADD_SEQUENCER_EDITOR_JACK(task)->sequencer_editor,
 				NULL);
+
+  gdk_threads_leave();
+
+  /* unlock gdk threads */
+  gdk_threads_leave();
 }
 
 /**
diff --git a/ags/X/task/ags_add_soundcard_editor_jack.c b/ags/X/task/ags_add_soundcard_editor_jack.c
index 939f012..22f881c 100644
--- a/ags/X/task/ags_add_soundcard_editor_jack.c
+++ b/ags/X/task/ags_add_soundcard_editor_jack.c
@@ -19,14 +19,20 @@
 
 #include <ags/X/task/ags_add_soundcard_editor_jack.h>
 
+#include <ags/object/ags_application_context.h>
 #include <ags/object/ags_connectable.h>
 
+#include <ags/thread/ags_mutex_manager.h>
+
 #include <ags/audio/ags_audio.h>
 #include <ags/audio/ags_channel.h>
 
+#include <ags/X/ags_window.h>
 #include <ags/X/ags_effect_bridge.h>
 #include <ags/X/ags_effect_bulk.h>
 
+#include <ags/X/thread/ags_gui_thread.h>
+
 void ags_add_soundcard_editor_jack_class_init(AgsAddSoundcardEditorJackClass *add_soundcard_editor_jack);
 void ags_add_soundcard_editor_jack_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_add_soundcard_editor_jack_init(AgsAddSoundcardEditorJack *add_soundcard_editor_jack);
@@ -147,8 +153,47 @@ ags_add_soundcard_editor_jack_finalize(GObject *gobject)
 void
 ags_add_soundcard_editor_jack_launch(AgsTask *task)
 {
+  AgsWindow *window;
+
+  AgsGuiThread *gui_thread;
+
+  AgsMutexManager *mutex_manager;
+  AgsThread *main_loop;
+
+  AgsApplicationContext *application_context;
+  
+  pthread_mutex_t *application_mutex;
+  
+  /* lock gdk threads */
+  gdk_threads_enter();
+
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) AGS_ADD_SOUNDCARD_EDITOR_JACK(task)->soundcard_editor);
+
+  application_context = (AgsApplicationContext *) window->application_context;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* get audio loop */
+  pthread_mutex_lock(application_mutex);
+
+  main_loop = (AgsThread *) application_context->main_loop;
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* get task thread */
+  gui_thread = (AgsGuiThread *) ags_thread_find_type((AgsThread *) main_loop,
+						      AGS_TYPE_GUI_THREAD);
+  /*  */
+  gdk_threads_enter();
+
   ags_soundcard_editor_add_jack(AGS_ADD_SOUNDCARD_EDITOR_JACK(task)->soundcard_editor,
 				NULL);
+
+  gdk_threads_leave();
+
+  /* unlock gdk threads */
+  gdk_threads_leave();
 }
 
 /**
diff --git a/ags/X/task/ags_remove_sequencer_editor_jack.c b/ags/X/task/ags_remove_sequencer_editor_jack.c
index ccfeae6..c2486f0 100644
--- a/ags/X/task/ags_remove_sequencer_editor_jack.c
+++ b/ags/X/task/ags_remove_sequencer_editor_jack.c
@@ -19,14 +19,20 @@
 
 #include <ags/X/task/ags_remove_sequencer_editor_jack.h>
 
+#include <ags/object/ags_application_context.h>
 #include <ags/object/ags_connectable.h>
 
+#include <ags/thread/ags_mutex_manager.h>
+
 #include <ags/audio/ags_audio.h>
 #include <ags/audio/ags_channel.h>
 
+#include <ags/X/ags_window.h>
 #include <ags/X/ags_effect_bridge.h>
 #include <ags/X/ags_effect_bulk.h>
 
+#include <ags/X/thread/ags_gui_thread.h>
+
 void ags_remove_sequencer_editor_jack_class_init(AgsRemoveSequencerEditorJackClass *remove_sequencer_editor_jack);
 void ags_remove_sequencer_editor_jack_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_remove_sequencer_editor_jack_init(AgsRemoveSequencerEditorJack *remove_sequencer_editor_jack);
@@ -148,8 +154,47 @@ ags_remove_sequencer_editor_jack_finalize(GObject *gobject)
 void
 ags_remove_sequencer_editor_jack_launch(AgsTask *task)
 {
+  AgsWindow *window;
+
+  AgsGuiThread *gui_thread;
+
+  AgsMutexManager *mutex_manager;
+  AgsThread *main_loop;
+
+  AgsApplicationContext *application_context;
+  
+  pthread_mutex_t *application_mutex;
+  
+  /* lock gdk threads */
+  gdk_threads_enter();
+
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) AGS_REMOVE_SEQUENCER_EDITOR_JACK(task)->sequencer_editor);
+
+  application_context = (AgsApplicationContext *) window->application_context;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* get audio loop */
+  pthread_mutex_lock(application_mutex);
+
+  main_loop = (AgsThread *) application_context->main_loop;
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* get task thread */
+  gui_thread = (AgsGuiThread *) ags_thread_find_type((AgsThread *) main_loop,
+						      AGS_TYPE_GUI_THREAD);
+  /*  */
+  gdk_threads_enter();
+
   ags_sequencer_editor_remove_jack(AGS_REMOVE_SEQUENCER_EDITOR_JACK(task)->sequencer_editor,
 				   AGS_REMOVE_SEQUENCER_EDITOR_JACK(task)->card);
+
+  gdk_threads_leave();
+
+  /* unlock gdk threads */
+  gdk_threads_leave();
 }
 
 /**
diff --git a/ags/X/task/ags_remove_soundcard_editor_jack.c b/ags/X/task/ags_remove_soundcard_editor_jack.c
index 3296bc3..a2fe458 100644
--- a/ags/X/task/ags_remove_soundcard_editor_jack.c
+++ b/ags/X/task/ags_remove_soundcard_editor_jack.c
@@ -19,14 +19,20 @@
 
 #include <ags/X/task/ags_remove_soundcard_editor_jack.h>
 
+#include <ags/object/ags_application_context.h>
 #include <ags/object/ags_connectable.h>
 
+#include <ags/thread/ags_mutex_manager.h>
+
 #include <ags/audio/ags_audio.h>
 #include <ags/audio/ags_channel.h>
 
+#include <ags/X/ags_window.h>
 #include <ags/X/ags_effect_bridge.h>
 #include <ags/X/ags_effect_bulk.h>
 
+#include <ags/X/thread/ags_gui_thread.h>
+
 void ags_remove_soundcard_editor_jack_class_init(AgsRemoveSoundcardEditorJackClass *remove_soundcard_editor_jack);
 void ags_remove_soundcard_editor_jack_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_remove_soundcard_editor_jack_init(AgsRemoveSoundcardEditorJack *remove_soundcard_editor_jack);
@@ -148,8 +154,47 @@ ags_remove_soundcard_editor_jack_finalize(GObject *gobject)
 void
 ags_remove_soundcard_editor_jack_launch(AgsTask *task)
 {
+  AgsWindow *window;
+
+  AgsGuiThread *gui_thread;
+
+  AgsMutexManager *mutex_manager;
+  AgsThread *main_loop;
+
+  AgsApplicationContext *application_context;
+  
+  pthread_mutex_t *application_mutex;
+  
+  /* lock gdk threads */
+  gdk_threads_enter();
+
+  window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) AGS_REMOVE_SOUNDCARD_EDITOR_JACK(task)->soundcard_editor);
+
+  application_context = (AgsApplicationContext *) window->application_context;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* get audio loop */
+  pthread_mutex_lock(application_mutex);
+
+  main_loop = (AgsThread *) application_context->main_loop;
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* get task thread */
+  gui_thread = (AgsGuiThread *) ags_thread_find_type((AgsThread *) main_loop,
+						      AGS_TYPE_GUI_THREAD);
+  /*  */
+  gdk_threads_enter();
+
   ags_soundcard_editor_remove_jack(AGS_REMOVE_SOUNDCARD_EDITOR_JACK(task)->soundcard_editor,
 				   AGS_REMOVE_SOUNDCARD_EDITOR_JACK(task)->card);
+
+  gdk_threads_leave();
+
+  /* unlock gdk threads */
+  gdk_threads_leave();
 }
 
 /**
diff --git a/ags/X/task/ags_scroll_on_play.c b/ags/X/task/ags_scroll_on_play.c
index 822eefd..8addee0 100644
--- a/ags/X/task/ags_scroll_on_play.c
+++ b/ags/X/task/ags_scroll_on_play.c
@@ -33,8 +33,10 @@
 #include <ags/X/ags_window.h>
 #include <ags/X/ags_machine.h>
 #include <ags/X/ags_editor.h>
+#include <ags/X/ags_automation_editor.h>
 #include <ags/X/editor/ags_pattern_edit.h>
 #include <ags/X/editor/ags_note_edit.h>
+#include <ags/X/editor/ags_automation_edit.h>
 
 #include <fontconfig/fontconfig.h>
 
@@ -162,6 +164,7 @@ ags_scroll_on_play_launch(AgsTask *task)
 {
   AgsMachine *machine;
   AgsEditor *editor;
+  AgsAutomationEditor *automation_editor;
   
   AgsCountBeatsAudioRun *count_beats_audio_run;
   
@@ -177,14 +180,34 @@ ags_scroll_on_play_launch(AgsTask *task)
   scroll_on_play = AGS_SCROLL_ON_PLAY(task);
 
   gdk_threads_enter();
-  
-  editor = AGS_EDITOR(scroll_on_play->editor);
 
-  editor_child = editor->editor_child;
+  if(AGS_IS_EDITOR(scroll_on_play->editor)){
+    editor = AGS_EDITOR(scroll_on_play->editor);
+    automation_editor = NULL;
+  }else if(AGS_IS_AUTOMATION_EDITOR(scroll_on_play->editor)){
+    editor = NULL;
+    automation_editor = AGS_AUTOMATION_EDITOR(scroll_on_play->editor);
 
-  while(editor_child != NULL){    
-    machine = AGS_EDITOR_CHILD(editor_child->data)->machine;
+    //TODO:JK: implement me
+
+    return;
+  }else{
+    return;
+  }
 
+  if(editor != NULL){
+    editor_child = editor->editor_child;
+  }else{
+    editor_child = automation_editor->automation_editor_child;
+  }
+  
+  while(editor_child != NULL){    
+    if(editor != NULL){
+      machine = AGS_EDITOR_CHILD(editor_child->data)->machine;
+    }else{
+      machine = AGS_AUTOMATION_EDITOR_CHILD(editor_child->data)->machine;
+    }
+    
     if(machine == NULL){
       editor_child = editor_child->next;
       
@@ -209,168 +232,170 @@ ags_scroll_on_play_launch(AgsTask *task)
     }
 
     count_beats_audio_run = AGS_COUNT_BEATS_AUDIO_RUN(recall->data);
-    
-    if(AGS_IS_NOTE_EDIT(AGS_EDITOR_CHILD(editor_child->data)->edit_widget)){
-      AgsNoteEdit *note_edit;
 
-      note_edit = AGS_NOTE_EDIT(AGS_EDITOR_CHILD(editor_child->data)->edit_widget);
+    if(editor != NULL){
+      if(AGS_IS_NOTE_EDIT(AGS_EDITOR_CHILD(editor_child->data)->edit_widget)){
+	AgsNoteEdit *note_edit;
 
-      control_width = note_edit->control_unit.control_width;
+	note_edit = AGS_NOTE_EDIT(AGS_EDITOR_CHILD(editor_child->data)->edit_widget);
+
+	control_width = note_edit->control_unit.control_width;
       
-      position = count_beats_audio_run->notation_counter * note_edit->control_unit.control_width;
+	position = count_beats_audio_run->notation_counter * note_edit->control_unit.control_width;
 
-      /* scroll */
-      note_edit->flags |= AGS_NOTE_EDIT_RESETING_HORIZONTALLY;
+	/* scroll */
+	note_edit->flags |= AGS_NOTE_EDIT_RESETING_HORIZONTALLY;
 
-      if(position - control_width > 0){
-	value = (position - control_width);
-      }else{
-	value = 0.0;
-      }
+	if(position - control_width > 0){
+	  value = (position - control_width);
+	}else{
+	  value = 0.0;
+	}
 
-      if(position - control_width > 0){
-	gtk_range_set_value(GTK_RANGE(note_edit->hscrollbar),
-			    value);
-	gtk_adjustment_set_value(note_edit->ruler->adjustment,
-				 (value) /
-				 note_edit->control_current.control_width);
-	gtk_widget_queue_draw((GtkWidget *) note_edit->ruler);
-      }
+	if(position - control_width > 0){
+	  gtk_range_set_value(GTK_RANGE(note_edit->hscrollbar),
+			      value);
+	  gtk_adjustment_set_value(note_edit->ruler->adjustment,
+				   (value) /
+				   note_edit->control_current.control_width);
+	  gtk_widget_queue_draw((GtkWidget *) note_edit->ruler);
+	}
       
-      /*  */
-      if(position - control_width > 0){
-	note_edit->control_current.x0 = ((guint) round((double) value)) % note_edit->control_current.control_width;
+	/*  */
+	if(position - control_width > 0){
+	  note_edit->control_current.x0 = ((guint) round((double) value)) % note_edit->control_current.control_width;
 
-	if(note_edit->control_current.x0 != 0){
-	  note_edit->control_current.x0 = note_edit->control_current.control_width - note_edit->control_current.x0;
-	}
+	  if(note_edit->control_current.x0 != 0){
+	    note_edit->control_current.x0 = note_edit->control_current.control_width - note_edit->control_current.x0;
+	  }
 	
-	note_edit->control_current.x1 = (note_edit->width - note_edit->control_current.x0) % note_edit->control_current.control_width;
+	  note_edit->control_current.x1 = (note_edit->width - note_edit->control_current.x0) % note_edit->control_current.control_width;
 
-	note_edit->control_current.nth_x = (guint) ceil((double)(value) / (double)(note_edit->control_current.control_width));
+	  note_edit->control_current.nth_x = (guint) ceil((double)(value) / (double)(note_edit->control_current.control_width));
 
-	note_edit->control_unit.x0 = ((guint)round((double) value)) % note_edit->control_unit.control_width;
+	  note_edit->control_unit.x0 = ((guint)round((double) value)) % note_edit->control_unit.control_width;
 
-	if(note_edit->control_unit.x0 != 0){
-	  note_edit->control_unit.x0 = note_edit->control_unit.control_width - note_edit->control_unit.x0;
-	}
+	  if(note_edit->control_unit.x0 != 0){
+	    note_edit->control_unit.x0 = note_edit->control_unit.control_width - note_edit->control_unit.x0;
+	  }
       
-	note_edit->control_unit.x1 = (note_edit->width - note_edit->control_unit.x0) % note_edit->control_unit.control_width;
+	  note_edit->control_unit.x1 = (note_edit->width - note_edit->control_unit.x0) % note_edit->control_unit.control_width;
       
-	note_edit->control_unit.nth_x = (guint) ceil(round((double) value) / (double) (note_edit->control_unit.control_width));
-	note_edit->control_unit.stop_x = note_edit->control_unit.nth_x + (note_edit->width - note_edit->control_unit.x0 - note_edit->control_unit.x1) / note_edit->control_unit.control_width;
-      }
+	  note_edit->control_unit.nth_x = (guint) ceil(round((double) value) / (double) (note_edit->control_unit.control_width));
+	  note_edit->control_unit.stop_x = note_edit->control_unit.nth_x + (note_edit->width - note_edit->control_unit.x0 - note_edit->control_unit.x1) / note_edit->control_unit.control_width;
+	}
       
-      note_edit->flags &= (~AGS_NOTE_EDIT_RESETING_HORIZONTALLY);
+	note_edit->flags &= (~AGS_NOTE_EDIT_RESETING_HORIZONTALLY);
 
-      /*  */
-      if(GTK_WIDGET_VISIBLE(AGS_EDITOR_CHILD(editor_child->data)->edit_widget)){
-	cr = gdk_cairo_create(GTK_WIDGET(note_edit->drawing_area)->window);
+	/*  */
+	if(GTK_WIDGET_VISIBLE(AGS_EDITOR_CHILD(editor_child->data)->edit_widget)){
+	  cr = gdk_cairo_create(GTK_WIDGET(note_edit->drawing_area)->window);
 
-	cairo_surface_flush(cairo_get_target(cr));
-	cairo_push_group(cr);
+	  cairo_surface_flush(cairo_get_target(cr));
+	  cairo_push_group(cr);
 
-	ags_note_edit_draw_segment(note_edit, cr);
-	ags_note_edit_draw_notation(note_edit, cr);
+	  ags_note_edit_draw_segment(note_edit, cr);
+	  ags_note_edit_draw_notation(note_edit, cr);
 
-	cairo_pop_group_to_source(cr);
-	cairo_paint(cr);
+	  cairo_pop_group_to_source(cr);
+	  cairo_paint(cr);
 
-	/* draw fader */
-	cairo_push_group(cr);
+	  /* draw fader */
+	  cairo_push_group(cr);
 
-	cr = gdk_cairo_create(GTK_WIDGET(note_edit->drawing_area)->window);
-	ags_note_edit_draw_scroll(note_edit, cr,
-				  position);
+	  cr = gdk_cairo_create(GTK_WIDGET(note_edit->drawing_area)->window);
+	  ags_note_edit_draw_scroll(note_edit, cr,
+				    position);
 
-	cairo_pop_group_to_source(cr);
-	cairo_paint(cr);
+	  cairo_pop_group_to_source(cr);
+	  cairo_paint(cr);
 
-	cairo_surface_mark_dirty(cairo_get_target(cr));
-	cairo_destroy(cr);
-      }
-    }else if(AGS_IS_PATTERN_EDIT(AGS_EDITOR_CHILD(editor_child->data)->edit_widget)){
-      AgsPatternEdit *pattern_edit;
+	  cairo_surface_mark_dirty(cairo_get_target(cr));
+	  cairo_destroy(cr);
+	}
+      }else if(AGS_IS_PATTERN_EDIT(AGS_EDITOR_CHILD(editor_child->data)->edit_widget)){
+	AgsPatternEdit *pattern_edit;
 
-      pattern_edit = AGS_PATTERN_EDIT(AGS_EDITOR_CHILD(editor_child->data)->edit_widget);
+	pattern_edit = AGS_PATTERN_EDIT(AGS_EDITOR_CHILD(editor_child->data)->edit_widget);
 
-      position = (count_beats_audio_run->notation_counter) * (pattern_edit->control_unit.control_width);
+	position = (count_beats_audio_run->notation_counter) * (pattern_edit->control_unit.control_width);
 
-      control_width = pattern_edit->control_unit.control_width;
+	control_width = pattern_edit->control_unit.control_width;
 
-      /* scroll */
-      pattern_edit->flags |= AGS_PATTERN_EDIT_RESETING_HORIZONTALLY;
+	/* scroll */
+	pattern_edit->flags |= AGS_PATTERN_EDIT_RESETING_HORIZONTALLY;
 	
-      if(position - control_width > 0){
-	value = (position - control_width);
-      }else{
-	value = 0.0;
-      }
+	if(position - control_width > 0){
+	  value = (position - control_width);
+	}else{
+	  value = 0.0;
+	}
 
-      if(position - control_width > 0){
-	gtk_range_set_value(GTK_RANGE(pattern_edit->hscrollbar),
-			    value);
-	gtk_adjustment_set_value(pattern_edit->ruler->adjustment,
-				 (value) /
-				 pattern_edit->control_current.control_width);
+	if(position - control_width > 0){
+	  gtk_range_set_value(GTK_RANGE(pattern_edit->hscrollbar),
+			      value);
+	  gtk_adjustment_set_value(pattern_edit->ruler->adjustment,
+				   (value) /
+				   pattern_edit->control_current.control_width);
 
-	gtk_widget_queue_draw((GtkWidget *) pattern_edit->ruler);
-      }
+	  gtk_widget_queue_draw((GtkWidget *) pattern_edit->ruler);
+	}
       
-      /*  */
-      if(position - control_width > 0){
-	pattern_edit->control_current.x0 = ((guint) round((double) value)) % pattern_edit->control_current.control_width;
+	/*  */
+	if(position - control_width > 0){
+	  pattern_edit->control_current.x0 = ((guint) round((double) value)) % pattern_edit->control_current.control_width;
 
-	if(pattern_edit->control_current.x0 != 0){
-	  pattern_edit->control_current.x0 = pattern_edit->control_current.control_width - pattern_edit->control_current.x0;
-	}
+	  if(pattern_edit->control_current.x0 != 0){
+	    pattern_edit->control_current.x0 = pattern_edit->control_current.control_width - pattern_edit->control_current.x0;
+	  }
 	
-	pattern_edit->control_current.x1 = (pattern_edit->width - pattern_edit->control_current.x0) % pattern_edit->control_current.control_width;
+	  pattern_edit->control_current.x1 = (pattern_edit->width - pattern_edit->control_current.x0) % pattern_edit->control_current.control_width;
 
-	pattern_edit->control_current.nth_x = (guint) ceil((double)(value) / (double)(pattern_edit->control_current.control_width));
+	  pattern_edit->control_current.nth_x = (guint) ceil((double)(value) / (double)(pattern_edit->control_current.control_width));
 
-	pattern_edit->control_unit.x0 = ((guint)round((double) value)) % pattern_edit->control_unit.control_width;
+	  pattern_edit->control_unit.x0 = ((guint)round((double) value)) % pattern_edit->control_unit.control_width;
 
-	if(pattern_edit->control_unit.x0 != 0){
-	  pattern_edit->control_unit.x0 = pattern_edit->control_unit.control_width - pattern_edit->control_unit.x0;
-	}
+	  if(pattern_edit->control_unit.x0 != 0){
+	    pattern_edit->control_unit.x0 = pattern_edit->control_unit.control_width - pattern_edit->control_unit.x0;
+	  }
       
-	pattern_edit->control_unit.x1 = (pattern_edit->width - pattern_edit->control_unit.x0) % pattern_edit->control_unit.control_width;
+	  pattern_edit->control_unit.x1 = (pattern_edit->width - pattern_edit->control_unit.x0) % pattern_edit->control_unit.control_width;
       
-	pattern_edit->control_unit.nth_x = (guint) ceil(round((double) value) / (double) (pattern_edit->control_unit.control_width));
-	pattern_edit->control_unit.stop_x = pattern_edit->control_unit.nth_x + (pattern_edit->width - pattern_edit->control_unit.x0 - pattern_edit->control_unit.x1) / pattern_edit->control_unit.control_width;
-      }
+	  pattern_edit->control_unit.nth_x = (guint) ceil(round((double) value) / (double) (pattern_edit->control_unit.control_width));
+	  pattern_edit->control_unit.stop_x = pattern_edit->control_unit.nth_x + (pattern_edit->width - pattern_edit->control_unit.x0 - pattern_edit->control_unit.x1) / pattern_edit->control_unit.control_width;
+	}
       
-      pattern_edit->flags &= (~AGS_PATTERN_EDIT_RESETING_HORIZONTALLY);
+	pattern_edit->flags &= (~AGS_PATTERN_EDIT_RESETING_HORIZONTALLY);
 
-      /*  */
-      if(GTK_WIDGET_VISIBLE(AGS_EDITOR_CHILD(editor_child->data)->edit_widget)){
-	cr = gdk_cairo_create(GTK_WIDGET(pattern_edit->drawing_area)->window);
+	/*  */
+	if(GTK_WIDGET_VISIBLE(AGS_EDITOR_CHILD(editor_child->data)->edit_widget)){
+	  cr = gdk_cairo_create(GTK_WIDGET(pattern_edit->drawing_area)->window);
 
-	cairo_surface_flush(cairo_get_target(cr));
-	cairo_push_group(cr);
+	  cairo_surface_flush(cairo_get_target(cr));
+	  cairo_push_group(cr);
 
-	ags_pattern_edit_draw_segment(pattern_edit, cr);
-	ags_pattern_edit_draw_notation(pattern_edit, cr);
+	  ags_pattern_edit_draw_segment(pattern_edit, cr);
+	  ags_pattern_edit_draw_notation(pattern_edit, cr);
 
-	cairo_pop_group_to_source(cr);
-	cairo_paint(cr);
+	  cairo_pop_group_to_source(cr);
+	  cairo_paint(cr);
 
-	/* draw fader */
-	cairo_push_group(cr);
+	  /* draw fader */
+	  cairo_push_group(cr);
 
-	cr = gdk_cairo_create(GTK_WIDGET(pattern_edit->drawing_area)->window);
-	ags_pattern_edit_draw_scroll(pattern_edit, cr,
-				     position);
+	  cr = gdk_cairo_create(GTK_WIDGET(pattern_edit->drawing_area)->window);
+	  ags_pattern_edit_draw_scroll(pattern_edit, cr,
+				       position);
 
-	cairo_pop_group_to_source(cr);
-	cairo_paint(cr);
+	  cairo_pop_group_to_source(cr);
+	  cairo_paint(cr);
 
-	cairo_surface_mark_dirty(cairo_get_target(cr));
-	cairo_destroy(cr);
+	  cairo_surface_mark_dirty(cairo_get_target(cr));
+	  cairo_destroy(cr);
+	}
       }
     }
-    
+  
     editor_child = editor_child->next;
   }
   
diff --git a/ags/X/thread/ags_gui_thread.c b/ags/X/thread/ags_gui_thread.c
index c20cfe7..47d20c4 100644
--- a/ags/X/thread/ags_gui_thread.c
+++ b/ags/X/thread/ags_gui_thread.c
@@ -26,8 +26,11 @@
 #include <ags/thread/ags_mutex_manager.h>
 #include <ags/thread/ags_polling_thread.h>
 #include <ags/thread/ags_poll_fd.h>
+#include <ags/thread/ags_task_thread.h>
 #include <ags/thread/ags_task_completion.h>
 
+#include <ags/X/ags_xorg_application_context.h>
+
 #include <gdk/gdk.h>
 
 #include <fontconfig/fontconfig.h>
@@ -48,6 +51,8 @@ void ags_gui_thread_suspend(AgsThread *thread);
 void ags_gui_thread_resume(AgsThread *thread);
 void ags_gui_thread_stop(AgsThread *thread);
 
+void* ags_gui_thread_do_poll_loop(void *ptr);
+
 guint ags_gui_thread_interrupted(AgsThread *thread,
 				 int sig,
 				 guint time_cycle, guint *time_spent);
@@ -143,7 +148,7 @@ ags_gui_thread_class_init(AgsGuiThreadClass *gui_thread)
   thread->resume = ags_gui_thread_resume;
   thread->stop = ags_gui_thread_stop;
 
-  thread->interrupted = ags_gui_thread_interrupted;
+  //  thread->interrupted = ags_gui_thread_interrupted;
 }
 
 void
@@ -193,9 +198,14 @@ ags_gui_thread_init(AgsGuiThread *gui_thread)
   gui_thread->task_completion_mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
   pthread_mutex_init(gui_thread->task_completion_mutex,
 		     &attr);
-    
+
   g_atomic_pointer_set(&(gui_thread->task_completion),
 		       NULL);
+
+  /*  */
+  gui_thread->dispatch_mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
+  pthread_mutex_init(gui_thread->dispatch_mutex,
+		     &attr);
 }
 
 void
@@ -232,8 +242,74 @@ ags_gui_thread_start(AgsThread *thread)
 
   /*  */
   if((AGS_THREAD_SINGLE_LOOP & (g_atomic_int_get(&(thread->flags)))) == 0){
-    AGS_THREAD_CLASS(ags_gui_thread_parent_class)->start(thread);
+    //    AGS_THREAD_CLASS(ags_gui_thread_parent_class)->start(thread);
+  }
+
+  g_atomic_int_or(&(gui_thread->flags),
+		  AGS_GUI_THREAD_RUNNING);
+
+  pthread_create(thread->thread, thread->thread_attr,
+		 ags_gui_thread_do_poll_loop, thread);
+}
+
+void
+ags_gui_thread_stop(AgsThread *thread)
+{
+  AgsGuiThread *gui_thread;
+
+  gui_thread = AGS_GUI_THREAD(thread);
+
+  g_atomic_int_and(&(gui_thread->flags),
+		   (~(AGS_GUI_THREAD_RUNNING)));
+  
+  /*  */
+  gdk_flush();
+}
+
+void*
+ags_gui_thread_do_poll_loop(void *ptr)
+{
+  AgsGuiThread *gui_thread;
+  AgsTaskThread *task_thread;
+  AgsThread *thread;
+  
+  AgsXorgApplicationContext *xorg_application_context;
+  
+  gui_thread = (AgsGuiThread *) ptr;
+  thread = (AgsThread *) ptr;
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* notify start */
+  pthread_mutex_lock(thread->start_mutex);
+      
+  g_atomic_int_set(&(thread->start_done),
+		   TRUE);    
+      
+  if(g_atomic_int_get(&(thread->start_wait)) == TRUE){
+    pthread_cond_broadcast(thread->start_cond);
   }
+      
+  pthread_mutex_unlock(thread->start_mutex);
+  
+  /* wait for audio loop */
+  while(g_atomic_int_get(&(xorg_application_context->gui_ready)) == 0){
+    usleep(500000);
+  }
+
+  task_thread = ags_thread_find_type(AGS_APPLICATION_CONTEXT(xorg_application_context)->main_loop,
+				     AGS_TYPE_TASK_THREAD);
+  
+  /* poll */
+  while((AGS_GUI_THREAD_RUNNING & (g_atomic_int_get(&(gui_thread->flags)))) != 0){
+    pthread_mutex_lock(task_thread->launch_mutex);
+    
+    AGS_THREAD_GET_CLASS(gui_thread)->run(gui_thread);
+
+    pthread_mutex_unlock(task_thread->launch_mutex);
+  }
+  
+  pthread_exit(NULL);
 }
 
 void
@@ -385,7 +461,11 @@ ags_gui_thread_run(AgsThread *thread)
   /* dispatch */  
   some_ready = g_main_context_check(main_context, gui_thread->max_priority, gui_thread->cached_poll_array, gui_thread->cached_poll_array_size);
 
+  gdk_threads_enter();
+  
   g_main_context_dispatch(main_context);
+
+  gdk_threads_leave();
   
   if(g_atomic_int_get(&(gui_thread->dispatching)) == TRUE){
     g_atomic_int_set(&(gui_thread->dispatching),
@@ -395,11 +475,16 @@ ags_gui_thread_run(AgsThread *thread)
   ags_gui_thread_complete_task();  
   
   g_main_context_release(main_context);
-  
+
+  gdk_threads_enter();
+
   //  pango_fc_font_map_cache_clear(pango_cairo_font_map_get_default());
   //  pango_cairo_font_map_set_default(NULL);
+
   //  cairo_debug_reset_static_data();
   //  FcFini();
+  
+  gdk_threads_leave();
 }
 
 guint
@@ -420,9 +505,9 @@ ags_gui_thread_interrupted(AgsThread *thread,
 		   SIGIO);
 
 #ifdef AGS_PTHREAD_SUSPEND
-    pthread_suspend(thread->thread);
+      pthread_suspend(thread->thread);
 #else
-    pthread_kill(*(thread->thread), AGS_THREAD_SUSPEND_SIG);
+      pthread_kill(*(thread->thread), AGS_THREAD_SUSPEND_SIG);
 #endif
     }
   }
@@ -463,16 +548,6 @@ ags_gui_thread_resume(AgsThread *thread)
 }
 
 void
-ags_gui_thread_stop(AgsThread *thread)
-{
-  /*  */
-  AGS_THREAD_CLASS(ags_gui_thread_parent_class)->stop(thread);  
-
-  /*  */
-  gdk_flush();
-}
-
-void
 ags_gui_thread_dispatch_callback(AgsPollFd *poll_fd,
 				 AgsGuiThread *gui_thread)
 {
@@ -487,9 +562,9 @@ ags_gui_thread_dispatch_callback(AgsPollFd *poll_fd,
 		     (~AGS_THREAD_INTERRUPTED));
 
 #ifdef AGS_PTHREAD_RESUME
-    pthread_resume(thread->thread);
+    //    pthread_resume(thread->thread);
 #else
-    pthread_kill(*(thread->thread), AGS_THREAD_RESUME_SIG);
+    //    pthread_kill(*(thread->thread), AGS_THREAD_RESUME_SIG);
 #endif
   }
 }
@@ -531,8 +606,8 @@ ags_gui_thread_polling_thread_run_callback(AgsThread *thread,
 
       poll_fd->delay = 5.0;
       
-      g_signal_connect(poll_fd, "dispatch\0",
-		       G_CALLBACK(ags_gui_thread_dispatch_callback), gui_thread);
+      //      g_signal_connect(poll_fd, "dispatch\0",
+      //	       G_CALLBACK(ags_gui_thread_dispatch_callback), gui_thread);
       
       ags_polling_thread_add_poll_fd(polling_thread,
 				     (GObject *) poll_fd);
diff --git a/ags/X/thread/ags_gui_thread.h b/ags/X/thread/ags_gui_thread.h
index a59e07c..8d531c7 100644
--- a/ags/X/thread/ags_gui_thread.h
+++ b/ags/X/thread/ags_gui_thread.h
@@ -38,17 +38,23 @@
 #define AGS_IS_GUI_THREAD_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_GUI_THREAD))
 #define AGS_GUI_THREAD_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS(obj, AGS_TYPE_GUI_THREAD, AgsGuiThreadClass))
 
-#define AGS_GUI_THREAD_RT_PRIORITY (0)
+#define AGS_GUI_THREAD_RT_PRIORITY (99)
 
 #define AGS_GUI_THREAD_DEFAULT_JIFFIE (60.0)
 
 typedef struct _AgsGuiThread AgsGuiThread;
 typedef struct _AgsGuiThreadClass AgsGuiThreadClass;
 
+typedef enum{
+  AGS_GUI_THREAD_RUNNING    = 1,
+}AgsGuiThreadFlags;
+
 struct _AgsGuiThread
 {
   AgsThread thread;
 
+  volatile guint flags;
+  
   volatile gboolean dispatching;
   
   GMutex mutex;
@@ -65,6 +71,8 @@ struct _AgsGuiThread
   
   pthread_mutex_t *task_completion_mutex;
   volatile GList *task_completion;
+
+  pthread_mutex_t *dispatch_mutex;
 };
 
 struct _AgsGuiThreadClass
diff --git a/ags/audio/ags_acceleration.c b/ags/audio/ags_acceleration.c
index 2c2d7b2..9e3d649 100644
--- a/ags/audio/ags_acceleration.c
+++ b/ags/audio/ags_acceleration.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -28,7 +28,7 @@ void ags_acceleration_connectable_interface_init(AgsConnectableInterface *connec
 void ags_acceleration_init(AgsAcceleration *acceleration);
 void ags_acceleration_connect(AgsConnectable *connectable);
 void ags_acceleration_disconnect(AgsConnectable *connectable);
-void ags_acceleration_finalize(GObject *object);
+void ags_acceleration_finalize(GObject *gobject);
 
 /**
  * SECTION:ags_acceleration
@@ -112,20 +112,43 @@ ags_acceleration_init(AgsAcceleration *acceleration)
 void
 ags_acceleration_connect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsAcceleration *acceleration;
+
+  acceleration = AGS_ACCELERATION(connectable);
+
+  if((AGS_ACCELERATION_CONNECTED & (acceleration->flags)) != 0){
+    return;
+  }
+
+  acceleration->flags |= AGS_ACCELERATION_CONNECTED;
 }
 
 void
 ags_acceleration_disconnect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsAcceleration *acceleration;
+
+  acceleration = AGS_ACCELERATION(connectable);
+
+  if((AGS_ACCELERATION_CONNECTED & (acceleration->flags)) == 0){
+    return;
+  }
+
+  acceleration->flags &= (~AGS_ACCELERATION_CONNECTED);
 }
 
 void
 ags_acceleration_finalize(GObject *gobject)
 {
-  /* empty */
+  AgsAcceleration *acceleration;
 
+  acceleration = AGS_ACCELERATION(gobject);
+  
+  if(acceleration->name != NULL){
+    free(acceleration->name);
+  }
+  
+  /* call parent */
   G_OBJECT_CLASS(ags_acceleration_parent_class)->finalize(gobject);
 }
 
diff --git a/ags/audio/ags_acceleration.h b/ags/audio/ags_acceleration.h
index f78eff0..f502625 100644
--- a/ags/audio/ags_acceleration.h
+++ b/ags/audio/ags_acceleration.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -35,6 +35,7 @@ typedef struct _AgsAccelerationClass AgsAccelerationClass;
 
 /**
  * AgsAccelerationFlags:
+ * @AGS_ACCELERATION_CONNECTED: if this object is already connected
  * @AGS_ACCELERATION_DEFAULT_START: if start is default start point
  * @AGS_ACCELERATION_DEFAULT_END: if end is default end point
  * @AGS_ACCELERATION_GUI: interpret x and y as GUI format
@@ -44,13 +45,14 @@ typedef struct _AgsAccelerationClass AgsAccelerationClass;
  * @AGS_ACCELERATION_IS_SELECTED: if the acceleration is selected
  */
 typedef enum{
-  AGS_ACCELERATION_DEFAULT_START   = 1,
-  AGS_ACCELERATION_DEFAULT_END     = 1 <<  1,
-  AGS_ACCELERATION_GUI             = 1 <<  2,
-  AGS_ACCELERATION_RUNTIME         = 1 <<  3,
-  AGS_ACCELERATION_HUMAN_READABLE  = 1 <<  4,
-  AGS_ACCELERATION_DEFAULT_LENGTH  = 1 <<  5,
-  AGS_ACCELERATION_IS_SELECTED     = 1 <<  6,
+  AGS_ACCELERATION_CONNECTED       = 1,
+  AGS_ACCELERATION_DEFAULT_START   = 1 <<  1,
+  AGS_ACCELERATION_DEFAULT_END     = 1 <<  2,
+  AGS_ACCELERATION_GUI             = 1 <<  3,
+  AGS_ACCELERATION_RUNTIME         = 1 <<  4,
+  AGS_ACCELERATION_HUMAN_READABLE  = 1 <<  5,
+  AGS_ACCELERATION_DEFAULT_LENGTH  = 1 <<  6,
+  AGS_ACCELERATION_IS_SELECTED     = 1 <<  7,
 }AgsAccelerationFlags;
 
 struct _AgsAcceleration
diff --git a/ags/audio/ags_audio.c b/ags/audio/ags_audio.c
index 7a44cf5..12581e0 100644
--- a/ags/audio/ags_audio.c
+++ b/ags/audio/ags_audio.c
@@ -25,6 +25,7 @@
 #include <ags/object/ags_connectable.h>
 #include <ags/object/ags_dynamic_connectable.h>
 #include <ags/object/ags_soundcard.h>
+#include <ags/object/ags_sequencer.h>
 
 #include <ags/thread/ags_mutex_manager.h>
 
@@ -42,6 +43,7 @@
 #include <ags/audio/ags_recall_container.h>
 #include <ags/audio/ags_recall.h>
 #include <ags/audio/ags_recall_audio.h>
+#include <ags/audio/ags_recall_audio_run.h>
 #include <ags/audio/ags_recall_id.h>
 
 #include <ags/audio/thread/ags_audio_thread.h>
@@ -89,6 +91,7 @@ void ags_audio_add_to_registry(AgsConnectable *connectable);
 void ags_audio_remove_from_registry(AgsConnectable *connectable);
 void ags_audio_connect(AgsConnectable *connectable);
 void ags_audio_disconnect(AgsConnectable *connectable);
+void ags_audio_dispose(GObject *gobject);
 void ags_audio_finalize(GObject *gobject);
 
 void ags_audio_real_check_connection(AgsAudio *audio);
@@ -98,6 +101,8 @@ void ags_audio_real_set_audio_channels(AgsAudio *audio,
 void ags_audio_real_set_pads(AgsAudio *audio,
 			     GType type,
 			     guint channels, guint channels_old);
+void ags_audio_real_done(AgsAudio *audio,
+			 AgsRecallID *recall_id);
 
 enum{
   CHECK_CONNECTION,
@@ -194,6 +199,7 @@ ags_audio_class_init(AgsAudioClass *audio)
   gobject->set_property = ags_audio_set_property;
   gobject->get_property = ags_audio_get_property;
 
+  gobject->dispose = ags_audio_dispose;
   gobject->finalize = ags_audio_finalize;
 
   /* properties */
@@ -569,11 +575,10 @@ ags_audio_class_init(AgsAudioClass *audio)
    * 
    * Since: 0.7.2
    */
-  param_spec = g_param_spec_object("notation\0",
-				   "containing notation\0",
-				   "The notation it contains\0",
-				   AGS_TYPE_NOTATION,
-				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  param_spec = g_param_spec_pointer("notation\0",
+				    "containing notation\0",
+				    "The notation it contains\0",
+				    G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
 				  PROP_NOTATION,
 				  param_spec);
@@ -585,11 +590,10 @@ ags_audio_class_init(AgsAudioClass *audio)
    * 
    * Since: 0.7.2
    */
-  param_spec = g_param_spec_object("automation\0",
-				   "containing automation\0",
-				   "The automation it contains\0",
-				   AGS_TYPE_AUTOMATION,
-				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  param_spec = g_param_spec_pointer("automation\0",
+				    "containing automation\0",
+				    "The automation it contains\0",
+				    G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
 				  PROP_AUTOMATION,
 				  param_spec);
@@ -601,11 +605,10 @@ ags_audio_class_init(AgsAudioClass *audio)
    * 
    * Since: 0.7.2
    */
-  param_spec = g_param_spec_object("recall-id\0",
-				   "assigned recall id\0",
-				   "The assigned recall id\0",
-				   AGS_TYPE_RECALL_ID,
-				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  param_spec = g_param_spec_pointer("recall-id\0",
+				    "assigned recall id\0",
+				    "The assigned recall id\0",
+				    G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
 				  PROP_OUTPUT,
 				  param_spec);
@@ -617,11 +620,10 @@ ags_audio_class_init(AgsAudioClass *audio)
    * 
    * Since: 0.7.2
    */
-  param_spec = g_param_spec_object("recycling-context\0",
-				   "assigned recycling context\0",
-				   "The assigned recall id\0",
-				   AGS_TYPE_RECYCLING_CONTEXT,
-				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  param_spec = g_param_spec_pointer("recycling-context\0",
+				    "assigned recycling context\0",
+				    "The assigned recall id\0",
+				    G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
 				  PROP_OUTPUT,
 				  param_spec);
@@ -633,11 +635,10 @@ ags_audio_class_init(AgsAudioClass *audio)
    * 
    * Since: 0.7.2
    */
-  param_spec = g_param_spec_object("recall-container\0",
-				   "containing recall container\0",
-				   "The recall container it contains\0",
-				   AGS_TYPE_RECALL_CONTAINER,
-				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  param_spec = g_param_spec_pointer("recall-container\0",
+				    "containing recall container\0",
+				    "The recall container it contains\0",
+				    G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
 				  PROP_RECALL_CONTAINER,
 				  param_spec);
@@ -649,11 +650,10 @@ ags_audio_class_init(AgsAudioClass *audio)
    * 
    * Since: 0.7.2
    */
-  param_spec = g_param_spec_object("play\0",
-				   "containing play\0",
-				   "The play it contains\0",
-				   AGS_TYPE_RECALL,
-				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  param_spec = g_param_spec_pointer("play\0",
+				    "containing play\0",
+				    "The play it contains\0",
+				    G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
 				  PROP_PLAY,
 				  param_spec);
@@ -665,11 +665,10 @@ ags_audio_class_init(AgsAudioClass *audio)
    * 
    * Since: 0.7.2
    */
-  param_spec = g_param_spec_object("recall\0",
-				   "containing recall\0",
-				   "The recall it contains\0",
-				   AGS_TYPE_RECALL,
-				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  param_spec = g_param_spec_pointer("recall\0",
+				    "containing recall\0",
+				    "The recall it contains\0",
+				    G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
 				  PROP_RECALL,
 				  param_spec);
@@ -683,7 +682,7 @@ ags_audio_class_init(AgsAudioClass *audio)
 
   audio->init_run = NULL;
   audio->tact = NULL;
-  audio->done = NULL;
+  audio->done = ags_audio_real_done;
 
   /* signals */
   /**
@@ -886,8 +885,6 @@ ags_audio_init(AgsAudio *audio)
 					 10);
 
     free(str);
-  }else{
-    audio->samplerate = AGS_SOUNDCARD_DEFAULT_SAMPLERATE;
   }
 
   /* buffer size */
@@ -907,8 +904,6 @@ ags_audio_init(AgsAudio *audio)
 					  10);
 
     free(str);
-  }else{
-    audio->buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
   }
 
   /* format */
@@ -928,8 +923,6 @@ ags_audio_init(AgsAudio *audio)
 				     10);
 
     free(str);
-  }else{
-    audio->format = AGS_SOUNDCARD_DEFAULT_FORMAT;
   }
 
   /* channel allocation */
@@ -958,58 +951,10 @@ ags_audio_init(AgsAudio *audio)
 
   /* playback domain */
   audio->playback_domain = (GObject *) ags_playback_domain_new();
-  AGS_PLAYBACK_DOMAIN(audio->playback_domain)->domain = (GObject *) audio;
-
-  /* thread model */
-  str0 = ags_config_get_value(config,
-			      AGS_CONFIG_THREAD,
-			      "model\0");
-  str1 = ags_config_get_value(config,
-			      AGS_CONFIG_THREAD,
-			      "super-threaded-scope\0");
-
-  if(str0 != NULL && str1 != NULL){
-    if(!g_ascii_strncasecmp(str0,
-			    "super-threaded\0",
-			    15)){
-      if(!g_ascii_strncasecmp(str1,
-			      "audio\0",
-			      6) ||
-	 !g_ascii_strncasecmp(str1,
-			      "channel\0",
-			      8) ||
-	 !g_ascii_strncasecmp(str1,
-			      "recycling\0",
-			      10)){
-	gdouble freq;
-	
-	freq = ceil((gdouble) audio->samplerate / (gdouble) audio->buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK;
-	
-	g_atomic_int_or(&(AGS_PLAYBACK_DOMAIN(audio->playback_domain)->flags),
-			AGS_PLAYBACK_DOMAIN_SUPER_THREADED_AUDIO);
-
-	AGS_PLAYBACK_DOMAIN(audio->playback_domain)->audio_thread[0] = (AgsThread *) ags_audio_thread_new(NULL,
-													  (GObject *) audio);
-	AGS_PLAYBACK_DOMAIN(audio->playback_domain)->audio_thread[0]->freq = freq;
-	
-	AGS_PLAYBACK_DOMAIN(audio->playback_domain)->audio_thread[1] = (AgsThread *) ags_audio_thread_new(NULL,
-													  (GObject *) audio);
-	AGS_PLAYBACK_DOMAIN(audio->playback_domain)->audio_thread[1]->freq = freq;
-
-	AGS_PLAYBACK_DOMAIN(audio->playback_domain)->audio_thread[2] = (AgsThread *) ags_audio_thread_new(NULL,
-													  (GObject *) audio);
-	AGS_PLAYBACK_DOMAIN(audio->playback_domain)->audio_thread[2]->freq = freq;
-      }
-    }
-  }
-  
-  if(str0 != NULL){
-    free(str0);
-  }
-
-  if(str1 != NULL){
-    free(str1);
-  }
+  g_object_ref(audio->playback_domain);
+  g_object_set(audio->playback_domain,
+	       "domain\0", audio,
+	       NULL);
 
   /* notation and automation */
   audio->notation = NULL;
@@ -1020,6 +965,24 @@ ags_audio_init(AgsAudio *audio)
   audio->recycling_context = NULL;
 
   /* recall */
+  attr = (pthread_mutexattr_t *) malloc(sizeof(pthread_mutexattr_t));
+  pthread_mutexattr_init(attr);
+  pthread_mutexattr_settype(attr,
+			    PTHREAD_MUTEX_RECURSIVE);
+
+  audio->recall_mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
+  pthread_mutex_init(audio->recall_mutex,
+		     attr);
+
+  attr = (pthread_mutexattr_t *) malloc(sizeof(pthread_mutexattr_t));
+  pthread_mutexattr_init(attr);
+  pthread_mutexattr_settype(attr,
+			    PTHREAD_MUTEX_RECURSIVE);
+
+  audio->play_mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
+  pthread_mutex_init(audio->play_mutex,
+		     attr);
+
   audio->container = NULL;
   
   audio->recall = NULL;
@@ -1028,7 +991,7 @@ ags_audio_init(AgsAudio *audio)
   audio->recall_remove= NULL;
   audio->play_remove = NULL;
 
-  /* widget */
+  /* data */
   audio->machine = NULL;
 }
 
@@ -1249,7 +1212,7 @@ ags_audio_set_property(GObject *gobject,
     {
       AgsNotation *notation;
 
-      notation = (AgsNotation *) g_value_get_object(value);
+      notation = (AgsNotation *) g_value_get_pointer(value);
 
       if(notation == NULL ||
 	 g_list_find(audio->notation, notation) != NULL){
@@ -1264,7 +1227,7 @@ ags_audio_set_property(GObject *gobject,
     {
       AgsAutomation *automation;
 
-      automation = (AgsAutomation *) g_value_get_object(value);
+      automation = (AgsAutomation *) g_value_get_pointer(value);
 
       if(automation == NULL ||
 	 g_list_find(audio->automation, automation) != NULL){
@@ -1279,7 +1242,7 @@ ags_audio_set_property(GObject *gobject,
     {
       AgsRecallID *recall_id;
 
-      recall_id = (AgsRecallID *) g_value_get_object(value);
+      recall_id = (AgsRecallID *) g_value_get_pointer(value);
 
       if(recall_id == NULL ||
 	 g_list_find(audio->recall_id, recall_id) != NULL){
@@ -1294,7 +1257,7 @@ ags_audio_set_property(GObject *gobject,
     {
       AgsRecyclingContext *recycling_context;
 
-      recycling_context = (AgsRecyclingContext *) g_value_get_object(value);
+      recycling_context = (AgsRecyclingContext *) g_value_get_pointer(value);
 
       if(recycling_context == NULL ||
 	 g_list_find(audio->recycling_context, recycling_context) != NULL){
@@ -1309,7 +1272,7 @@ ags_audio_set_property(GObject *gobject,
     {
       AgsRecallContainer *recall_container;
 
-      recall_container = (AgsRecallContainer *) g_value_get_object(value);
+      recall_container = (AgsRecallContainer *) g_value_get_pointer(value);
 
       if(recall_container == NULL ||
 	 g_list_find(audio->container, recall_container) != NULL){
@@ -1324,10 +1287,18 @@ ags_audio_set_property(GObject *gobject,
     {
       AgsRecall *recall;
 
-      recall = (AgsRecall *) g_value_get_object(value);
+      gboolean play_added;
+      
+      recall = (AgsRecall *) g_value_get_pointer(value);
 
+      pthread_mutex_lock(audio->play_mutex);
+      
+      play_added = (g_list_find(audio->play, recall) != NULL) ? TRUE: FALSE;
+
+      pthread_mutex_unlock(audio->play_mutex);
+      
       if(recall == NULL ||
-	 g_list_find(audio->play, recall) != NULL){
+	 play_added){
 	return;
       }
 
@@ -1340,10 +1311,18 @@ ags_audio_set_property(GObject *gobject,
     {
       AgsRecall *recall;
 
-      recall = (AgsRecall *) g_value_get_object(value);
+      gboolean recall_added;
+      
+      recall = (AgsRecall *) g_value_get_pointer(value);
+
+      pthread_mutex_lock(audio->recall_mutex);
+      
+      recall_added = (g_list_find(audio->recall, recall) != NULL) ? TRUE: FALSE;
+
+      pthread_mutex_unlock(audio->recall_mutex);
 
       if(recall == NULL ||
-	 g_list_find(audio->recall, recall) != NULL){
+	 recall_added){
 	return;
       }
 
@@ -1495,12 +1474,20 @@ ags_audio_get_property(GObject *gobject,
     break;
   case PROP_PLAY:
     {
+      pthread_mutex_lock(audio->play_mutex);
+      
       g_value_set_pointer(value, g_list_copy(audio->play));
+
+      pthread_mutex_unlock(audio->play_mutex);
     }
     break;
   case PROP_RECALL:
     {
+      pthread_mutex_lock(audio->recall_mutex);
+      
       g_value_set_pointer(value, g_list_copy(audio->recall));
+
+      pthread_mutex_unlock(audio->recall_mutex);
     }
     break;
   default:
@@ -1509,6 +1496,225 @@ ags_audio_get_property(GObject *gobject,
 }
 
 void
+ags_audio_dispose(GObject *gobject)
+{
+  AgsAudio *audio;
+
+  GList *list, *list_next;
+
+  audio = AGS_AUDIO(gobject);
+  
+  /* soundcard */
+  if(audio->soundcard != NULL){    
+    g_object_unref(audio->soundcard);
+
+    audio->soundcard = NULL;
+  }
+
+  /* sequencer */
+  if(audio->sequencer != NULL){
+    g_object_unref(audio->sequencer);
+
+    audio->sequencer = NULL;
+  }
+
+  /* midi file */
+  if(audio->midi_file != NULL){
+    g_object_unref(audio->midi_file);
+
+    audio->midi_file = NULL;
+  }
+
+  /* audio connection */
+  if(audio->audio_connection != NULL){
+    list = audio->audio_connection;
+
+    while(list != NULL){
+      list_next = list->next;
+      
+      g_object_run_dispose(list->data);
+
+      list = list_next;
+    }
+  
+    g_list_free_full(audio->audio_connection,
+		     g_object_unref);
+
+    audio->audio_connection = NULL;
+  }
+  
+  /* notation */
+  if(audio->notation != NULL){
+    list = audio->notation;
+
+    while(list != NULL){
+      list_next = list->next;
+      
+      g_object_run_dispose(list->data);
+
+      list = list_next;
+    }
+  
+    g_list_free_full(audio->notation,
+		     g_object_unref);
+
+    audio->notation = NULL;
+  }
+  
+  /* automation */
+  if(audio->automation != NULL){
+    list = audio->automation;
+
+    while(list != NULL){
+      list_next = list->next;
+      
+      g_object_run_dispose(list->data);
+
+      list = list_next;
+    }
+  
+    g_list_free_full(audio->automation,
+		     g_object_unref);
+
+    audio->automation = NULL;
+  }
+
+  /* recall id */
+  if(audio->recall_id != NULL){
+    list = audio->recall_id;
+    
+    while(list != NULL){
+      list_next = list->next;
+      
+      g_object_run_dispose(list->data);
+      
+      list = list_next;
+    }
+
+    
+    g_list_free_full(audio->recall_id,
+		     g_object_unref);
+
+    audio->recall_id = NULL;
+  }
+  
+  /* recycling context */
+  if(audio->recycling_context != NULL){
+    list = audio->recycling_context;
+
+    while(list != NULL){
+      list_next = list->next;
+      
+      g_object_run_dispose(list->data);
+
+      list = list_next;
+    }
+  
+    g_list_free_full(audio->recycling_context,
+		     g_object_unref);
+
+    audio->recycling_context = NULL;
+  }
+  
+  /* recall container */
+  if(audio->container != NULL){
+    list = audio->container;
+
+    while(list != NULL){
+      list_next = list->next;
+      
+      g_object_run_dispose(list->data);
+
+      list = list_next;
+    }
+
+    g_list_free_full(audio->container,
+		     g_object_unref);
+
+    audio->container = NULL;
+  }
+
+  /* recall */
+  if(audio->recall != NULL){
+    pthread_mutex_lock(audio->recall_mutex);
+    
+    list = audio->recall;
+  
+    while(list != NULL){
+      list_next = list->next;
+      
+      g_object_run_dispose(list->data);
+    
+      list = list_next;
+    }
+
+    g_list_free_full(audio->recall,
+		     g_object_unref);
+
+    audio->recall = NULL;
+
+    pthread_mutex_unlock(audio->recall_mutex);
+  }
+
+  /* play */
+  if(audio->play != NULL){
+    pthread_mutex_lock(audio->play_mutex);
+
+    list = audio->play;
+
+    while(list != NULL){
+      list_next = list->next;
+      
+      g_object_run_dispose(list->data);
+    
+      list = list_next;
+    }
+
+    g_list_free_full(audio->play,
+		     g_object_unref);
+
+    audio->play = NULL;
+
+    pthread_mutex_unlock(audio->play_mutex);
+  }
+  
+  /* remove */
+  if(audio->recall_remove != NULL){
+    g_list_free_full(audio->recall_remove,
+		     g_object_unref);
+  }
+
+  if(audio->play_remove != NULL){
+    g_list_free_full(audio->play_remove,
+		     g_object_unref);
+  }
+  
+  audio->recall_remove = NULL;
+  audio->play_remove = NULL;
+  
+  /* channels */
+  ags_audio_set_audio_channels(audio,
+			       0);
+
+  ags_audio_set_pads(audio,
+		     AGS_TYPE_INPUT,
+		     0);
+  ags_audio_set_pads(audio,
+		     AGS_TYPE_OUTPUT,
+		     0);
+
+  /* playback domain */
+  if(audio->playback_domain != NULL){
+    g_object_run_dispose(audio->playback_domain);
+
+    audio->playback_domain = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_audio_parent_class)->dispose(gobject);
+}
+
+void
 ags_audio_finalize(GObject *gobject)
 {
   AgsAudio *audio;
@@ -1516,6 +1722,8 @@ ags_audio_finalize(GObject *gobject)
 
   AgsMutexManager *mutex_manager;
 
+  GList *list;
+
   pthread_mutex_t *application_mutex;
   
   mutex_manager = ags_mutex_manager_get_instance();
@@ -1542,46 +1750,134 @@ ags_audio_finalize(GObject *gobject)
     g_object_unref(audio->midi_file);
   }
   
-  /* output */
-  channel = audio->output;
+  /* audio connection */
+  if(audio->audio_connection != NULL){
+    list = audio->audio_connection;
 
-  if(channel != NULL){
-    while(channel->next != NULL){
-      channel = channel->next;
-      g_object_unref((GObject *) channel->prev);
+    while(list != NULL){
+      g_object_set(list->data,
+		   "audio", NULL,
+		   NULL);
+
+      list = list->next;
     }
 
-    g_object_unref((GObject *) channel);
+    g_list_free_full(audio->audio_connection,
+		     g_object_unref);
+  }
+  
+  /* playback domain */
+  if(audio->playback_domain != NULL){
+    g_object_unref(audio->playback_domain);
   }
+  
+  /* notation */
+  if(audio->notation != NULL){
+    list = audio->notation;
 
-  /* input */
-  channel = audio->input;
+    while(list != NULL){
+      g_object_set(list->data,
+		   "audio\0", NULL,
+		   NULL);
 
-  if(channel != NULL){
-    while(channel->next != NULL){
-      channel = channel->next;
-      g_object_unref((GObject *) channel->prev);
+      list = list->next;
     }
 
-    g_object_unref(channel);
+    g_list_free_full(audio->notation,
+		     g_object_unref);
   }
+  
+  /* automation */
+  if(audio->automation != NULL){
+    list = audio->automation;
+
+    while(list != NULL){
+      g_object_set(list->data,
+		   "audio\0", NULL,
+		   NULL);
+
+      list = list->next;
+    }
+
+    g_list_free_full(audio->automation,
+		     g_object_unref);
+  }
+  
+  /* recall id */
+  if(audio->recall_id != NULL){
+    g_list_free_full(audio->recall_id,
+		     g_object_unref);
+  }
+  
+  /* recycling context */
+  if(audio->recycling_context != NULL){
+    g_list_free_full(audio->recycling_context,
+		     g_object_unref);
+  }
+  
+  /* recall */
+  if(audio->container != NULL){
+    g_list_free_full(audio->container,
+		     g_object_unref);
+  }
+
+  if(audio->recall != NULL){
+    list = audio->recall;
+
+    while(list != NULL){
+      if(AGS_IS_RECALL_AUDIO(list->data) ||
+	 AGS_IS_RECALL_AUDIO_RUN(list->data)){
+	g_object_set(list->data,
+		     "audio\0", NULL,
+		     NULL);
+      }
+    
+      list = list->next;
+    }
+
+    g_list_free_full(audio->recall,
+		     g_object_unref);
+  }
+
+  if(audio->play != NULL){
+    list = audio->play;
 
-  /* free some lists */
-  g_list_free_full(audio->notation,
-		   g_object_unref);
+    while(list != NULL){
+      if(AGS_IS_RECALL_AUDIO(list->data) ||
+	 AGS_IS_RECALL_AUDIO_RUN(list->data)){
+	g_object_set(list->data,
+		     "audio\0", NULL,
+		     NULL);
+      }
+    
+      list = list->next;
+    }
 
-  g_list_free_full(audio->recall_id,
-		   g_object_unref);
+    g_list_free_full(audio->play,
+		     g_object_unref);
+  }
+  
+  /* remove */
+  if(audio->recall_remove != NULL){
+    g_list_free_full(audio->recall_remove,
+		     g_object_unref);
+  }
 
-  g_list_free_full(audio->recall,
-		   g_object_unref);
-  g_list_free_full(audio->play,
-		   g_object_unref);
+  if(audio->play_remove != NULL){
+    g_list_free_full(audio->play_remove,
+		     g_object_unref);
+  }
+  
+  /* channels */
+  ags_audio_set_audio_channels(audio,
+			       0);
 
-  g_list_free_full(audio->recall_remove,
-		   g_object_unref);
-  g_list_free_full(audio->play_remove,
-		   g_object_unref);
+  ags_audio_set_pads(audio,
+		     AGS_TYPE_INPUT,
+		     0);
+  ags_audio_set_pads(audio,
+		     AGS_TYPE_OUTPUT,
+		     0);
 
   /* call parent */
   G_OBJECT_CLASS(ags_audio_parent_class)->finalize(gobject);
@@ -1806,17 +2102,20 @@ ags_audio_set_soundcard(AgsAudio *audio, GObject *soundcard)
   }
   
   audio->soundcard = (GObject *) soundcard;
-  ags_soundcard_get_presets(AGS_SOUNDCARD(soundcard),
-			    NULL,
-			    &samplerate,
-			    &buffer_size,
-			    &format);
-  g_object_set(audio,
-	       "samplerate\0", samplerate,
-	       "buffer-size\0", buffer_size,
-	       "format\0", format,
-	       NULL);
 
+  if(soundcard != NULL){
+    ags_soundcard_get_presets(AGS_SOUNDCARD(soundcard),
+			      NULL,
+			      &samplerate,
+			      &buffer_size,
+			      &format);
+    g_object_set(audio,
+		 "samplerate\0", samplerate,
+		 "buffer-size\0", buffer_size,
+		 "format\0", format,
+		 NULL);
+  }
+  
   /* playback domain */
   if(AGS_PLAYBACK_DOMAIN(audio->playback_domain)->audio_thread[1] != NULL){
     g_object_set(AGS_PLAYBACK_DOMAIN(audio->playback_domain)->audio_thread[1],
@@ -2206,7 +2505,8 @@ ags_audio_real_set_audio_channels(AgsAudio *audio,
 					      "samplerate\0", audio->samplerate,
 					      "buffer-size\0", audio->buffer_size,
 					      NULL);
-
+	g_object_ref(channel);
+	
 	if(start == NULL){
 	  start = channel;
 
@@ -2270,8 +2570,9 @@ ags_audio_real_set_audio_channels(AgsAudio *audio,
 	  first_recycling =
 	    last_recycling = ags_recycling_new(audio->soundcard);
 	  g_object_ref(first_recycling);
-	  
-	  first_recycling->channel = (GObject *) channel;
+	  g_object_set(first_recycling,
+		       "channel\0", channel,
+		       NULL);
 	  
 	  ags_channel_set_recycling(channel,
 				    first_recycling, last_recycling,
@@ -2329,11 +2630,14 @@ ags_audio_real_set_audio_channels(AgsAudio *audio,
   ags_audio_set_audio_channel_shrink_zero0:
 
     while(channel != NULL){
-      ags_channel_set_link(channel, NULL, &error);
-      ags_channel_set_recycling(channel,
-				NULL, NULL,
-				TRUE, TRUE);
+      error =  NULL;
+      ags_channel_set_link(channel, NULL,
+			   &error);
 
+      if(error != NULL){
+	g_error("%s\0", error->message);
+      }
+      
       channel = channel->next;
     }
 
@@ -2342,6 +2646,7 @@ ags_audio_real_set_audio_channels(AgsAudio *audio,
     while(channel != NULL){
       channel_next = channel->next;
 
+      g_object_run_dispose(channel);
       g_object_unref((GObject *) channel);
 
       channel = channel_next;
@@ -2379,7 +2684,14 @@ ags_audio_real_set_audio_channels(AgsAudio *audio,
       channel = ags_channel_nth(channel, audio_channels);
 
       for(j = audio_channels; j < audio->audio_channels; j++){
-	ags_channel_set_link(channel, NULL, &error);
+	error = NULL;
+	ags_channel_set_link(channel, NULL,
+			     &error);
+	
+	if(error != NULL){
+	  g_error("%s\0", error->message);
+	}
+	
 	channel = channel->next;
       }
     }
@@ -2405,6 +2717,7 @@ ags_audio_real_set_audio_channels(AgsAudio *audio,
 	for(; j < audio->audio_channels; j++){
 	  channel1 = channel0->next;
       
+	  g_object_run_dispose(channel0);
 	  g_object_unref((GObject *) channel0);
 
 	  channel0 = channel1;
@@ -2579,6 +2892,8 @@ ags_audio_real_set_audio_channels(AgsAudio *audio,
 				   (audio->output_pads - j - 1) * audio_channels)->data;
 	playback_domain->playback = g_list_remove(playback_domain->playback,
 						  playback);
+	g_object_run_dispose(playback);
+	g_object_unref(playback);
       }
     }
   }
@@ -2717,6 +3032,8 @@ ags_audio_real_set_pads(AgsAudio *audio,
 					      "samplerate\0", audio->samplerate,
 					      "buffer-size\0", audio->buffer_size,
 					      NULL);
+	g_object_ref(channel);
+	
 	if(start == NULL){
 	  /* set first channel in AgsAudio */
 	  if(type == AGS_TYPE_OUTPUT){
@@ -2776,8 +3093,9 @@ ags_audio_real_set_pads(AgsAudio *audio,
 	  first_recycling =
 	    last_recycling = ags_recycling_new(audio->soundcard);
 	  g_object_ref(first_recycling);
-	  
-	  first_recycling->channel = (GObject *) channel;
+	  g_object_set(first_recycling,
+		       "channel\0", channel,
+		       NULL);
 	  
 	  ags_channel_set_recycling(channel,
 				    first_recycling, last_recycling,
@@ -2824,7 +3142,8 @@ ags_audio_real_set_pads(AgsAudio *audio,
 
     while(channel != NULL){
       error = NULL;
-      ags_channel_set_link(channel, NULL, &error);
+      ags_channel_set_link(channel, NULL,
+			   &error);
 
       if(error != NULL){
 	g_error("%s\0", error->message);
@@ -2837,9 +3156,20 @@ ags_audio_real_set_pads(AgsAudio *audio,
   void ags_audio_set_pads_shrink_zero(AgsChannel *channel){
     AgsChannel *channel_next;
 
+    GError *error;
+    
     while(channel != NULL){
       channel_next = channel->next;
 
+      error = NULL;
+      ags_channel_set_link(channel, NULL,
+			   &error);
+
+      if(error != NULL){
+	g_error("%s\0", error->message);
+      }
+      
+      g_object_run_dispose(channel);
       g_object_unref((GObject *) channel);
 
       channel = channel_next;
@@ -3046,7 +3376,9 @@ ags_audio_real_set_pads(AgsAudio *audio,
 	  current = current->next;
 	}
       }
-    }else if(pads == 0){      
+    }else if(pads == 0){
+      GList *list;
+      
       ags_audio_set_pads_shrink_automation();      
 
       if((AGS_AUDIO_HAS_NOTATION & (audio->flags)) != 0 &&
@@ -3063,7 +3395,16 @@ ags_audio_real_set_pads(AgsAudio *audio,
       audio->output = NULL;
 
       /* remove playback domain */
-      g_list_free(AGS_PLAYBACK_DOMAIN(audio->playback_domain)->playback);
+      list = AGS_PLAYBACK_DOMAIN(audio->playback_domain)->playback;
+
+      while(list != NULL){
+	g_object_run_dispose(list->data);
+
+	list = list->next;
+      }
+      
+      g_list_free_full(AGS_PLAYBACK_DOMAIN(audio->playback_domain)->playback,
+		       g_object_unref);
 
       AGS_PLAYBACK_DOMAIN(audio->playback_domain)->playback = NULL;
     }else if(pads < audio->output_pads){
@@ -3071,6 +3412,8 @@ ags_audio_real_set_pads(AgsAudio *audio,
 
       guint i;
       
+      channel = audio->output;
+
       ags_audio_set_pads_shrink_automation();      
       ags_audio_set_pads_remove_notes();
 
@@ -3092,6 +3435,8 @@ ags_audio_real_set_pads(AgsAudio *audio,
 	  playback = list->data;
 	  playback_domain->playback = g_list_remove(playback_domain->playback,
 						    playback);
+	  g_object_run_dispose(playback);
+	  g_object_unref(playback);
 	}
       }
     }
@@ -3857,34 +4202,27 @@ ags_audio_remove_recall_container(AgsAudio *audio, GObject *recall_container)
 void
 ags_audio_add_recall(AgsAudio *audio, GObject *recall, gboolean play)
 {
-  AgsMutexManager *mutex_manager;
-
-  pthread_mutex_t *application_mutex;
-  pthread_mutex_t *mutex;
-
-  /* lookup mutex */
-  mutex_manager = ags_mutex_manager_get_instance();
-  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
-
-  pthread_mutex_lock(application_mutex);
-
-  mutex = ags_mutex_manager_lookup(mutex_manager,
-				   (GObject *) audio);
+  if(audio == NULL ||
+     recall == NULL){
+    return;
+  }
   
-  pthread_mutex_unlock(application_mutex);
-
   /* add recall */
-  pthread_mutex_lock(mutex);
-  
   g_object_ref(G_OBJECT(recall));
 
   if(play){
+    pthread_mutex_lock(audio->play_mutex);
+    
     audio->play = g_list_prepend(audio->play, recall);
+
+    pthread_mutex_unlock(audio->play_mutex);
   }else{
+    pthread_mutex_lock(audio->recall_mutex);
+
     audio->recall = g_list_prepend(audio->recall, recall);
+
+    pthread_mutex_unlock(audio->recall_mutex);
   }
-  
-  pthread_mutex_unlock(mutex);
 }
 
 /**
@@ -3900,34 +4238,27 @@ ags_audio_add_recall(AgsAudio *audio, GObject *recall, gboolean play)
 void
 ags_audio_remove_recall(AgsAudio *audio, GObject *recall, gboolean play)
 {
-  AgsMutexManager *mutex_manager;
-
-  pthread_mutex_t *application_mutex;
-  pthread_mutex_t *mutex;
-
-  /* lookup mutex */
-  mutex_manager = ags_mutex_manager_get_instance();
-  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
-
-  pthread_mutex_lock(application_mutex);
-
-  mutex = ags_mutex_manager_lookup(mutex_manager,
-				   (GObject *) audio);
-  
-  pthread_mutex_unlock(application_mutex);
+  if(audio == NULL ||
+     recall == NULL){
+    return;
+  }
 
   /* remove recall */
-  pthread_mutex_lock(mutex);
-
   if(play){
+    pthread_mutex_lock(audio->play_mutex);
+
     audio->play = g_list_remove(audio->play, recall);
+
+    pthread_mutex_unlock(audio->play_mutex);
   }else{
+    pthread_mutex_lock(audio->recall_mutex);
+
     audio->recall = g_list_remove(audio->recall, recall);
+
+    pthread_mutex_unlock(audio->recall_mutex);
   }
 
   g_object_unref(G_OBJECT(recall));
-  
-  pthread_mutex_unlock(mutex);
 }
 
 /**
@@ -4365,12 +4696,12 @@ ags_audio_play(AgsAudio *audio,
 	       gint stage)
 {
   AgsRecall *recall;
-  GList *list, *list_next;
+  GList *list_start, *list, *list_next;
   AgsMutexManager *mutex_manager;
 
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *mutex;
-
+  
   if(audio == NULL ||
      recall_id == NULL){
     return;
@@ -4430,28 +4761,40 @@ ags_audio_play(AgsAudio *audio,
 
   /* retrieve appropriate recalls */
   if(recall_id->recycling_context->parent == NULL){
-    list = audio->play;
+    g_object_get(audio,
+		 "play\0", &list_start,
+		 NULL);
   }else{
-    list = audio->recall;
+    g_object_get(audio,
+		 "recall\0", &list_start,
+		 NULL);
   }
   
+  pthread_mutex_unlock(mutex);
+
+  list = list_start;
+  
   /* play */
   while(list != NULL){
+    guint recall_flags;
+    
     list_next = list->next;
 
-    recall = AGS_RECALL(list->data);
+    recall = (AgsRecall *) list->data;
 
-    if(recall == NULL){
-      if(recall_id->recycling_context->parent != NULL){
-	audio->recall = g_list_remove(audio->recall,
-				      recall);
-      }else{
-	audio->play = g_list_remove(audio->play,
-				    recall);
-      }
+    if(recall == NULL ||
+       !AGS_IS_RECALL(recall)){
+      //      if(recall_id->recycling_context->parent != NULL){
+      //	audio->recall = g_list_remove(audio->recall,
+      //				      recall);
+      //      }else{
+      //	audio->play = g_list_remove(audio->play,
+      //				    recall);
+      //      }
 
-      g_warning("recall == NULL\0");
       list = list_next;
+      g_warning("recall == NULL\0");
+      
       continue;
     }
 
@@ -4461,7 +4804,7 @@ ags_audio_play(AgsAudio *audio,
       }
 
       list = list_next;
-
+      
       continue;
     }
 
@@ -4472,22 +4815,28 @@ ags_audio_play(AgsAudio *audio,
       continue;
     }
 
-    if((AGS_RECALL_TEMPLATE & (recall->flags)) == 0){
-      if((AGS_RECALL_HIDE & (recall->flags)) == 0){
+    recall_flags = recall->flags;
+    
+    if((AGS_RECALL_TEMPLATE & (recall_flags)) == 0){
+      if((AGS_RECALL_HIDE & (recall_flags)) == 0){
+	g_object_ref(recall);
+	
 	if(stage == 0){
-	  ags_recall_run_pre(recall);
+	  AGS_RECALL_GET_CLASS(recall)->run_pre(recall);
 	}else if(stage == 1){
-	  ags_recall_run_inter(recall);
+	  AGS_RECALL_GET_CLASS(recall)->run_inter(recall);
 	}else{
-	  ags_recall_run_post(recall);
+	  AGS_RECALL_GET_CLASS(recall)->run_post(recall);
 	}
+
+	g_object_unref(recall);
       }
     }
     
     list = list_next;
   }
-  
-  pthread_mutex_unlock(mutex);
+
+  g_list_free(list_start);
 }
 
 /**
@@ -4535,6 +4884,76 @@ ags_audio_tact(AgsAudio *audio, AgsRecallID *recall_id)
   pthread_mutex_unlock(mutex);
 }
 
+void
+ags_audio_real_done(AgsAudio *audio,
+		    AgsRecallID *recall_id)
+{
+  AgsRecall *recall;
+
+  AgsMutexManager *mutex_manager;
+
+  GList *list, *list_next;
+
+  gboolean is_toplevel;
+  
+  pthread_mutex_t *application_mutex;
+  pthread_mutex_t *mutex;
+
+  /* lookup mutex */
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  pthread_mutex_lock(application_mutex);
+
+  mutex = ags_mutex_manager_lookup(mutex_manager,
+				   (GObject *) audio);
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* get context */
+  pthread_mutex_lock(mutex);
+
+  if(recall_id->recycling_context->parent == NULL){
+    list = audio->play;
+    
+    is_toplevel = TRUE;
+  }else{
+    list = audio->recall;
+
+    is_toplevel = FALSE;
+  }
+
+  /* remove recall, run dispose and unref */
+ ags_audio_real_done_RECALL0:
+  
+  while(list != NULL){
+    list_next = list->next;
+
+    recall = AGS_RECALL(list->data);
+    
+    if(recall->recall_id != NULL &&
+       recall->recall_id->recycling_context == recall_id->recycling_context){
+      g_object_run_dispose(recall);
+      ags_audio_remove_recall(audio,
+			      recall,
+			      is_toplevel);
+      g_object_unref(recall);
+    }
+
+    list = list_next;
+  }
+
+  if(is_toplevel &&
+     (AGS_AUDIO_OUTPUT_HAS_RECYCLING & (audio->flags)) != 0){
+    list = audio->recall;
+    is_toplevel = FALSE;
+    
+    goto ags_audio_real_done_RECALL0;
+  }
+  
+  pthread_mutex_unlock(mutex);
+}
+
 /**
  * ags_audio_done:
  * @audio: the #AgsAudio
@@ -4552,6 +4971,12 @@ ags_audio_done(AgsAudio *audio, AgsRecallID *recall_id)
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *mutex;
 
+  if(audio == NULL ||
+     recall_id == NULL ||
+     recall_id->recycling_context == NULL){
+    return;
+  }
+  
   /* lookup mutex */
   mutex_manager = ags_mutex_manager_get_instance();
   application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
@@ -4565,7 +4990,8 @@ ags_audio_done(AgsAudio *audio, AgsRecallID *recall_id)
 
   pthread_mutex_lock(mutex);
 
-  if(!AGS_IS_AUDIO(audio)){
+  if(!(AGS_IS_AUDIO(audio) ||
+       AGS_IS_RECALL_ID(recall_id))){
     pthread_mutex_unlock(mutex);
     return;
   }
@@ -4594,7 +5020,7 @@ ags_audio_cancel(AgsAudio *audio,
 		 AgsRecallID *recall_id)
 {
   AgsRecall *recall;
-  GList *list, *list_next;
+  GList *list_start, *list, *list_next;
   AgsMutexManager *mutex_manager;
 
   pthread_mutex_t *application_mutex;
@@ -4618,20 +5044,31 @@ ags_audio_cancel(AgsAudio *audio,
   /* cancel recalls */
   pthread_mutex_lock(mutex);
 
+  /* retrieve appropriate recalls */
   if(recall_id->recycling_context->parent == NULL){
-    list = audio->play;
+    g_object_get(audio,
+		 "play\0", &list_start,
+		 NULL);
   }else{
-    list = audio->recall;
+    g_object_get(audio,
+		 "recall\0", &list_start,
+		 NULL);
   }
   
   g_object_ref(recall_id);
+  
+  pthread_mutex_unlock(mutex);
 
+  list = list_start;
+  
   while(list != NULL){
     list_next = list->next;
 
     recall = AGS_RECALL(list->data);
 
-    if((AGS_RECALL_TEMPLATE & (recall->flags)) ||
+    if(recall == NULL ||
+       !AGS_IS_RECALL(recall) ||
+       (AGS_RECALL_TEMPLATE & (recall->flags)) ||
        recall->recall_id == NULL ||
        recall->recall_id->recycling_context != recall_id->recycling_context){
       list = list_next;
@@ -4639,14 +5076,12 @@ ags_audio_cancel(AgsAudio *audio,
       continue;
     }
 
-    g_object_ref(recall_id);
-    g_object_ref(recall);
     ags_recall_cancel(recall);
     
     list = list_next;
-  }
-  
-  pthread_mutex_unlock(mutex);
+  }  
+
+  g_list_free(list_start);
 }
 
 /**
diff --git a/ags/audio/ags_audio.h b/ags/audio/ags_audio.h
index 4743dff..03d11e1 100644
--- a/ags/audio/ags_audio.h
+++ b/ags/audio/ags_audio.h
@@ -20,9 +20,13 @@
 #ifndef __AGS_AUDIO_H__
 #define __AGS_AUDIO_H__
 
+#include <glib.h>
 #include <glib-object.h>
 
+#include <pthread.h>
+
 #include <ags/audio/ags_channel.h>
+#include <ags/audio/ags_recall_id.h>
 
 #define AGS_TYPE_AUDIO                (ags_audio_get_type ())
 #define AGS_AUDIO(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_AUDIO, AgsAudio))
@@ -48,6 +52,7 @@ typedef enum{
   AGS_AUDIO_RUNNING                     = 1 << 10,
   AGS_AUDIO_PLAYING                     = 1 << 11,
   AGS_AUDIO_CONNECTED                   = 1 << 12,
+  AGS_AUDIO_CAN_NEXT_ACTIVE             = 1 << 13,
 }AgsAudioFlags;
 
 struct _AgsAudio
@@ -96,10 +101,13 @@ struct _AgsAudio
   GList *recall_id;
   GList *recycling_context;
 
+  pthread_mutex_t *recall_mutex;
+  pthread_mutex_t *play_mutex;
+
   GList *container;
   GList *recall;
   GList *play;
-
+  
   GList *recall_remove; //TODO:JK: verify deprecation
   GList *play_remove; //TODO:JK: verify deprecation
 
diff --git a/ags/audio/ags_audio_application_context.c b/ags/audio/ags_audio_application_context.c
index bcc80fe..52f297d 100644
--- a/ags/audio/ags_audio_application_context.c
+++ b/ags/audio/ags_audio_application_context.c
@@ -118,6 +118,9 @@ void ags_audio_application_context_disconnect(AgsConnectable *connectable);
 AgsThread* ags_audio_application_context_get_main_loop(AgsConcurrencyProvider *concurrency_provider);
 AgsThread* ags_audio_application_context_get_task_thread(AgsConcurrencyProvider *concurrency_provider);
 AgsThreadPool* ags_audio_application_context_get_thread_pool(AgsConcurrencyProvider *concurrency_provider);
+GList* ags_audio_application_context_get_worker(AgsConcurrencyProvider *concurrency_provider);
+void ags_audio_application_context_set_worker(AgsConcurrencyProvider *concurrency_provider,
+					      GList *worker);
 GList* ags_audio_application_context_get_soundcard(AgsSoundProvider *sound_provider);
 GObject* ags_audio_application_context_get_default_soundcard_thread(AgsSoundProvider *sound_provider);
 void ags_audio_application_context_set_default_soundcard_thread(AgsSoundProvider *sound_provider,
@@ -128,6 +131,7 @@ GList* ags_audio_application_context_get_sequencer(AgsSoundProvider *sound_provi
 void ags_audio_application_context_set_sequencer(AgsSoundProvider *sound_provider,
 						 GList *sequencer);
 GList* ags_audio_application_context_get_distributed_manager(AgsSoundProvider *sound_provider);
+void ags_audio_application_context_dispose(GObject *gobject);
 void ags_audio_application_context_finalize(GObject *gobject);
 
 void ags_audio_application_context_register_types(AgsApplicationContext *application_context);
@@ -228,6 +232,7 @@ ags_audio_application_context_class_init(AgsAudioApplicationContextClass *audio_
   gobject->set_property = ags_audio_application_context_set_property;
   gobject->get_property = ags_audio_application_context_get_property;
 
+  gobject->dispose = ags_audio_application_context_dispose;
   gobject->finalize = ags_audio_application_context_finalize;
   
   /**
@@ -270,6 +275,8 @@ ags_audio_application_context_concurrency_provider_interface_init(AgsConcurrency
   concurrency_provider->get_main_loop = ags_audio_application_context_get_main_loop;
   concurrency_provider->get_task_thread = ags_audio_application_context_get_task_thread;
   concurrency_provider->get_thread_pool = ags_audio_application_context_get_thread_pool;
+  concurrency_provider->get_worker = ags_audio_application_context_get_worker;
+  concurrency_provider->set_worker = ags_audio_application_context_set_worker;
 }
 
 void
@@ -315,6 +322,7 @@ ags_audio_application_context_init(AgsAudioApplicationContext *audio_application
   /**/
   config = ags_config_get_instance();
   AGS_APPLICATION_CONTEXT(audio_application_context)->config = config;
+  g_object_ref(config);
   g_object_set(config,
 	       "application-context\0", audio_application_context,
 	       NULL);
@@ -609,6 +617,9 @@ ags_audio_application_context_init(AgsAudioApplicationContext *audio_application
   ags_thread_add_child_extended(AGS_THREAD(audio_loop),
 				AGS_THREAD(AGS_APPLICATION_CONTEXT(audio_application_context)->task_thread),
 				TRUE, TRUE);
+
+  /* AgsWorkerThread */
+  audio_application_context->worker = NULL;
   
   /* AgsSoundcardThread */
   audio_application_context->soundcard_thread = NULL;
@@ -820,6 +831,19 @@ ags_audio_application_context_get_thread_pool(AgsConcurrencyProvider *concurrenc
 }
 
 GList*
+ags_audio_application_context_get_worker(AgsConcurrencyProvider *concurrency_provider)
+{
+  return(AGS_AUDIO_APPLICATION_CONTEXT(concurrency_provider)->worker);
+}
+
+void
+ags_audio_application_context_set_worker(AgsConcurrencyProvider *concurrency_provider,
+					 GList *worker)
+{
+  AGS_AUDIO_APPLICATION_CONTEXT(concurrency_provider)->worker = worker;
+}
+
+GList*
 ags_audio_application_context_get_soundcard(AgsSoundProvider *sound_provider)
 {
   return(AGS_AUDIO_APPLICATION_CONTEXT(sound_provider)->soundcard);
@@ -865,6 +889,103 @@ ags_audio_application_context_get_distributed_manager(AgsSoundProvider *sound_pr
 }
 
 void
+ags_audio_application_context_dispose(GObject *gobject)
+{
+  AgsAudioApplicationContext *audio_application_context;
+
+  GList *list;
+  
+  audio_application_context = AGS_AUDIO_APPLICATION_CONTEXT(gobject);
+
+  /* thread pool */
+  if(audio_application_context->thread_pool != NULL){
+    g_object_unref(audio_application_context->thread_pool);
+    
+    audio_application_context->thread_pool = NULL;
+  }
+
+  /* soundcard and export thread */
+  if(audio_application_context->soundcard_thread != NULL){
+    g_object_unref(audio_application_context->soundcard_thread);
+
+    audio_application_context->soundcard_thread = NULL;
+  }
+
+  if(audio_application_context->export_thread != NULL){
+    g_object_unref(audio_application_context->export_thread);
+
+    audio_application_context->export_thread = NULL;
+  }
+
+  /* server */
+  if(audio_application_context->server != NULL){
+    g_object_set(audio_application_context->server,
+		 "application-context\0", NULL,
+		 NULL);
+    
+    g_object_unref(audio_application_context->server);
+
+    audio_application_context->server = NULL;
+  }
+
+  /* soundcard and sequencer */
+  if(audio_application_context->soundcard != NULL){
+    list = audio_application_context->soundcard;
+
+    while(list != NULL){
+      g_object_set(list->data,
+		   "application-context\0", NULL,
+		   NULL);
+
+      list = list->next;
+    }
+    
+    g_list_free_full(audio_application_context->soundcard,
+		     g_object_unref);
+
+    audio_application_context->soundcard = NULL;
+  }
+
+  if(audio_application_context->sequencer != NULL){
+    list = audio_application_context->sequencer;
+
+    while(list != NULL){
+      g_object_set(list->data,
+		   "application-context\0", NULL,
+		   NULL);
+
+      list = list->next;
+    }
+
+    g_list_free_full(audio_application_context->sequencer,
+		     g_object_unref);
+
+    audio_application_context->sequencer = NULL;
+  }
+
+  /* distributed manager */
+  if(audio_application_context->distributed_manager != NULL){
+    list = audio_application_context->distributed_manager;
+
+    while(list != NULL){
+      g_object_set(list->data,
+		   "application-context\0", NULL,
+		   NULL);
+
+      list = list->next;
+    }
+
+    g_list_free_full(audio_application_context->distributed_manager,
+		     g_object_unref);
+
+    audio_application_context->distributed_manager = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_audio_application_context_parent_class)->dispose(gobject);
+}
+
+void
 ags_audio_application_context_finalize(GObject *gobject)
 {
   AgsAudioApplicationContext *audio_application_context;
diff --git a/ags/audio/ags_audio_application_context.h b/ags/audio/ags_audio_application_context.h
index 6492b91..0cc89da 100644
--- a/ags/audio/ags_audio_application_context.h
+++ b/ags/audio/ags_audio_application_context.h
@@ -52,8 +52,8 @@
 
 #define AGS_AUDIO_RT_PRIORITY (49)
 
-#define AGS_AUDIO_BUILD_ID "Wed Apr 13 00:16:43 CEST 2016\0"
-#define AGS_AUDIO_DEFAULT_VERSION "0.7.13\0"
+#define AGS_AUDIO_DEFAULT_VERSION "0.7.122.8\0"
+#define AGS_AUDIO_BUILD_ID "Tue Mar 21 20:03:29 CET 2017\0"
 
 #define AGS_EFFECTS_DEFAULT_VERSION "0.7.13\0"
 
@@ -75,6 +75,8 @@ struct _AgsAudioApplicationContext
 
   AgsThreadPool *thread_pool;
 
+  GList *worker;
+
   AgsThread *soundcard_thread;
   AgsThread *export_thread;
 
diff --git a/ags/audio/ags_audio_connection.c b/ags/audio/ags_audio_connection.c
index 4c02a19..8f13a32 100644
--- a/ags/audio/ags_audio_connection.c
+++ b/ags/audio/ags_audio_connection.c
@@ -122,7 +122,7 @@ ags_audio_connection_class_init(AgsAudioConnectionClass *audio_connection)
   param_spec = g_param_spec_ulong("channel-type\0",
 				  "channel type\0",
 				  "The channel type belonging to\0",
-				  0, G_MAXUINT32,
+				  0, G_MAXULONG,
 				  G_TYPE_NONE,
 				  G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
diff --git a/ags/audio/ags_audio_signal.c b/ags/audio/ags_audio_signal.c
index 8c9b6d9..46c9957 100644
--- a/ags/audio/ags_audio_signal.c
+++ b/ags/audio/ags_audio_signal.c
@@ -57,9 +57,10 @@ void ags_audio_signal_get_property(GObject *gobject,
 				   guint prop_id,
 				   GValue *value,
 				   GParamSpec *param_spec);
-void ags_audio_signal_finalize(GObject *gobject);
 void ags_audio_signal_connect(AgsConnectable *connectable);
 void ags_audio_signal_disconnect(AgsConnectable *connectable);
+void ags_audio_signal_dispose(GObject *gobject);
+void ags_audio_signal_finalize(GObject *gobject);
 
 void ags_audio_signal_real_realloc_buffer_size(AgsAudioSignal *audio_signal, guint buffer_size);
 
@@ -145,6 +146,7 @@ ags_audio_signal_class_init(AgsAudioSignalClass *audio_signal)
   gobject->set_property = ags_audio_signal_set_property;
   gobject->get_property = ags_audio_signal_get_property;
 
+  gobject->dispose = ags_audio_signal_dispose;
   gobject->finalize = ags_audio_signal_finalize;
 
   /* properties */
@@ -946,6 +948,70 @@ ags_audio_signal_get_property(GObject *gobject,
 }
 
 void
+ags_audio_signal_connect(AgsConnectable *connectable)
+{
+  AgsAudioSignal *audio_signal;
+
+  audio_signal = AGS_AUDIO_SIGNAL(connectable);
+
+  if((AGS_AUDIO_SIGNAL_CONNECTED & (audio_signal->flags)) != 0){
+    return;
+  }
+
+  audio_signal->flags |= AGS_AUDIO_SIGNAL_CONNECTED;
+}
+
+void
+ags_audio_signal_disconnect(AgsConnectable *connectable)
+{
+  AgsAudioSignal *audio_signal;
+
+  audio_signal = AGS_AUDIO_SIGNAL(connectable);
+
+  if((AGS_AUDIO_SIGNAL_CONNECTED & (audio_signal->flags)) == 0){
+    return;
+  }
+
+  audio_signal->flags &= (~AGS_AUDIO_SIGNAL_CONNECTED);
+}
+
+void
+ags_audio_signal_dispose(GObject *gobject)
+{
+  AgsAudioSignal *audio_signal;
+
+  audio_signal = AGS_AUDIO_SIGNAL(gobject);
+
+  /* soundcard */
+  if(audio_signal->soundcard != NULL){
+    g_object_unref(audio_signal->soundcard);
+
+    audio_signal->soundcard = NULL;
+  }
+
+  /* recycling */
+  if(audio_signal->recycling != NULL){
+    g_object_unref(audio_signal->recycling);
+    
+    audio_signal->recycling = NULL;  
+  }
+
+  /* recall id */
+  if(audio_signal->recall_id != NULL){
+    g_object_unref(audio_signal->recall_id);
+
+    audio_signal->recall_id = NULL;
+  }
+
+  /* note */
+  if(audio_signal->note != NULL){
+    g_object_unref(audio_signal->note);
+
+    audio_signal->note = NULL;
+  }
+}
+
+void
 ags_audio_signal_finalize(GObject *gobject)
 {
   AgsAudioSignal *audio_signal;
@@ -962,7 +1028,8 @@ ags_audio_signal_finalize(GObject *gobject)
   if((AGS_AUDIO_SIGNAL_TEMPLATE & (audio_signal->flags)) != 0){
     g_warning("AGS_AUDIO_SIGNAL_TEMPLATE: destroying\n\0");
   }
-  
+
+  /* disconnect */
   ids = g_signal_list_ids(AGS_TYPE_AUDIO_SIGNAL,
 			  &n_ids);
   
@@ -977,24 +1044,29 @@ ags_audio_signal_finalize(GObject *gobject)
   }
 
   g_free(ids);
-  
+
+  /* soundcard */
   if(audio_signal->soundcard != NULL){
     g_object_unref(audio_signal->soundcard);
   }
-  
+
+  /* recycling */
   if(audio_signal->recycling != NULL){
     g_object_unref(audio_signal->recycling);
   }
-  
+
+  /* recall id */
   if(audio_signal->recall_id != NULL){
     g_object_unref(audio_signal->recall_id);
   }
-  
+
+  /* audio data */
   if(audio_signal->stream_beginning != NULL){
     g_list_free_full(audio_signal->stream_beginning,
 		     (GDestroyNotify) ags_stream_free);
   }
 
+  /* note */
   if(audio_signal->note != NULL){
     g_object_unref(audio_signal->note);
   }
@@ -1003,18 +1075,6 @@ ags_audio_signal_finalize(GObject *gobject)
   G_OBJECT_CLASS(ags_audio_signal_parent_class)->finalize(gobject);
 }
 
-void
-ags_audio_signal_connect(AgsConnectable *connectable)
-{
-  // empty
-}
-
-void
-ags_audio_signal_disconnect(AgsConnectable *connectable)
-{
-  // empty
-}
-
 /**
  * ags_stream_alloc:
  * @buffer_size: the buffer size
@@ -2658,6 +2718,45 @@ ags_audio_signal_envelope(AgsAudioSignal *audio_signal,
 }
 
 /**
+ * ags_audio_signal_is_active:
+ * @audio_signal: the #GList-struct containing #AgsAudioSignal
+ * @recall_id: the #AgsRecallID
+ * 
+ * Check if is active.
+ * 
+ * Returns: %TRUE if related audio signal to recall id is available, otherwise %FALSE
+ * 
+ * Since: 0.7.122.9
+ */
+gboolean
+ags_audio_signal_is_active(GList *audio_signal,
+			   GObject *recall_id)
+{
+  AgsAudioSignal *current;
+  AgsRecyclingContext *recycling_context;
+  
+  if(recall_id == NULL ||
+     AGS_RECALL_ID(recall_id)->recycling_context == NULL){
+    return(FALSE);
+  }
+  
+  recycling_context = AGS_RECALL_ID(recall_id)->recycling_context;
+  
+  while(audio_signal != NULL){
+    current = AGS_AUDIO_SIGNAL(audio_signal->data);
+    
+    if(current->recall_id != NULL &&
+       AGS_RECALL_ID(current->recall_id)->recycling_context == recycling_context){
+      return(TRUE);
+    }
+    
+    audio_signal = audio_signal->next;
+  }
+  
+  return(FALSE);
+}
+
+/**
  * ags_audio_signal_new:
  * @soundcard: the assigned #AgsSoundcard
  * @recycling: the #AgsRecycling
diff --git a/ags/audio/ags_audio_signal.h b/ags/audio/ags_audio_signal.h
index 4e7eed8..16eb146 100644
--- a/ags/audio/ags_audio_signal.h
+++ b/ags/audio/ags_audio_signal.h
@@ -34,9 +34,10 @@ typedef struct _AgsAudioSignal AgsAudioSignal;
 typedef struct _AgsAudioSignalClass AgsAudioSignalClass;
 
 typedef enum{
-  AGS_AUDIO_SIGNAL_TEMPLATE             = 1,
-  AGS_AUDIO_SIGNAL_PLAY_DONE            = 1 << 1,
-  AGS_AUDIO_SIGNAL_STANDALONE           = 1 << 2,
+  AGS_AUDIO_SIGNAL_CONNECTED            = 1,
+  AGS_AUDIO_SIGNAL_TEMPLATE             = 1 <<  1,
+  AGS_AUDIO_SIGNAL_PLAY_DONE            = 1 <<  2,
+  AGS_AUDIO_SIGNAL_STANDALONE           = 1 <<  3,
 }AgsAudioSignalFlags;
 
 struct _AgsAudioSignal
@@ -126,6 +127,9 @@ void ags_audio_signal_envelope(AgsAudioSignal *audio_signal,
 			       gdouble release,
 			       gdouble ratio);
 
+gboolean ags_audio_signal_is_active(GList *audio_signal,
+				    GObject *recall_id);
+
 AgsAudioSignal* ags_audio_signal_new(GObject *soundcard,
 				     GObject *recycling,
 				     GObject *recall_id);
diff --git a/ags/audio/ags_automation.c b/ags/audio/ags_automation.c
index 082d5a4..a977536 100644
--- a/ags/audio/ags_automation.c
+++ b/ags/audio/ags_automation.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -35,6 +35,8 @@
 
 #include <ags/config.h>
 
+#include <pthread.h>
+
 #include <stdlib.h>
 
 #include <math.h>
@@ -54,7 +56,8 @@ void ags_automation_get_property(GObject *gobject,
 				 GParamSpec *param_spec);
 void ags_automation_connect(AgsConnectable *connectable);
 void ags_automation_disconnect(AgsConnectable *connectable);
-void ags_automation_finalize(GObject *object);
+void ags_automation_dispose(GObject *gobject);
+void ags_automation_finalize(GObject *gobject);
 
 void ags_automation_set_port(AgsPortlet *portlet, GObject *port);
 GObject* ags_automation_get_port(AgsPortlet *portlet);
@@ -155,6 +158,7 @@ ags_automation_class_init(AgsAutomationClass *automation)
   gobject->set_property = ags_automation_set_property;
   gobject->get_property = ags_automation_get_property;
 
+  gobject->dispose = ags_automation_dispose;
   gobject->finalize = ags_automation_finalize;
 
   /* properties */
@@ -315,7 +319,22 @@ ags_automation_class_init(AgsAutomationClass *automation)
 				  PROP_DEFAULT_VALUE,
 				  param_spec);
 
-    
+
+  /**
+   * AgsAutomation:acceleration:
+   *
+   * The acceleration list.
+   * 
+   * Since: 0.7.122.8
+   */
+  param_spec = g_param_spec_pointer("acceleration\0",
+				    "acceleration\0",
+				    "The acceleration\0",
+				    G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_ACCELERATION,
+				  param_spec);
+
   /**
    * AgsAutomation:current-accelerations:
    *
@@ -432,13 +451,51 @@ ags_automation_init(AgsAutomation *automation)
 void
 ags_automation_connect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsAutomation *automation;
+
+  GList *list;
+  
+  automation = AGS_AUTOMATION(connectable);
+
+  if((AGS_AUTOMATION_CONNECTED & (automation->flags)) != 0){
+    return;
+  }
+
+  automation->flags |= AGS_AUTOMATION_CONNECTED;
+
+  /* acceleration */
+  list = automation->acceleration;
+
+  while(list != NULL){
+    ags_connectable_connect(AGS_CONNECTABLE(list->data));
+
+    list = list->next;
+  }
 }
 
 void
 ags_automation_disconnect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsAutomation *automation;
+
+  GList *list;
+
+  automation = AGS_AUTOMATION(connectable);
+
+  if((AGS_AUTOMATION_CONNECTED & (automation->flags)) == 0){
+    return;
+  }
+
+  automation->flags &= (~AGS_AUTOMATION_CONNECTED);
+
+  /* acceleration */
+  list = automation->acceleration;
+
+  while(list != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
+
+    list = list->next;
+  }
 }
 
 void
@@ -520,6 +577,10 @@ ags_automation_set_property(GObject *gobject,
 
       if(port != NULL){
 	g_object_ref(port);
+
+	if((AGS_PORT_INFINITE_RANGE & (port->flags)) != 0){
+	  automation->steps = AGS_AUTOMATION_MAXIMUM_STEPS;
+	}
       }
 
       automation->port = (GObject *) port;
@@ -723,19 +784,103 @@ ags_automation_get_property(GObject *gobject,
 }
 
 void
+ags_automation_dispose(GObject *gobject)
+{
+  AgsAutomation *automation;
+
+  GList *list;
+  
+  automation = AGS_AUTOMATION(gobject);
+
+  /* timestamp */
+  if(automation->timestamp != NULL){
+    g_object_unref(automation->timestamp);
+
+    automation->timestamp = NULL;
+  }
+
+  /* audio */
+  if(automation->audio != NULL){
+    g_object_unref(automation->audio);
+
+    automation->audio = NULL;
+  }
+
+  /* source function */
+  if(automation->source_function != NULL){
+    g_object_run_dispose(automation->source_function);
+    
+    g_object_unref(automation->source_function);
+
+    automation->source_function = NULL;
+  }
+
+  /* acceleration */
+  list = automation->acceleration;
+
+  while(list != NULL){
+    g_object_run_dispose(G_OBJECT(list->data));
+
+    list = list->next;
+  }
+  
+  g_list_free_full(automation->acceleration,
+		   g_object_unref);
+  g_list_free(automation->selection);
+
+  automation->acceleration = NULL;
+  automation->selection = NULL;
+
+  /* port */
+  if(automation->port != NULL){
+    g_object_unref(automation->port);
+
+    automation->port = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_automation_parent_class)->dispose(gobject);
+}
+
+void
 ags_automation_finalize(GObject *gobject)
 {
   AgsAutomation *automation;
 
   automation = AGS_AUTOMATION(gobject);
+
+  /* timestamp */
+  if(automation->timestamp != NULL){
+    g_object_unref(automation->timestamp);
+  }
   
+  /* audio */
   if(automation->audio != NULL){
     g_object_unref(automation->audio);
   }
+
+  /* control name */
+  if(automation->control_name != NULL){
+    free(automation->control_name);
+  }
+
+  /* source function */
+  if(automation->source_function != NULL){
+    g_object_unref(automation->source_function);
+  }
   
+  /* acceleration */
   g_list_free_full(automation->acceleration,
 		   g_object_unref);
 
+  g_list_free(automation->selection);
+
+  /* port */
+  if(automation->port != NULL){
+    g_object_unref(automation->port);
+  }
+  
+  /* call parent */
   G_OBJECT_CLASS(ags_automation_parent_class)->finalize(gobject);
 }
 
@@ -762,9 +907,20 @@ ags_automation_get_port(AgsPortlet *portlet)
 GList*
 ags_automation_list_safe_properties(AgsPortlet *portlet)
 {
-  //TODO:JK: implement me
+  static GList *list = NULL;
 
-  return(NULL);
+  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+  pthread_mutex_lock(&mutex);
+
+  if(list == NULL){
+    list = g_list_prepend(list, "current-accelerations\0");
+    list = g_list_prepend(list, "next-accelerations\0");
+  }
+
+  pthread_mutex_unlock(&mutex);
+
+  return(list);
 }
 
 void
diff --git a/ags/audio/ags_automation.h b/ags/audio/ags_automation.h
index 53d4d82..d9e1b01 100644
--- a/ags/audio/ags_automation.h
+++ b/ags/audio/ags_automation.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -45,6 +45,7 @@
 #define AGS_AUTOMATION_DEFAULT_DURATION (AGS_AUTOMATION_DEFAULT_LENGTH * AGS_AUTOMATION_DEFAULT_JIFFIE * AGS_MICROSECONDS_PER_SECOND)
 
 #define AGS_AUTOMATION_DEFAULT_PRECISION (8)
+#define AGS_AUTOMATION_MAXIMUM_STEPS (128)
 
 typedef struct _AgsAutomation AgsAutomation;
 typedef struct _AgsAutomationClass AgsAutomationClass;
diff --git a/ags/audio/ags_channel.c b/ags/audio/ags_channel.c
index 9c8c51c..2274545 100644
--- a/ags/audio/ags_channel.c
+++ b/ags/audio/ags_channel.c
@@ -111,7 +111,8 @@ void ags_channel_add_to_registry(AgsConnectable *connectable);
 void ags_channel_remove_from_registry(AgsConnectable *connectable);
 void ags_channel_connect(AgsConnectable *connectable);
 void ags_channel_disconnect(AgsConnectable *connectable);
-static void ags_channel_finalize(GObject *gobject);
+void ags_channel_dispose(GObject *gobject);
+void ags_channel_finalize(GObject *gobject);
 
 GList* ags_channel_add_ladspa_effect(AgsChannel *channel,
 				     gchar *filename,
@@ -127,6 +128,8 @@ GList* ags_channel_real_add_effect(AgsChannel *channel,
 				   gchar *effect);
 void ags_channel_real_remove_effect(AgsChannel *channel,
 				    guint nth);
+void ags_channel_real_done(AgsChannel *channel,
+			   AgsRecallID *recall_id);
 
 enum{
   ADD_EFFECT,
@@ -212,6 +215,7 @@ ags_channel_class_init(AgsChannelClass *channel)
   gobject->set_property = ags_channel_set_property;
   gobject->get_property = ags_channel_get_property;
 
+  gobject->dispose = ags_channel_dispose;
   gobject->finalize = ags_channel_finalize;
 
   /* properties */
@@ -394,11 +398,10 @@ ags_channel_class_init(AgsChannelClass *channel)
    * 
    * Since: 0.7.2
    */
-  param_spec = g_param_spec_object("recall-id\0",
-				   "assigned recall id\0",
-				   "The recall id it is assigned with\0",
-				   AGS_TYPE_RECALL_ID,
-				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  param_spec = g_param_spec_pointer("recall-id\0",
+				    "assigned recall id\0",
+				    "The recall id it is assigned with\0",
+				    G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
 				  PROP_RECALL_ID,
 				  param_spec);
@@ -410,11 +413,10 @@ ags_channel_class_init(AgsChannelClass *channel)
    * 
    * Since: 0.7.2
    */
-  param_spec = g_param_spec_object("recall-container\0",
-				   "containing recall-container\0",
-				   "The recall container it contains\0",
-				   AGS_TYPE_RECALL_CONTAINER,
-				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  param_spec = g_param_spec_pointer("recall-container\0",
+				    "containing recall-container\0",
+				    "The recall container it contains\0",
+				    G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
 				  PROP_RECALL_CONTAINER,
 				  param_spec);
@@ -426,11 +428,10 @@ ags_channel_class_init(AgsChannelClass *channel)
    * 
    * Since: 0.7.2
    */
-  param_spec = g_param_spec_object("recall\0",
-				   "containing recall\0",
-				   "The recall it contains\0",
-				   AGS_TYPE_RECALL,
-				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  param_spec = g_param_spec_pointer("recall\0",
+				    "containing recall\0",
+				    "The recall it contains\0",
+				    G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
 				  PROP_RECALL,
 				  param_spec);
@@ -442,11 +443,10 @@ ags_channel_class_init(AgsChannelClass *channel)
    * 
    * Since: 0.7.2
    */
-  param_spec = g_param_spec_object("play\0",
-				   "containing play\0",
-				   "The play it contains\0",
-				   AGS_TYPE_RECALL,
-				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  param_spec = g_param_spec_pointer("play\0",
+				    "containing play\0",
+				    "The play it contains\0",
+				    G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
 				  PROP_PLAY,
 				  param_spec);
@@ -506,11 +506,10 @@ ags_channel_class_init(AgsChannelClass *channel)
    * 
    * Since: 0.7.2
    */
-  param_spec = g_param_spec_object("pattern\0",
-				   "containing pattern\0",
-				   "The pattern it contains\0",
-				   AGS_TYPE_PATTERN,
-				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  param_spec = g_param_spec_pointer("pattern\0",
+				    "containing pattern\0",
+				    "The pattern it contains\0",
+				    G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
 				  PROP_PATTERN,
 				  param_spec);
@@ -521,7 +520,7 @@ ags_channel_class_init(AgsChannelClass *channel)
 
   channel->recycling_changed = NULL;
 
-  channel->done = NULL;
+  channel->done = ags_channel_real_done;
 
   /* signals */
     /**
@@ -753,80 +752,46 @@ ags_channel_init(AgsChannel *channel)
 
   /* playback */
   channel->playback = (GObject *) ags_playback_new();
-  AGS_PLAYBACK(channel->playback)->source = (GObject *) channel;
-
-  /* thread model */
-  str0 = ags_config_get_value(config,
-			      AGS_CONFIG_THREAD,
-			      "model\0");
-  str1 = ags_config_get_value(config,
-			      AGS_CONFIG_THREAD,
-			      "super-threaded-scope\0");
+  g_object_ref(channel->playback);
+  g_object_set(channel->playback,
+	       "source\0", channel,
+	       NULL);
 
-  if(str0 != NULL && str1 != NULL){
-    if(!g_ascii_strncasecmp(str0,
-			    "super-threaded\0",
-			    15)){
-      if(!g_ascii_strncasecmp(str1,
-			      "channel\0",
-			      8) ||
-	 !g_ascii_strncasecmp(str1,
-			      "recycling\0",
-			      10)){
-	gdouble freq;
-	
-	freq = ceil((gdouble) channel->samplerate / (gdouble) channel->buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK;
+  channel->recall_id = NULL;
 
-	g_atomic_int_or(&(AGS_PLAYBACK(channel->playback)->flags),
-			AGS_PLAYBACK_SUPER_THREADED_CHANNEL);
+  /* recall */
+  attr = (pthread_mutexattr_t *) malloc(sizeof(pthread_mutexattr_t));
+  pthread_mutexattr_init(attr);
+  pthread_mutexattr_settype(attr,
+			    PTHREAD_MUTEX_RECURSIVE);
 
-	AGS_PLAYBACK(channel->playback)->channel_thread[0] = (AgsThread *) ags_channel_thread_new(NULL,
-												  (GObject *) channel);
-	AGS_PLAYBACK(channel->playback)->channel_thread[0]->freq = freq;
-	
-	AGS_PLAYBACK(channel->playback)->channel_thread[1] = (AgsThread *) ags_channel_thread_new(NULL,
-												  (GObject *) channel);
-	AGS_PLAYBACK(channel->playback)->channel_thread[1]->freq = freq;
+  channel->recall_mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
+  pthread_mutex_init(channel->recall_mutex,
+		     attr);
 
-	AGS_PLAYBACK(channel->playback)->channel_thread[2] = (AgsThread *) ags_channel_thread_new(NULL,
-												  (GObject *) channel);
-	AGS_PLAYBACK(channel->playback)->channel_thread[2]->freq = freq;
-	
-	if(!g_ascii_strncasecmp(str1,
-				"recycling\0",
-				10)){
-	  AGS_PLAYBACK(channel->playback)->recycling_thread[0] = (AgsThread *) ags_recycling_thread_new(NULL,
-													NULL);
-	  AGS_PLAYBACK(channel->playback)->recycling_thread[1] = (AgsThread *) ags_recycling_thread_new(NULL,
-													NULL);
-	  AGS_PLAYBACK(channel->playback)->recycling_thread[2] = (AgsThread *) ags_recycling_thread_new(NULL,
-													NULL);
-	}
-      }
-    }
-  } 
+  attr = (pthread_mutexattr_t *) malloc(sizeof(pthread_mutexattr_t));
+  pthread_mutexattr_init(attr);
+  pthread_mutexattr_settype(attr,
+			    PTHREAD_MUTEX_RECURSIVE);
 
-  if(str0 != NULL){
-    free(str0);
-  }
+  channel->play_mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
+  pthread_mutex_init(channel->play_mutex,
+		     attr);
 
-  if(str1 != NULL){
-    free(str1);
-  }
-  
-  channel->recall_id = NULL;
   channel->container = NULL;
-
   channel->recall = NULL;
   channel->play = NULL;
 
+  /* link and recycling */
   channel->link = NULL;
   
   channel->first_recycling = NULL;
   channel->last_recycling = NULL;
 
+  /* pattern */
   channel->pattern = NULL;
 
+  /* data */
   channel->line_widget = NULL;
   channel->file_data = NULL;
 }
@@ -959,7 +924,7 @@ ags_channel_set_property(GObject *gobject,
     {
       AgsRecallID *recall_id;
 
-      recall_id = (AgsRecallID *) g_value_get_object(value);
+      recall_id = (AgsRecallID *) g_value_get_pointer(value);
 
       if(recall_id == NULL ||
 	 g_list_find(channel->recall_id, recall_id) != NULL){
@@ -974,7 +939,7 @@ ags_channel_set_property(GObject *gobject,
     {
       AgsRecallContainer *recall_container;
 
-      recall_container = (AgsRecallContainer *) g_value_get_object(value);
+      recall_container = (AgsRecallContainer *) g_value_get_pointer(value);
 
       if(recall_container == NULL ||
 	 g_list_find(channel->container, recall_container) != NULL){
@@ -989,10 +954,18 @@ ags_channel_set_property(GObject *gobject,
     {
       AgsRecall *recall;
 
-      recall = (AgsRecall *) g_value_get_object(value);
+      gboolean recall_added;
+      
+      recall = (AgsRecall *) g_value_get_pointer(value);
+
+      pthread_mutex_lock(channel->recall_mutex);
+
+      recall_added = (g_list_find(channel->recall, recall) != NULL) ? TRUE: FALSE;
+      
+      pthread_mutex_unlock(channel->recall_mutex);
 
       if(recall == NULL ||
-	 g_list_find(channel->recall, recall) != NULL){
+	 recall_added){
 	return;
       }
 
@@ -1005,10 +978,18 @@ ags_channel_set_property(GObject *gobject,
     {
       AgsRecall *play;
 
-      play = (AgsRecall *) g_value_get_object(value);
+      gboolean play_added;
+      
+      play = (AgsRecall *) g_value_get_pointer(value);
+
+      pthread_mutex_lock(channel->play_mutex);
 
+      play_added = (g_list_find(channel->play, play) != NULL) ? TRUE: FALSE;
+      
+      pthread_mutex_unlock(channel->play_mutex);
+	    
       if(play == NULL ||
-	 g_list_find(channel->play, play) != NULL){
+	 play_added){
 	return;
       }
 
@@ -1036,7 +1017,7 @@ ags_channel_set_property(GObject *gobject,
     {
       AgsPattern *pattern;
 
-      pattern = (AgsPattern *) g_value_get_object(value);
+      pattern = (AgsPattern *) g_value_get_pointer(value);
 
       if(pattern == NULL ||
 	 g_list_find(channel->pattern, pattern) != NULL){
@@ -1131,13 +1112,22 @@ ags_channel_get_property(GObject *gobject,
     break;
   case PROP_RECALL:
     {
+      pthread_mutex_lock(channel->recall_mutex);
+      
       g_value_set_pointer(value, g_list_copy(channel->recall));
+
+      pthread_mutex_unlock(channel->recall_mutex);
     }
     break;
   case PROP_PLAY:
     {
+      pthread_mutex_lock(channel->play_mutex);
+      
       g_value_set_pointer(value, g_list_copy(channel->play));
+      
+      pthread_mutex_unlock(channel->play_mutex);      
     }
+    break;
   case PROP_LINK:
     {
       g_value_set_object(value, channel->link);
@@ -1222,6 +1212,11 @@ ags_channel_connect(AgsConnectable *connectable)
   GList *list;
   
   channel = AGS_CHANNEL(connectable);
+
+  if((AGS_CHANNEL_CONNECTED & (channel->flags)) != 0){
+    return;
+  }
+
   channel->flags |= AGS_CHANNEL_CONNECTED;
   
 #ifdef AGS_DEBUG
@@ -1289,11 +1284,269 @@ ags_channel_connect(AgsConnectable *connectable)
 void
 ags_channel_disconnect(AgsConnectable *connectable)
 {
-  //TODO:JK: implement me
-  /* empty */
+  AgsChannel *channel;
+  AgsRecycling *recycling;
+
+  GList *list;
+  
+  channel = AGS_CHANNEL(connectable);
+
+  if((AGS_CHANNEL_CONNECTED & (channel->flags)) == 0){
+    return;
+  }
+  
+  channel->flags &= (~AGS_CHANNEL_CONNECTED);
+  
+#ifdef AGS_DEBUG
+  g_message("disconnecting channel\0");
+#endif
+
+  //  ags_connectable_add_to_registry(connectable);
+
+  /* connect recall ids */
+  list = channel->recall_id;
+
+  while(list != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
+
+    list = list->next;
+  }
+
+  /* connect recall containers */
+  list = channel->container;
+
+  while(list != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
+
+    list = list->next;
+  }
+
+  /* connect recalls */
+  list = channel->recall;
+
+  while(list != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
+
+    list = list->next;
+  }
+
+  list = channel->play;
+
+  while(list != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
+
+    list = list->next;
+  }
+
+  /* connect recycling */
+  recycling = channel->first_recycling;
+
+  if(recycling != NULL){
+    while(recycling != channel->last_recycling->next){
+      ags_connectable_disconnect(AGS_CONNECTABLE(recycling));
+      
+      recycling = recycling->next;
+    }
+  }
+
+  /* connect pattern and notation */
+  list = channel->pattern;
+
+  while(list != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
+
+    list = list->next;
+  }
 }
 
-static void
+void
+ags_channel_dispose(GObject *gobject)
+{
+  AgsChannel *channel;
+  AgsRecycling *recycling, *recycling_next;
+  AgsRecycling *end_region;
+
+  GList *list, *list_next;
+  
+  gboolean dispose_recycling;
+  
+  channel = AGS_CHANNEL(gobject);
+
+  /* audio */
+  dispose_recycling = FALSE;
+
+  if(channel->audio != NULL){
+    if(((AGS_AUDIO_INPUT_HAS_RECYCLING & (AGS_AUDIO(channel->audio)->flags)) != 0 &&
+	AGS_IS_INPUT(channel) &&
+	channel->link == NULL) ||
+       ((AGS_AUDIO_OUTPUT_HAS_RECYCLING & (AGS_AUDIO(channel->audio)->flags)) != 0 &&
+	AGS_IS_OUTPUT(channel))){
+      dispose_recycling = TRUE;
+    }
+    
+    g_object_unref(channel->audio);
+
+    channel->audio = NULL;
+  }
+
+  /* soundcard */
+  if(channel->soundcard != NULL){
+    g_object_unref(channel->soundcard);
+
+    channel->soundcard = NULL;
+  }
+
+  /* recycling */
+  recycling = channel->first_recycling;
+
+  if(recycling != NULL){
+    end_region = channel->last_recycling->next;
+    
+    while(recycling != end_region){
+      recycling_next = recycling->next;
+
+      if(dispose_recycling){
+	g_object_run_dispose(recycling);
+	g_object_unref((GObject *) recycling);
+      }
+      
+      recycling = recycling_next;
+    }
+
+    channel->first_recycling = NULL;
+    channel->last_recycling = NULL;
+  }
+
+  /* remote channel */
+  if(channel->remote_channel != NULL){
+    list = channel->remote_channel;
+
+    while(list != NULL){
+      list_next = list->next;
+
+      g_object_run_dispose(list->data);
+
+      list = list_next;
+    }
+
+    g_list_free_full(channel->remote_channel,
+		     g_object_unref);
+  
+    channel->remote_channel = NULL;
+  }
+  
+  /* playback */
+  //  if(channel->playback != NULL){
+  //    g_object_run_dispose(channel->playback);
+  //    g_object_unref(channel->playback);
+  
+  //    channel->playback = NULL;
+  //  }
+
+  /* recall id */
+  if(channel->recall_id != NULL){
+    list = channel->recall_id;
+
+    while(list != NULL){
+      list_next = list->next;
+
+      g_object_run_dispose(list->data);
+
+      list = list_next;
+    }
+
+    g_list_free_full(channel->recall_id,
+		     g_object_unref);
+  
+    channel->recall_id = NULL;
+  }
+  
+  /* recall container */
+  if(channel->container != NULL){
+    list = channel->container;
+
+    while(list != NULL){
+      list_next = list->next;
+
+      g_object_run_dispose(list->data);
+
+      list = list_next;
+    }
+
+    g_list_free_full(channel->container,
+		     g_object_unref);
+
+    channel->container = NULL;
+  }
+  
+  /* recall */
+  if(channel->recall != NULL){
+    pthread_mutex_lock(channel->recall_mutex);
+
+    list = channel->recall;
+
+    while(list != NULL){
+      list_next = list->next;
+
+      g_object_run_dispose(list->data);
+
+      list = list_next;
+    }
+
+    g_list_free_full(channel->recall,
+		     g_object_unref);
+  
+    channel->recall = NULL;
+
+    pthread_mutex_unlock(channel->recall_mutex);
+  }
+  
+  /* play */
+  if(channel->play != NULL){
+    pthread_mutex_lock(channel->play_mutex);
+
+    list = channel->play;
+
+    while(list != NULL){
+      list_next = list->next;
+
+      g_object_run_dispose(list->data);
+
+      list = list_next;
+    }
+
+    g_list_free_full(channel->play,
+		     g_object_unref);
+
+    channel->play = NULL;
+
+    pthread_mutex_unlock(channel->play_mutex);
+  }
+  
+  /* pattern */
+  if(channel->remote_channel != NULL){
+    list = channel->pattern;
+
+    while(list != NULL){
+      list_next = list->next;
+      
+      g_object_run_dispose(list->data);
+
+      list = list_next;
+    }
+
+    
+    g_list_free_full(channel->pattern,
+		     g_object_unref);
+
+    channel->pattern = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_channel_parent_class)->dispose(gobject);
+}
+
+void
 ags_channel_finalize(GObject *gobject)
 {
   AgsChannel *channel;
@@ -1315,25 +1568,26 @@ ags_channel_finalize(GObject *gobject)
 
   channel = AGS_CHANNEL(gobject);
 
-  //FIXME:JK: wrong ref count
+  /* audio */
   if(channel->audio != NULL){
-    //    g_object_unref(channel->audio);
+    g_object_unref(channel->audio);
   }
-  
-  /* AgsRecycling */
-  if(((AGS_AUDIO_INPUT_HAS_RECYCLING & (AGS_AUDIO(channel->audio)->flags)) != 0 && AGS_IS_INPUT(channel)) ||
-     ((AGS_AUDIO_OUTPUT_HAS_RECYCLING & (AGS_AUDIO(channel->audio)->flags)) != 0 && AGS_IS_OUTPUT(channel))){
 
-    recycling = channel->first_recycling;
+  /* soundcard */
+  if(channel->soundcard != NULL){
+    g_object_unref(channel->soundcard);
+  }
 
-    if(recycling != NULL){
-      while(recycling != channel->last_recycling->next){
-	recycling_next = recycling->next;
+  /* recycling */
+  recycling = channel->first_recycling;
 
-	g_object_unref((GObject *) recycling);
+  if(recycling != NULL){
+    while(recycling != channel->last_recycling->next){
+      recycling_next = recycling->next;
 
-	recycling = recycling_next;
-      }
+      g_object_unref((GObject *) recycling);
+
+      recycling = recycling_next;
     }
   }
 
@@ -1342,13 +1596,22 @@ ags_channel_finalize(GObject *gobject)
     free(channel->note);
   }
 
+  /* remote channel */
+  if(channel->remote_channel != NULL){
+    g_list_free_full(channel->remote_channel,
+		     g_object_unref);
+  }
+
+  /* playback */
   if(channel->playback != NULL){
     g_object_unref(channel->playback);  
   }
 
-  /* free some lists */
+  /* recall id */
   g_list_free_full(channel->recall_id,
 		   g_object_unref);
+
+  /* recall */
   g_list_free_full(channel->container,
 		   g_object_unref);
   
@@ -1357,6 +1620,13 @@ ags_channel_finalize(GObject *gobject)
   g_list_free_full(channel->play,
 		   g_object_unref);
 
+  pthread_mutex_destroy(channel->recall_mutex);
+  pthread_mutex_destroy(channel->play_mutex);
+
+  free(channel->recall_mutex);
+  free(channel->play_mutex);
+  
+  /* pattern */
   g_list_free_full(channel->pattern,
 		   g_object_unref);
   
@@ -2628,38 +2898,26 @@ ags_channel_remove_recall_container(AgsChannel *channel, GObject *recall_contain
 void
 ags_channel_add_recall(AgsChannel *channel, GObject *recall, gboolean play)
 {
-  AgsMutexManager *mutex_manager;
-
-  pthread_mutex_t *application_mutex;
-  pthread_mutex_t *mutex;
-
   if(channel == NULL || recall == NULL){
     return;
   }
 
-  /* lookup mutex */
-  mutex_manager = ags_mutex_manager_get_instance();
-  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
-
-  pthread_mutex_lock(application_mutex);
-  
-  mutex = ags_mutex_manager_lookup(mutex_manager,
-				   (GObject *) channel);
-
-  pthread_mutex_unlock(application_mutex);
-
-  /* remove recall */
-  pthread_mutex_lock(mutex);
-
+  /* add recall */
   g_object_ref(recall);
 
   if(play){
+    pthread_mutex_lock(channel->play_mutex);
+
     channel->play = g_list_prepend(channel->play, recall);
+
+    pthread_mutex_unlock(channel->play_mutex);
   }else{
+    pthread_mutex_lock(channel->recall_mutex);
+
     channel->recall = g_list_prepend(channel->recall, recall);
-  }
 
-  pthread_mutex_unlock(mutex);
+    pthread_mutex_unlock(channel->recall_mutex);
+  }
 }
 
 /**
@@ -2675,38 +2933,26 @@ ags_channel_add_recall(AgsChannel *channel, GObject *recall, gboolean play)
 void
 ags_channel_remove_recall(AgsChannel *channel, GObject *recall, gboolean play)
 {
-  AgsMutexManager *mutex_manager;
-
-  pthread_mutex_t *application_mutex;
-  pthread_mutex_t *mutex;
-
   if(channel == NULL || recall == NULL){
     return;
   }
 
-  /* lookup mutex */
-  mutex_manager = ags_mutex_manager_get_instance();
-  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
-
-  pthread_mutex_lock(application_mutex);
-  
-  mutex = ags_mutex_manager_lookup(mutex_manager,
-				   (GObject *) channel);
-
-  pthread_mutex_unlock(application_mutex);
-
-  /* add recall */
-  pthread_mutex_lock(mutex);
-
+  /* remove recall */
   if(play){
+    pthread_mutex_lock(channel->play_mutex);
+
     channel->play = g_list_remove(channel->play, recall);
+
+    pthread_mutex_unlock(channel->play_mutex);
   }else{
+    pthread_mutex_lock(channel->recall_mutex);
+
     channel->recall = g_list_remove(channel->recall, recall);
+
+    pthread_mutex_unlock(channel->recall_mutex);
   }
 
   g_object_unref(G_OBJECT(recall));
-
-  pthread_mutex_unlock(mutex);
 }
 
 /**
@@ -3465,12 +3711,14 @@ ags_channel_add_lv2_effect(AgsChannel *channel,
 	       "soundcard\0", soundcard,
 	       "recall-container\0", recall_container,
 	       NULL);
+  AGS_RECALL(recall_lv2)->flags |= AGS_RECALL_TEMPLATE;
   ags_channel_add_recall(channel,
 			 (GObject *) recall_lv2,
 			 FALSE);
   
-  AGS_RECALL(recall_lv2)->flags |= AGS_RECALL_TEMPLATE;
+  /* load */
   ags_recall_lv2_load(recall_lv2);
+  port = ags_recall_lv2_load_ports(recall_lv2);
 
   if(port != NULL){
     port = g_list_concat(port,
@@ -3491,6 +3739,7 @@ ags_channel_add_lv2_effect(AgsChannel *channel,
 			 (GObject *) recall_channel_run_dummy,
 			 FALSE);  
   
+  /* check if connected or running */
   pthread_mutex_lock(channel_mutex);
 
   if((AGS_CHANNEL_CONNECTED & (channel->flags)) != 0){
@@ -4319,10 +4568,11 @@ ags_channel_play(AgsChannel *channel,
 		 gint stage)
 {
   AgsRecall *recall;
-  GList *list, *list_next;
 
   AgsMutexManager *mutex_manager;
 
+  GList *list_start, *list, *list_next;
+
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *mutex;
 
@@ -4347,28 +4597,40 @@ ags_channel_play(AgsChannel *channel,
   pthread_mutex_lock(mutex);
 
   if(recall_id->recycling_context->parent != NULL){
-    list = channel->recall;
+    g_object_get(channel,
+		 "recall\0", &list_start,
+		 NULL);
   }else{
-    list = channel->play;
+    g_object_get(channel,
+		 "play\0", &list_start,
+		 NULL);
   }
 
+  pthread_mutex_unlock(mutex);
+
+  list = list_start;
+  
   /* run */
   while(list != NULL){
+    guint recall_flags;
+    
     list_next = list->next;
 
     recall = AGS_RECALL(list->data);
     
-    if(recall == NULL){
-      if(recall_id->recycling_context->parent != NULL){
-	channel->recall = g_list_remove(channel->recall,
-					recall);
-      }else{
-	channel->play = g_list_remove(channel->play,
-				      recall);
-      }
+    if(recall == NULL ||
+       !AGS_IS_RECALL(recall)){
+      //      if(recall_id->recycling_context->parent != NULL){
+      //	channel->recall = g_list_remove(channel->recall,
+      //					recall);
+      //      }else{
+      //	channel->play = g_list_remove(channel->play,
+      //				      recall);
+      //      }
 
-      g_warning("recall == NULL\0");
       list = list_next;
+      g_warning("recall == NULL\0");
+      
       continue;
     }
 
@@ -4379,34 +4641,101 @@ ags_channel_play(AgsChannel *channel,
       }
 
       list = list_next;
+
       continue;
     }
 
     if(recall->recall_id == NULL ||
        recall->recall_id->recycling_context != recall_id->recycling_context){
       list = list_next;
+
       continue;
     }
-    
-    if((AGS_RECALL_TEMPLATE & (recall->flags)) == 0){
+
+    recall_flags = recall->flags;
+        
+    if((AGS_RECALL_TEMPLATE & (recall_flags)) == 0){
 #ifdef AGS_DEBUG
       g_message("%s play channel %x:%d @%x -> %x\0", G_OBJECT_TYPE_NAME(recall), channel, channel->line, recall, recall->recall_id);
 #endif
 
-      if((AGS_RECALL_HIDE & (recall->flags)) == 0){
+      if((AGS_RECALL_HIDE & (recall_flags)) == 0){
+	g_object_ref(recall);
+	
 	if(stage == 0){
-	  ags_recall_run_pre(recall);
+	  AGS_RECALL_GET_CLASS(recall)->run_pre(recall);
 	}else if(stage == 1){
-	  ags_recall_run_inter(recall);
+	  AGS_RECALL_GET_CLASS(recall)->run_inter(recall);
 	}else{
-	  ags_recall_run_post(recall);
+	  AGS_RECALL_GET_CLASS(recall)->run_post(recall);
 	}
+
+	g_object_unref(recall);
       }
     }
 
     list = list_next;
   }
 
+  g_list_free(list_start);
+}
+
+void
+ags_channel_real_done(AgsChannel *channel,
+		      AgsRecallID *recall_id)
+{
+  AgsRecall *recall;
+  
+  AgsMutexManager *mutex_manager;
+
+  GList *list, *list_next;
+
+  gboolean is_toplevel;
+  
+  pthread_mutex_t *application_mutex;
+  pthread_mutex_t *mutex;
+
+  /* lookup mutex */
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  pthread_mutex_lock(application_mutex);
+  
+  mutex = ags_mutex_manager_lookup(mutex_manager,
+				   (GObject *) channel);
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* get context */
+  pthread_mutex_lock(mutex);
+
+  if(recall_id->recycling_context->parent == NULL){
+    list = channel->play;
+
+    is_toplevel = TRUE;
+  }else{
+    list = channel->recall;
+
+    is_toplevel = FALSE;
+  }
+
+  /* remove recall, run dispose and unref */
+  while(list != NULL){
+    list_next = list->next;
+
+    recall = AGS_RECALL(list->data);
+    if(recall->recall_id != NULL &&
+       recall->recall_id->recycling_context == recall_id->recycling_context){
+      g_object_run_dispose(recall);
+      ags_channel_remove_recall(channel,
+				recall,
+				is_toplevel);
+      g_object_unref(recall);
+    }
+
+    list = list_next;
+  }
+  
   pthread_mutex_unlock(mutex);
 }
 
@@ -4428,7 +4757,9 @@ ags_channel_done(AgsChannel *channel,
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *mutex;
 
-  if(channel == NULL){
+  if(channel == NULL ||
+     recall_id == NULL ||
+     recall_id->recycling_context == NULL){
     return;
   }
 
@@ -4446,7 +4777,8 @@ ags_channel_done(AgsChannel *channel,
   /* verify type */
   pthread_mutex_lock(mutex);
 
-  if(!(AGS_IS_CHANNEL(channel))){
+  if(!(AGS_IS_CHANNEL(channel) ||
+       AGS_IS_RECALL_ID(recall_id))){
     pthread_mutex_unlock(mutex);
 
     return;
@@ -4517,6 +4849,7 @@ ags_channel_cancel(AgsChannel *channel,
     recall = AGS_RECALL(list->data);
 
     if((AGS_RECALL_TEMPLATE & (recall->flags)) != 0 ||
+       recall->recall_id == NULL ||
        recall->recall_id->recycling_context != recall_id->recycling_context){
       list = list_next;
       continue;
@@ -5052,24 +5385,36 @@ ags_channel_set_link(AgsChannel *channel, AgsChannel *link,
   /* set link */
   if(channel != NULL){
     channel->link = link;
+
+    if(link != NULL){
+      g_object_ref(channel);
+      g_object_ref(link);
+    }else{
+      g_object_unref(channel);
+    }
   }  
 
   if(link != NULL){
     link->link = channel;
 
     if(channel != NULL){
+      /* notify */
       ags_channel_set_link(link,
 			   channel,
 			   &this_error);
+    }else{
+      g_object_unref(link);
     }
   }
 
   /* set old input/output to NULL */
   if(old_link_link != NULL){
     old_link_link->link = NULL;
+    g_object_unref(old_link_link);
     
     this_error = NULL;
 
+    /* notify */
     ags_channel_set_link(old_link_link,
 			 NULL,
 			 &this_error);
@@ -5078,9 +5423,11 @@ ags_channel_set_link(AgsChannel *channel, AgsChannel *link,
   /* set old input/output to NULL */
   if(old_channel_link != NULL){
     old_channel_link->link = NULL;
+    g_object_unref(old_channel_link);
       
     this_error = NULL;
     
+    /* notify */
     ags_channel_set_link(old_channel_link,
 			 NULL,
 			 &this_error);
@@ -5104,6 +5451,7 @@ ags_channel_set_link(AgsChannel *channel, AgsChannel *link,
 					 "channel\0", channel,
 					 "soundcard\0", AGS_AUDIO(channel->audio)->soundcard,
 					 NULL);
+	  g_object_ref(first_recycling);
 	  last_recycling = first_recycling;
 
 	  ags_channel_set_recycling(old_channel_link,
@@ -5141,6 +5489,7 @@ ags_channel_set_link(AgsChannel *channel, AgsChannel *link,
 					 "channel\0", channel,
 					 "soundcard\0", channel->soundcard,
 					 NULL);
+	  g_object_ref(first_recycling);
 	  last_recycling = first_recycling;
 
 	  ags_channel_set_recycling(channel,
@@ -5168,6 +5517,7 @@ ags_channel_set_link(AgsChannel *channel, AgsChannel *link,
 				       "channel\0", link,
 				       "soundcard\0", link->soundcard,
 				       NULL);
+	g_object_ref(first_recycling);
 	last_recycling = first_recycling;
       
 	ags_channel_set_recycling(link,
@@ -5252,6 +5602,8 @@ ags_channel_set_recycling(AgsChannel *channel,
   gboolean find_prev, find_next;
   gboolean change_old_last, change_old_first;
 
+  auto void ags_channel_set_recycling_ref_and_unref();
+  
   auto gboolean ags_channel_set_recycling_recursive_input(AgsChannel *input);
   auto void ags_channel_set_recycling_recursive_output(AgsChannel *output);
   auto void ags_channel_set_recycling_recursive(AgsChannel *input);
@@ -5259,7 +5611,33 @@ ags_channel_set_recycling(AgsChannel *channel,
   auto void ags_channel_set_recycling_emit_changed_input(AgsChannel *input);
   auto void ags_channel_set_recycling_emit_changed_output(AgsChannel *output);
   auto void ags_channel_set_recycling_emit_changed(AgsChannel *input);
- 
+
+  void ags_channel_set_recycling_ref_and_unref(){
+    /* ref new recycling */
+    if(first_recycling != NULL){
+      nth_recycling = first_recycling;
+      
+      while(nth_recycling != last_recycling->next){
+	//	g_object_ref(G_OBJECT(nth_recycling));
+	
+	nth_recycling = nth_recycling->next;
+      }
+    }
+    
+    /* unref old recycling */
+    if(destroy_old && old_first_recycling != NULL){
+      nth_recycling = old_first_recycling;
+      
+      while(nth_recycling != old_last_recycling->next){
+	next_recycling = nth_recycling->next;
+	
+	//	g_object_unref(G_OBJECT(nth_recycling));
+	
+	nth_recycling = next_recycling;
+      }
+    }
+  }
+  
   gboolean ags_channel_set_recycling_recursive_input(AgsChannel *input){
     AgsChannel *nth_channel_prev, *nth_channel_next;
 
@@ -5270,13 +5648,16 @@ ags_channel_set_recycling(AgsChannel *channel,
     }
 
     /* set recycling */
+    ags_channel_set_recycling_ref_and_unref();
+
     if(replace_first){
       input->first_recycling = replace_with_first_recycling;
     }
+
     if(replace_last){
       input->last_recycling = replace_with_last_recycling;
     }
-    
+
     /* search for neighboor recyclings */
     if((AGS_AUDIO_ASYNC & (AGS_AUDIO(input->audio)->flags)) != 0){
       if(find_prev){
@@ -5383,6 +5764,7 @@ ags_channel_set_recycling(AgsChannel *channel,
     //    ags_recall_id_reset_recycling(output->recall_id,
     //				  output->first_recycling,
     //				  replace_with_first_recycling, replace_with_last_recycling);
+    ags_channel_set_recycling_ref_and_unref();
 
     if(replace_last){      
       /* do it so */
@@ -5656,19 +6038,6 @@ ags_channel_set_recycling(AgsChannel *channel,
       }
     }
   }
-  
-  /* destroy old recycling */
-  if(destroy_old && old_first_recycling != NULL){
-    nth_recycling = old_first_recycling;
-
-    while(nth_recycling != old_last_recycling->next){
-      next_recycling = nth_recycling->next;
-      
-      g_object_unref(G_OBJECT(nth_recycling));
-      
-      nth_recycling = next_recycling;
-    }
-  }
 
   /* find and set parent */
   if(first_recycling != NULL){
@@ -8580,12 +8949,12 @@ ags_channel_recursive_play(AgsChannel *channel,
 						       recall_id->recycling_context);
       
     ags_channel_recursive_play_up_OUTPUT:
+      pthread_mutex_unlock(current_mutex);      
+      
       ags_channel_play(current,
 		       recall_id,
 		       stage);
 
-      pthread_mutex_unlock(current_mutex);
-      
       /* iterate */
       pthread_mutex_lock(current_mutex);
       
@@ -8603,13 +8972,14 @@ ags_channel_recursive_play(AgsChannel *channel,
     AgsAudio *audio;
     AgsChannel *input, *input_start;
     AgsChannel *link;
-    AgsRecycling *first_recycling;
+    AgsRecycling *first_recycling, *end_region;
     AgsRecyclingContext *recycling_context;
     AgsRecallID *input_recall_id;
 
     guint flags;
     guint audio_channel, line;
-
+    gboolean can_next_active;
+    
     pthread_mutex_t *audio_mutex;
     pthread_mutex_t *mutex, *input_mutex;
     
@@ -8633,6 +9003,8 @@ ags_channel_recursive_play(AgsChannel *channel,
     audio_channel = output->audio_channel;
     line = output->line;
 
+    can_next_active = ((AGS_AUDIO_CAN_NEXT_ACTIVE & (audio->flags)) != 0) ? TRUE: FALSE;
+    
     pthread_mutex_unlock(mutex);
 
     /* lookup mutex */
@@ -8665,6 +9037,15 @@ ags_channel_recursive_play(AgsChannel *channel,
 
       /* play recalls on input */
       while(input != NULL){
+	if(can_next_active){
+	  input = ags_input_next_active(input,
+					recycling_context);
+
+	  if(input == NULL){
+	    break;
+	  }
+	}
+	
 	/* lookup mutex */
 	pthread_mutex_lock(application_mutex);
 
@@ -8711,6 +9092,15 @@ ags_channel_recursive_play(AgsChannel *channel,
       input = input_start;
 
       while(input != NULL){
+	if(can_next_active){
+	  input = ags_input_next_active(input,
+					recycling_context);
+
+	  if(input == NULL){
+	    break;
+	  }
+	}
+	
 	/* lookup mutex */
 	pthread_mutex_lock(application_mutex);
 
@@ -8731,6 +9121,7 @@ ags_channel_recursive_play(AgsChannel *channel,
 	  pthread_mutex_lock(input_mutex);
 	
 	  first_recycling = input->first_recycling;
+	  end_region = input->last_recycling->next;
 	  
 	  pthread_mutex_unlock(input_mutex);
 
@@ -8738,14 +9129,22 @@ ags_channel_recursive_play(AgsChannel *channel,
 	  pthread_mutex_lock(input_mutex);
 	  
 	  input_recall_id = ags_recall_id_find_recycling_context(input->recall_id,
-								 default_recall_id->recycling_context);
+								 recycling_context);
 
 	  pthread_mutex_unlock(input_mutex);
 
 	  /* traverse the tree */
-	  if(link != NULL){
-	    ags_channel_recursive_play_down(input->link,
-					    input_recall_id);
+	  if(link != NULL &&
+	     first_recycling != NULL){
+	    gboolean is_active;
+
+	    is_active = ags_recycling_is_active(first_recycling, end_region,
+						input_recall_id);
+
+	    if(is_active){
+	      ags_channel_recursive_play_down(link,
+					      input_recall_id);
+	    }
 	  }
 	}
 
@@ -8760,41 +9159,54 @@ ags_channel_recursive_play(AgsChannel *channel,
       /* retrieve input */
       input = ags_channel_nth(input,
 			      line);
-      
-      /* lookup mutex */
-      pthread_mutex_lock(application_mutex);
 
-      input_mutex = ags_mutex_manager_lookup(mutex_manager,
-					     (GObject *) input);
+      if(ags_input_is_active(input,
+			     recycling_context)){
+	/* lookup mutex */
+	pthread_mutex_lock(application_mutex);
+
+	input_mutex = ags_mutex_manager_lookup(mutex_manager,
+					       (GObject *) input);
     
-      pthread_mutex_unlock(application_mutex);
+	pthread_mutex_unlock(application_mutex);
 
-      /* get first recycling, find input recall id and get link */
-      pthread_mutex_lock(input_mutex);
+	/* get first recycling, find input recall id and get link */
+	pthread_mutex_lock(input_mutex);
 
-      first_recycling = input->first_recycling;
-      input_recall_id = ags_recall_id_find_recycling_context(input->recall_id,
-							     default_recall_id->recycling_context);
+	first_recycling = input->first_recycling;
+	end_region = input->last_recycling->next;
+	
+	input_recall_id = ags_recall_id_find_recycling_context(input->recall_id,
+							       recycling_context);
 
-      link = input->link;
+	link = input->link;
 
-      pthread_mutex_unlock(input_mutex);
+	pthread_mutex_unlock(input_mutex);
 
-      /* lock context */
-      //      ags_concurrent_tree_lock_context(AGS_CONCURRENT_TREE(first_recycling));
+	/* lock context */
+	//      ags_concurrent_tree_lock_context(AGS_CONCURRENT_TREE(first_recycling));
       
-      /* play recalls on input */
-      ags_channel_play(input,
-		       input_recall_id,
-		       stage);
+	/* play recalls on input */
+	ags_channel_play(input,
+			 input_recall_id,
+			 stage);
 
-      /* unlock context */
-      //      ags_concurrent_tree_unlock_context(AGS_CONCURRENT_TREE(first_recycling));
+	/* unlock context */
+	//      ags_concurrent_tree_unlock_context(AGS_CONCURRENT_TREE(first_recycling));
       
-      /* traverse the tree */
-      if(link != NULL){
-	ags_channel_recursive_play_down(link,
-					input_recall_id);
+	/* traverse the tree */
+	if(link != NULL &&
+	   first_recycling != NULL){
+	  gboolean is_active;
+
+	  is_active = ags_recycling_is_active(first_recycling, end_region,
+					      input_recall_id);
+
+	  if(is_active){
+	    ags_channel_recursive_play_down(link,
+					    input_recall_id);
+	  }
+	}
       }
     }
   }
diff --git a/ags/audio/ags_channel.h b/ags/audio/ags_channel.h
index cde0408..dcfc86b 100644
--- a/ags/audio/ags_channel.h
+++ b/ags/audio/ags_channel.h
@@ -20,8 +20,11 @@
 #ifndef __AGS_CHANNEL_H__
 #define __AGS_CHANNEL_H__
 
+#include <glib.h>
 #include <glib-object.h>
 
+#include <pthread.h>
+
 #include <ags/audio/ags_recall_id.h>
 #include <ags/audio/ags_recall.h>
 #include <ags/audio/ags_recycling.h>
@@ -85,8 +88,11 @@ struct _AgsChannel
 
   // GObject *recycling_context; // contains child recycling
   GList *recall_id; // there may be several recall's running
-  GList *container;
 
+  pthread_mutex_t *recall_mutex;
+  pthread_mutex_t *play_mutex;
+
+  GList *container;
   GList *recall;
   GList *play;
 
diff --git a/ags/audio/ags_devout.c b/ags/audio/ags_devout.c
index 426c233..e75e1f0 100644
--- a/ags/audio/ags_devout.c
+++ b/ags/audio/ags_devout.c
@@ -22,17 +22,20 @@
 #include <ags/lib/ags_time.h>
 
 #include <ags/object/ags_application_context.h>
-#include <ags/object/ags_connectable.h>
-
 #include <ags/object/ags_config.h>
+#include <ags/object/ags_connectable.h>
 #include <ags/object/ags_soundcard.h>
 #include <ags/object/ags_concurrent_tree.h>
 
+#include <ags/audio/ags_sound_provider.h>
+#include <ags/audio/ags_audio_buffer_util.h>
+
 #include <ags/thread/ags_mutex_manager.h>
 #include <ags/thread/ags_task_thread.h>
 #include <ags/thread/ags_poll_fd.h>
 
 #include <ags/audio/task/ags_tic_device.h>
+#include <ags/audio/task/ags_clear_buffer.h>
 #include <ags/audio/task/ags_switch_buffer_flag.h>
 #include <ags/audio/task/ags_notify_soundcard.h>
 
@@ -82,6 +85,7 @@ void ags_devout_disconnect(AgsConnectable *connectable);
 void ags_devout_connect(AgsConnectable *connectable);
 pthread_mutex_t* ags_devout_get_lock(AgsConcurrentTree *concurrent_tree);
 pthread_mutex_t* ags_devout_get_parent_lock(AgsConcurrentTree *concurrent_tree);
+void ags_devout_dispose(GObject *gobject);
 void ags_devout_finalize(GObject *gobject);
 
 void ags_devout_set_application_context(AgsSoundcard *soundcard,
@@ -281,6 +285,7 @@ ags_devout_class_init(AgsDevoutClass *devout)
   gobject->set_property = ags_devout_set_property;
   gobject->get_property = ags_devout_get_property;
 
+  gobject->dispose = ags_devout_dispose;
   gobject->finalize = ags_devout_finalize;
 
   /* properties */
@@ -1124,13 +1129,51 @@ ags_devout_get_parent_lock(AgsConcurrentTree *concurrent_tree)
 }
 
 void
+ags_devout_dispose(GObject *gobject)
+{
+  AgsDevout *devout;
+
+  GList *list;
+
+  devout = AGS_DEVOUT(gobject);
+
+  /* application context */
+  if(devout->application_context != NULL){
+    g_object_unref(devout->application_context);
+
+    devout->application_context = NULL;
+  }
+
+  /* unref audio */  
+  if(devout->audio != NULL){
+    list = devout->audio;
+
+    while(list != NULL){
+      g_object_set(G_OBJECT(list->data),
+		   "soundcard\0", NULL,
+		   NULL);
+      
+      list = list->next;
+    }
+    
+    g_list_free_full(devout->audio,
+		     g_object_unref);
+
+    devout->audio = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_devout_parent_class)->dispose(gobject);
+}
+
+void
 ags_devout_finalize(GObject *gobject)
 {
   AgsDevout *devout;
 
   AgsMutexManager *mutex_manager;
   
-  GList *list, *list_next;
+  GList *list;
 
   devout = AGS_DEVOUT(gobject);
 
@@ -1156,14 +1199,33 @@ ags_devout_finalize(GObject *gobject)
   /* free AgsAttack */
   free(devout->attack);
 
+  /* notify soundcard */
   if(devout->notify_soundcard != NULL){
-    ags_task_thread_remove_cyclic_task(ags_application_context_get_instance()->task_thread,
-				       devout->notify_soundcard);
+    if(devout->application_context != NULL){
+      ags_task_thread_remove_cyclic_task(AGS_APPLICATION_CONTEXT(devout->application_context)->task_thread,
+					 devout->notify_soundcard);
+    }
 
     g_object_unref(devout->notify_soundcard);
   }
+
+  /* application context */
+  if(devout->application_context != NULL){
+    g_object_unref(devout->application_context);
+  }
   
+  /* unref audio */  
   if(devout->audio != NULL){
+    list = devout->audio;
+
+    while(list != NULL){
+      g_object_set(G_OBJECT(list->data),
+		   "soundcard\0", NULL,
+		   NULL);
+      
+      list = list->next;
+    }
+
     g_list_free_full(devout->audio,
 		     g_object_unref);
   }
@@ -2210,6 +2272,7 @@ ags_devout_oss_play(AgsSoundcard *soundcard,
   AgsDevout *devout;
 
   AgsTicDevice *tic_device;
+  AgsClearBuffer *clear_buffer;
   AgsSwitchBufferFlag *switch_buffer_flag;
   
   AgsThread *task_thread;
@@ -2402,9 +2465,6 @@ ags_devout_oss_play(AgsSoundcard *soundcard,
     nth_ring_buffer = 1;
   }
 
-  /* clear next buffer */
-  memset(devout->buffer[next_buffer], 0, (size_t) devout->pcm_channels * devout->buffer_size * word_size);
-
 #ifdef AGS_WITH_OSS    
   /* fill ring buffer */
   ags_devout_oss_play_fill_ring_buffer(devout->buffer[nth_buffer],
@@ -2434,6 +2494,11 @@ ags_devout_oss_play(AgsSoundcard *soundcard,
   tic_device = ags_tic_device_new((GObject *) devout);
   task = g_list_append(task,
 		       tic_device);
+
+  /* reset - clear buffer */
+  clear_buffer = ags_clear_buffer_new((GObject *) devout);
+  task = g_list_append(task,
+		       clear_buffer);
   
   /* reset - switch buffer flags */
   switch_buffer_flag = ags_switch_buffer_flag_new((GObject *) devout);
@@ -2951,6 +3016,7 @@ ags_devout_alsa_play(AgsSoundcard *soundcard,
   AgsDevout *devout;
 
   AgsTicDevice *tic_device;
+  AgsClearBuffer *clear_buffer;
   AgsSwitchBufferFlag *switch_buffer_flag;
   
   AgsThread *task_thread;
@@ -3166,9 +3232,6 @@ ags_devout_alsa_play(AgsSoundcard *soundcard,
     nth_ring_buffer = 1;
   }
 
-  /* clear next buffer */
-  memset(devout->buffer[next_buffer], 0, (size_t) devout->pcm_channels * devout->buffer_size * word_size);
-
 #ifdef AGS_WITH_ALSA
 
   /* fill ring buffer */
@@ -3227,6 +3290,11 @@ ags_devout_alsa_play(AgsSoundcard *soundcard,
   tic_device = ags_tic_device_new((GObject *) devout);
   task = g_list_append(task,
 		       tic_device);
+
+  /* reset - clear buffer */
+  clear_buffer = ags_clear_buffer_new((GObject *) devout);
+  task = g_list_append(task,
+		       clear_buffer);
   
   /* reset - switch buffer flags */
   switch_buffer_flag = ags_switch_buffer_flag_new((GObject *) devout);
diff --git a/ags/audio/ags_input.c b/ags/audio/ags_input.c
index 8817810..aa91771 100644
--- a/ags/audio/ags_input.c
+++ b/ags/audio/ags_input.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -19,13 +19,17 @@
 
 #include <ags/audio/ags_input.h>
 
+#include <ags/object/ags_application_context.h>
 #include <ags/object/ags_connectable.h>
 
+#include <ags/thread/ags_mutex_manager.h>
+
 #include <ags/file/ags_file_link.h>
 
 #include <ags/audio/ags_playable.h>
 #include <ags/audio/ags_recycling.h>
 #include <ags/audio/ags_audio_signal.h>
+#include <ags/audio/ags_synth_generator.h>
 
 #include <ags/audio/file/ags_audio_file_link.h>
 #include <ags/audio/file/ags_audio_file.h>
@@ -42,7 +46,8 @@ void ags_input_get_property(GObject *gobject,
 			    GValue *value,
 			    GParamSpec *param_spec);
 void ags_input_init (AgsInput *input);
-void ags_input_finalize (GObject *gobject);
+void ags_input_dispose(GObject *gobject);
+void ags_input_finalize(GObject *gobject);
 void ags_input_connect(AgsConnectable *connectable);
 void ags_input_disconnect(AgsConnectable *connectable);
 
@@ -62,6 +67,7 @@ static AgsConnectableInterface *ags_input_parent_connectable_interface;
 enum{
   PROP_0,
   PROP_FILE_LINK,
+  PROP_SYNTH_GENERATOR,
 };
 
 GType
@@ -114,6 +120,7 @@ ags_input_class_init(AgsInputClass *input)
   gobject->set_property = ags_input_set_property;
   gobject->get_property = ags_input_get_property;
 
+  gobject->dispose = ags_input_dispose;
   gobject->finalize = ags_input_finalize;
   
   /* properties */
@@ -132,6 +139,22 @@ ags_input_class_init(AgsInputClass *input)
   g_object_class_install_property(gobject,
 				  PROP_FILE_LINK,
 				  param_spec);
+
+  /**
+   * AgsInput:synth-generator:
+   *
+   * An optional synth generator that might be used.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("synth-generator\0",
+				   "the synth generator\0",
+				   "The synth generator to be used\0",
+				   AGS_TYPE_SYNTH_GENERATOR,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_SYNTH_GENERATOR,
+				  param_spec);
 }
 
 void
@@ -165,7 +188,6 @@ ags_input_set_property(GObject *gobject,
   switch(prop_id){
   case PROP_FILE_LINK:
     {
-      AgsAudioFile *audio_file;
       AgsFileLink *file_link;
 
       file_link = (AgsFileLink *) g_value_get_object(value);
@@ -185,6 +207,27 @@ ags_input_set_property(GObject *gobject,
       input->file_link = (GObject *) file_link;
     }
     break;
+  case PROP_SYNTH_GENERATOR:
+    {
+      AgsFileLink *synth_generator;
+
+      synth_generator = (AgsFileLink *) g_value_get_object(value);
+
+      if(input->synth_generator == (GObject *) synth_generator){
+	return;
+      }
+      
+      if(input->synth_generator != NULL){
+	g_object_unref(G_OBJECT(input->synth_generator));
+      }
+
+      if(synth_generator != NULL){
+	g_object_ref(G_OBJECT(synth_generator));
+      }
+
+      input->synth_generator = (GObject *) synth_generator;
+    }
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
     break;
@@ -203,7 +246,14 @@ ags_input_get_property(GObject *gobject,
 
   switch(prop_id){
   case PROP_FILE_LINK:
-    g_value_set_object(value, input->file_link);
+    {
+      g_value_set_object(value, input->file_link);
+    }
+    break;
+  case PROP_SYNTH_GENERATOR:
+    {
+      g_value_set_object(value, input->synth_generator);
+    }
     break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
@@ -212,16 +262,52 @@ ags_input_get_property(GObject *gobject,
 }
 
 void
+ags_input_dispose(GObject *gobject)
+{
+  AgsInput *input;
+
+  input = AGS_INPUT(gobject);
+
+  /* file link */
+  if(input->file_link != NULL){
+    g_object_run_dispose(G_OBJECT(input->file_link));
+
+    g_object_unref(G_OBJECT(input->file_link));
+    
+    input->file_link = NULL;
+  }
+
+  /* synth generator */
+  if(input->synth_generator != NULL){
+    g_object_run_dispose(G_OBJECT(input->synth_generator));
+
+    g_object_unref(G_OBJECT(input->synth_generator));
+    
+    input->synth_generator = NULL;
+  }
+
+  /* finalize */
+  G_OBJECT_CLASS(ags_input_parent_class)->dispose(gobject);
+}
+
+void
 ags_input_finalize(GObject *gobject)
 {
   AgsInput *input;
 
   input = AGS_INPUT(gobject);
 
+  /* file link */
   if(input->file_link != NULL){
     g_object_unref(G_OBJECT(input->file_link));
   }
 
+  /* synth generator */
+  if(input->synth_generator != NULL){
+    g_object_unref(G_OBJECT(input->synth_generator));
+  }
+
+  /* finalize */
   G_OBJECT_CLASS(ags_input_parent_class)->finalize(gobject);
 }
 
@@ -376,9 +462,198 @@ ags_input_apply_synth(AgsInput *input,
 		      gdouble volume,
 		      guint n_frames)
 {
+  AgsMutexManager *mutex_manager;
+
+  pthread_mutex_t *application_mutex;
+  pthread_mutex_t *mutex;
+
   //TODO:JK: implement me
 }
 
+gboolean
+ags_input_is_active(AgsInput *input,
+		    GObject *recycling_context)
+{
+  AgsChannel *channel;
+  AgsRecycling *recycling, *end_region;
+  AgsAudioSignal *audio_signal;
+  AgsRecyclingContext *active_context;
+  
+  AgsMutexManager *mutex_manager;
+
+  GList *list;
+  
+  pthread_mutex_t *application_mutex;
+  pthread_mutex_t *input_mutex;
+  pthread_mutex_t *recycling_mutex;
+  
+  channel = input;
+
+  if(input == NULL ||
+     channel->first_recycling == NULL ||
+     recycling_context == NULL){
+    return(FALSE);
+  }
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* lookup mutex */
+  pthread_mutex_lock(application_mutex);
+  
+  input_mutex = ags_mutex_manager_lookup(mutex_manager,
+					 (GObject *) channel);
+  
+  pthread_mutex_unlock(application_mutex);
+
+  /* get recycling */
+  pthread_mutex_lock(input_mutex);
+
+  recycling = channel->first_recycling;
+  end_region = channel->last_recycling->next;
+
+  if(channel->link == NULL){
+    active_context = AGS_RECYCLING_CONTEXT(recycling_context)->parent;
+  }else{
+    active_context = recycling_context;
+  }
+  
+  pthread_mutex_unlock(input_mutex);
+
+  /* check if active */
+  while(recycling != end_region){
+    /* lookup mutex */
+    pthread_mutex_lock(application_mutex);
+  
+    recycling_mutex = ags_mutex_manager_lookup(mutex_manager,
+					       (GObject *) recycling);
+  
+    pthread_mutex_unlock(application_mutex);
+
+    pthread_mutex_lock(recycling_mutex);
+
+    list = recycling->audio_signal;
+
+    while(list != NULL){
+      audio_signal = list->data;
+      
+      if(audio_signal->recall_id != NULL &&
+	 AGS_RECALL_ID(audio_signal->recall_id)->recycling_context != NULL &&
+	 AGS_RECYCLING_CONTEXT(AGS_RECALL_ID(audio_signal->recall_id)->recycling_context)->parent == active_context){
+	pthread_mutex_unlock(recycling_mutex);
+      
+	return(TRUE);
+      }
+
+      list = list->next;
+    }
+
+    /* iterate */
+    recycling = recycling->next;
+    
+    pthread_mutex_unlock(recycling_mutex);  
+  }
+  
+  return(FALSE);
+}
+
+AgsInput*
+ags_input_next_active(AgsInput *input,
+		      GObject *recycling_context)
+{
+  AgsChannel *channel;
+  AgsRecycling *recycling, *end_region;
+  AgsAudioSignal *audio_signal;  
+  AgsRecyclingContext *active_context;
+  
+  AgsMutexManager *mutex_manager;
+
+  GList *list;
+  
+  pthread_mutex_t *application_mutex;
+  pthread_mutex_t *input_mutex;
+  pthread_mutex_t *recycling_mutex;
+
+  channel = input;
+  
+  if(input == NULL ||
+     recycling_context == NULL){
+    return(NULL);
+  }
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* check if active */
+  while(channel != NULL){
+    /* lookup mutex */
+    pthread_mutex_lock(application_mutex);
+  
+    input_mutex = ags_mutex_manager_lookup(mutex_manager,
+					   (GObject *) channel);
+  
+    pthread_mutex_unlock(application_mutex);
+
+    /* get recycling */
+    pthread_mutex_lock(input_mutex);
+
+    recycling = channel->first_recycling;
+    end_region = channel->last_recycling->next;
+  
+    if(channel->link == NULL){
+      active_context = AGS_RECYCLING_CONTEXT(recycling_context)->parent;
+    }else{
+      active_context = recycling_context;
+    }
+    
+    pthread_mutex_unlock(input_mutex);
+    
+    /* check recycling */
+    while(recycling != end_region){
+      /* lookup mutex */
+      pthread_mutex_lock(application_mutex);
+  
+      recycling_mutex = ags_mutex_manager_lookup(mutex_manager,
+						 (GObject *) recycling);
+  
+      pthread_mutex_unlock(application_mutex);
+
+      /* check audio signal */
+      pthread_mutex_lock(recycling_mutex);
+
+      list = recycling->audio_signal;
+
+      while(list != NULL){
+	audio_signal = list->data;
+      
+	if(audio_signal->recall_id != NULL &&
+	   AGS_RECALL_ID(audio_signal->recall_id)->recycling_context != NULL &&
+	   AGS_RECYCLING_CONTEXT(AGS_RECALL_ID(audio_signal->recall_id)->recycling_context)->parent == active_context){
+	  pthread_mutex_unlock(recycling_mutex);
+      
+	  return(channel);
+	}
+
+	list = list->next;
+      }
+
+      /* iterate */
+      recycling = recycling->next;
+    
+      pthread_mutex_unlock(recycling_mutex);  
+    }
+
+    /* iterate */
+    pthread_mutex_lock(input_mutex);
+
+    channel = channel->next_pad;
+    
+    pthread_mutex_unlock(input_mutex);
+  }
+  
+  return(NULL);
+}
+
 /**
  * ags_input_new:
  * @audio: the #AgsAudio
diff --git a/ags/audio/ags_input.h b/ags/audio/ags_input.h
index 2ca4517..6514e1d 100644
--- a/ags/audio/ags_input.h
+++ b/ags/audio/ags_input.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -64,6 +64,12 @@ gboolean ags_input_apply_synth(AgsInput *input,
 			       gdouble volume,
 			       guint n_frames);
 
+gboolean ags_input_is_active(AgsInput *input,
+			     GObject *parent_recycling_context);
+
+AgsInput* ags_input_next_active(AgsInput *input,
+				GObject *parent_recycling_context);
+
 AgsInput* ags_input_new(GObject *audio);
 
 #endif /*__AGS_INPUT_H__*/
diff --git a/ags/audio/ags_midiin.c b/ags/audio/ags_midiin.c
index 8166143..3d24108 100644
--- a/ags/audio/ags_midiin.c
+++ b/ags/audio/ags_midiin.c
@@ -72,6 +72,7 @@ void ags_midiin_get_property(GObject *gobject,
 			     GParamSpec *param_spec);
 void ags_midiin_disconnect(AgsConnectable *connectable);
 void ags_midiin_connect(AgsConnectable *connectable);
+void ags_midiin_dispose(GObject *gobject);
 void ags_midiin_finalize(GObject *gobject);
 
 void ags_midiin_switch_buffer_flag(AgsMidiin *midiin);
@@ -219,6 +220,7 @@ ags_midiin_class_init(AgsMidiinClass *midiin)
   gobject->set_property = ags_midiin_set_property;
   gobject->get_property = ags_midiin_get_property;
 
+  gobject->dispose = ags_midiin_dispose;
   gobject->finalize = ags_midiin_finalize;
 
   /* properties */
@@ -702,13 +704,44 @@ ags_midiin_get_property(GObject *gobject,
 }
 
 void
+ags_midiin_dispose(GObject *gobject)
+{
+  AgsMidiin *midiin;
+
+  GList *list;
+
+  midiin = AGS_MIDIIN(gobject);
+
+  /* audio */  
+  if(midiin->audio != NULL){
+    list = midiin->audio;
+
+    while(list != NULL){
+      g_object_set(list->data,
+		   "sequencer\0", NULL,
+		   NULL);
+
+      list = list->next;
+    }
+    
+    g_list_free_full(midiin->audio,
+		     g_object_unref);
+
+    midiin->audio = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_midiin_parent_class)->dispose(gobject);
+}
+
+void
 ags_midiin_finalize(GObject *gobject)
 {
   AgsMidiin *midiin;
 
   AgsMutexManager *mutex_manager;
   
-  GList *list, *list_next;
+  GList *list;
 
   midiin = AGS_MIDIIN(gobject);
 
@@ -742,7 +775,18 @@ ags_midiin_finalize(GObject *gobject)
   /* free buffer array */
   free(midiin->buffer);
 
+  /* audio */
   if(midiin->audio != NULL){
+    list = midiin->audio;
+
+    while(list != NULL){
+      g_object_set(list->data,
+		   "sequencer\0", NULL,
+		   NULL);
+
+      list = list->next;
+    }
+    
     g_list_free_full(midiin->audio,
 		     g_object_unref);
   }
diff --git a/ags/audio/ags_notation.c b/ags/audio/ags_notation.c
index 7bfd84d..8819f97 100644
--- a/ags/audio/ags_notation.c
+++ b/ags/audio/ags_notation.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -28,6 +28,8 @@
 #include <ags/audio/ags_audio.h>
 #include <ags/audio/ags_port.h>
 
+#include <pthread.h>
+
 #include <stdlib.h>
 #include <errno.h>
 
@@ -46,7 +48,8 @@ void ags_notation_get_property(GObject *gobject,
 			       GParamSpec *param_spec);
 void ags_notation_connect(AgsConnectable *connectable);
 void ags_notation_disconnect(AgsConnectable *connectable);
-void ags_notation_finalize(GObject *object);
+void ags_notation_dispose(GObject *gobject);
+void ags_notation_finalize(GObject *gobject);
 
 void ags_notation_change_bpm(AgsTactable *tactable, gdouble new_bpm, gdouble old_bpm);
 
@@ -156,6 +159,7 @@ ags_notation_class_init(AgsNotationClass *notation)
   gobject->set_property = ags_notation_set_property;
   gobject->get_property = ags_notation_get_property;
 
+  gobject->dispose = ags_notation_dispose;
   gobject->finalize = ags_notation_finalize;
 
   /* properties */
@@ -335,13 +339,51 @@ ags_notation_init(AgsNotation *notation)
 void
 ags_notation_connect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsNotation *notation;
+
+  GList *list;
+  
+  notation = AGS_NOTATION(connectable);
+
+  if((AGS_NOTATION_CONNECTED & (notation->flags)) != 0){
+    return;
+  }
+
+  notation->flags |= AGS_NOTATION_CONNECTED;
+
+  /* note */
+  list = notation->notes;
+
+  while(list != NULL){
+    ags_connectable_connect(AGS_CONNECTABLE(list->data));
+
+    list = list->next;
+  }
 }
 
 void
 ags_notation_disconnect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsNotation *notation;
+
+  GList *list;
+
+  notation = AGS_NOTATION(connectable);
+
+  if((AGS_NOTATION_CONNECTED & (notation->flags)) == 0){
+    return;
+  }
+
+  notation->flags &= (~AGS_NOTATION_CONNECTED);
+
+  /* note */
+  list = notation->notes;
+
+  while(list != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
+
+    list = list->next;
+  }
 }
 
 void
@@ -608,16 +650,107 @@ ags_notation_get_property(GObject *gobject,
 }
 
 void
+ags_notation_dispose(GObject *gobject)
+{
+  AgsNotation *notation;
+
+  GList *list;
+  
+  notation = AGS_NOTATION(gobject);
+
+  /* timestamp */
+  if(notation->timestamp != NULL){
+    g_object_unref(notation->timestamp);
+
+    notation->timestamp = NULL;
+  }
+
+  /* audio */
+  if(notation->audio != NULL){
+    g_object_unref(notation->audio);
+
+    notation->audio = NULL;
+  }
+
+  /* key and base note */
+  if(notation->key != NULL){
+    free(notation->key);
+
+    notation->key = NULL;
+  }
+
+  if(notation->base_note != NULL){
+    free(notation->base_note);
+
+    notation->base_note = NULL;
+  }
+    
+  /* note and selection */
+  list = notation->notes;
+
+  while(list != NULL){
+    g_object_run_dispose(G_OBJECT(list->data));
+    
+    list = list->next;
+  }
+  
+  g_list_free_full(notation->notes,
+		   g_object_unref);
+
+  g_list_free(notation->selection);
+
+  notation->notes = NULL;
+  notation->selection = NULL;
+  
+  /* port */
+  if(notation->port != NULL){
+    g_object_unref(notation->port);
+
+    notation->port = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_notation_parent_class)->dispose(gobject);
+}
+
+void
 ags_notation_finalize(GObject *gobject)
 {
   AgsNotation *notation;
-  GList *list, *list_next;
 
   notation = AGS_NOTATION(gobject);
 
+  /* timestamp */
+  if(notation->timestamp != NULL){
+    g_object_unref(notation->timestamp);
+  }
+
+  /* audio */
+  if(notation->audio != NULL){
+    g_object_unref(notation->audio);
+  }
+
+  /* key and base note */
+  if(notation->key != NULL){
+    free(notation->key);
+  }
+
+  if(notation->base_note != NULL){
+    free(notation->base_note);
+  }
+    
+  /* note and selection */
   g_list_free_full(notation->notes,
 		   g_object_unref);
 
+  g_list_free(notation->selection);
+
+  /* port */
+  if(notation->port != NULL){
+    g_object_unref(notation->port);
+  }
+  
+  /* call parent */
   G_OBJECT_CLASS(ags_notation_parent_class)->finalize(gobject);
 }
 
@@ -650,9 +783,10 @@ ags_notation_get_port(AgsPortlet *portlet)
 GList*
 ags_notation_list_safe_properties(AgsPortlet *portlet)
 {
-  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
   static GList *list = NULL;
 
+  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
   pthread_mutex_lock(&mutex);
 
   if(list == NULL){
diff --git a/ags/audio/ags_notation.h b/ags/audio/ags_notation.h
index d0003e2..9d90bd8 100644
--- a/ags/audio/ags_notation.h
+++ b/ags/audio/ags_notation.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -53,8 +53,9 @@ typedef struct _AgsNotation AgsNotation;
 typedef struct _AgsNotationClass AgsNotationClass;
 
 typedef enum{
-  AGS_NOTATION_STICKY              =  1,
-  AGS_NOTATION_PATTERN_MODE        =  1 <<  1,
+  AGS_NOTATION_CONNECTED           = 1,
+  AGS_NOTATION_STICKY              = 1 <<  1,
+  AGS_NOTATION_PATTERN_MODE        = 1 <<  2,
 }AgsNotationFlags;
 
 struct _AgsNotation
diff --git a/ags/audio/ags_note.c b/ags/audio/ags_note.c
index 0e4595b..83efaa7 100644
--- a/ags/audio/ags_note.c
+++ b/ags/audio/ags_note.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -38,7 +38,7 @@ void ags_note_get_property(GObject *gobject,
 			   GParamSpec *param_spec);
 void ags_note_connect(AgsConnectable *connectable);
 void ags_note_disconnect(AgsConnectable *connectable);
-void ags_note_finalize(GObject *object);
+void ags_note_finalize(GObject *gobject);
 
 /**
  * SECTION:ags_note
@@ -327,13 +327,29 @@ ags_note_init(AgsNote *note)
 void
 ags_note_connect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsNote *note;
+
+  note = AGS_NOTE(connectable);
+
+  if((AGS_NOTE_CONNECTED & (note->flags)) != 0){
+    return;
+  }
+
+  note->flags |= AGS_NOTE_CONNECTED;
 }
 
 void
 ags_note_disconnect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsNote *note;
+
+  note = AGS_NOTE(connectable);
+
+  if((AGS_NOTE_CONNECTED & (note->flags)) == 0){
+    return;
+  }
+
+  note->flags &= (~AGS_NOTE_CONNECTED);
 }
 
 void
@@ -478,8 +494,16 @@ ags_note_get_property(GObject *gobject,
 void
 ags_note_finalize(GObject *gobject)
 {
-  /* empty */
+  AgsNote *note;
 
+  note = AGS_NOTE(gobject);
+
+  /* name */
+  if(note->name != NULL){
+    free(note->name);
+  }
+  
+  /* call parent */
   G_OBJECT_CLASS(ags_note_parent_class)->finalize(gobject);
 }
 
diff --git a/ags/audio/ags_note.h b/ags/audio/ags_note.h
index 65edf2c..044bf7a 100644
--- a/ags/audio/ags_note.h
+++ b/ags/audio/ags_note.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -41,12 +41,13 @@ typedef struct _AgsNote AgsNote;
 typedef struct _AgsNoteClass AgsNoteClass;
 
 typedef enum{
-  AGS_NOTE_GUI             =  1,
-  AGS_NOTE_RUNTIME         =  1 <<  1,
-  AGS_NOTE_HUMAN_READABLE  =  1 <<  2,
-  AGS_NOTE_DEFAULT_LENGTH  =  1 <<  3,
-  AGS_NOTE_IS_SELECTED     =  1 <<  4,
-  AGS_NOTE_FEED            =  1 <<  5,
+  AGS_NOTE_CONNECTED       = 1,
+  AGS_NOTE_GUI             = 1 <<  1,
+  AGS_NOTE_RUNTIME         = 1 <<  2,
+  AGS_NOTE_HUMAN_READABLE  = 1 <<  3,
+  AGS_NOTE_DEFAULT_LENGTH  = 1 <<  4,
+  AGS_NOTE_IS_SELECTED     = 1 <<  5,
+  AGS_NOTE_FEED            = 1 <<  6,
 }AgsNoteFlags;
 
 struct _AgsNote
diff --git a/ags/audio/ags_output.h b/ags/audio/ags_output.h
index 1a9c75e..7310d5d 100644
--- a/ags/audio/ags_output.h
+++ b/ags/audio/ags_output.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/audio/ags_pattern.c b/ags/audio/ags_pattern.c
index d1dd77e..9ad2883 100644
--- a/ags/audio/ags_pattern.c
+++ b/ags/audio/ags_pattern.c
@@ -46,6 +46,7 @@ void ags_pattern_get_property(GObject *gobject,
 			      GParamSpec *param_spec);
 void ags_pattern_connect(AgsConnectable *connectable);
 void ags_pattern_disconnect(AgsConnectable *connectable);
+void ags_pattern_dispose(GObject *gobject);
 void ags_pattern_finalize(GObject *gobject);
 
 void ags_pattern_change_bpm(AgsTactable *tactable, gdouble new_bpm, gdouble old_bpm);
@@ -148,6 +149,7 @@ ags_pattern_class_init(AgsPatternClass *pattern)
   gobject->set_property = ags_pattern_set_property;
   gobject->get_property = ags_pattern_get_property;
 
+  gobject->dispose = ags_pattern_dispose;
   gobject->finalize = ags_pattern_finalize;
 
   /* properties */
@@ -307,35 +309,29 @@ ags_pattern_init(AgsPattern *pattern)
   
   pthread_mutex_unlock(application_mutex);
 
-  /*  */
+  /* base initialization */
+  pattern->flags = 0;
+
+  /* timestamp */
   pattern->timestamp = NULL;
 
+  /* dimension and pattern */
   pattern->dim[0] = 0;
   pattern->dim[1] = 0;
   pattern->dim[2] = 0;
 
   pattern->pattern = NULL;
 
+  /* port */
   pattern->port = NULL;
 
+  /* indices */
   pattern->i = 0;
   pattern->j = 0;
   pattern->bit = 0;
 }
 
 void
-ags_pattern_connect(AgsConnectable *connectable)
-{
-  /* empty */
-}
-
-void
-ags_pattern_disconnect(AgsConnectable *connectable)
-{
-  /* empty */
-}
-
-void
 ags_pattern_set_property(GObject *gobject,
 			 guint prop_id,
 			 const GValue *value,
@@ -521,23 +517,95 @@ ags_pattern_get_property(GObject *gobject,
 }
 
 void
+ags_pattern_connect(AgsConnectable *connectable)
+{
+  AgsPattern *pattern;
+
+  pattern = AGS_PATTERN(connectable);
+
+  if((AGS_PATTERN_CONNECTED & (pattern->flags)) != 0){
+    return;
+  }
+
+  pattern->flags |= AGS_PATTERN_CONNECTED;
+}
+
+void
+ags_pattern_disconnect(AgsConnectable *connectable)
+{
+  AgsPattern *pattern;
+
+  pattern = AGS_PATTERN(connectable);
+
+  if((AGS_PATTERN_CONNECTED & (pattern->flags)) == 0){
+    return;
+  }
+
+  pattern->flags &= (~AGS_PATTERN_CONNECTED);
+}
+
+void
+ags_pattern_dispose(GObject *gobject)
+{
+  AgsPattern *pattern;
+
+  pattern = AGS_PATTERN(gobject);
+
+  /* timestamp */
+  if(pattern->timestamp != NULL){
+    g_object_run_dispose(G_OBJECT(pattern->timestamp));
+    
+    g_object_unref(G_OBJECT(pattern->timestamp));
+  }
+
+  /* port */
+  if(pattern->port != NULL){
+    g_object_unref(G_OBJECT(pattern->port));
+
+    pattern->port = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_pattern_parent_class)->dispose(gobject);
+}
+
+void
 ags_pattern_finalize(GObject *gobject)
 {
   AgsPattern *pattern;
+  
   guint i, j;
 
   pattern = AGS_PATTERN(gobject);
 
-  for(i = 0; i < pattern->dim[0]; i++){
-    for(j = 0; i < pattern->dim[1]; i++){
-      free(pattern->pattern[i][j]);
-    }
-
-    free(pattern->pattern[i]);
+  /* timestamp */
+  if(pattern->timestamp != NULL){
+    g_object_unref(G_OBJECT(pattern->timestamp));
   }
 
-  free(pattern->pattern);
+  /* pattern */
+  if(pattern->pattern != NULL){
+    for(i = 0; i < pattern->dim[0]; i++){
+      if(pattern->pattern[i] != NULL){
+	for(j = 0; j < pattern->dim[1]; j++){
+	  if(pattern->pattern[i][j] != NULL){
+	    free(pattern->pattern[i][j]);
+	  }
+	}
+
+	free(pattern->pattern[i]);
+      }
+    }
 
+    free(pattern->pattern);
+  }
+ 
+  /* port */
+  if(pattern->port != NULL){
+    g_object_unref(G_OBJECT(pattern->port));
+  }
+  
+  /* call parent */
   G_OBJECT_CLASS(ags_pattern_parent_class)->finalize(gobject);
 }
 
@@ -570,9 +638,10 @@ ags_pattern_get_port(AgsPortlet *portlet)
 GList*
 ags_pattern_list_safe_properties(AgsPortlet *portlet)
 {
-  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
   static GList *list = NULL;
 
+  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+  
   pthread_mutex_lock(&mutex);
 
   if(list == NULL){
@@ -668,24 +737,23 @@ ags_pattern_set_dim(AgsPattern *pattern, guint dim0, guint dim1, guint length)
   // shrink
   if(pattern->dim[0] > dim0){
     for(i = dim0; i < pattern->dim[0]; i++){
-      for(j = 0; j < pattern->dim[1]; j++)
+      for(j = 0; j < pattern->dim[1]; j++){
 	free(pattern->pattern[i][j]);
+      }
 
       free(pattern->pattern[i]);
     }
 
     if(dim0 == 0){
       free(pattern->pattern);
-      ags_pattern_init(pattern);
+      
+      pattern->pattern = NULL;
+      pattern->dim[0] = 0;
+
       return;
     }else{
-      index0 = (guint ***) malloc((int) dim0 * sizeof(guint**));
-
-      for(i = 0; i < dim0; i++)
-	index0[i] = pattern->pattern[i];
-
-      free(pattern->pattern);
-      pattern->pattern = index0;
+      pattern->pattern = (guint ***) realloc(pattern->pattern,
+					     (int) dim0 * sizeof(guint **));
 
       pattern->dim[0] = dim0;
     }
@@ -697,9 +765,13 @@ ags_pattern_set_dim(AgsPattern *pattern, guint dim0, guint dim1, guint length)
 	for(j = dim1; j < pattern->dim[1]; j++){
 	  free(pattern->pattern[i][j]);
 	}
+
 	pattern->pattern[i] = NULL;
       }
 
+      pattern->dim[1] = 0;
+      
+      return;
     }else{
       for(i = 0; i < pattern->dim[0]; i++){
 	for(j = dim1; j < pattern->dim[1]; j++){
@@ -708,87 +780,103 @@ ags_pattern_set_dim(AgsPattern *pattern, guint dim0, guint dim1, guint length)
       }
 
       for(i = 0; pattern->dim[0]; i++){
-	index1 = (guint **) malloc(dim1 * sizeof(guint*));
+	pattern->pattern[i] = (guint **) realloc(pattern->pattern[i],
+						 dim1 * sizeof(guint *));
+      }
+
+      pattern->dim[1] = dim1;
+    }
+  }
 
-	for(j = 0; j < dim1; j++){
-	  index1[j] = pattern->pattern[i][j];
+  if(pattern->dim[2] > length){
+    if(length == 0){
+      for(i = 0; i < pattern->dim[0]; i++){
+	for(j = 0; j < pattern->dim[1]; j++){
+      	  free(pattern->pattern[i][j]);
+	  
+	  pattern->pattern[i][j] = NULL;
 	}
+      }
 
-	free(pattern->pattern[i]);
-	pattern->pattern[i] = index1;
+      pattern->dim[2] = 0;
+    }else{
+      for(i = 0; i < pattern->dim[0]; i++){
+	for(j = 0; j < pattern->dim[1]; j++){
+	  pattern->pattern[i][j] = (guint *) realloc(pattern->pattern[i][j],
+						     (int) ceil((double) length / (double) (sizeof(guint) * 8)) * sizeof(guint));
+	}
       }
-    }
 
-    pattern->dim[1] = dim1;
+      pattern->dim[2] = length;
+    }
   }
 
-  if(pattern->dim[2] > length){
-    for(i = 0; i < pattern->dim[0]; i++)
-      for(j = 0; j < pattern->dim[1]; j++){
-	bitmap = (guint *) malloc((int) ceil((double) length / (double) (sizeof(guint) * 8)) * sizeof(guint));
+  // grow
+  bitmap_size = (int) ceil((double) pattern->dim[2] / (double) (sizeof(guint) * 8)) * sizeof(guint);
+    
+  if(pattern->dim[0] < dim0){
+    if(pattern->pattern == NULL){
+      pattern->pattern = (guint ***) malloc(dim0 * sizeof(guint **));
+    }else{
+      pattern->pattern = (guint ***) realloc(pattern->pattern,
+					     dim0 * sizeof(guint **));
+    }
 
-	for(k = 0; k < (guint) ceil((double) length / (double) (sizeof(guint) * 8)); k++)
-	  bitmap[k] = pattern->pattern[i][j][k];
+    for(i = pattern->dim[0]; i < dim0; i++){
+      pattern->pattern[i] = (guint **) malloc(pattern->dim[1] * sizeof(guint *));
 
-	free(pattern->pattern[i][j]);
-	pattern->pattern[i][j] = bitmap;
-      }
-  }else if(pattern->dim[2] < length){ // grow
-    for(i = 0; i < pattern->dim[0]; i++)
       for(j = 0; j < pattern->dim[1]; j++){
-	bitmap = (guint *) malloc((int) ceil((double) length / (double) (sizeof(guint) * 8)) * sizeof(guint));
-
-	for(k = 0; k < (guint) ceil((double) pattern->dim[2] / (double) (sizeof(guint) * 8)); k++)
-	  bitmap[k] = pattern->pattern[i][j][k];
-
-	free(pattern->pattern[i][j]);
-	pattern->pattern[i][j] = bitmap;
+	if(bitmap_size == 0){
+	  pattern->pattern[i][j] = NULL;
+	}else{
+	  pattern->pattern[i][j] = (guint *) malloc(bitmap_size);
+	  memset(pattern->pattern[i][j], 0, bitmap_size);
+	}
       }
-  }
+    }
 
-  pattern->dim[2] = length;
-  bitmap_size = (guint) ceil((double) pattern->dim[2] / (double) (sizeof(guint) * 8)) * sizeof(guint);
+    pattern->dim[0] = dim0;
+  }
 
-  if(pattern->dim[1] < dim1){
+  if(pattern->dim[1] < dim1){  
     for(i = 0; i < pattern->dim[0]; i++){
-      index1 = (guint**) malloc(dim1 * sizeof(guint*));
-
-      for(j = 0; j < pattern->dim[1]; j++)
-	index1[j] = pattern->pattern[i][j];
-
-      free(pattern->pattern[i]);
-      pattern->pattern[i] = index1;
+      if(pattern->pattern[i] == NULL){
+	pattern->pattern[i] = (guint **) malloc(dim1 * sizeof(guint *));
+      }else{
+	pattern->pattern[i] = (guint **) realloc(pattern->pattern[i],
+						 dim1 * sizeof(guint *));
+      }
 
       for(j = pattern->dim[1]; j < dim1; j++){
-	pattern->pattern[i][j] = (guint*) malloc(bitmap_size);
-	memset(pattern->pattern[i][j], 0, bitmap_size);
+	if(bitmap_size == 0){
+	  pattern->pattern[i][j] = NULL;
+	}else{
+	  pattern->pattern[i][j] = (guint *) malloc(bitmap_size);
+	  memset(pattern->pattern[i][j], 0, bitmap_size);
+	}
       }
     }
 
     pattern->dim[1] = dim1;
   }
 
-  if(pattern->dim[0] < dim0){
-    index0 = (guint***) malloc(dim0 * sizeof(guint**));
-
-    for(i = 0; i < pattern->dim[0]; i++)
-      index0[i] = pattern->pattern[i];
-
-    if(pattern->pattern != NULL)
-      free(pattern->pattern);
-
-    pattern->pattern = index0;
-
-    for(i = pattern->dim[0]; i < dim0; i++){
-      pattern->pattern[i] = (guint**) malloc(pattern->dim[1] * sizeof(guint*));
-
+  if(pattern->dim[2] < length){
+    guint new_bitmap_size;
+    
+    new_bitmap_size = (int) ceil((double) length / (double) (sizeof(guint) * 8)) * sizeof(guint);
+    
+    for(i = 0; i < pattern->dim[0]; i++){
       for(j = 0; j < pattern->dim[1]; j++){
-	pattern->pattern[i][j] = (guint*) malloc(bitmap_size);
-	memset(pattern->pattern[i][j], 0, bitmap_size);
+	if(pattern->pattern[i][j] == NULL){
+	  pattern->pattern[i][j] = (guint *) malloc(new_bitmap_size);
+	  memset(pattern->pattern[i][j], 0, new_bitmap_size);
+	}else{
+	  pattern->pattern[i][j] =(guint *) realloc(pattern->pattern[i][j],
+						    new_bitmap_size);
+	  memset(pattern->pattern[i][j] + bitmap_size, 0, new_bitmap_size - bitmap_size);
+	}
       }
     }
-
-    pattern->dim[0] = dim0;
   }
 }
 
diff --git a/ags/audio/ags_pattern.h b/ags/audio/ags_pattern.h
index e385cd9..3d44b36 100644
--- a/ags/audio/ags_pattern.h
+++ b/ags/audio/ags_pattern.h
@@ -46,10 +46,16 @@
 typedef struct _AgsPattern AgsPattern;
 typedef struct _AgsPatternClass AgsPatternClass;
 
+typedef enum{
+  AGS_PATTERN_CONNECTED   = 1,
+}AgsPatternFlags;
+
 struct _AgsPattern
 {
-  GObject object;
+  GObject gobject;
 
+  guint flags;
+  
   GObject *timestamp;
 
   guint dim[3];
@@ -64,7 +70,7 @@ struct _AgsPattern
 
 struct _AgsPatternClass
 {
-  GObjectClass object;
+  GObjectClass gobject;
 };
 
 GType ags_pattern_get_type();
diff --git a/ags/audio/ags_playback.c b/ags/audio/ags_playback.c
index a270921..b86d056 100644
--- a/ags/audio/ags_playback.c
+++ b/ags/audio/ags_playback.c
@@ -19,12 +19,14 @@
 
 #include <ags/audio/ags_playback.h>
 
+#include <ags/object/ags_config.h>
 #include <ags/object/ags_connectable.h>
 
-#include <ags/audio/ags_recall_id.h>
-#include <ags/audio/thread/ags_iterator_thread.h>
+#include <ags/audio/ags_channel.h>
 
 #include <ags/audio/thread/ags_channel_thread.h>
+#include <ags/audio/thread/ags_iterator_thread.h>
+#include <ags/audio/thread/ags_recycling_thread.h>
 
 /**
  * SECTION:ags_playback
@@ -39,12 +41,28 @@
 void ags_playback_class_init(AgsPlaybackClass *playback);
 void ags_playback_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_playback_init(AgsPlayback *playback);
+void ags_playback_set_property(GObject *gobject,
+				      guint prop_id,
+				      const GValue *value,
+				      GParamSpec *param_spec);
+void ags_playback_get_property(GObject *gobject,
+				      guint prop_id,
+				      GValue *value,
+				      GParamSpec *param_spec);
 void ags_playback_disconnect(AgsConnectable *connectable);
 void ags_playback_connect(AgsConnectable *connectable);
+void ags_playback_dispose(GObject *gobject);
 void ags_playback_finalize(GObject *gobject);
 
 static gpointer ags_playback_parent_class = NULL;
 
+enum{
+  PROP_0,
+  PROP_PLAYBACK_DOMAIN,
+  PROP_SOURCE,
+  PROP_AUDIO_CHANNEL,
+};
+
 GType
 ags_playback_get_type (void)
 {
@@ -93,7 +111,62 @@ ags_playback_class_init(AgsPlaybackClass *playback)
   /* GObjectClass */
   gobject = (GObjectClass *) playback;
 
+  gobject->set_property = ags_playback_set_property;
+  gobject->get_property = ags_playback_get_property;
+
+  gobject->dispose = ags_playback_dispose;
   gobject->finalize = ags_playback_finalize;
+
+  /* properties */
+  /**
+   * AgsPlayback:playback-domain:
+   *
+   * The parent playback domain.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("playback-domain\0",
+				   "parent playback domain\0",
+				   "The playback domain it is child of\0",
+				   G_TYPE_OBJECT,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_PLAYBACK_DOMAIN,
+				  param_spec);
+
+  /**
+   * AgsPlayback:source:
+   *
+   * The assigned source.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("source\0",
+				   "assigned source\0",
+				   "The source it is assigned with\0",
+				   G_TYPE_OBJECT,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_SOURCE,
+				  param_spec);
+
+  /**
+   * AgsPlayback:audio-channel:
+   *
+   * The assigned audio channel.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_uint("audio-channel\0",
+				 "assigned audio channel\0",
+				 "The audio channel it is assigned with\0",
+				 0,
+				 G_MAXUINT,
+				 0,
+				 G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_AUDIO_CHANNEL,
+				  param_spec);
 }
 
 void
@@ -108,9 +181,123 @@ ags_playback_connectable_interface_init(AgsConnectableInterface *connectable)
 void
 ags_playback_init(AgsPlayback *playback)
 {
+  AgsConfig *config;
+
+  gchar *str, *str0, *str1;
+
+  gdouble freq;
+  guint samplerate, buffer_size;
+  gboolean super_threaded_channel, super_threaded_recycling;
+  
+  /* config */
+  config = ags_config_get_instance();
+
+  /* thread model */
+  super_threaded_channel = FALSE;
+  super_threaded_recycling = FALSE;
+  
+  str0 = ags_config_get_value(config,
+			      AGS_CONFIG_THREAD,
+			      "model\0");
+  str1 = ags_config_get_value(config,
+			      AGS_CONFIG_THREAD,
+			      "super-threaded-scope\0");
+
+  if(str0 != NULL && str1 != NULL){
+    if(!g_ascii_strncasecmp(str0,
+			    "super-threaded\0",
+			    15)){
+      if(!g_ascii_strncasecmp(str1,
+			      "channel\0",
+			      8)){
+	super_threaded_channel = TRUE;
+      }else if(!g_ascii_strncasecmp(str1,
+				    "recycling\0",
+				    10)){
+	super_threaded_recycling = TRUE;
+      }
+    }
+  }
+
+  if(str0 != NULL){
+    free(str0);
+  }
+
+  if(str1 != NULL){
+    free(str1);
+  }
+
   /* default flags */
-  g_atomic_int_set(&(playback->flags),
-		   AGS_PLAYBACK_SUPER_THREADED_CHANNEL);
+  if(super_threaded_channel ||
+     super_threaded_recycling){
+    g_atomic_int_set(&(playback->flags),
+		     AGS_PLAYBACK_SUPER_THREADED_CHANNEL);
+
+    if(super_threaded_recycling){
+      g_atomic_int_or(&(playback->flags),
+		      AGS_PLAYBACK_SUPER_THREADED_RECYCLING);
+    }
+  }else{
+    g_atomic_int_set(&(playback->flags),
+		     0);
+  }
+
+  /* source */
+  playback->source = NULL;
+  playback->audio_channel = 0;
+
+  /* samplerate and buffer size */
+  samplerate = AGS_SOUNDCARD_DEFAULT_SAMPLERATE;
+  buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
+
+  /* samplerate */
+  str = ags_config_get_value(config,
+			     AGS_CONFIG_SOUNDCARD,
+			     "samplerate\0");
+
+  if(str == NULL){
+    str = ags_config_get_value(config,
+			       AGS_CONFIG_SOUNDCARD_0,
+			       "samplerate\0");
+  }
+  
+  if(str != NULL){
+    samplerate = g_ascii_strtoull(str,
+				  NULL,
+				  10);
+
+    free(str);
+  }
+
+  /* buffer size */
+  str = ags_config_get_value(config,
+			     AGS_CONFIG_SOUNDCARD,
+			     "buffer-size\0");
+
+  if(str == NULL){
+    str = ags_config_get_value(config,
+			       AGS_CONFIG_SOUNDCARD_0,
+			       "buffer-size\0");
+  }
+  
+  if(str != NULL){
+    buffer_size = g_ascii_strtoull(str,
+				   NULL,
+				   10);
+
+    free(str);
+  }
+
+  /* playback domain */
+  playback->playback_domain = NULL;
+
+  /* source and audio channel */
+  playback->source = NULL;
+
+  playback->audio_channel = 0;
+  
+  /* thread frequency */
+  freq = ceil((gdouble) samplerate / (gdouble) buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK;
 
   /* super threaded channel */
   playback->channel_thread = (AgsThread **) malloc(3 * sizeof(AgsThread *));
@@ -119,13 +306,34 @@ ags_playback_init(AgsPlayback *playback)
   playback->channel_thread[1] = NULL;
   playback->channel_thread[2] = NULL;
 
+  if(super_threaded_channel ||
+     super_threaded_recycling){
+    playback->channel_thread[0] = (AgsThread *) ags_channel_thread_new(NULL,
+								       NULL);
+    playback->channel_thread[0]->freq = freq;
+	
+    playback->channel_thread[1] = (AgsThread *) ags_channel_thread_new(NULL,
+								       NULL);
+    playback->channel_thread[1]->freq = freq;
+
+    playback->channel_thread[2] = (AgsThread *) ags_channel_thread_new(NULL,
+								       NULL);
+    playback->channel_thread[2]->freq = freq;
+  }
+  
   /* iterator thread */
   playback->iterator_thread = (AgsIteratorThread **) malloc(3 * sizeof(AgsIteratorThread *));
 
-  playback->iterator_thread[0] = ags_iterator_thread_new();
-  playback->iterator_thread[1] = ags_iterator_thread_new();
-  playback->iterator_thread[2] = ags_iterator_thread_new();
+  playback->iterator_thread[0] = NULL;
+  playback->iterator_thread[1] = NULL;
+  playback->iterator_thread[2] = NULL;
 
+  if(super_threaded_recycling){
+    playback->iterator_thread[0] = ags_iterator_thread_new();
+    playback->iterator_thread[1] = ags_iterator_thread_new();
+    playback->iterator_thread[2] = ags_iterator_thread_new();
+  }
+  
   /* super threaded recycling */
   playback->recycling_thread = (AgsThread **) malloc(3 * sizeof(AgsThread *));
 
@@ -133,11 +341,21 @@ ags_playback_init(AgsPlayback *playback)
   playback->recycling_thread[1] = NULL;
   playback->recycling_thread[2] = NULL;
 
-  /*  */
-  playback->source = NULL;
-  playback->audio_channel = 0;
-
-  /*  */
+  if(super_threaded_recycling){
+    playback->recycling_thread[0] = (AgsThread *) ags_recycling_thread_new(NULL,
+									   NULL);
+    playback->recycling_thread[0]->freq = freq;
+    
+    playback->recycling_thread[1] = (AgsThread *) ags_recycling_thread_new(NULL,
+									   NULL);
+    playback->recycling_thread[1]->freq = freq;
+
+    playback->recycling_thread[2] = (AgsThread *) ags_recycling_thread_new(NULL,
+									   NULL);  
+    playback->recycling_thread[2]->freq = freq;
+  }
+  
+  /* recall id */
   playback->recall_id = (AgsRecallID **) malloc(3 * sizeof(AgsRecallID *));
 
   playback->recall_id[0] = NULL;
@@ -146,17 +364,295 @@ ags_playback_init(AgsPlayback *playback)
 }
 
 void
+ags_playback_set_property(GObject *gobject,
+				 guint prop_id,
+				 const GValue *value,
+				 GParamSpec *param_spec)
+{
+  AgsPlayback *playback;
+  
+  playback = AGS_PLAYBACK(gobject);
+
+  switch(prop_id){
+  case PROP_PLAYBACK_DOMAIN:
+    {
+      GObject *playback_domain;
+
+      playback_domain = (GObject *) g_value_get_object(value);
+
+      if((GObject *) playback->playback_domain == playback_domain){
+	return;
+      }
+
+      if(playback->playback_domain != NULL){
+	g_object_unref(G_OBJECT(playback->playback_domain));
+      }
+
+      if(playback_domain != NULL){
+	g_object_ref(G_OBJECT(playback_domain));
+      }
+
+      playback->playback_domain = (GObject *) playback_domain;
+    }
+    break;
+  case PROP_SOURCE:
+    {
+      GObject *source;
+
+      source = (GObject *) g_value_get_object(value);
+
+      if(source == playback->source){
+	return;
+      }
+
+      if(playback->source != NULL){
+	g_object_unref(G_OBJECT(playback->source));
+      }
+
+      if(source != NULL){
+	g_object_ref(G_OBJECT(source));
+
+	if(AGS_IS_CHANNEL(source) &&
+	   ((AGS_PLAYBACK_SUPER_THREADED_CHANNEL & (g_atomic_int_get(&(playback->flags)))) != 0 ||
+	    (AGS_PLAYBACK_SUPER_THREADED_RECYCLING & (g_atomic_int_get(&(playback->flags)))) != 0)){
+	  gdouble freq;
+	  
+	  /* thread frequency */
+	  freq = ceil((gdouble) AGS_CHANNEL(source)->samplerate / (gdouble) AGS_CHANNEL(source)->buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK;
+
+	  /* channel thread */
+	  g_object_set(playback->channel_thread[0],
+		       "frequency\0", freq,
+		       "channel\0", source,
+		       NULL);
+
+	  g_object_set(playback->channel_thread[1],
+		       "frequency\0", freq,
+		       "channel\0", source,
+		       NULL);
+
+	  g_object_set(playback->channel_thread[2],
+		       "frequency\0", freq,
+		       "channel\0", source,
+		       NULL);
+
+	  if((AGS_PLAYBACK_SUPER_THREADED_RECYCLING & (g_atomic_int_get(&(playback->flags)))) != 0){
+	    /* recycling thread */
+	    g_object_set(playback->recycling_thread[0],
+			 "frequency\0", freq,
+			 NULL);
+
+	    g_object_set(playback->recycling_thread[1],
+			 "frequency\0", freq,
+			 NULL);
+
+	    g_object_set(playback->recycling_thread[2],
+			 "frequency\0", freq,
+			 NULL);
+
+	    /* iterator thread */
+	    g_object_set(playback->iterator_thread[0],
+			 "frequency\0", freq,
+			 NULL);
+
+	    g_object_set(playback->iterator_thread[1],
+			 "frequency\0", freq,
+			 NULL);
+
+	    g_object_set(playback->iterator_thread[2],
+			 "frequency\0", freq,
+			 NULL);
+	  }
+	}
+      }
+
+      playback->source = (GObject *) source;
+    }
+    break;
+  case PROP_AUDIO_CHANNEL:
+    {
+      playback->audio_channel = g_value_get_uint(value);
+    }
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  }
+}
+
+void
+ags_playback_get_property(GObject *gobject,
+				 guint prop_id,
+				 GValue *value,
+				 GParamSpec *param_spec)
+{
+  AgsPlayback *playback;
+
+  playback = AGS_PLAYBACK(gobject);
+
+  switch(prop_id){
+  case PROP_PLAYBACK_DOMAIN:
+    {
+      g_value_set_object(value,
+			 playback->playback_domain);
+    }
+    break;
+  case PROP_SOURCE:
+    {
+      g_value_set_object(value,
+			  playback->source);
+    }
+    break;
+  case PROP_AUDIO_CHANNEL:
+    {
+      g_value_set_uint(value,
+		       playback->audio_channel);      
+    }
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  }
+}
+
+void
+ags_playback_dispose(GObject *gobject)
+{
+  AgsPlayback *playback;
+
+  guint i;
+  
+  playback = AGS_PLAYBACK(gobject);
+
+  /* playback domain */
+  if(playback->playback_domain != NULL){
+    g_object_unref(playback->playback_domain);
+
+    playback->playback_domain = NULL;
+  }
+
+  /* source */
+  if(playback->source != NULL){
+    g_object_unref(playback->source);
+
+    playback->source = NULL;
+  }
+  
+  /* channel thread */
+  if(playback->channel_thread != NULL){
+    for(i = 0; i < 3; i++){
+      if(playback->channel_thread[i] != NULL){
+	g_object_run_dispose(playback->channel_thread[i]);
+	g_object_unref(playback->channel_thread[i]);
+
+	playback->channel_thread[i] = NULL;
+      }
+    }
+  }
+  
+  /* recycling thread */
+  if(playback->recycling_thread != NULL){
+    for(i = 0; i < 3; i++){
+      if(playback->recycling_thread[i] != NULL){
+	g_object_run_dispose(playback->recycling_thread[i]);
+	g_object_unref(playback->recycling_thread[i]);
+
+	playback->recycling_thread[i] = NULL;
+      }
+    }
+    
+  }
+  
+  /* iterator thread */
+  if(playback->iterator_thread != NULL){
+    for(i = 0; i < 3; i++){
+      if(playback->iterator_thread[i] != NULL){
+	g_object_run_dispose(playback->iterator_thread[i]);
+	g_object_unref(playback->iterator_thread[i]);
+
+	playback->iterator_thread[i] = NULL;
+      }
+    }
+    
+  }
+  
+  /* recall id */
+  if(playback->recall_id != NULL){
+    for(i = 0; i < 3; i++){
+      if(playback->recall_id[i] != NULL){
+	g_object_unref(playback->recall_id[i]);
+
+	playback->recall_id[i] = NULL;
+      }
+    }
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_playback_parent_class)->dispose(gobject);
+}
+
+void
 ags_playback_finalize(GObject *gobject)
 {
   AgsPlayback *playback;
 
+  guint i;
+  
   playback = AGS_PLAYBACK(gobject);
 
-  g_object_unref(G_OBJECT(playback->iterator_thread[0]));
-  g_object_unref(G_OBJECT(playback->iterator_thread[1]));
-  g_object_unref(G_OBJECT(playback->iterator_thread[2]));
+  /* playback domain */
+  if(playback->playback_domain != NULL){
+    g_object_unref(playback->playback_domain);
+  }
 
-  free(playback->iterator_thread);
+  /* source */
+  if(playback->source != NULL){
+    g_object_unref(playback->source);
+  }
+  
+  /* channel thread */
+  if(playback->channel_thread != NULL){
+    for(i = 0; i < 3; i++){
+      if(playback->channel_thread[i] != NULL){
+	g_object_unref(playback->channel_thread[i]);
+      }
+    }
+    
+    free(playback->channel_thread);
+  }
+  
+  /* recycling thread */
+  if(playback->recycling_thread != NULL){
+    for(i = 0; i < 3; i++){
+      if(playback->recycling_thread[i] != NULL){
+	g_object_unref(playback->recycling_thread[i]);
+      }
+    }
+    
+    free(playback->recycling_thread);
+  }
+  
+  /* iterator thread */
+  if(playback->iterator_thread != NULL){
+    for(i = 0; i < 3; i++){
+      if(playback->iterator_thread[i] != NULL){
+	g_object_unref(playback->iterator_thread[i]);
+      }
+    }
+    
+    free(playback->iterator_thread);
+  }
+  
+  /* recall id */
+  if(playback->recall_id != NULL){
+    for(i = 0; i < 3; i++){
+      if(playback->recall_id[i] != NULL){
+	g_object_unref(playback->recall_id[i]);
+      }
+    }
+    
+    free(playback->recall_id);
+  }
 
   /* call parent */
   G_OBJECT_CLASS(ags_playback_parent_class)->finalize(gobject);
@@ -165,13 +661,250 @@ ags_playback_finalize(GObject *gobject)
 void
 ags_playback_connect(AgsConnectable *connectable)
 {
-  //TODO:JK: implement me
+  AgsPlayback *playback;
+
+  playback = AGS_PLAYBACK(connectable);
+
+  if((AGS_PLAYBACK_CONNECTED & (playback->flags)) != 0){
+    return;
+  }
+
+  playback->flags |= AGS_PLAYBACK_CONNECTED;
 }
 
 void
 ags_playback_disconnect(AgsConnectable *connectable)
 {
-  //TODO:JK: implement me
+  AgsPlayback *playback;
+
+  playback = AGS_PLAYBACK(connectable);
+
+
+  if((AGS_PLAYBACK_CONNECTED & (playback->flags)) == 0){
+    return;
+  }
+
+  playback->flags &= (~AGS_PLAYBACK_CONNECTED);
+}
+
+/**
+ * ags_playback_set_channel_thread:
+ * @playback: the #AgsPlayback
+ * @thread: the #AgsChannelThread
+ * @scope: the scope of the thread to set
+ * 
+ * Set channel thread of appropriate scope.
+ * 
+ * Since: 0.7.122.7
+ */
+void
+ags_playback_set_channel_thread(AgsPlayback *playback,
+				AgsThread *thread,
+				guint scope)
+{
+  if(playback == NULL ||
+     scope > 2){
+    return;
+  }
+
+  if(playback->channel_thread[scope] != NULL){
+    g_object_unref(playback->channel_thread[scope]);
+  }
+
+  if(thread != NULL){
+    g_object_ref(thread);
+  }
+  
+  playback->channel_thread[scope] = thread;
+}
+
+/**
+ * ags_playback_get_channel_thread:
+ * @playback: the #AgsPlayback
+ * @scope: the scope of the thread to get
+ * 
+ * Get channel thread of appropriate scope.
+ * 
+ * Returns: the matching #AgsThread or %NULL
+ * 
+ * Since: 0.7.122.7
+ */
+AgsThread*
+ags_playback_get_channel_thread(AgsPlayback *playback,
+				guint scope)
+{
+  if(playback == NULL ||
+     playback->channel_thread == NULL ||
+     scope > 2){
+    return(NULL);
+  }
+
+  return(playback->channel_thread[scope]);
+}
+
+/**
+ * ags_playback_set_iterator_thread:
+ * @playback: the #AgsPlayback
+ * @thread: the #AgsIteratorThread
+ * @scope: the scope of the thread to set
+ * 
+ * Set iterator thread of appropriate scope.
+ * 
+ * Since: 0.7.122.7
+ */
+void
+ags_playback_set_iterator_thread(AgsPlayback *playback,
+				 AgsThread *thread,
+				 guint scope)
+{
+  if(playback == NULL ||
+     scope > 2){
+    return;
+  }
+
+  if(playback->iterator_thread[scope] != NULL){
+    g_object_unref(playback->iterator_thread[scope]);
+  }
+
+  if(thread != NULL){
+    g_object_ref(thread);
+  }
+  
+  playback->iterator_thread[scope] = thread;
+}
+
+/**
+ * ags_playback_get_iterator_thread:
+ * @playback: the #AgsPlayback
+ * @scope: the scope of the thread to get
+ * 
+ * Get iterator thread of appropriate scope.
+ * 
+ * Returns: the matching #AgsThread or %NULL
+ * 
+ * Since: 0.7.122.7
+ */
+AgsThread*
+ags_playback_get_iterator_thread(AgsPlayback *playback,
+				 guint scope)
+{
+  if(playback == NULL ||
+     playback->iterator_thread == NULL ||
+     scope > 2){
+    return(NULL);
+  }
+
+  return(playback->iterator_thread[scope]);
+}
+
+/**
+ * ags_playback_set_recycling_thread:
+ * @playback: the #AgsPlayback
+ * @thread: the #AgsRecyclingThread
+ * @scope: the scope of the thread to set
+ * 
+ * Set recycling thread of appropriate scope.
+ * 
+ * Since: 0.7.122.7
+ */
+void
+ags_playback_set_recycling_thread(AgsPlayback *playback,
+				  AgsThread *thread,
+				  guint scope)
+{
+  if(playback == NULL ||
+     scope > 2){
+    return;
+  }
+
+  if(playback->recycling_thread[scope] != NULL){
+    g_object_unref(playback->recycling_thread[scope]);
+  }
+
+  if(thread != NULL){
+    g_object_ref(thread);
+  }
+  
+  playback->recycling_thread[scope] = thread;
+}
+
+/**
+ * ags_playback_get_recycling_thread:
+ * @playback: the #AgsPlayback
+ * @scope: the scope of the thread to get
+ * 
+ * Get recycling thread of appropriate scope.
+ * 
+ * Returns: the matching #AgsThread or %NULL
+ * 
+ * Since: 0.7.122.7
+ */
+AgsThread*
+ags_playback_get_recycling_thread(AgsPlayback *playback,
+				  guint scope)
+{
+  if(playback == NULL ||
+     playback->recycling_thread == NULL ||
+     scope > 2){
+    return(NULL);
+  }
+
+  return(playback->recycling_thread[scope]);
+}
+
+/**
+ * ags_playback_set_recall_id:
+ * @playback: the #AgsPlayback
+ * @recall_id: the #AgsRecallID
+ * @scope: the scope of the recall id to set
+ * 
+ * Set recall id of appropriate scope.
+ * 
+ * Since: 0.7.122.7
+ */
+void
+ags_playback_set_recall_id(AgsPlayback *playback,
+			   AgsRecallID *recall_id,
+			   guint scope)
+{
+  if(playback == NULL ||
+     scope > 2){
+    return;
+  }
+
+  if(playback->recall_id[scope] != NULL){
+    g_object_unref(playback->recall_id[scope]);
+  }
+
+  if(recall_id != NULL){
+    g_object_ref(recall_id);
+  }
+  
+  playback->recall_id[scope] = recall_id;
+}
+
+/**
+ * ags_playback_get_recall_id:
+ * @playback: the #AgsPlayback
+ * @scope: the scope of the recall id to get
+ * 
+ * Get recall id of appropriate scope.
+ * 
+ * Returns: the matching #AgsRecallID or %NULL
+ * 
+ * Since: 0.7.122.7
+ */
+AgsRecallID*
+ags_playback_get_recall_id(AgsPlayback *playback,
+			   guint scope)
+{
+  if(playback == NULL ||
+     playback->recall_id == NULL ||
+     scope > 2){
+    return(NULL);
+  }
+
+  return(playback->recall_id[scope]);
 }
 
 /**
diff --git a/ags/audio/ags_playback.h b/ags/audio/ags_playback.h
index 0c055a7..6d942cc 100644
--- a/ags/audio/ags_playback.h
+++ b/ags/audio/ags_playback.h
@@ -31,8 +31,6 @@
 
 #include <ags/audio/ags_recall_id.h>
 
-#include <ags/audio/thread/ags_iterator_thread.h>
-
 #define AGS_TYPE_PLAYBACK                (ags_playback_get_type())
 #define AGS_PLAYBACK(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_PLAYBACK, AgsPlayback))
 #define AGS_PLAYBACK_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST(class, AGS_TYPE_PLAYBACK, AgsPlayback))
@@ -43,35 +41,43 @@
 typedef struct _AgsPlayback AgsPlayback;
 typedef struct _AgsPlaybackClass AgsPlaybackClass;
 
-typedef enum
-{
-  AGS_PLAYBACK_DONE                         = 1,
-  AGS_PLAYBACK_REMOVE                       = 1 <<  1,
-  AGS_PLAYBACK_CHANNEL                      = 1 <<  2,
-  AGS_PLAYBACK_PAD                          = 1 <<  3,
-  AGS_PLAYBACK_AUDIO                        = 1 <<  4,
-  AGS_PLAYBACK_PLAYBACK                     = 1 <<  5,
-  AGS_PLAYBACK_SEQUENCER                    = 1 <<  6,
-  AGS_PLAYBACK_NOTATION                     = 1 <<  7,
-  AGS_PLAYBACK_SINGLE_THREADED              = 1 <<  8,
-  AGS_PLAYBACK_SUPER_THREADED_CHANNEL       = 1 <<  9,
-  AGS_PLAYBACK_SUPER_THREADED_RECYCLING     = 1 << 10,
+typedef enum{
+  AGS_PLAYBACK_CONNECTED                    = 1,
+  AGS_PLAYBACK_DONE                         = 1 <<  1,
+  AGS_PLAYBACK_REMOVE                       = 1 <<  2,
+  AGS_PLAYBACK_CHANNEL                      = 1 <<  3,
+  AGS_PLAYBACK_PAD                          = 1 <<  4,
+  AGS_PLAYBACK_AUDIO                        = 1 <<  5,
+  AGS_PLAYBACK_PLAYBACK                     = 1 <<  6,
+  AGS_PLAYBACK_SEQUENCER                    = 1 <<  7,
+  AGS_PLAYBACK_NOTATION                     = 1 <<  8,
+  AGS_PLAYBACK_SINGLE_THREADED              = 1 <<  9,
+  AGS_PLAYBACK_SUPER_THREADED_CHANNEL       = 1 << 10,
+  AGS_PLAYBACK_SUPER_THREADED_RECYCLING     = 1 << 11,
 }AgsPlaybackFlags;
 
+typedef enum{
+  AGS_PLAYBACK_SCOPE_PLAYBACK,
+  AGS_PLAYBACK_SCOPE_SEQUENCER,
+  AGS_PLAYBACK_SCOPE_NOTATION,  
+}AgsPlaybackScope;
+
 struct _AgsPlayback
 {
   GObject gobject;
   
   volatile guint flags;
 
-  AgsThread **channel_thread;
-  AgsIteratorThread **iterator_thread;
-
-  AgsThread **recycling_thread;
+  GObject *playback_domain;
   
   GObject *source;
   guint audio_channel;
 
+  AgsThread **channel_thread;
+  AgsThread **iterator_thread;
+
+  AgsThread **recycling_thread;
+  
   AgsRecallID **recall_id;
 };
 
@@ -82,9 +88,36 @@ struct _AgsPlaybackClass
 
 GType ags_playback_get_type();
 
+/* get and set */
+void ags_playback_set_channel_thread(AgsPlayback *playback,
+				     AgsThread *thread,
+				     guint scope);
+AgsThread* ags_playback_get_channel_thread(AgsPlayback *playback,
+					   guint scope);
+
+void ags_playback_set_iterator_thread(AgsPlayback *playback,
+				      AgsThread *thread,
+				      guint scope);
+AgsThread* ags_playback_get_iterator_thread(AgsPlayback *playback,
+					    guint scope);
+
+void ags_playback_set_recycling_thread(AgsPlayback *playback,
+				       AgsThread *thread,
+				       guint scope);
+AgsThread* ags_playback_get_recycling_thread(AgsPlayback *playback,
+					     guint scope);
+
+void ags_playback_set_recall_id(AgsPlayback *playback,
+				AgsRecallID *recall_id,
+				guint scope);
+AgsRecallID* ags_playback_get_recall_id(AgsPlayback *playback,
+					guint scope);
+
+/* find */
 AgsPlayback* ags_playback_find_source(GList *playback,
 				      GObject *source);
 
+/* instance */
 AgsPlayback* ags_playback_new();
 
 #endif /*__AGS_PLAYBACK_H__*/
diff --git a/ags/audio/ags_playback_domain.c b/ags/audio/ags_playback_domain.c
index 438c997..c804661 100644
--- a/ags/audio/ags_playback_domain.c
+++ b/ags/audio/ags_playback_domain.c
@@ -19,7 +19,12 @@
 
 #include <ags/audio/ags_playback_domain.h>
 
+#include <ags/object/ags_config.h>
 #include <ags/object/ags_connectable.h>
+#include <ags/object/ags_soundcard.h>
+
+#include <ags/audio/ags_audio.h>
+#include <ags/audio/ags_playback.h>
 
 #include <ags/audio/thread/ags_audio_thread.h>
 
@@ -36,12 +41,27 @@
 void ags_playback_domain_class_init(AgsPlaybackDomainClass *playback_domain);
 void ags_playback_domain_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_playback_domain_init(AgsPlaybackDomain *playback_domain);
+void ags_playback_domain_set_property(GObject *gobject,
+				      guint prop_id,
+				      const GValue *value,
+				      GParamSpec *param_spec);
+void ags_playback_domain_get_property(GObject *gobject,
+				      guint prop_id,
+				      GValue *value,
+				      GParamSpec *param_spec);
 void ags_playback_domain_disconnect(AgsConnectable *connectable);
 void ags_playback_domain_connect(AgsConnectable *connectable);
+void ags_playback_domain_dispose(GObject *gobject);
 void ags_playback_domain_finalize(GObject *gobject);
 
 static gpointer ags_playback_domain_parent_class = NULL;
 
+enum{
+  PROP_0,
+  PROP_DOMAIN,
+  PROP_PLAYBACK,
+};
+
 GType
 ags_playback_domain_get_type (void)
 {
@@ -90,7 +110,44 @@ ags_playback_domain_class_init(AgsPlaybackDomainClass *playback_domain)
   /* GObjectClass */
   gobject = (GObjectClass *) playback_domain;
 
+  gobject->set_property = ags_playback_domain_set_property;
+  gobject->get_property = ags_playback_domain_get_property;
+
+  gobject->dispose = ags_playback_domain_dispose;
   gobject->finalize = ags_playback_domain_finalize;
+
+  /* properties */
+  /**
+   * AgsPlaybackDomain:domain:
+   *
+   * The assigned domain.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("domain\0",
+				   "assigned domain\0",
+				   "The domain it is assigned with\0",
+				   G_TYPE_OBJECT,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_DOMAIN,
+				  param_spec);
+
+  /**
+   * AgsPlaybackDomain:playback:
+   *
+   * The assigned playback.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("playback\0",
+				   "assigned playback\0",
+				   "The playback it is assigned with\0",
+				   G_TYPE_OBJECT,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_PLAYBACK,
+				  param_spec);
 }
 
 void
@@ -105,9 +162,60 @@ ags_playback_domain_connectable_interface_init(AgsConnectableInterface *connecta
 void
 ags_playback_domain_init(AgsPlaybackDomain *playback_domain)
 {
+  AgsConfig *config;
+
+  gchar *str, *str0, *str1;
+
+  gboolean super_threaded_audio;
+  
+  /* config */
+  config = ags_config_get_instance();
+
+  /* thread model */
+  str0 = ags_config_get_value(config,
+			      AGS_CONFIG_THREAD,
+			      "model\0");
+  str1 = ags_config_get_value(config,
+			      AGS_CONFIG_THREAD,
+			      "super-threaded-scope\0");
+
+  if(str0 != NULL && str1 != NULL){
+    if(!g_ascii_strncasecmp(str0,
+			    "super-threaded\0",
+			    15)){
+      if(!g_ascii_strncasecmp(str1,
+			      "audio\0",
+			      6) ||
+	 !g_ascii_strncasecmp(str1,
+			      "channel\0",
+			      8) ||
+	 !g_ascii_strncasecmp(str1,
+			      "recycling\0",
+			      10)){
+	super_threaded_audio = TRUE;
+      }
+    }
+  }
+  
+  if(str0 != NULL){
+    free(str0);
+  }
+
+  if(str1 != NULL){
+    free(str1);
+  }
+  
   /* default flags */
-  g_atomic_int_set(&(playback_domain->flags),
-		   AGS_PLAYBACK_DOMAIN_SUPER_THREADED_AUDIO);
+  if(super_threaded_audio){
+    g_atomic_int_set(&(playback_domain->flags),
+		     AGS_PLAYBACK_DOMAIN_SUPER_THREADED_AUDIO);
+  }else{
+    g_atomic_int_set(&(playback_domain->flags),
+		     0);
+  }
+
+  /* domain */
+  playback_domain->domain = NULL;
 
   /* super threaded audio */
   playback_domain->audio_thread = (AgsThread **) malloc(3 * sizeof(AgsThread *));
@@ -115,20 +223,248 @@ ags_playback_domain_init(AgsPlaybackDomain *playback_domain)
   playback_domain->audio_thread[0] = NULL;
   playback_domain->audio_thread[1] = NULL;
   playback_domain->audio_thread[2] = NULL;
+  
+  if(super_threaded_audio){
+    guint samplerate, buffer_size;
+    gdouble freq;
+    
+    samplerate = AGS_SOUNDCARD_DEFAULT_SAMPLERATE;
+    buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
 
-  playback_domain->domain = NULL;
+    /* samplerate */
+    str = ags_config_get_value(config,
+			       AGS_CONFIG_SOUNDCARD,
+			       "samplerate\0");
+
+    if(str == NULL){
+      str = ags_config_get_value(config,
+				 AGS_CONFIG_SOUNDCARD_0,
+				 "samplerate\0");
+    }
+  
+    if(str != NULL){
+      samplerate = g_ascii_strtoull(str,
+				    NULL,
+				    10);
+
+      free(str);
+    }
+
+    /* buffer size */
+    str = ags_config_get_value(config,
+			       AGS_CONFIG_SOUNDCARD,
+			       "buffer-size\0");
+
+    if(str == NULL){
+      str = ags_config_get_value(config,
+				 AGS_CONFIG_SOUNDCARD_0,
+				 "buffer-size\0");
+    }
+  
+    if(str != NULL){
+      buffer_size = g_ascii_strtoull(str,
+				     NULL,
+				     10);
+
+      free(str);
+    }
+
+    /* thread frequency */
+    freq = ceil((gdouble) samplerate / (gdouble) buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK;
+
+    /* playback audio thread */
+    playback_domain->audio_thread[0] = (AgsThread *) ags_audio_thread_new(NULL,
+									  NULL);
+    g_object_ref(playback_domain->audio_thread[0]);
+    playback_domain->audio_thread[0]->freq = freq;
+
+    /* sequencer audio thread */
+    playback_domain->audio_thread[1] = (AgsThread *) ags_audio_thread_new(NULL,
+									  NULL);
+    g_object_ref(playback_domain->audio_thread[1]);
+    playback_domain->audio_thread[1]->freq = freq;
+
+    /* notation audio thread */
+    playback_domain->audio_thread[2] = (AgsThread *) ags_audio_thread_new(NULL,
+									  NULL);
+    g_object_ref(playback_domain->audio_thread[2]);
+    playback_domain->audio_thread[2]->freq = freq;
+  }
+
+  /* playback */
   playback_domain->playback = NULL;
 }
 
 void
+ags_playback_domain_set_property(GObject *gobject,
+				 guint prop_id,
+				 const GValue *value,
+				 GParamSpec *param_spec)
+{
+  AgsPlaybackDomain *playback_domain;
+  
+  playback_domain = AGS_PLAYBACK_DOMAIN(gobject);
+
+  switch(prop_id){
+  case PROP_DOMAIN:
+    {
+      GObject *domain;
+
+      domain = (GObject *) g_value_get_object(value);
+
+      if((GObject *) playback_domain->domain == domain){
+	return;
+      }
+
+      if(playback_domain->domain != NULL){
+	g_object_unref(G_OBJECT(playback_domain->domain));
+      }
+
+      if(domain != NULL){
+	g_object_ref(G_OBJECT(domain));
+
+	if(AGS_IS_AUDIO(domain) &&
+	   (AGS_PLAYBACK_DOMAIN_SUPER_THREADED_AUDIO & (g_atomic_int_get(&(playback_domain->flags)))) != 0){
+	  gdouble freq;
+	  
+	  /* thread frequency */
+	  freq = ceil((gdouble) AGS_AUDIO(domain)->samplerate / (gdouble) AGS_AUDIO(domain)->buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK;
+
+	  g_object_set(playback_domain->audio_thread[0],
+		       "frequency\0", freq,
+		       "audio\0", domain,
+		       NULL);
+
+	  g_object_set(playback_domain->audio_thread[1],
+		       "frequency\0", freq,
+		       "audio\0", domain,
+		       NULL);
+
+	  g_object_set(playback_domain->audio_thread[2],
+		       "frequency\0", freq,
+		       "audio\0", domain,
+		       NULL);
+	}
+      }
+
+      playback_domain->domain = (GObject *) domain;
+    }
+    break;
+  case PROP_PLAYBACK:
+    {
+      AgsPlayback *playback;
+
+      playback = (AgsPlayback *) g_value_get_object(value);
+
+      if(playback == NULL ||
+	 g_list_find(playback_domain->playback, playback) != NULL){
+	return;
+      }
+
+      ags_playback_domain_add_playback(playback_domain,
+				       (GObject *) playback);
+    }
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  }
+}
+
+void
+ags_playback_domain_get_property(GObject *gobject,
+				 guint prop_id,
+				 GValue *value,
+				 GParamSpec *param_spec)
+{
+  AgsPlaybackDomain *playback_domain;
+
+  playback_domain = AGS_PLAYBACK_DOMAIN(gobject);
+
+  switch(prop_id){
+  case PROP_DOMAIN:
+    {
+      g_value_set_object(value,
+			 playback_domain->domain);
+    }
+    break;
+  case PROP_PLAYBACK:
+    {
+      g_value_set_pointer(value,
+			  g_list_copy(playback_domain->playback));
+    }
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  }
+}
+
+void
+ags_playback_domain_dispose(GObject *gobject)
+{
+  AgsPlaybackDomain *playback_domain;
+
+  guint i;
+  
+  playback_domain = AGS_PLAYBACK_DOMAIN(gobject);
+  
+  if(playback_domain->audio_thread != NULL){
+    for(i = 0; i < 3; i++){
+      if(playback_domain->audio_thread[i] != NULL){
+	g_object_run_dispose(playback_domain->audio_thread[i]);
+	g_object_unref(playback_domain->audio_thread[i]);
+
+	playback_domain->audio_thread[i] = NULL;
+      }
+    }
+  }
+
+  /* domain */
+  if(playback_domain->domain != NULL){
+    g_object_unref(playback_domain->domain);
+
+    playback_domain->domain = NULL;
+  }
+
+  /* playback */
+  if(playback_domain->playback != NULL){
+    g_list_free_full(playback_domain->playback,
+		     g_object_unref);
+    
+    playback_domain->playback = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_playback_domain_parent_class)->dispose(gobject);
+}
+
+void
 ags_playback_domain_finalize(GObject *gobject)
 {
   AgsPlaybackDomain *playback_domain;
 
+  guint i;
+  
   playback_domain = AGS_PLAYBACK_DOMAIN(gobject);
 
-  free(playback_domain->audio_thread);
+  /* audio thread */
+  if(playback_domain->audio_thread != NULL){
+    for(i = 0; i < 3; i++){
+      if(playback_domain->audio_thread[i] != NULL){
+	g_object_unref(playback_domain->audio_thread[i]);
+      }
+    }
+    
+    free(playback_domain->audio_thread);
+  }
+
+  /* domain */
+  if(playback_domain->domain != NULL){
+    g_object_unref(playback_domain->domain);
+  }
   
+  /* playback */
   g_list_free_full(playback_domain->playback,
 		   g_object_unref);
 
@@ -139,13 +475,133 @@ ags_playback_domain_finalize(GObject *gobject)
 void
 ags_playback_domain_connect(AgsConnectable *connectable)
 {
-  //TODO:JK: implement me
+  AgsPlaybackDomain *playback_domain;
+
+  playback_domain = AGS_PLAYBACK_DOMAIN(connectable);
+
+  if((AGS_PLAYBACK_DOMAIN_CONNECTED & (playback_domain->flags)) != 0){
+    return;
+  }
+
+  playback_domain->flags |= AGS_PLAYBACK_DOMAIN_CONNECTED;
 }
 
 void
 ags_playback_domain_disconnect(AgsConnectable *connectable)
 {
-  //TODO:JK: implement me
+  AgsPlaybackDomain *playback_domain;
+
+  playback_domain = AGS_PLAYBACK_DOMAIN(connectable);
+
+
+  if((AGS_PLAYBACK_DOMAIN_CONNECTED & (playback_domain->flags)) == 0){
+    return;
+  }
+
+  playback_domain->flags &= (~AGS_PLAYBACK_DOMAIN_CONNECTED);
+}
+
+/**
+ * ags_playback_domain_set_audio_thread:
+ * @playback_domain: the #AgsPlaybackDomain
+ * @thread: the #AgsThread
+ * @scope: the thread's scope
+ * 
+ * Set audio thread to specified scope.
+ * 
+ * Since: 0.7.122.7
+ */
+void
+ags_playback_domain_set_audio_thread(AgsPlaybackDomain *playback_domain,
+				     AgsThread *thread,
+				     guint scope)
+{
+  if(playback_domain == NULL ||
+     scope > 2){
+    return;
+  }
+
+  if(playback_domain->audio_thread[scope] != NULL){
+    g_object_unref(playback_domain->audio_thread[scope]);
+  }
+
+  if(thread != NULL){
+    g_object_ref(thread);
+  }
+  
+  playback_domain->audio_thread[scope] = thread;
+}
+
+/**
+ * ags_playback_domain_set_audio_thread:
+ * @playback_domain: the #AgsPlaybackDomain
+ * @scope: the thread's scope
+ * 
+ * Get audio thread of specified scope.
+ * 
+ * Returns: the matching #AgsThread or %NULL
+ * 
+ * Since: 0.7.122.7
+ */
+AgsThread*
+ags_playback_domain_get_audio_thread(AgsPlaybackDomain *playback_domain,
+				     guint scope)
+{
+  if(playback_domain == NULL ||
+     playback_domain->audio_thread == NULL ||
+     scope > 2){
+    return(NULL);
+  }
+
+  return(playback_domain->audio_thread[scope]);
+}
+
+
+/**
+ * ags_playback_domain_add_playback:
+ * @playback_domain: the #AgsPlaybackDomain
+ * @playback: the #AgsPlayback
+ * 
+ * Add @playback to @playback_domain.
+ * 
+ * Since: 0.7.122.7
+ */
+void
+ags_playback_domain_add_playback(AgsPlaybackDomain *playback_domain,
+				 GObject *playback)
+{
+  if(playback_domain == NULL ||
+     playback == NULL){
+    return;
+  }
+
+  //TODO:JK: rather use prepend but needs refactoring
+  g_object_ref(playback);
+  playback_domain->playback = g_list_append(playback_domain->playback,
+					    playback);
+}
+
+/**
+ * ags_playback_domain_remove_playback:
+ * @playback_domain: the #AgsPlaybackDomain
+ * @playback: the #AgsPlayback
+ * 
+ * Remove @playback of @playback_domain.
+ * 
+ * Since: 0.7.122.7
+ */
+void
+ags_playback_domain_remove_playback(AgsPlaybackDomain *playback_domain,
+				    GObject *playback)
+{
+  if(playback_domain == NULL ||
+     playback == NULL){
+    return;
+  }
+
+  playback_domain->playback = g_list_remove(playback_domain->playback,
+					    playback);
+  g_object_unref(playback);
 }
 
 /**
diff --git a/ags/audio/ags_playback_domain.h b/ags/audio/ags_playback_domain.h
index 396f67e..15b462f 100644
--- a/ags/audio/ags_playback_domain.h
+++ b/ags/audio/ags_playback_domain.h
@@ -40,22 +40,30 @@ typedef struct _AgsPlaybackDomain AgsPlaybackDomain;
 typedef struct _AgsPlaybackDomainClass AgsPlaybackDomainClass;
 
 typedef enum{
-  AGS_PLAYBACK_DOMAIN_PLAYBACK                   = 1,
-  AGS_PLAYBACK_DOMAIN_SEQUENCER                  = 1 <<  1,
-  AGS_PLAYBACK_DOMAIN_NOTATION                   = 1 <<  2,
-  AGS_PLAYBACK_DOMAIN_SINGLE_THREADED            = 1 <<  3,
-  AGS_PLAYBACK_DOMAIN_SUPER_THREADED_AUDIO       = 1 <<  4,
+  AGS_PLAYBACK_DOMAIN_CONNECTED                  = 1,
+  AGS_PLAYBACK_DOMAIN_PLAYBACK                   = 1 <<  1,
+  AGS_PLAYBACK_DOMAIN_SEQUENCER                  = 1 <<  2,
+  AGS_PLAYBACK_DOMAIN_NOTATION                   = 1 <<  3,
+  AGS_PLAYBACK_DOMAIN_SINGLE_THREADED            = 1 <<  4,
+  AGS_PLAYBACK_DOMAIN_SUPER_THREADED_AUDIO       = 1 <<  5,
 }AgsPlaybackDomainFlags;
 
+typedef enum{
+  AGS_PLAYBACK_DOMAIN_SCOPE_PLAYBACK,
+  AGS_PLAYBACK_DOMAIN_SCOPE_SEQUENCER,
+  AGS_PLAYBACK_DOMAIN_SCOPE_NOTATION,  
+}AgsPlaybackDomainScope;
+
 struct _AgsPlaybackDomain
 {
   GObject gobject;
 
   volatile guint flags;
+  
+  GObject *domain;
 
   AgsThread **audio_thread;
 
-  GObject *domain;
   GList *playback;
 };
 
@@ -66,6 +74,20 @@ struct _AgsPlaybackDomainClass
 
 GType ags_playback_domain_get_type();
 
+/* get and set */
+void ags_playback_domain_set_audio_thread(AgsPlaybackDomain *playback_domain,
+					  AgsThread *thread,
+					  guint scope);
+AgsThread* ags_playback_domain_get_audio_thread(AgsPlaybackDomain *playback_domain,
+						guint scope);
+
+/* add and remove */
+void ags_playback_domain_add_playback(AgsPlaybackDomain *playback_domain,
+				      GObject *playback);
+void ags_playback_domain_remove_playback(AgsPlaybackDomain *playback_domain,
+					 GObject *playback);
+
+/* instance */
 AgsPlaybackDomain* ags_playback_domain_new();
 
 #endif /*__AGS_PLAYBACK_DOMAIN_H__*/
diff --git a/ags/audio/ags_port.h b/ags/audio/ags_port.h
index 39aeec2..e354fc3 100644
--- a/ags/audio/ags_port.h
+++ b/ags/audio/ags_port.h
@@ -23,13 +23,13 @@
 #include <glib.h>
 #include <glib-object.h>
 
-#include <ags/lib/ags_complex.h>
-#include <ags/lib/ags_conversion.h>
-
 #include <pthread.h>
 
 #include <ladspa.h>
 
+#include <ags/lib/ags_complex.h>
+#include <ags/lib/ags_conversion.h>
+
 #define AGS_TYPE_PORT                (ags_port_get_type())
 #define AGS_PORT(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_PORT, AgsPort))
 #define AGS_PORT_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_PORT, AgsPortClass))
@@ -43,6 +43,8 @@ typedef struct _AgsPortClass AgsPortClass;
 typedef enum{
   AGS_PORT_CONVERT_ALWAYS   =  1,
   AGS_PORT_USE_LADSPA_FLOAT =  1 <<  1,
+  AGS_PORT_IS_OUTPUT        =  1 <<  2,
+  AGS_PORT_INFINITE_RANGE   =  1 <<  3,
 }AgsPortFlags;
 
 struct _AgsPort
diff --git a/ags/audio/ags_recall.c b/ags/audio/ags_recall.c
index fe75526..f219ed4 100644
--- a/ags/audio/ags_recall.c
+++ b/ags/audio/ags_recall.c
@@ -19,10 +19,13 @@
 
 #include <ags/audio/ags_recall.h>
 
+#include <ags/util/ags_destroy_util.h>
 #include <ags/util/ags_id_generator.h>
+#include <ags/util/ags_list_util.h>
 
 #include <ags/lib/ags_parameter.h>
 
+#include <ags/object/ags_application_context.h>
 #include <ags/object/ags_marshal.h>
 #include <ags/object/ags_connectable.h>
 #include <ags/object/ags_soundcard.h>
@@ -30,6 +33,10 @@
 #include <ags/object/ags_dynamic_connectable.h>
 #include <ags/object/ags_plugin.h>
 
+#include <ags/thread/ags_mutex_manager.h>
+#include <ags/thread/ags_concurrency_provider.h>
+#include <ags/thread/ags_destroy_worker.h>
+
 #include <ags/server/ags_server.h>
 #include <ags/server/ags_service_provider.h>
 #include <ags/server/ags_registry.h>
@@ -96,7 +103,8 @@ void ags_recall_set_xml_type(AgsPlugin *plugin, gchar *xml_type);
 GList* ags_recall_get_ports(AgsPlugin *plugin);
 void ags_recall_read(AgsFile *file, xmlNode *node, AgsPlugin *plugin);
 xmlNode* ags_recall_write(AgsFile *file, xmlNode *parent, AgsPlugin *plugin);
-void ags_recall_finalize(GObject *recall);
+void ags_recall_dispose(GObject *gobject);
+void ags_recall_finalize(GObject *gobject);
 
 void ags_recall_real_load_automation(AgsRecall *recall,
 				     GList *automation_port);
@@ -250,6 +258,7 @@ ags_recall_class_init(AgsRecallClass *recall)
   gobject->set_property = ags_recall_set_property;
   gobject->get_property = ags_recall_get_property;
 
+  gobject->dispose = ags_recall_dispose;
   gobject->finalize = ags_recall_finalize;
 
   /* properties */
@@ -751,23 +760,43 @@ ags_recall_plugin_interface_init(AgsPluginInterface *plugin)
 void
 ags_recall_init(AgsRecall *recall)
 {
+  pthread_mutexattr_t *attr;
+
   recall->flags = 0;
 
+  /* soundcard */
   recall->soundcard = NULL;
+
+  /* container */
   recall->container = NULL;
 
+  /* version and build id */
   recall->version = NULL;
   recall->build_id = NULL;
 
+  /* effect and name */
   recall->effect = NULL;
   recall->name = NULL;
 
+  /* xml type  */
   recall->xml_type = NULL;
 
+  /* dependency */
   recall->dependencies = NULL;
 
+  /* recall id */
   recall->recall_id = NULL;
 
+  /* nested recall */
+  attr = (pthread_mutexattr_t *) malloc(sizeof(pthread_mutexattr_t));
+  pthread_mutexattr_init(attr);
+  pthread_mutexattr_settype(attr,
+			    PTHREAD_MUTEX_RECURSIVE);
+
+  recall->children_mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
+  pthread_mutex_init(recall->children_mutex,
+		     attr);
+
   recall->parent = NULL;
   recall->children = NULL;
 
@@ -775,9 +804,11 @@ ags_recall_init(AgsRecall *recall)
   recall->child_parameters = NULL;
   recall->n_params = 0;
 
+  /* port */
   recall->port = NULL;
   recall->automation_port = NULL;
 
+  /* handlers */
   recall->handlers = NULL;
 }
 
@@ -885,8 +916,9 @@ ags_recall_set_property(GObject *gobject,
 
       recall_id = (AgsRecallID *) g_value_get_object(value);
 
-      if(recall->recall_id == recall_id)
+      if(recall->recall_id == recall_id){
 	return;
+      }
 
       if(recall->recall_id != NULL){
 	g_object_unref(G_OBJECT(recall->recall_id));
@@ -902,18 +934,43 @@ ags_recall_set_property(GObject *gobject,
   case PROP_PARENT:
     {
       AgsRecall *parent;
-
+      
       parent = (AgsRecall *) g_value_get_object(value);
 
-      ags_recall_add_child(parent, recall);
+      if(recall->parent == parent){
+	return;
+      }
+
+      if(recall->parent != NULL){
+	g_object_unref(recall->parent);
+      }
+
+      if(parent != NULL){
+	g_object_ref(parent);
+      }
+      
+      recall->parent = parent;
     }
     break;
   case PROP_CHILD:
     {
       AgsRecall *child;
 
+      gboolean child_added;
+      
       child = (AgsRecall *) g_value_get_object(value);
 
+      pthread_mutex_lock(recall->children_mutex);
+
+      child_added = (g_list_find(recall->children, child) != NULL) ? TRUE: FALSE;
+      
+      pthread_mutex_unlock(recall->children_mutex);
+
+      if(child == NULL ||
+	 child_added){
+	return;
+      }
+      
       ags_recall_add_child(recall, child);
     }
     break;
@@ -1297,6 +1354,81 @@ ags_recall_write(AgsFile *file, xmlNode *parent, AgsPlugin *plugin)
 }
 
 void
+ags_recall_dispose(GObject *gobject)
+{
+  AgsRecall *recall;
+
+  GList *list, *list_next;
+
+  recall = AGS_RECALL(gobject);
+
+  /* soundcard */
+  if(recall->soundcard != NULL){
+    g_object_unref(recall->soundcard);
+
+    recall->soundcard = NULL;
+  }
+
+  /* dependency */
+  if(recall->dependencies != NULL){
+    g_list_free_full(recall->dependencies,
+		     g_object_unref);
+
+    recall->dependencies = NULL;
+  }
+  
+  /* recall id */
+  if(recall->recall_id != NULL){
+    g_object_unref(recall->recall_id);
+
+    recall->recall_id = NULL;
+  }
+  
+  /* children */
+  if(recall->children != NULL){
+    list = recall->children;
+
+    while(list != NULL){
+      list_next = list->next;
+      
+      g_object_run_dispose(G_OBJECT(list->data));
+
+      list = list_next;
+    }
+    
+    g_list_free_full(recall->children,
+		     g_object_unref);
+
+    recall->children = NULL;
+  }
+  
+  if(recall->container != NULL){
+    ags_packable_unpack(AGS_PACKABLE(recall));
+
+    recall->container = NULL;
+  }
+
+  /* port */
+  if(recall->port != NULL){
+    g_list_free_full(recall->port,
+		     g_object_unref);
+
+    recall->port = NULL;
+  }
+  
+  /* parent */
+  if(recall->parent != NULL){
+    ags_recall_remove_child(recall->parent,
+			    recall);
+
+    recall->parent = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_recall_parent_class)->dispose(gobject);
+}
+
+void
 ags_recall_finalize(GObject *gobject)
 {
   AgsRecall *recall;
@@ -1324,7 +1456,8 @@ ags_recall_finalize(GObject *gobject)
   }
 
   g_free(ids);
-  
+
+  /* soundcard */
   if(recall->soundcard != NULL){
     g_object_unref(recall->soundcard);
   }
@@ -1333,11 +1466,21 @@ ags_recall_finalize(GObject *gobject)
     //    g_free(recall->name);
   //  }
 
+  /* dependency */
   g_list_free_full(recall->dependencies,
 		   g_object_unref);
 
+  /* recall id */
+  if(recall->recall_id != NULL){
+    g_object_unref(recall->recall_id);
+  }
+  
+  /* children */
   g_list_free_full(recall->children,
 		   g_object_unref);
+
+  pthread_mutex_destroy(recall->children_mutex);
+  free(recall->children_mutex);
   
   if(recall->container != NULL){
     ags_packable_unpack(AGS_PACKABLE(recall));
@@ -1348,9 +1491,11 @@ ags_recall_finalize(GObject *gobject)
     g_free(recall->child_parameters);
   }
 
+  /* port */
   g_list_free_full(recall->port,
 		   g_object_unref);
 
+  /* parent */
   if(recall->parent != NULL){
     ags_recall_remove_child(recall->parent,
 			    recall);
@@ -1620,28 +1765,32 @@ ags_recall_automate(AgsRecall *recall)
 void
 ags_recall_real_run_pre(AgsRecall *recall)
 {
-  GList *list, *list_next;
+  GList *list, *list_start;
 
   /* lock ports */
   ags_recall_lock_port(recall);
 
   /* run */
-  list = recall->children;
+  list_start = 
+    list = ags_list_util_copy_and_ref(recall->children);
 
   while(list != NULL){
-    list_next = list->next;
-
     if((AGS_RECALL_TEMPLATE & (AGS_RECALL(list->data)->flags)) != 0){
       g_warning("running on template\0");
-      list = list_next;
+      list = list->next;
       continue;
     }
 
-    ags_recall_run_pre(AGS_RECALL(list->data));
-
-    list = list_next;
+    g_object_ref(list->data);
+    AGS_RECALL_GET_CLASS(AGS_RECALL(list->data))->run_pre(AGS_RECALL(list->data));
+    g_object_unref(list->data);
+    g_object_unref(list->data);
+    
+    list = list->next;
   }
 
+  g_list_free(list_start);
+
   /* unlock ports */
   ags_recall_unlock_port(recall);
 }
@@ -1668,28 +1817,32 @@ ags_recall_run_pre(AgsRecall *recall)
 void
 ags_recall_real_run_inter(AgsRecall *recall)
 {
-  GList *list, *list_next;
+  GList *list, *list_start;
 
   /* lock port */
   ags_recall_lock_port(recall);
 
   /* run */
-  list = recall->children;
+  list_start = 
+    list = ags_list_util_copy_and_ref(recall->children);
 
   while(list != NULL){
-    list_next = list->next;
-
     if((AGS_RECALL_TEMPLATE & (AGS_RECALL(list->data)->flags)) != 0){
       g_warning("running on template\0");
-      list = list_next;
+      list = list->next;
       continue;
     }
 
-    ags_recall_run_inter(AGS_RECALL(list->data));
-
-    list = list_next;
+    g_object_ref(list->data);
+    AGS_RECALL_GET_CLASS(AGS_RECALL(list->data))->run_inter(AGS_RECALL(list->data));
+    g_object_unref(list->data);
+    g_object_unref(list->data);
+    
+    list = list->next;
   }
 
+  g_list_free(list_start);
+
   /* unlock port */
   ags_recall_unlock_port(recall);
 }
@@ -1716,28 +1869,32 @@ ags_recall_run_inter(AgsRecall *recall)
 void
 ags_recall_real_run_post(AgsRecall *recall)
 {
-  GList *list, *list_next;
+  GList *list, *list_start;
 
   /* lock port */
   ags_recall_lock_port(recall);
 
   /* run */
-  list = recall->children;
-
+  list_start = 
+    list = ags_list_util_copy_and_ref(recall->children);
+  
   while(list != NULL){
-    list_next = list->next;
-
     if((AGS_RECALL_TEMPLATE & (AGS_RECALL(list->data)->flags)) != 0){
       g_warning("running on template\0");
-      list = list_next;
+      list = list->next;
       continue;
     }
 
-    ags_recall_run_post(AGS_RECALL(list->data));
-
-    list = list_next;
+    g_object_ref(list->data);
+    AGS_RECALL_GET_CLASS(AGS_RECALL(list->data))->run_post(AGS_RECALL(list->data));
+    g_object_unref(list->data);
+    g_object_unref(list->data);
+    
+    list = list->next;
   }
 
+  g_list_free(list_start);
+  
   if((AGS_RECALL_INITIAL_RUN & (recall->flags)) != 0){
     recall->flags &= (~AGS_RECALL_INITIAL_RUN);
   }
@@ -1889,23 +2046,64 @@ ags_recall_cancel(AgsRecall *recall)
 void
 ags_recall_real_remove(AgsRecall *recall)
 {
+  AgsMutexManager *mutex_manager;
+  AgsDestroyWorker *destroy_worker;
+  
+  AgsApplicationContext *application_context;
+
   AgsRecall *parent;
 
-  if(recall == NULL){
-    return;
+  GList *worker;
+  
+  pthread_mutex_t *application_mutex;
+  
+  application_context = ags_application_context_get_instance();
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* get destroy worker */
+  pthread_mutex_lock(application_mutex);
+  
+  worker = ags_concurrency_provider_get_worker(AGS_CONCURRENCY_PROVIDER(application_context));
+  worker = ags_list_util_find_type(worker,
+				   AGS_TYPE_DESTROY_WORKER);
+
+  if(worker != NULL){
+    destroy_worker = worker->data;
+  }else{
+    destroy_worker = NULL;
   }
   
+  pthread_mutex_unlock(application_mutex);
+  
+  /* dispose and unref */
   g_object_ref(recall);
 
   if(recall->parent == NULL){
-    parent = NULL;
-    g_object_unref(recall);
+    if(destroy_worker != NULL){
+      ags_destroy_worker_add(destroy_worker,
+			     recall, ags_destroy_util_dispose_and_unref);
+    }else{
+      g_object_run_dispose(recall);
+      g_object_unref(recall);
+    }
+    
     return;
   }else{
     parent = AGS_RECALL(recall->parent);
 
     ags_recall_remove_child(parent,
-			    recall);
+    			    recall);
+
+    if(destroy_worker != NULL){
+      ags_destroy_worker_add(destroy_worker,
+			     recall, ags_destroy_util_dispose_and_unref);
+    }else{
+      g_object_run_dispose(recall);
+      g_object_unref(recall);
+    }
   }
 
   /* propagate done */
@@ -2206,8 +2404,13 @@ ags_recall_remove_child(AgsRecall *recall, AgsRecall *child)
     ags_dynamic_connectable_disconnect_dynamic(AGS_DYNAMIC_CONNECTABLE(child));
   }
   
+  pthread_mutex_lock(recall->children_mutex);
+
   recall->children = g_list_remove(recall->children,
 				   child);
+
+  pthread_mutex_unlock(recall->children_mutex);
+  
   child->parent = NULL;
 
   g_object_unref(recall);
@@ -2227,10 +2430,14 @@ void
 ags_recall_add_child(AgsRecall *parent, AgsRecall *child)
 {
   guint inheritated_flags_mask;
-
+  
   if(child == NULL ||
-     child->parent == parent)
+     parent == NULL ||
+     child->parent == parent){
     return;
+  }
+
+  g_object_ref(child);
 
   inheritated_flags_mask = (AGS_RECALL_PLAYBACK |
 			    AGS_RECALL_SEQUENCER |
@@ -2249,7 +2456,12 @@ ags_recall_add_child(AgsRecall *parent, AgsRecall *child)
   if(child->parent != NULL){
     child->flags &= (~inheritated_flags_mask);
 
+    pthread_mutex_lock(child->parent->children_mutex);
+    
     child->parent->children = g_list_remove(child->parent->children, child);
+
+    pthread_mutex_unlock(child->parent->children_mutex);
+
     g_object_unref(child->parent);
     g_object_unref(child);
     g_object_set(G_OBJECT(child),
@@ -2264,9 +2476,13 @@ ags_recall_add_child(AgsRecall *parent, AgsRecall *child)
 
     child->flags |= (inheritated_flags_mask & (parent->flags));
 
+    pthread_mutex_lock(parent->children_mutex);
+    
     parent->children = g_list_prepend(parent->children,
 				      child);
 
+    pthread_mutex_unlock(parent->children_mutex);
+
     g_object_set(G_OBJECT(child),
 		 "soundcard\0", parent->soundcard,
 		 "recall_id\0", parent->recall_id,
@@ -2293,6 +2509,8 @@ ags_recall_add_child(AgsRecall *parent, AgsRecall *child)
     ags_recall_run_init_inter(AGS_RECALL(child));
     ags_recall_run_init_post(AGS_RECALL(child));
   }
+
+  g_object_unref(child);
 }
 
 /**
@@ -2439,8 +2657,9 @@ ags_recall_find_type(GList *recall_i, GType type)
   while(recall_i != NULL){
     recall = AGS_RECALL(recall_i->data);
 
-    if(G_OBJECT_TYPE(recall) == type)
+    if(G_OBJECT_TYPE(recall) == type){
       break;
+    }
 
     recall_i = recall_i->next;
   }
@@ -2594,8 +2813,9 @@ ags_recall_find_type_with_recycling_context(GList *recall_i, GType type, GObject
 
     if(g_type_is_a(G_OBJECT_TYPE(recall), type) &&
        recall->recall_id != NULL &&
-       recall->recall_id->recycling_context == (AgsRecyclingContext *) recycling_context)
+       recall->recall_id->recycling_context == (AgsRecyclingContext *) recycling_context){
       return(recall_i);
+    }
 
     recall_i = recall_i->next;
   }
@@ -2852,6 +3072,7 @@ ags_recall_child_done(AgsRecall *child,
   
   ags_recall_remove_child(parent,
 			  child);
+  g_object_run_dispose(child);
 }
 
 /**
diff --git a/ags/audio/ags_recall.h b/ags/audio/ags_recall.h
index 98e133b..7f44607 100644
--- a/ags/audio/ags_recall.h
+++ b/ags/audio/ags_recall.h
@@ -23,6 +23,8 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include <pthread.h>
+
 #include <ags/audio/ags_port.h>
 #include <ags/audio/ags_recall_id.h>
 #include <ags/audio/ags_recall_dependency.h>
@@ -67,6 +69,7 @@ typedef enum{
   AGS_RECALL_PERSISTENT_NOTATION   = 1 << 19,
   AGS_RECALL_SKIP_DEPENDENCIES     = 1 << 20,
   AGS_RECALL_BULK_MODE             = 1 << 21,
+  AGS_RECALL_HAS_OUTPUT_PORT       = 1 << 22,
 }AgsRecallFlags;
 
 typedef enum{
@@ -99,6 +102,8 @@ struct _AgsRecall
 
   AgsRecallID *recall_id;
 
+  pthread_mutex_t *children_mutex;
+
   AgsRecall *parent;
   GList *children;
 
diff --git a/ags/audio/ags_recall_audio.c b/ags/audio/ags_recall_audio.c
index c88846b..f7cc542 100644
--- a/ags/audio/ags_recall_audio.c
+++ b/ags/audio/ags_recall_audio.c
@@ -44,6 +44,7 @@ void ags_recall_audio_connect(AgsConnectable *connectable);
 void ags_recall_audio_disconnect(AgsConnectable *connectable);
 gboolean ags_recall_audio_pack(AgsPackable *packable, GObject *container);
 gboolean ags_recall_audio_unpack(AgsPackable *packable);
+void ags_recall_audio_dispose(GObject *gobject);
 void ags_recall_audio_finalize(GObject *gobject);
 
 void ags_recall_audio_load_automation(AgsRecall *recall,
@@ -132,6 +133,7 @@ ags_recall_audio_class_init(AgsRecallAudioClass *recall_audio)
   /* GObjectClass */
   gobject = (GObjectClass *) recall_audio;
 
+  gobject->dispose = ags_recall_audio_dispose;
   gobject->finalize = ags_recall_audio_finalize;
 
   gobject->set_property = ags_recall_audio_set_property;
@@ -337,15 +339,39 @@ ags_recall_audio_unpack(AgsPackable *packable)
 }
 
 void
+ags_recall_audio_dispose(GObject *gobject)
+{
+  AgsRecallAudio *recall_audio;
+
+  recall_audio = AGS_RECALL_AUDIO(gobject);
+
+  /* unpack */
+  ags_packable_unpack(AGS_PACKABLE(recall_audio));
+  
+  /* audio */
+  if(recall_audio->audio != NULL){
+    g_object_unref(G_OBJECT(recall_audio->audio));
+
+    recall_audio->audio = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_recall_audio_parent_class)->dispose(gobject);
+}
+
+void
 ags_recall_audio_finalize(GObject *gobject)
 {
   AgsRecallAudio *recall_audio;
 
   recall_audio = AGS_RECALL_AUDIO(gobject);
 
-  if(recall_audio->audio != NULL)
+  /* audio */
+  if(recall_audio->audio != NULL){
     g_object_unref(G_OBJECT(recall_audio->audio));
+  }
 
+  /* call parent */
   G_OBJECT_CLASS(ags_recall_audio_parent_class)->finalize(gobject);
 }
 
@@ -362,6 +388,12 @@ ags_recall_audio_load_automation(AgsRecall *recall,
   audio = AGS_RECALL_AUDIO(recall)->audio;
 
   while(automation_port != NULL){
+    if((AGS_PORT_IS_OUTPUT & (AGS_PORT(automation_port->data)->flags)) != 0){
+      automation_port = automation_port->next;
+
+      continue;
+    }
+
     if(ags_automation_find_port(audio->automation,
 				automation_port->data) == NULL){
       current = ags_automation_new((GObject *) audio,
diff --git a/ags/audio/ags_recall_audio_run.c b/ags/audio/ags_recall_audio_run.c
index 4decaa5..333dd1d 100644
--- a/ags/audio/ags_recall_audio_run.c
+++ b/ags/audio/ags_recall_audio_run.c
@@ -51,6 +51,7 @@ gboolean ags_recall_audio_run_pack(AgsPackable *packable, GObject *container);
 gboolean ags_recall_audio_run_unpack(AgsPackable *packable);
 void ags_recall_audio_run_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
 void ags_recall_audio_run_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+void ags_recall_audio_run_dispose(GObject *gobject);
 void ags_recall_audio_run_finalize(GObject *gobject);
 
 void ags_recall_audio_run_remove(AgsRecall *recall);
@@ -71,6 +72,7 @@ enum{
 
 enum{
   PROP_0,
+  PROP_AUDIO,
   PROP_RECALL_AUDIO,
 };
 
@@ -152,10 +154,27 @@ ags_recall_audio_run_class_init(AgsRecallAudioRunClass *recall_audio_run)
   gobject->set_property = ags_recall_audio_run_set_property;
   gobject->get_property = ags_recall_audio_run_get_property;
 
+  gobject->dispose = ags_recall_audio_run_dispose;
   gobject->finalize = ags_recall_audio_run_finalize;
 
   /* properties */
   /**
+   * AgsRecallAudioRun:audio:
+   *
+   * The assigned audio.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("audio\0",
+				   "assigned audio\0",
+				   "The audio object it is assigned to\0",
+				   AGS_TYPE_AUDIO,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_AUDIO,
+				  param_spec);
+
+  /**
    * AgsRecallAudioRun:recall-audio:
    *
    * The recall audio belonging to.
@@ -210,10 +229,10 @@ ags_recall_audio_run_dynamic_connectable_interface_init(AgsDynamicConnectableInt
 void
 ags_recall_audio_run_init(AgsRecallAudioRun *recall_audio_run)
 {
+  recall_audio_run->audio = NULL;
   recall_audio_run->recall_audio = NULL;
 }
 
-
 void
 ags_recall_audio_run_set_property(GObject *gobject,
 				  guint prop_id,
@@ -225,14 +244,36 @@ ags_recall_audio_run_set_property(GObject *gobject,
   recall_audio_run = AGS_RECALL_AUDIO_RUN(gobject);
 
   switch(prop_id){
+  case PROP_AUDIO:
+    {
+      AgsRecallAudio *audio;
+
+      audio = (AgsRecallAudio *) g_value_get_object(value);
+
+      if(recall_audio_run->audio == audio){
+	return;
+      }
+
+      if(recall_audio_run->audio != NULL){
+	g_object_unref(G_OBJECT(recall_audio_run->audio));
+      }
+
+      if(audio != NULL){
+	g_object_ref(G_OBJECT(audio));
+      }
+
+      recall_audio_run->audio = audio;
+    }
+    break;
   case PROP_RECALL_AUDIO:
     {
       AgsRecallAudio *recall_audio;
 
       recall_audio = (AgsRecallAudio *) g_value_get_object(value);
 
-      if(recall_audio_run->recall_audio == recall_audio)
+      if(recall_audio_run->recall_audio == recall_audio){
 	return;
+      }
 
       if(recall_audio_run->recall_audio != NULL){
 	g_object_unref(G_OBJECT(recall_audio_run->recall_audio));
@@ -262,6 +303,11 @@ ags_recall_audio_run_get_property(GObject *gobject,
   recall_audio_run = AGS_RECALL_AUDIO_RUN(gobject);
 
   switch(prop_id){
+  case PROP_AUDIO:
+    {
+      g_value_set_object(value, recall_audio_run->audio);
+    }
+    break;
   case PROP_RECALL_AUDIO:
     {
       g_value_set_object(value, recall_audio_run->recall_audio);
@@ -274,15 +320,74 @@ ags_recall_audio_run_get_property(GObject *gobject,
 }
 
 void
+ags_recall_audio_run_dispose(GObject *gobject)
+{
+  AgsRecallAudioRun *recall_audio_run;
+
+  recall_audio_run = AGS_RECALL_AUDIO_RUN(gobject);
+
+  /* unpack */
+  ags_packable_unpack(AGS_PACKABLE(recall_audio_run));
+
+  if(AGS_RECALL(gobject)->container != NULL){
+    AgsRecallContainer *recall_container;
+
+    recall_container = AGS_RECALL(gobject)->container;
+
+    recall_container->recall_audio_run = g_list_remove(recall_container->recall_audio_run,
+						       gobject);
+    g_object_unref(gobject);
+    g_object_unref(AGS_RECALL(gobject)->container);
+
+    AGS_RECALL(gobject)->container = NULL;
+  }
+
+  /* audio */
+  if(recall_audio_run->audio != NULL){
+    g_object_unref(G_OBJECT(recall_audio_run->audio));
+
+    recall_audio_run->audio = NULL;
+  }
+
+  /* recall audio */
+  if(recall_audio_run->recall_audio != NULL){
+    g_object_unref(G_OBJECT(recall_audio_run->recall_audio));
+
+    recall_audio_run->recall_audio = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_recall_audio_run_parent_class)->dispose(gobject);
+}
+
+void
 ags_recall_audio_run_finalize(GObject *gobject)
 {
   AgsRecallAudioRun *recall_audio_run;
 
   recall_audio_run = AGS_RECALL_AUDIO_RUN(gobject);
 
-  if(recall_audio_run->recall_audio != NULL)
+  if(AGS_RECALL(gobject)->container != NULL){
+    AgsRecallContainer *recall_container;
+
+    recall_container = AGS_RECALL(gobject)->container;
+
+    recall_container->recall_audio_run = g_list_remove(recall_container->recall_audio_run,
+						       gobject);
+    g_object_unref(AGS_RECALL(gobject)->container);
+  }
+  
+  /* audio */
+  if(recall_audio_run->audio != NULL){
+    g_object_unref(G_OBJECT(recall_audio_run->audio));
+  }
+
+  /* recall audio */
+  if(recall_audio_run->recall_audio != NULL){
     g_object_unref(G_OBJECT(recall_audio_run->recall_audio));
+  }
 
+  /* call parent */
   G_OBJECT_CLASS(ags_recall_audio_run_parent_class)->finalize(gobject);
 }
 
diff --git a/ags/audio/ags_recall_audio_signal.c b/ags/audio/ags_recall_audio_signal.c
index 2174c78..9b6a345 100644
--- a/ags/audio/ags_recall_audio_signal.c
+++ b/ags/audio/ags_recall_audio_signal.c
@@ -49,6 +49,7 @@ void ags_recall_audio_signal_connect(AgsConnectable *connectable);
 void ags_recall_audio_signal_disconnect(AgsConnectable *connectable);
 void ags_recall_audio_signal_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
 void ags_recall_audio_signal_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+void ags_recall_audio_signal_dispose(GObject *gobject);
 void ags_recall_audio_signal_finalize(GObject *gobject);
 
 void ags_recall_audio_signal_run_init_pre(AgsRecall *recall);
@@ -150,6 +151,7 @@ ags_recall_audio_signal_class_init(AgsRecallAudioSignalClass *recall_audio_signa
   gobject->set_property = ags_recall_audio_signal_set_property;
   gobject->get_property = ags_recall_audio_signal_get_property;
 
+  gobject->dispose = ags_recall_audio_signal_dispose;
   gobject->finalize = ags_recall_audio_signal_finalize;
 
   /* for debugging purpose */
@@ -385,23 +387,48 @@ ags_recall_audio_signal_disconnect_dynamic(AgsDynamicConnectable *dynamic_connec
 }
 
 void
-ags_recall_audio_signal_finalize(GObject *gobject)
+ags_recall_audio_signal_dispose(GObject *gobject)
 {
   AgsRecallAudioSignal *recall_audio_signal;
 
   recall_audio_signal = AGS_RECALL_AUDIO_SIGNAL(gobject);
-  
+
+  /* destination */
   if(recall_audio_signal->destination != NULL){
     g_object_unref(recall_audio_signal->destination);
+
     recall_audio_signal->destination = NULL;
   }
 
+  /* source */
   if(recall_audio_signal->source != NULL){
     g_object_unref(recall_audio_signal->source);
+
     recall_audio_signal->source = NULL;
   }
 
   /* call parent */
+  G_OBJECT_CLASS(ags_recall_audio_signal_parent_class)->dispose(gobject);
+}
+
+void
+ags_recall_audio_signal_finalize(GObject *gobject)
+{
+  AgsRecallAudioSignal *recall_audio_signal;
+
+  recall_audio_signal = AGS_RECALL_AUDIO_SIGNAL(gobject);
+
+  /* destination */
+  if(recall_audio_signal->destination != NULL){
+    g_object_unref(recall_audio_signal->destination);
+  }
+
+  /* source */
+  if(recall_audio_signal->source != NULL){
+    g_object_unref(recall_audio_signal->source);
+  }
+
+  /* call parent */
   G_OBJECT_CLASS(ags_recall_audio_signal_parent_class)->finalize(gobject);
 }
 
@@ -412,6 +439,7 @@ ags_recall_audio_signal_duplicate(AgsRecall *recall,
 {
   AgsRecallAudioSignal *recall_audio_signal, *copy;
 
+#if 0
   recall_audio_signal = AGS_RECALL_AUDIO_SIGNAL(recall);
   parameter = ags_parameter_grow(G_OBJECT_TYPE(recall),
 				 parameter, n_params,
@@ -424,8 +452,9 @@ ags_recall_audio_signal_duplicate(AgsRecall *recall,
   copy = (AgsRecallAudioSignal *) AGS_RECALL_CLASS(ags_recall_audio_signal_parent_class)->duplicate(recall,
 												    recall_id,
 												    n_params, parameter);
-
-  return((AgsRecall *) copy);
+#endif
+  
+  return((AgsRecall *) NULL);
 }
 
 void
diff --git a/ags/audio/ags_recall_channel.c b/ags/audio/ags_recall_channel.c
index caf2cd8..31d986e 100644
--- a/ags/audio/ags_recall_channel.c
+++ b/ags/audio/ags_recall_channel.c
@@ -49,6 +49,7 @@ void ags_recall_channel_connect(AgsConnectable *connectable);
 void ags_recall_channel_disconnect(AgsConnectable *connectable);
 gboolean ags_recall_channel_pack(AgsPackable *packable, GObject *container);
 gboolean ags_recall_channel_unpack(AgsPackable *packable);
+void ags_recall_channel_dispose(GObject *gobject);
 void ags_recall_channel_finalize(GObject *gobject);
 
 void ags_recall_channel_load_automation(AgsRecall *recall,
@@ -141,6 +142,7 @@ ags_recall_channel_class_init(AgsRecallChannelClass *recall_channel)
   gobject->set_property = ags_recall_channel_set_property;
   gobject->get_property = ags_recall_channel_get_property;
 
+  gobject->dispose = ags_recall_channel_dispose;
   gobject->finalize = ags_recall_channel_finalize;
 
   /* properties */
@@ -229,15 +231,18 @@ ags_recall_channel_class_init(AgsRecallChannelClass *recall_channel)
 
        destination = (AgsChannel *) g_value_get_object(value);
 
-       if(recall_channel->destination == destination)
+       if(recall_channel->destination == destination){
 	 return;
+       }
 
-       if(recall_channel->destination != NULL)
+       if(recall_channel->destination != NULL){
 	 g_object_unref(recall_channel->destination);
-
-       if(destination != NULL)
+       }
+       
+       if(destination != NULL){
 	 g_object_ref(destination);
-
+       }
+       
        recall_channel->destination = destination;
      }
      break;
@@ -247,23 +252,26 @@ ags_recall_channel_class_init(AgsRecallChannelClass *recall_channel)
 
        source = (AgsChannel *) g_value_get_object(value);
 
-       if(recall_channel->source == source)
+       if(recall_channel->source == source){
 	 return;
+       }
 
-       if(recall_channel->source != NULL)
+       if(recall_channel->source != NULL){
 	 g_object_unref(recall_channel->source);
-
-      if(source != NULL)
-	g_object_ref(source);
-
-      recall_channel->source = source;
-    }
-    break;
-  default:
-    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
-    break;
-  }
-}
+       }
+	
+       if(source != NULL){
+	 g_object_ref(source);
+       }
+       
+       recall_channel->source = source;
+     }
+     break;
+   default:
+     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+     break;
+   }
+ }
 
 void
 ags_recall_channel_get_property(GObject *gobject,
@@ -277,10 +285,14 @@ ags_recall_channel_get_property(GObject *gobject,
 
   switch(prop_id){
   case PROP_DESTINATION:
-    g_value_set_object(value, recall_channel->destination);
+    {
+      g_value_set_object(value, recall_channel->destination);
+    }
     break;
   case PROP_SOURCE:
-    g_value_set_object(value, recall_channel->source);
+    {
+      g_value_set_object(value, recall_channel->source);
+    }
     break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
@@ -289,18 +301,51 @@ ags_recall_channel_get_property(GObject *gobject,
 }
 
 void
+ags_recall_channel_dispose(GObject *gobject)
+{
+  AgsRecallChannel *recall_channel;
+
+  recall_channel = AGS_RECALL_CHANNEL(gobject);
+
+  /* unpack */
+  ags_packable_unpack(AGS_PACKABLE(recall_channel));
+  
+  /* source */
+  if(recall_channel->source != NULL){
+    g_object_unref(recall_channel->source);
+
+    recall_channel->source = NULL;
+  }
+
+  /* destination */
+  if(recall_channel->destination != NULL){
+    g_object_unref(G_OBJECT(recall_channel->destination));
+
+    recall_channel->destination = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_recall_channel_parent_class)->dispose(gobject);
+}
+
+void
 ags_recall_channel_finalize(GObject *gobject)
 {
   AgsRecallChannel *recall_channel;
 
   recall_channel = AGS_RECALL_CHANNEL(gobject);
 
-  if(recall_channel->source != NULL)
+  /* source */
+  if(recall_channel->source != NULL){
     g_object_unref(recall_channel->source);
+  }
 
-  if(recall_channel->destination != NULL)
+  /* destination */
+  if(recall_channel->destination != NULL){
     g_object_unref(G_OBJECT(recall_channel->destination));
+  }
 
+  /* call parent */
   G_OBJECT_CLASS(ags_recall_channel_parent_class)->finalize(gobject);
 }
 
@@ -327,8 +372,9 @@ ags_recall_channel_pack(AgsPackable *packable, GObject *container)
   AgsRecallChannel *recall_channel;
   GList *list;
 
-  if(ags_recall_channel_parent_packable_interface->pack(packable, container))
+  if(ags_recall_channel_parent_packable_interface->pack(packable, container)){
     return(TRUE);
+  }
 
   recall_container = AGS_RECALL_CONTAINER(container);
   recall_channel = AGS_RECALL_CHANNEL(packable);
@@ -360,13 +406,15 @@ ags_recall_channel_unpack(AgsPackable *packable)
   
   recall = AGS_RECALL(packable);
 
-  if(recall == NULL)
+  if(recall == NULL){
     return(TRUE);
+  }
 
   recall_container = AGS_RECALL_CONTAINER(recall->container);
 
-  if(recall_container == NULL)
+  if(recall_container == NULL){
     return(TRUE);
+  }
 
   /* ref */
   g_object_ref(recall);
@@ -425,6 +473,12 @@ ags_recall_channel_load_automation(AgsRecall *recall,
   }
   
   while(automation_port != NULL){
+    if((AGS_PORT_IS_OUTPUT & (AGS_PORT(automation_port->data)->flags)) != 0){
+      automation_port = automation_port->next;
+
+      continue;
+    }
+    
     if((automation = ags_automation_find_port(audio->automation,
 					      automation_port->data)) == NULL){
       current = ags_automation_new(channel->audio,
diff --git a/ags/audio/ags_recall_channel_run.c b/ags/audio/ags_recall_channel_run.c
index 40b81f6..bab81f5 100644
--- a/ags/audio/ags_recall_channel_run.c
+++ b/ags/audio/ags_recall_channel_run.c
@@ -63,6 +63,7 @@ gboolean ags_recall_channel_run_pack(AgsPackable *packable, GObject *container);
 gboolean ags_recall_channel_run_unpack(AgsPackable *packable);
 void ags_recall_channel_run_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
 void ags_recall_channel_run_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+void ags_recall_channel_run_dispose(GObject *gobject);
 void ags_recall_channel_run_finalize(GObject *gobject);
 
 void ags_recall_channel_run_remove(AgsRecall *recall);
@@ -198,6 +199,7 @@ ags_recall_channel_run_class_init(AgsRecallChannelRunClass *recall_channel_run)
   gobject->set_property = ags_recall_channel_run_set_property;
   gobject->get_property = ags_recall_channel_run_get_property;
 
+  gobject->dispose = ags_recall_channel_run_dispose;
   gobject->finalize = ags_recall_channel_run_finalize;
 
   /* properties */
@@ -378,8 +380,9 @@ ags_recall_channel_run_set_property(GObject *gobject,
 
       recall_audio_run = (AgsRecallAudioRun *) g_value_get_object(value);
 
-      if(recall_channel_run->recall_audio_run == recall_audio_run)
+      if(recall_channel_run->recall_audio_run == recall_audio_run){
 	return;
+      }
 
       if(recall_channel_run->recall_audio_run != NULL){
 	g_object_unref(G_OBJECT(recall_channel_run->recall_audio_run));
@@ -398,8 +401,9 @@ ags_recall_channel_run_set_property(GObject *gobject,
 
       recall_channel = (AgsRecallChannel *) g_value_get_object(value);
 
-      if(recall_channel_run->recall_channel == recall_channel)
+      if(recall_channel_run->recall_channel == recall_channel){
 	return;
+      }
 
       if(recall_channel_run->recall_channel != NULL){
 	g_object_unref(G_OBJECT(recall_channel_run->recall_channel));
@@ -460,11 +464,13 @@ ags_recall_channel_run_set_property(GObject *gobject,
 
       recall_channel_run->source = source;
 
-      if(source == recall_channel_run->destination)
+      if(source == recall_channel_run->destination){
 	g_warning("destination == recall_channel_run->source\0");
-
-      if(old_source != NULL)
+      }
+      
+      if(old_source != NULL){
 	g_object_unref(G_OBJECT(old_source));
+      }
     }
     break;
   default:
@@ -516,28 +522,98 @@ ags_recall_channel_run_get_property(GObject *gobject,
 }
 
 void
-ags_recall_channel_run_finalize(GObject *gobject)
+ags_recall_channel_run_dispose(GObject *gobject)
 {
   AgsRecallChannelRun *recall_channel_run;
 
   recall_channel_run = AGS_RECALL_CHANNEL_RUN(gobject);
 
+  /* unpack */
+  ags_packable_unpack(AGS_PACKABLE(recall_channel_run));
+
+  if(AGS_RECALL(gobject)->container != NULL){
+    AgsRecallContainer *recall_container;
+
+    recall_container = AGS_RECALL(gobject)->container;
+
+    recall_container->recall_channel_run = g_list_remove(recall_container->recall_channel_run,
+							 gobject);
+    g_object_unref(gobject);
+    g_object_unref(AGS_RECALL(gobject)->container);
+
+    AGS_RECALL(gobject)->container = NULL;
+  }
+  
+  /* recall audio run */
   if(recall_channel_run->recall_audio_run != NULL){
     g_object_unref(G_OBJECT(recall_channel_run->recall_audio_run));
+
+    recall_channel_run->recall_audio_run = NULL;
   }
   
+  /* recall channel */
   if(recall_channel_run->recall_channel != NULL){
     g_object_unref(G_OBJECT(recall_channel_run->recall_channel));
+
+    recall_channel_run->recall_channel = NULL;
   }
-  
+
+  /* destination */
   if(recall_channel_run->destination != NULL){
     g_object_unref(recall_channel_run->destination);
+
+    recall_channel_run->destination = NULL;
   }
-  
+
+  /* source */
   if(recall_channel_run->source != NULL){
     g_object_unref(recall_channel_run->source);
+
+    recall_channel_run->source = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_recall_channel_run_parent_class)->dispose(gobject);
+}
+
+void
+ags_recall_channel_run_finalize(GObject *gobject)
+{
+  AgsRecallChannelRun *recall_channel_run;
+
+  recall_channel_run = AGS_RECALL_CHANNEL_RUN(gobject);
+
+  if(AGS_RECALL(gobject)->container != NULL){
+    AgsRecallContainer *recall_container;
+
+    recall_container = AGS_RECALL(gobject)->container;
+
+    recall_container->recall_channel_run = g_list_remove(recall_container->recall_channel_run,
+							 gobject);
+    g_object_unref(AGS_RECALL(gobject)->container);
+  }
+
+  /* recall audio run */
+  if(recall_channel_run->recall_audio_run != NULL){
+    g_object_unref(G_OBJECT(recall_channel_run->recall_audio_run));
   }
   
+  /* recall channel */
+  if(recall_channel_run->recall_channel != NULL){
+    g_object_unref(G_OBJECT(recall_channel_run->recall_channel));
+  }
+
+  /* destination */
+  if(recall_channel_run->destination != NULL){
+    g_object_unref(recall_channel_run->destination);
+  }
+
+  /* source */
+  if(recall_channel_run->source != NULL){
+    g_object_unref(recall_channel_run->source);
+  }
+
+  /* call parent */
   G_OBJECT_CLASS(ags_recall_channel_run_parent_class)->finalize(gobject);
 }
 
@@ -685,13 +761,15 @@ ags_recall_channel_run_unpack(AgsPackable *packable)
 
   recall = AGS_RECALL(packable);
 
-  if(recall == NULL)
+  if(recall == NULL){
     return(TRUE);
+  }
 
   recall_container = AGS_RECALL_CONTAINER(recall->container);
 
-  if(recall_container == NULL)
+  if(recall_container == NULL){
     return(TRUE);
+  }
 
   /* ref */
   g_object_ref(recall);
diff --git a/ags/audio/ags_recall_container.c b/ags/audio/ags_recall_container.c
index 414a912..b532cf5 100644
--- a/ags/audio/ags_recall_container.c
+++ b/ags/audio/ags_recall_container.c
@@ -324,14 +324,16 @@ ags_recall_container_set_property(GObject *gobject,
       recall_audio_run = (AgsRecallAudioRun *) g_value_get_object(value);
 
       if(recall_audio_run == NULL ||
-	 g_list_find(recall_container->recall_audio_run, recall_audio_run) != NULL)
+	 g_list_find(recall_container->recall_audio_run, recall_audio_run) != NULL){
 	return;
+      }
 
       if(recall_audio_run != NULL){
 	g_object_ref(G_OBJECT(recall_audio_run));
       }
 
-      recall_container->recall_audio_run = g_list_prepend(recall_container->recall_audio_run, recall_audio_run);
+      recall_container->recall_audio_run = g_list_prepend(recall_container->recall_audio_run,
+							  recall_audio_run);
     }
     break;
   case PROP_RECALL_CHANNEL_TYPE:
@@ -350,12 +352,14 @@ ags_recall_container_set_property(GObject *gobject,
       recall_channel = (AgsRecallChannel *) g_value_get_object(value);
 
       if(recall_channel == NULL ||
-	 g_list_find(recall_container->recall_channel, recall_channel) != NULL)
+	 g_list_find(recall_container->recall_channel, recall_channel) != NULL){
 	return;
+      }
 
-	g_object_ref(G_OBJECT(recall_channel));
-
-	recall_container->recall_channel = g_list_prepend(recall_container->recall_channel, recall_channel);
+      g_object_ref(G_OBJECT(recall_channel));
+      
+      recall_container->recall_channel = g_list_prepend(recall_container->recall_channel,
+							recall_channel);
     }
     break;
   case PROP_RECALL_CHANNEL_RUN_TYPE:
@@ -374,12 +378,14 @@ ags_recall_container_set_property(GObject *gobject,
       recall_channel_run = (AgsRecallChannelRun *) g_value_get_object(value);
 
       if(recall_channel_run == NULL ||
-	 g_list_find(recall_container->recall_channel_run, recall_channel_run) != NULL)
+	 g_list_find(recall_container->recall_channel_run, recall_channel_run) != NULL){
 	return;
+      }
 
       g_object_ref(G_OBJECT(recall_channel_run));
 
-      recall_container->recall_channel_run = g_list_prepend(recall_container->recall_channel_run, recall_channel_run);
+      recall_container->recall_channel_run = g_list_prepend(recall_container->recall_channel_run,
+							    recall_channel_run);
     }
     break;
   default:
diff --git a/ags/audio/ags_recall_dependency.c b/ags/audio/ags_recall_dependency.c
index 0c1a425..a425c7a 100644
--- a/ags/audio/ags_recall_dependency.c
+++ b/ags/audio/ags_recall_dependency.c
@@ -32,8 +32,17 @@
 void ags_recall_dependency_class_init(AgsRecallDependencyClass *recall_dependency);
 void ags_recall_dependency_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_recall_dependency_init(AgsRecallDependency *recall_dependency);
+void ags_recall_dependency_set_property(GObject *gobject,
+					guint prop_id,
+					const GValue *value,
+					GParamSpec *param_spec);
+void ags_recall_dependency_get_property(GObject *gobject,
+					guint prop_id,
+					GValue *value,
+					GParamSpec *param_spec);
 void ags_recall_dependency_connect(AgsConnectable *connectable);
 void ags_recall_dependency_disconnect(AgsConnectable *connectable);
+void ags_recall_dependency_dispose(GObject *gobject);
 void ags_recall_dependency_finalize(GObject *gobject);
 
 /**
@@ -49,6 +58,11 @@ void ags_recall_dependency_finalize(GObject *gobject);
 
 static gpointer ags_recall_dependency_parent_class = NULL;
 
+enum{
+  PROP_0,
+  PROP_DEPENDENCY,
+};
+
 GType
 ags_recall_dependency_get_type(void)
 {
@@ -90,11 +104,34 @@ void
 ags_recall_dependency_class_init(AgsRecallDependencyClass *recall_dependency)
 {
   GObjectClass *gobject;
-
+  GParamSpec *param_spec;
+  
   ags_recall_dependency_parent_class = g_type_class_peek_parent(recall_dependency);
 
   gobject = (GObjectClass *) recall_dependency;
+
+  gobject->set_property = ags_recall_dependency_set_property;
+  gobject->get_property = ags_recall_dependency_get_property;
+  
+  gobject->dispose = ags_recall_dependency_dispose;
   gobject->finalize = ags_recall_dependency_finalize;
+
+  /* properties */
+  /**
+   * AgsRecallDependency:dependency:
+   *
+   * The dependency.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("dependency\0",
+				   "dependency of recall\0",
+				   "A dependency of the recall\0",
+				   AGS_TYPE_RECALL,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_DEPENDENCY,
+				  param_spec);
 }
 
 void
@@ -107,24 +144,130 @@ ags_recall_dependency_connectable_interface_init(AgsConnectableInterface *connec
 void
 ags_recall_dependency_init(AgsRecallDependency *recall_dependency)
 {
+  recall_dependency->flags = 0;
+  
   recall_dependency->dependency = NULL;
 }
 
 void
+ags_recall_dependency_set_property(GObject *gobject,
+				   guint prop_id,
+				   const GValue *value,
+				   GParamSpec *param_spec)
+{
+  AgsRecallDependency *recall_dependency;
+
+  recall_dependency = AGS_RECALL_DEPENDENCY(gobject);
+  
+  switch(prop_id){
+  case PROP_DEPENDENCY:
+    {
+      AgsRecall *dependency;
+      
+      dependency = (AgsRecall *) g_value_get_object(value);
+      
+      if(recall_dependency->dependency == dependency){
+	return;
+      }
+	
+      if(recall_dependency->dependency != NULL){
+	g_object_unref(G_OBJECT(recall_dependency->dependency));
+      }
+
+      if(dependency != NULL){
+	g_object_ref(G_OBJECT(dependency));
+      }
+
+      recall_dependency->dependency = dependency;
+    }
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  };
+}
+
+void
+ags_recall_dependency_get_property(GObject *gobject,
+				   guint prop_id,
+				   GValue *value,
+				   GParamSpec *param_spec)
+{
+  AgsRecallDependency *recall_dependency;
+
+  recall_dependency = AGS_RECALL_DEPENDENCY(gobject);
+
+  switch(prop_id){
+  case PROP_DEPENDENCY:
+    {
+      g_value_set_object(value, recall_dependency->dependency);
+    }
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  };
+}
+
+void
 ags_recall_dependency_connect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsRecallDependency *recall_dependency;
+
+  recall_dependency = AGS_RECALL_DEPENDENCY(connectable);
+
+  if((AGS_RECALL_DEPENDENCY_CONNECTED & (recall_dependency->flags)) != 0){
+    return;
+  }
+
+  recall_dependency->flags |= AGS_RECALL_DEPENDENCY_CONNECTED;
 }
 
 void
 ags_recall_dependency_disconnect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsRecallDependency *recall_dependency;
+
+  recall_dependency = AGS_RECALL_DEPENDENCY(connectable);
+
+  if((AGS_RECALL_DEPENDENCY_CONNECTED & (recall_dependency->flags)) == 0){
+    return;
+  }
+
+  recall_dependency->flags &= (~AGS_RECALL_DEPENDENCY_CONNECTED);
+}
+
+void
+ags_recall_dependency_dispose(GObject *gobject)
+{
+  AgsRecallDependency *recall_dependency;
+
+  recall_dependency = AGS_RECALL_DEPENDENCY(gobject);
+
+  /* dependency */
+  if(recall_dependency->dependency != NULL){
+    g_object_unref(recall_dependency->dependency);
+
+    recall_dependency->dependency = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_recall_dependency_parent_class)->dispose(gobject);
 }
 
 void
 ags_recall_dependency_finalize(GObject *gobject)
 {
+  AgsRecallDependency *recall_dependency;
+
+  recall_dependency = AGS_RECALL_DEPENDENCY(gobject);
+
+  /* dependency */
+  if(recall_dependency->dependency != NULL){
+    g_object_unref(recall_dependency->dependency);
+  }
+
+  /* call parent */
   G_OBJECT_CLASS(ags_recall_dependency_parent_class)->finalize(gobject);
 }
 
@@ -296,9 +439,8 @@ ags_recall_dependency_new(GObject *dependency)
   AgsRecallDependency *recall_dependency;
 
   recall_dependency = (AgsRecallDependency *) g_object_new(AGS_TYPE_RECALL_DEPENDENCY,
+							   "dependency\0", dependency,
 							   NULL);
 
-  recall_dependency->dependency = dependency;
-
   return(recall_dependency);
 }
diff --git a/ags/audio/ags_recall_dependency.h b/ags/audio/ags_recall_dependency.h
index 321d494..913d8de 100644
--- a/ags/audio/ags_recall_dependency.h
+++ b/ags/audio/ags_recall_dependency.h
@@ -35,10 +35,16 @@
 typedef struct _AgsRecallDependency AgsRecallDependency;
 typedef struct _AgsRecallDependencyClass AgsRecallDependencyClass;
 
+typedef enum{
+  AGS_RECALL_DEPENDENCY_CONNECTED      = 1,
+}AgsRecallDependencyFlags;
+
 struct _AgsRecallDependency
 {
   GObject object;
 
+  guint flags;
+  
   GObject *dependency;
 };
 
diff --git a/ags/audio/ags_recall_dssi.c b/ags/audio/ags_recall_dssi.c
index d63c3ec..0ff41ee 100644
--- a/ags/audio/ags_recall_dssi.c
+++ b/ags/audio/ags_recall_dssi.c
@@ -639,7 +639,19 @@ ags_recall_dssi_load_ports(AgsRecallDssi *recall_dssi)
 			       "port-value-is-pointer\0", FALSE,
 			       "port-value-type\0", G_TYPE_FLOAT,
 			       NULL);
+	g_object_ref(current);
 	current->flags |= AGS_PORT_USE_LADSPA_FLOAT;
+
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  AGS_RECALL(recall_dssi)->flags |= AGS_RECALL_HAS_OUTPUT_PORT;
+
+	  current->flags |= AGS_PORT_IS_OUTPUT;
+	}else{
+	  if((AGS_PORT_DESCRIPTOR_INTEGER & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) == 0 &&
+	     (AGS_PORT_DESCRIPTOR_TOGGLED & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) == 0){
+	    current->flags |= AGS_PORT_INFINITE_RANGE;
+	  }
+	}
 	
 	current->port_descriptor = port_descriptor->data;
 	ags_recall_dssi_load_conversion(recall_dssi,
diff --git a/ags/audio/ags_recall_dssi_run.c b/ags/audio/ags_recall_dssi_run.c
index 87456ee..0425eaa 100644
--- a/ags/audio/ags_recall_dssi_run.c
+++ b/ags/audio/ags_recall_dssi_run.c
@@ -195,9 +195,11 @@ ags_recall_dssi_run_finalize(GObject *gobject)
   free(recall_dssi_run->event_count);    
 
   free(recall_dssi_run->ladspa_handle);
-  
-  AGS_ROUTE_DSSI_AUDIO_RUN(recall_dssi_run->route_dssi_audio_run)->feed_midi = g_list_remove(AGS_ROUTE_DSSI_AUDIO_RUN(recall_dssi_run->route_dssi_audio_run)->feed_midi,
-											     recall_dssi_run->note);
+
+  if(recall_dssi_run->route_dssi_audio_run != NULL){
+    AGS_ROUTE_DSSI_AUDIO_RUN(recall_dssi_run->route_dssi_audio_run)->feed_midi = g_list_remove(AGS_ROUTE_DSSI_AUDIO_RUN(recall_dssi_run->route_dssi_audio_run)->feed_midi,
+											       recall_dssi_run->note);
+  }
   
   /* call parent */
   G_OBJECT_CLASS(ags_recall_dssi_run_parent_class)->finalize(gobject);
diff --git a/ags/audio/ags_recall_factory.c b/ags/audio/ags_recall_factory.c
index 2b77b12..3d5daf8 100644
--- a/ags/audio/ags_recall_factory.c
+++ b/ags/audio/ags_recall_factory.c
@@ -47,6 +47,8 @@
 #include <ags/audio/recall/ags_loop_channel_run.h>
 #include <ags/audio/recall/ags_play_channel.h>
 #include <ags/audio/recall/ags_play_channel_run.h>
+#include <ags/audio/recall/ags_prepare_channel.h>
+#include <ags/audio/recall/ags_prepare_channel_run.h>
 #include <ags/audio/recall/ags_copy_channel.h>
 #include <ags/audio/recall/ags_copy_channel_run.h>
 #include <ags/audio/recall/ags_feed_channel.h>
@@ -94,6 +96,12 @@ GList* ags_recall_factory_create_play_master(AgsAudio *audio,
 					     guint start_audio_channel, guint stop_audio_channel,
 					     guint start_pad, guint stop_pad,
 					     guint create_flags, guint recall_flags);
+GList* ags_recall_factory_create_prepare(AgsAudio *audio,
+					 AgsRecallContainer *play_container, AgsRecallContainer *recall_container,
+					 gchar *plugin_name,
+					 guint start_audio_channel, guint stop_audio_channel,
+					 guint start_pad, guint stop_pad,
+					 guint create_flags, guint recall_flags);
 GList* ags_recall_factory_create_copy(AgsAudio *audio,
 				      AgsRecallContainer *play_container, AgsRecallContainer *recall_container,
 				      gchar *plugin_name,
@@ -646,6 +654,227 @@ ags_recall_factory_create_play_master(AgsAudio *audio,
 }
 
 GList*
+ags_recall_factory_create_prepare(AgsAudio *audio,
+				  AgsRecallContainer *play_container, AgsRecallContainer *recall_container,
+				  gchar *plugin_name,
+				  guint start_audio_channel, guint stop_audio_channel,
+				  guint start_pad, guint stop_pad,
+				  guint create_flags, guint recall_flags)
+{
+  AgsPrepareChannel *prepare_channel;
+  AgsPrepareChannelRun *prepare_channel_run;
+  AgsChannel *start, *channel, *output;
+  AgsPort *port;
+
+  GList *list;
+  GList *recall;
+
+  guint i, j;
+
+  if(audio == NULL){
+    return(NULL);
+  }
+
+  if((AGS_RECALL_FACTORY_OUTPUT & (create_flags)) != 0){
+    start =
+      channel = ags_channel_nth(audio->output,
+				start_pad * audio->audio_channels);
+  }else{
+    start =
+      channel = ags_channel_nth(audio->input,
+				start_pad * audio->audio_channels);
+  }
+
+  recall = NULL;
+
+  /* play */
+  if((AGS_RECALL_FACTORY_PLAY & (create_flags)) != 0){
+    gboolean found_prepare;
+
+    channel = start;
+    
+    for(i = 0; i < stop_pad - start_pad; i++){
+      channel = ags_channel_nth(channel,
+				start_audio_channel);
+      
+      for(j = 0; j < stop_audio_channel - start_audio_channel; j++){
+	output = ags_channel_nth(audio->output,
+				 start_audio_channel + j);
+	
+	while(output != NULL){
+	  found_prepare = FALSE;
+	  list = channel->recall;
+
+	  while((list = ags_recall_template_find_type(list,
+						      AGS_TYPE_PREPARE_CHANNEL)) != NULL){
+	    if(AGS_RECALL_CHANNEL(list->data)->destination == output){
+	      found_prepare = TRUE;
+	      break;
+	    }
+	
+	    list = list->next;
+	  }
+      
+	  if(found_prepare){
+	    output = output->next_pad;
+	    continue;
+	  }
+	
+	  if(play_container == NULL){
+	    play_container = ags_recall_container_new();
+	    play_container->flags |= AGS_RECALL_CONTAINER_PLAY;
+	    ags_audio_add_recall_container(audio, (GObject *) play_container);
+	  }
+	
+	  ags_channel_add_recall_container(channel, (GObject *) play_container);
+
+	  /* AgsPrepareChannel */
+	  prepare_channel = (AgsPrepareChannel *) g_object_new(AGS_TYPE_PREPARE_CHANNEL,
+							       "soundcard\0", audio->soundcard,
+							       "source\0", channel,
+							       "destination\0", output,
+							       "recall_container\0", play_container,
+							       NULL);
+							      
+	  ags_recall_set_flags(AGS_RECALL(prepare_channel), (AGS_RECALL_TEMPLATE |
+							     (((AGS_RECALL_FACTORY_OUTPUT & create_flags) != 0) ? AGS_RECALL_OUTPUT_ORIENTATED: AGS_RECALL_INPUT_ORIENTATED) |
+							     AGS_RECALL_PLAYBACK |
+							     AGS_RECALL_SEQUENCER |
+							     AGS_RECALL_NOTATION));
+	  g_object_ref(prepare_channel);
+	  channel->play = g_list_append(channel->play, prepare_channel);
+	  recall = g_list_prepend(recall,
+				  prepare_channel);
+	  ags_connectable_connect(AGS_CONNECTABLE(prepare_channel));
+
+	  /* AgsPrepareChannelRun */
+	  prepare_channel_run = (AgsPrepareChannelRun *) g_object_new(AGS_TYPE_PREPARE_CHANNEL_RUN,
+								      "soundcard\0", audio->soundcard,
+								      "recall_channel\0", prepare_channel,
+								      "source\0", channel,
+								      "destination\0", output,
+								      "recall_container\0", play_container,
+								      NULL);
+	  ags_recall_set_flags(AGS_RECALL(prepare_channel_run), (AGS_RECALL_TEMPLATE |
+								 (((AGS_RECALL_FACTORY_OUTPUT & create_flags) != 0) ? AGS_RECALL_OUTPUT_ORIENTATED: AGS_RECALL_INPUT_ORIENTATED) |
+								 AGS_RECALL_PLAYBACK |
+								 AGS_RECALL_SEQUENCER |
+								 AGS_RECALL_NOTATION));
+	  g_object_ref(prepare_channel);
+	  channel->play = g_list_append(channel->play, prepare_channel_run);
+	  recall = g_list_prepend(recall,
+				  prepare_channel_run);
+	  ags_connectable_connect(AGS_CONNECTABLE(prepare_channel_run));
+
+	  /* iterate */
+	  output = output->next_pad;
+	}
+
+	channel = channel->next;
+      }
+
+      channel = ags_channel_nth(channel,
+				audio->audio_channels - stop_audio_channel);
+    }
+  }
+
+  /* recall */
+  if((AGS_RECALL_FACTORY_RECALL & (create_flags)) != 0){
+    gboolean found_prepare;
+    
+    channel = start;
+    
+    for(i = 0; i < stop_pad - start_pad; i++){
+      channel = ags_channel_nth(channel,
+				start_audio_channel);
+      
+      for(j = 0; j < stop_audio_channel - start_audio_channel; j++){
+	output = ags_channel_nth(audio->output,
+				 start_audio_channel + j);
+	
+	while(output != NULL){
+	  list = channel->recall;
+	  found_prepare = FALSE;
+	
+	  while((list = ags_recall_template_find_type(list,
+						      AGS_TYPE_PREPARE_CHANNEL)) != NULL){
+	    if(AGS_RECALL_CHANNEL(list->data)->destination == output){
+	      found_prepare = TRUE;
+	      break;
+	    }
+	
+	    list = list->next;
+	  }
+	
+	  if(found_prepare){
+	    output = output->next_pad;
+	    continue;
+	  }
+
+	  if(recall_container == NULL){
+	    recall_container = ags_recall_container_new();
+	    ags_audio_add_recall_container(audio, (GObject *) recall_container);
+	  }
+	
+	  ags_channel_add_recall_container(channel, (GObject *) recall_container);
+
+	  /* AgsPrepareChannel */
+	  prepare_channel = (AgsPrepareChannel *) g_object_new(AGS_TYPE_PREPARE_CHANNEL,
+							       "soundcard\0", audio->soundcard,
+							       "source\0", channel,
+							       "destination\0", output,
+							       "recall_container\0", recall_container,
+							       NULL);
+							      
+	  ags_recall_set_flags(AGS_RECALL(prepare_channel), (AGS_RECALL_TEMPLATE |
+							     (((AGS_RECALL_FACTORY_OUTPUT & create_flags) != 0) ? AGS_RECALL_OUTPUT_ORIENTATED: AGS_RECALL_INPUT_ORIENTATED) |
+							     AGS_RECALL_PLAYBACK |
+							     AGS_RECALL_SEQUENCER |
+							     AGS_RECALL_NOTATION));
+	  g_object_ref(prepare_channel);
+	  channel->recall = g_list_append(channel->recall, prepare_channel);
+	  recall = g_list_prepend(recall,
+				  prepare_channel);
+	  ags_connectable_connect(AGS_CONNECTABLE(prepare_channel));
+
+	  /* AgsPrepareChannelRun */
+	  prepare_channel_run = (AgsPrepareChannelRun *) g_object_new(AGS_TYPE_PREPARE_CHANNEL_RUN,
+								      "soundcard\0", audio->soundcard,
+								      "recall_channel\0", prepare_channel,
+								      "source\0", channel,
+								      "destination\0", output,
+								      "recall_container\0", recall_container,
+								      NULL);
+	  ags_recall_set_flags(AGS_RECALL(prepare_channel_run), (AGS_RECALL_TEMPLATE |
+								 (((AGS_RECALL_FACTORY_OUTPUT & create_flags) != 0) ? AGS_RECALL_OUTPUT_ORIENTATED: AGS_RECALL_INPUT_ORIENTATED) |
+								 AGS_RECALL_PLAYBACK |
+								 AGS_RECALL_SEQUENCER |
+								 AGS_RECALL_NOTATION));
+	  g_object_ref(prepare_channel);
+	  channel->recall = g_list_append(channel->recall, prepare_channel_run);
+	  recall = g_list_prepend(recall,
+				  prepare_channel_run);
+	  ags_connectable_connect(AGS_CONNECTABLE(prepare_channel_run));
+
+	  /* iterate */
+	  output = output->next_pad;
+	}
+	
+	channel = channel->next;
+      }
+
+      channel = ags_channel_nth(channel,
+				audio->audio_channels - stop_audio_channel);
+    }
+  }
+
+  /* return instantiated recall */
+  recall = g_list_reverse(recall);
+
+  return(recall);
+}
+
+GList*
 ags_recall_factory_create_copy(AgsAudio *audio,
 			       AgsRecallContainer *play_container, AgsRecallContainer *recall_container,
 			       gchar *plugin_name,
@@ -655,7 +884,7 @@ ags_recall_factory_create_copy(AgsAudio *audio,
 {
   AgsCopyChannel *copy_channel;
   AgsCopyChannelRun *copy_channel_run;
-  AgsChannel *start, *channel;
+  AgsChannel *start, *channel, *output;
   AgsPort *port;
 
   GList *list;
@@ -681,54 +910,87 @@ ags_recall_factory_create_copy(AgsAudio *audio,
 
   /* play */
   if((AGS_RECALL_FACTORY_PLAY & (create_flags)) != 0){
-    if(play_container == NULL){
-      play_container = ags_recall_container_new();
-    }
-
-    play_container->flags |= AGS_RECALL_CONTAINER_PLAY;
-    ags_audio_add_recall_container(audio, (GObject *) play_container);
+    gboolean found_copy;
 
+    channel = start;
+    
     for(i = 0; i < stop_pad - start_pad; i++){
       channel = ags_channel_nth(channel,
 				start_audio_channel);
       
       for(j = 0; j < stop_audio_channel - start_audio_channel; j++){
-	ags_channel_add_recall_container(channel, (GObject *) play_container);
+	output = ags_channel_nth(audio->output,
+				 start_audio_channel + j);
+	
+	while(output != NULL){
+	  found_copy = FALSE;
+	  list = channel->recall;
 
-	/* AgsCopyChannel */
-	copy_channel = (AgsCopyChannel *) g_object_new(AGS_TYPE_COPY_CHANNEL,
-						       "soundcard\0", audio->soundcard,
-						       "source\0", channel,
-						       "recall_container\0", play_container,
-						       NULL);
-	ags_recall_set_flags(AGS_RECALL(copy_channel), (AGS_RECALL_TEMPLATE |
-							(((AGS_RECALL_FACTORY_OUTPUT & create_flags) != 0) ? AGS_RECALL_OUTPUT_ORIENTATED: AGS_RECALL_INPUT_ORIENTATED) |
-							AGS_RECALL_PLAYBACK |
-							AGS_RECALL_SEQUENCER |
-							AGS_RECALL_NOTATION));
-	ags_channel_add_recall(channel, (GObject *) copy_channel, TRUE);
-	recall = g_list_prepend(recall,
-				copy_channel);
-	ags_connectable_connect(AGS_CONNECTABLE(copy_channel));
+	  while((list = ags_recall_template_find_type(list,
+						      AGS_TYPE_COPY_CHANNEL)) != NULL){
+	    if(AGS_RECALL_CHANNEL(list->data)->destination == output){
+	      found_copy = TRUE;
+	      break;
+	    }
+	
+	    list = list->next;
+	  }
+      
+	  if(found_copy){
+	    output = output->next_pad;
+	    continue;
+	  }
+	
+	  if(play_container == NULL){
+	    play_container = ags_recall_container_new();
+	    play_container->flags |= AGS_RECALL_CONTAINER_PLAY;
+	    ags_audio_add_recall_container(audio, (GObject *) play_container);
+	  }
+	
+	  ags_channel_add_recall_container(channel, (GObject *) play_container);
 
-	/* AgsCopyChannelRun */
-	copy_channel_run = (AgsCopyChannelRun *) g_object_new(AGS_TYPE_COPY_CHANNEL_RUN,
-							      "soundcard\0", audio->soundcard,
-							      "source\0", channel,
-							      "recall_channel\0", copy_channel,
-							      "recall_container\0", play_container,
-							      NULL);
-	ags_recall_set_flags(AGS_RECALL(copy_channel_run), (AGS_RECALL_TEMPLATE |
-							    (((AGS_RECALL_FACTORY_OUTPUT & create_flags) != 0) ? AGS_RECALL_OUTPUT_ORIENTATED: AGS_RECALL_INPUT_ORIENTATED) |
-							    AGS_RECALL_PLAYBACK |
-							    AGS_RECALL_SEQUENCER |
-							    AGS_RECALL_NOTATION));
-	ags_channel_add_recall(channel, (GObject *) copy_channel_run, TRUE);
-	recall = g_list_prepend(recall,
-				copy_channel_run);
-	ags_connectable_connect(AGS_CONNECTABLE(copy_channel_run));
+	  /* AgsCopyChannel */
+	  copy_channel = (AgsCopyChannel *) g_object_new(AGS_TYPE_COPY_CHANNEL,
+							 "soundcard\0", audio->soundcard,
+							 "source\0", channel,
+							 "destination\0", output,
+							 "recall_container\0", play_container,
+							 NULL);
+							      
+	  ags_recall_set_flags(AGS_RECALL(copy_channel), (AGS_RECALL_TEMPLATE |
+							  (((AGS_RECALL_FACTORY_OUTPUT & create_flags) != 0) ? AGS_RECALL_OUTPUT_ORIENTATED: AGS_RECALL_INPUT_ORIENTATED) |
+							  AGS_RECALL_PLAYBACK |
+							  AGS_RECALL_SEQUENCER |
+							  AGS_RECALL_NOTATION));
+	  g_object_ref(copy_channel);
+	  channel->play = g_list_append(channel->play, copy_channel);
+	  recall = g_list_prepend(recall,
+				  copy_channel);
+	  ags_connectable_connect(AGS_CONNECTABLE(copy_channel));
+
+	  /* AgsCopyChannelRun */
+	  copy_channel_run = (AgsCopyChannelRun *) g_object_new(AGS_TYPE_COPY_CHANNEL_RUN,
+								"soundcard\0", audio->soundcard,
+								"recall_channel\0", copy_channel,
+								"source\0", channel,
+								"destination\0", output,
+								"recall_container\0", play_container,
+								NULL);
+	  ags_recall_set_flags(AGS_RECALL(copy_channel_run), (AGS_RECALL_TEMPLATE |
+							      (((AGS_RECALL_FACTORY_OUTPUT & create_flags) != 0) ? AGS_RECALL_OUTPUT_ORIENTATED: AGS_RECALL_INPUT_ORIENTATED) |
+							      AGS_RECALL_PLAYBACK |
+							      AGS_RECALL_SEQUENCER |
+							      AGS_RECALL_NOTATION));
+	  g_object_ref(copy_channel);
+	  channel->play = g_list_append(channel->play, copy_channel_run);
+	  recall = g_list_prepend(recall,
+				  copy_channel_run);
+	  ags_connectable_connect(AGS_CONNECTABLE(copy_channel_run));
+
+	  /* iterate */
+	  output = output->next_pad;
+	}
 
-	/* iterate */
 	channel = channel->next;
       }
 
@@ -739,55 +1001,86 @@ ags_recall_factory_create_copy(AgsAudio *audio,
 
   /* recall */
   if((AGS_RECALL_FACTORY_RECALL & (create_flags)) != 0){
+    gboolean found_copy;
+    
     channel = start;
-
-    if(recall_container == NULL){
-      recall_container = ags_recall_container_new();
-    }
-
-    ags_audio_add_recall_container(audio, (GObject *) recall_container);
-
+    
     for(i = 0; i < stop_pad - start_pad; i++){
       channel = ags_channel_nth(channel,
 				start_audio_channel);
       
       for(j = 0; j < stop_audio_channel - start_audio_channel; j++){
-	ags_channel_add_recall_container(channel, (GObject *) recall_container);
+	output = ags_channel_nth(audio->output,
+				 start_audio_channel + j);
+	
+	while(output != NULL){
+	  list = channel->recall;
+	  found_copy = FALSE;
+	
+	  while((list = ags_recall_template_find_type(list,
+						      AGS_TYPE_COPY_CHANNEL)) != NULL){
+	    if(AGS_RECALL_CHANNEL(list->data)->destination == output){
+	      found_copy = TRUE;
+	      break;
+	    }
+	
+	    list = list->next;
+	  }
+	
+	  if(found_copy){
+	    output = output->next_pad;
+	    continue;
+	  }
 
-	/* AgsCopyChannel */
-	copy_channel = (AgsCopyChannel *) g_object_new(AGS_TYPE_COPY_CHANNEL,
-						       "soundcard\0", AGS_SOUNDCARD(audio->soundcard),
-						       "source\0", channel,
-						       "recall_container\0", recall_container,
-						       NULL);
-	ags_recall_set_flags(AGS_RECALL(copy_channel), (AGS_RECALL_TEMPLATE |
-							(((AGS_RECALL_FACTORY_OUTPUT & create_flags) != 0) ? AGS_RECALL_OUTPUT_ORIENTATED: AGS_RECALL_INPUT_ORIENTATED) |
-							AGS_RECALL_PLAYBACK |
-							AGS_RECALL_SEQUENCER |
-							AGS_RECALL_NOTATION));
-	ags_channel_add_recall(channel, (GObject *) copy_channel, FALSE);
-	recall = g_list_prepend(recall,
-				copy_channel);
-	ags_connectable_connect(AGS_CONNECTABLE(copy_channel));
+	  if(recall_container == NULL){
+	    recall_container = ags_recall_container_new();
+	    ags_audio_add_recall_container(audio, (GObject *) recall_container);
+	  }
+	
+	  ags_channel_add_recall_container(channel, (GObject *) recall_container);
 
-	/* AgsCopyChannelRun */
-	copy_channel_run = (AgsCopyChannelRun *) g_object_new(AGS_TYPE_COPY_CHANNEL_RUN,
-							      "soundcard\0", audio->soundcard,
-							      "source\0", channel,
-							      "recall_channel\0", copy_channel,
-							      "recall_container\0", recall_container,
-							      NULL);
-	ags_recall_set_flags(AGS_RECALL(copy_channel_run), (AGS_RECALL_TEMPLATE |
-							    (((AGS_RECALL_FACTORY_OUTPUT & create_flags) != 0) ? AGS_RECALL_OUTPUT_ORIENTATED: AGS_RECALL_INPUT_ORIENTATED) |
-							    AGS_RECALL_PLAYBACK |
-							    AGS_RECALL_SEQUENCER |
-							    AGS_RECALL_NOTATION));
-	ags_channel_add_recall(channel, (GObject *) copy_channel_run, FALSE);
-	recall = g_list_prepend(recall,
-				copy_channel_run);
-	ags_connectable_connect(AGS_CONNECTABLE(copy_channel_run));
+	  /* AgsCopyChannel */
+	  copy_channel = (AgsCopyChannel *) g_object_new(AGS_TYPE_COPY_CHANNEL,
+							 "soundcard\0", audio->soundcard,
+							 "source\0", channel,
+							 "destination\0", output,
+							 "recall_container\0", recall_container,
+							 NULL);
+							      
+	  ags_recall_set_flags(AGS_RECALL(copy_channel), (AGS_RECALL_TEMPLATE |
+							  (((AGS_RECALL_FACTORY_OUTPUT & create_flags) != 0) ? AGS_RECALL_OUTPUT_ORIENTATED: AGS_RECALL_INPUT_ORIENTATED) |
+							  AGS_RECALL_PLAYBACK |
+							  AGS_RECALL_SEQUENCER |
+							  AGS_RECALL_NOTATION));
+	  g_object_ref(copy_channel);
+	  channel->recall = g_list_append(channel->recall, copy_channel);
+	  recall = g_list_prepend(recall,
+				  copy_channel);
+	  ags_connectable_connect(AGS_CONNECTABLE(copy_channel));
 
-	/* iterate */
+	  /* AgsCopyChannelRun */
+	  copy_channel_run = (AgsCopyChannelRun *) g_object_new(AGS_TYPE_COPY_CHANNEL_RUN,
+								"soundcard\0", audio->soundcard,
+								"recall_channel\0", copy_channel,
+								"source\0", channel,
+								"destination\0", output,
+								"recall_container\0", recall_container,
+								NULL);
+	  ags_recall_set_flags(AGS_RECALL(copy_channel_run), (AGS_RECALL_TEMPLATE |
+							      (((AGS_RECALL_FACTORY_OUTPUT & create_flags) != 0) ? AGS_RECALL_OUTPUT_ORIENTATED: AGS_RECALL_INPUT_ORIENTATED) |
+							      AGS_RECALL_PLAYBACK |
+							      AGS_RECALL_SEQUENCER |
+							      AGS_RECALL_NOTATION));
+	  g_object_ref(copy_channel);
+	  channel->recall = g_list_append(channel->recall, copy_channel_run);
+	  recall = g_list_prepend(recall,
+				  copy_channel_run);
+	  ags_connectable_connect(AGS_CONNECTABLE(copy_channel_run));
+
+	  /* iterate */
+	  output = output->next_pad;
+	}
+	
 	channel = channel->next;
       }
 
@@ -3646,6 +3939,15 @@ ags_recall_factory_create(AgsAudio *audio,
 						   start_pad, stop_pad,
 						   create_flags, recall_flags);
   }else if(!strncmp(plugin_name,
+		    "ags-prepare\0",
+		    12)){
+    recall = ags_recall_factory_create_prepare(audio,
+					       play_container, recall_container,
+					       plugin_name,
+					       start_audio_channel, stop_audio_channel,
+					       start_pad, stop_pad,
+					       create_flags, recall_flags);
+  }else if(!strncmp(plugin_name,
 		    "ags-copy\0",
 		    9)){
     recall = ags_recall_factory_create_copy(audio,
diff --git a/ags/audio/ags_recall_id.c b/ags/audio/ags_recall_id.c
index 2475ea3..4151a31 100644
--- a/ags/audio/ags_recall_id.c
+++ b/ags/audio/ags_recall_id.c
@@ -37,6 +37,7 @@ void ags_recall_id_get_property(GObject *gobject,
 				GParamSpec *param_spec);
 void ags_recall_id_connect(AgsConnectable *connectable);
 void ags_recall_id_disconnect(AgsConnectable *connectable);
+void ags_recall_id_dispose(GObject *gobject);
 void ags_recall_id_finalize(GObject *gobject);
 
 /**
@@ -108,6 +109,7 @@ ags_recall_id_class_init(AgsRecallIDClass *recall_id)
   gobject->set_property = ags_recall_id_set_property;
   gobject->get_property = ags_recall_id_get_property;
 
+  gobject->dispose = ags_recall_id_dispose;
   gobject->finalize = ags_recall_id_finalize;
 
   /* properties */
@@ -177,8 +179,9 @@ ags_recall_id_set_property(GObject *gobject,
 
       recycling = g_value_get_object(value);
 
-      if(recall_id->recycling == (GObject *) recycling)
+      if(recall_id->recycling == (GObject *) recycling){
 	return;
+      }
 
       if(recall_id->recycling != NULL){
 	g_object_unref(recycling);
@@ -230,10 +233,14 @@ ags_recall_id_get_property(GObject *gobject,
 
   switch(prop_id){
   case PROP_RECYCLING:
-    g_value_set_object(value, recall_id->recycling);
+    {
+      g_value_set_object(value, recall_id->recycling);
+    }
     break;
   case PROP_RECYCLING_CONTEXT:
-    g_value_set_object(value, recall_id->recycling_context);
+    {
+      g_value_set_object(value, recall_id->recycling_context);
+    }
     break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
@@ -244,18 +251,71 @@ ags_recall_id_get_property(GObject *gobject,
 void
 ags_recall_id_connect(AgsConnectable *connectable)
 {
+  AgsRecallID *recall_id;
+
+  recall_id = AGS_RECALL_ID(connectable);
+
+  if((AGS_RECALL_ID_CONNECTED & (recall_id->flags)) != 0){
+    return;
+  }
+
+  recall_id->flags |= AGS_RECALL_ID_CONNECTED;
 }
 
 void
 ags_recall_id_disconnect(AgsConnectable *connectable)
 {
+  AgsRecallID *recall_id;
+
+  recall_id = AGS_RECALL_ID(connectable);
+
+
+  if((AGS_RECALL_ID_CONNECTED & (recall_id->flags)) == 0){
+    return;
+  }
+
+  recall_id->flags &= (~AGS_RECALL_ID_CONNECTED);
+}
+
+void
+ags_recall_id_dispose(GObject *gobject)
+{
+  AgsRecallID *recall_id;
+
+  recall_id = AGS_RECALL_ID(gobject);
+
+  if(recall_id->recycling != NULL){
+    g_object_unref(recall_id->recycling);
+
+    recall_id->recycling = NULL;
+  }
+  
+  if(recall_id->recycling_context != NULL){
+    g_object_unref(recall_id->recycling_context);
+
+    recall_id->recycling_context = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_recall_id_parent_class)->dispose(gobject);
 }
 
 void
 ags_recall_id_finalize(GObject *gobject)
 {
-  g_warning("ags_recall_id_finalize\0");
+  AgsRecallID *recall_id;
+
+  recall_id = AGS_RECALL_ID(gobject);
+
+  if(recall_id->recycling != NULL){
+    g_object_unref(recall_id->recycling);
+  }
+  
+  if(recall_id->recycling_context != NULL){
+    g_object_unref(recall_id->recycling_context);
+  }
 
+  /* call parent */
   G_OBJECT_CLASS(ags_recall_id_parent_class)->finalize(gobject);
 }
 
@@ -276,18 +336,25 @@ ags_recall_id_get_run_stage(AgsRecallID *id, gint stage)
 {
   switch(stage){
   case 0:
-    if((AGS_RECALL_ID_PRE & (id->flags)) == 0)
-      return(TRUE);
-
+    {
+      if((AGS_RECALL_ID_PRE & (id->flags)) == 0){
+	return(TRUE);
+      }
+    }
     break;
   case 1:
-    if((AGS_RECALL_ID_INTER & (id->flags)) == 0)
-      return(TRUE);
-
+    {
+      if((AGS_RECALL_ID_INTER & (id->flags)) == 0){
+	return(TRUE);
+      }
+    }
     break;
   case 2:
-    if((AGS_RECALL_ID_POST & (id->flags)) == 0)
-      return(TRUE);
+    {
+      if((AGS_RECALL_ID_POST & (id->flags)) == 0){
+	return(TRUE);
+      }
+    }
     break;
   }
 
diff --git a/ags/audio/ags_recall_id.h b/ags/audio/ags_recall_id.h
index 537964b..5ed0e81 100644
--- a/ags/audio/ags_recall_id.h
+++ b/ags/audio/ags_recall_id.h
@@ -37,18 +37,19 @@ typedef struct _AgsRecallID AgsRecallID;
 typedef struct _AgsRecallIDClass AgsRecallIDClass;
 
 typedef enum{
-  AGS_RECALL_ID_PLAYBACK          = 1,
-  AGS_RECALL_ID_SEQUENCER         = 1 << 1,
-  AGS_RECALL_ID_NOTATION          = 1 << 2,
-  AGS_RECALL_ID_DUPLICATE         = 1 << 3,
-  AGS_RECALL_ID_RESOLVE           = 1 << 4,
-  AGS_RECALL_ID_INIT_PRE          = 1 << 5,
-  AGS_RECALL_ID_INIT_INTER        = 1 << 6,
-  AGS_RECALL_ID_INIT_POST         = 1 << 7,
-  AGS_RECALL_ID_PRE               = 1 << 8,
-  AGS_RECALL_ID_INTER             = 1 << 9,
-  AGS_RECALL_ID_POST              = 1 << 10,
-  AGS_RECALL_ID_CANCEL            = 1 << 11,
+  AGS_RECALL_ID_CONNECTED         = 1,
+  AGS_RECALL_ID_PLAYBACK          = 1 <<  1,
+  AGS_RECALL_ID_SEQUENCER         = 1 <<  2,
+  AGS_RECALL_ID_NOTATION          = 1 <<  3,
+  AGS_RECALL_ID_DUPLICATE         = 1 <<  4,
+  AGS_RECALL_ID_RESOLVE           = 1 <<  5,
+  AGS_RECALL_ID_INIT_PRE          = 1 <<  6,
+  AGS_RECALL_ID_INIT_INTER        = 1 <<  7,
+  AGS_RECALL_ID_INIT_POST         = 1 <<  8,
+  AGS_RECALL_ID_PRE               = 1 <<  9,
+  AGS_RECALL_ID_INTER             = 1 << 10,
+  AGS_RECALL_ID_POST              = 1 << 11,
+  AGS_RECALL_ID_CANCEL            = 1 << 12,
 }AgsRecallIDFlags;
 
 struct _AgsRecallID
diff --git a/ags/audio/ags_recall_ladspa.c b/ags/audio/ags_recall_ladspa.c
index d439fec..458be10 100644
--- a/ags/audio/ags_recall_ladspa.c
+++ b/ags/audio/ags_recall_ladspa.c
@@ -639,7 +639,19 @@ ags_recall_ladspa_load_ports(AgsRecallLadspa *recall_ladspa)
 			       "port-value-is-pointer\0", FALSE,
 			       "port-value-type\0", G_TYPE_FLOAT,
 			       NULL);
+	g_object_ref(current);
 	current->flags |= AGS_PORT_USE_LADSPA_FLOAT;
+
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  AGS_RECALL(recall_ladspa)->flags |= AGS_RECALL_HAS_OUTPUT_PORT;
+
+	  current->flags |= AGS_PORT_IS_OUTPUT;
+	}else{
+	  if((AGS_PORT_DESCRIPTOR_INTEGER & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) == 0 &&
+	     (AGS_PORT_DESCRIPTOR_TOGGLED & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) == 0){
+	    current->flags |= AGS_PORT_INFINITE_RANGE;
+	  }
+	}
 	
 	current->port_descriptor = port_descriptor->data;	
 	ags_recall_ladspa_load_conversion(recall_ladspa,
diff --git a/ags/audio/ags_recall_lv2.c b/ags/audio/ags_recall_lv2.c
index 25b62c6..104d410 100644
--- a/ags/audio/ags_recall_lv2.c
+++ b/ags/audio/ags_recall_lv2.c
@@ -60,6 +60,7 @@ void ags_recall_lv2_get_property(GObject *gobject,
 void ags_recall_lv2_connect(AgsConnectable *connectable);
 void ags_recall_lv2_disconnect(AgsConnectable *connectable);
 void ags_recall_lv2_set_ports(AgsPlugin *plugin, GList *port);
+void ags_recall_lv2_dispose(GObject *gobject);
 void ags_recall_lv2_finalize(GObject *gobject);
 
 void ags_recall_lv2_read(AgsFile *file, xmlNode *node, AgsPlugin *plugin);
@@ -149,6 +150,7 @@ ags_recall_lv2_class_init(AgsRecallLv2Class *recall_lv2)
   gobject->set_property = ags_recall_lv2_set_property;
   gobject->get_property = ags_recall_lv2_get_property;
 
+  gobject->dispose = ags_recall_lv2_dispose;
   gobject->finalize = ags_recall_lv2_finalize;
 
   /* properties */
@@ -440,10 +442,11 @@ ags_recall_lv2_connect(AgsConnectable *connectable)
     return;
   }
 
-  //  g_message("load automation %x\0", recall);
+  /* load automation */
   ags_recall_load_automation(recall,
 			     g_list_copy(recall->port));
 
+  /* call parent */
   ags_recall_lv2_parent_connectable_interface->connect(connectable);
 }
 
@@ -550,16 +553,36 @@ ags_recall_lv2_set_ports(AgsPlugin *plugin, GList *port)
 }
 
 void
+ags_recall_lv2_dispose(GObject *gobject)
+{
+  AgsRecallLv2 *recall_lv2;
+  
+  recall_lv2 = AGS_RECALL_LV2(gobject);
+
+  /* turtle */
+  if(recall_lv2->turtle != NULL){
+    g_object_unref(recall_lv2->turtle);
+
+    recall_lv2->turtle = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_recall_lv2_parent_class)->dispose(gobject);
+}
+
+void
 ags_recall_lv2_finalize(GObject *gobject)
 {
   AgsRecallLv2 *recall_lv2;
   
   recall_lv2 = AGS_RECALL_LV2(gobject);
 
+  /* turtle */
   if(recall_lv2->turtle != NULL){
     g_object_unref(recall_lv2->turtle);
   }
 
+  /* filename, effect and uri */
   g_free(recall_lv2->filename);
   g_free(recall_lv2->effect);
   g_free(recall_lv2->uri);
@@ -686,6 +709,10 @@ ags_recall_lv2_load(AgsRecallLv2 *recall_lv2)
     if(dlerror() == NULL && lv2_descriptor){
       recall_lv2->plugin_descriptor = 
 	plugin_descriptor = lv2_descriptor(recall_lv2->index);
+
+      if((AGS_LV2_PLUGIN_NEEDS_WORKER & (lv2_plugin->flags)) != 0){
+	recall_lv2->flags |= AGS_RECALL_LV2_HAS_WORKER;
+      }
     }
   }
 }
@@ -767,7 +794,20 @@ ags_recall_lv2_load_ports(AgsRecallLv2 *recall_lv2)
 			       "port-value-is-pointer\0", FALSE,
 			       "port-value-type\0", G_TYPE_FLOAT,
 			       NULL);
-
+	g_object_ref(current);
+	
+	if((AGS_PORT_DESCRIPTOR_OUTPUT & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) != 0){
+	  AGS_RECALL(recall_lv2)->flags |= AGS_RECALL_HAS_OUTPUT_PORT;
+	  
+	  current->flags |= AGS_PORT_IS_OUTPUT;
+	}else{
+	  if((AGS_PORT_DESCRIPTOR_INTEGER & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) == 0 &&
+	     (AGS_PORT_DESCRIPTOR_TOGGLED & (AGS_PORT_DESCRIPTOR(port_descriptor->data)->flags)) == 0 &&
+	     AGS_PORT_DESCRIPTOR(port_descriptor->data)->scale_steps == -1){
+	    current->flags |= AGS_PORT_INFINITE_RANGE;
+	  }
+	}
+	
 	current->port_descriptor = port_descriptor->data;
 	ags_recall_lv2_load_conversion(recall_lv2,
 				       (GObject *) current,
diff --git a/ags/audio/ags_recall_lv2.h b/ags/audio/ags_recall_lv2.h
index acf55a6..f216f10 100644
--- a/ags/audio/ags_recall_lv2.h
+++ b/ags/audio/ags_recall_lv2.h
@@ -44,6 +44,7 @@ typedef struct _AgsRecallLv2Class AgsRecallLv2Class;
 typedef enum{
   AGS_RECALL_LV2_HAS_EVENT_PORT   = 1,
   AGS_RECALL_LV2_HAS_ATOM_PORT    = 1 <<  1,
+  AGS_RECALL_LV2_HAS_WORKER       = 1 <<  2,
 }AgsRecallLv2FLags;
 
 struct _AgsRecallLv2
diff --git a/ags/audio/ags_recall_lv2_run.c b/ags/audio/ags_recall_lv2_run.c
index f0c1c9a..d668084 100644
--- a/ags/audio/ags_recall_lv2_run.c
+++ b/ags/audio/ags_recall_lv2_run.c
@@ -203,7 +203,7 @@ ags_recall_lv2_run_finalize(GObject *gobject)
   uint32_t i;
 
   recall_lv2_run = AGS_RECALL_LV2_RUN(gobject);
-
+  
   free(recall_lv2_run->lv2_handle);
 
   if(recall_lv2_run->feature != NULL){
@@ -250,10 +250,7 @@ ags_recall_lv2_run_finalize(GObject *gobject)
     if(AGS_LV2_WORKER(recall_lv2_run->worker_handle)->returnable_thread != NULL){  
       g_atomic_int_and(&(AGS_RETURNABLE_THREAD(AGS_LV2_WORKER(recall_lv2_run->worker_handle)->returnable_thread)->flags),
 		       (~AGS_RETURNABLE_THREAD_IN_USE));
-      g_atomic_int_and(&(AGS_THREAD(AGS_LV2_WORKER(recall_lv2_run->worker_handle)->returnable_thread)->flags),
-		       (~AGS_THREAD_RUNNING));
-
-      g_object_unref(AGS_LV2_WORKER(recall_lv2_run->worker_handle)->returnable_thread);
+      ags_thread_stop(AGS_LV2_WORKER(recall_lv2_run->worker_handle)->returnable_thread);
     }
     
     g_object_unref(recall_lv2_run->worker_handle);
@@ -269,8 +266,13 @@ ags_recall_lv2_run_run_init_pre(AgsRecall *recall)
   AgsRecallLv2 *recall_lv2;
   AgsRecallLv2Run *recall_lv2_run;
   AgsAudioSignal *audio_signal;
+  
   AgsConfig *config;
+
   gchar *path;
+
+  guint total_feature;
+  guint nth;
   double samplerate;
   uint32_t buffer_size;
   uint32_t i;
@@ -299,30 +301,41 @@ ags_recall_lv2_run_run_init_pre(AgsRecall *recall)
 		   rindex(recall_lv2->filename, '/') - recall_lv2->filename + 1);
 
   /**/
+  total_feature = 7;
+  nth = 0;
+    
   recall_lv2_run->feature = 
-    feature = (LV2_Feature **) malloc(7 * sizeof(LV2_Feature *));
-
-  /* URI map feature */
+    feature = (LV2_Feature **) malloc(total_feature * sizeof(LV2_Feature *));
+  
+  /* URI map feature */  
   uri_map_feature = (LV2_URI_Map_Feature *) malloc(sizeof(LV2_URI_Map_Feature));
   uri_map_feature->callback_data = NULL;
   uri_map_feature->uri_to_id = ags_lv2_uri_map_manager_uri_to_id;
   
-  feature[0] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
-  feature[0]->URI = LV2_URI_MAP_URI;
-  feature[0]->data = uri_map_feature;
+  feature[nth] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
+  feature[nth]->URI = LV2_URI_MAP_URI;
+  feature[nth]->data = uri_map_feature;
 
+  nth++;
+  
   /* worker feature */
-  recall_lv2_run->worker_handle = 
-    worker_handle = ags_lv2_worker_manager_pull_worker(ags_lv2_worker_manager_get_instance());
+  if((AGS_RECALL_LV2_HAS_WORKER & (recall_lv2->flags)) != 0){
+    recall_lv2_run->worker_handle = 
+      worker_handle = ags_lv2_worker_manager_pull_worker(ags_lv2_worker_manager_get_instance());
   
-  worker_schedule = (LV2_Worker_Schedule *) malloc(sizeof(LV2_Worker_Schedule));
-  worker_schedule->handle = worker_handle;
-  worker_schedule->schedule_work = ags_lv2_worker_schedule_work;
+    worker_schedule = (LV2_Worker_Schedule *) malloc(sizeof(LV2_Worker_Schedule));
+    worker_schedule->handle = worker_handle;
+    worker_schedule->schedule_work = ags_lv2_worker_schedule_work;
   
-  feature[1] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
-  feature[1]->URI = LV2_WORKER__schedule;
-  feature[1]->data = worker_schedule;
+    feature[nth] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
+    feature[nth]->URI = LV2_WORKER__schedule;
+    feature[nth]->data = worker_schedule;
 
+    nth++;
+  }else{
+    worker_handle = NULL;
+  }
+  
   /* log feature */
   log_feature = (LV2_Log_Log *) malloc(sizeof(LV2_Log_Log));
   
@@ -330,10 +343,12 @@ ags_recall_lv2_run_run_init_pre(AgsRecall *recall)
   log_feature->printf = ags_lv2_log_manager_printf;
   log_feature->vprintf = ags_lv2_log_manager_vprintf;
 
-  feature[2] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
-  feature[2]->URI = LV2_LOG__log;
-  feature[2]->data = log_feature;
+  feature[nth] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
+  feature[nth]->URI = LV2_LOG__log;
+  feature[nth]->data = log_feature;
 
+  nth++;
+  
   /* event feature */
   event_feature = (LV2_Event_Feature *) malloc(sizeof(LV2_Event_Feature));
   
@@ -341,29 +356,37 @@ ags_recall_lv2_run_run_init_pre(AgsRecall *recall)
   event_feature->lv2_event_ref = ags_lv2_event_manager_lv2_event_ref;
   event_feature->lv2_event_unref = ags_lv2_event_manager_lv2_event_unref;
   
-  feature[3] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
-  feature[3]->URI = LV2_EVENT_URI;
-  feature[3]->data = event_feature;
-  
+  feature[nth] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
+  feature[nth]->URI = LV2_EVENT_URI;
+  feature[nth]->data = event_feature;
+
+  nth++;
+    
   /* URID map feature */
   urid_map = (LV2_URID_Map *) malloc(sizeof(LV2_URID_Map));
   urid_map->handle = NULL;
   urid_map->map = ags_lv2_urid_manager_map;
   
-  feature[4] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
-  feature[4]->URI = LV2_URID_MAP_URI;
-  feature[4]->data = urid_map;
+  feature[nth] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
+  feature[nth]->URI = LV2_URID_MAP_URI;
+  feature[nth]->data = urid_map;
 
+  nth++;
+  
   /* URID unmap feature */
   urid_unmap = (LV2_URID_Unmap *) malloc(sizeof(LV2_URID_Unmap));
   urid_unmap->handle = NULL;
   urid_unmap->unmap = ags_lv2_urid_manager_unmap;
   
-  feature[5] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
-  feature[5]->URI = LV2_URID_UNMAP_URI;
-  feature[5]->data = urid_unmap;
+  feature[nth] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
+  feature[nth]->URI = LV2_URID_UNMAP_URI;
+  feature[nth]->data = urid_unmap;
 
-  feature[6] = NULL;
+  nth++;
+
+  for(; nth < total_feature; nth++){
+    feature[nth] = NULL;
+  }
 
   /* set up buffer */
   audio_signal = AGS_RECALL_AUDIO_SIGNAL(recall_lv2_run)->source;
@@ -387,8 +410,10 @@ ags_recall_lv2_run_run_init_pre(AgsRecall *recall)
 											  samplerate,
 											  path,
 											  feature);
-  AGS_LV2_WORKER(worker_handle)->handle = recall_lv2_run->lv2_handle[0];
-
+  if(worker_handle != NULL){
+    AGS_LV2_WORKER(worker_handle)->handle = recall_lv2_run->lv2_handle[0];
+  }
+  
   free(path);
   
 #ifdef AGS_DEBUG
@@ -482,8 +507,8 @@ ags_recall_lv2_run_run_pre(AgsRecall *recall)
 
   if(audio_signal->stream_current == NULL ||
      (count_beats_audio_run == NULL ||
-      ((AGS_NOTE(recall_lv2_run->note)->x[1] <= count_beats_audio_run->notation_counter  &&
-      (AGS_NOTE_FEED & (AGS_NOTE(recall_lv2_run->note)->flags)) == 0) ||
+      ((AGS_NOTE(recall_lv2_run->note)->x[1] <= count_beats_audio_run->notation_counter &&
+	(AGS_NOTE_FEED & (AGS_NOTE(recall_lv2_run->note)->flags)) == 0) ||
        AGS_NOTE(recall_lv2_run->note)->x[0] > count_beats_audio_run->notation_counter))){
     //    g_message("done\0");
     /* deactivate */
diff --git a/ags/audio/ags_recall_recycling.c b/ags/audio/ags_recall_recycling.c
index 250b0c2..06ce240 100644
--- a/ags/audio/ags_recall_recycling.c
+++ b/ags/audio/ags_recall_recycling.c
@@ -60,6 +60,7 @@ void ags_recall_recycling_connect(AgsConnectable *connectable);
 void ags_recall_recycling_disconnect(AgsConnectable *connectable);
 void ags_recall_recycling_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
 void ags_recall_recycling_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+void ags_recall_recycling_dispose(GObject *gobject);
 void ags_recall_recycling_finalize(GObject *gobject);
 
 AgsRecall* ags_recall_recycling_duplicate(AgsRecall *recall,
@@ -164,6 +165,7 @@ ags_recall_recycling_class_init(AgsRecallRecyclingClass *recall_recycling)
   gobject->set_property = ags_recall_recycling_set_property;
   gobject->get_property = ags_recall_recycling_get_property;
 
+  gobject->dispose = ags_recall_recycling_dispose;
   gobject->finalize = ags_recall_recycling_finalize;
 
   /* properties */
@@ -280,7 +282,6 @@ ags_recall_recycling_dynamic_connectable_interface_init(AgsDynamicConnectableInt
 void
 ags_recall_recycling_init(AgsRecallRecycling *recall_recycling)
 {
-  recall_recycling->flags = 0;
   recall_recycling->flags = (AGS_RECALL_RECYCLING_MAP_CHILD_DESTINATION  |
 			     AGS_RECALL_RECYCLING_MAP_CHILD_SOURCE);
 
@@ -315,17 +316,18 @@ ags_recall_recycling_set_property(GObject *gobject,
 
       destination = (AgsRecycling *) g_value_get_object(value);
 
-      if(recall_recycling->destination == destination)
+      if(recall_recycling->destination == destination){
 	return;
+      }
 
       if(recall_recycling->destination != NULL){
 	if((AGS_RECALL_TEMPLATE & (AGS_RECALL(recall_recycling)->flags)) == 0){
 	  gobject = G_OBJECT(recall_recycling->destination);
 	    
 	  if((AGS_RECALL_DYNAMIC_CONNECTED & (AGS_RECALL(recall_recycling)->flags)) != 0){
-	    g_signal_handler_disconnect(gobject, recall_recycling->destination_add_audio_signal_handler);
+	    //	    g_signal_handler_disconnect(gobject, recall_recycling->destination_add_audio_signal_handler);
 	      
-	    g_signal_handler_disconnect(gobject, recall_recycling->destination_remove_audio_signal_handler);
+	    //	    g_signal_handler_disconnect(gobject, recall_recycling->destination_remove_audio_signal_handler);
 	  }
 	}
 
@@ -340,13 +342,13 @@ ags_recall_recycling_set_property(GObject *gobject,
 	gobject = G_OBJECT(destination);
 	  
 	if((AGS_RECALL_DYNAMIC_CONNECTED & (AGS_RECALL(recall_recycling)->flags)) != 0){
-	  recall_recycling->destination_add_audio_signal_handler =
-	    g_signal_connect_after(gobject, "add_audio_signal\0",
-				   G_CALLBACK(ags_recall_recycling_destination_add_audio_signal_callback), recall_recycling);
+	  //	  recall_recycling->destination_add_audio_signal_handler =
+	  //	    g_signal_connect_after(gobject, "add_audio_signal\0",
+	  //				   G_CALLBACK(ags_recall_recycling_destination_add_audio_signal_callback), recall_recycling);
 	    
-	  recall_recycling->destination_remove_audio_signal_handler =
-	    g_signal_connect(gobject, "remove_audio_signal\0",
-			     G_CALLBACK(ags_recall_recycling_destination_remove_audio_signal_callback), recall_recycling);
+	  //	  recall_recycling->destination_remove_audio_signal_handler =
+	  //	    g_signal_connect(gobject, "remove_audio_signal\0",
+	  //			     G_CALLBACK(ags_recall_recycling_destination_remove_audio_signal_callback), recall_recycling);
 	}
       }
 
@@ -359,8 +361,9 @@ ags_recall_recycling_set_property(GObject *gobject,
 
       source = (AgsRecycling *) g_value_get_object(value);
 
-      if(recall_recycling->source == source)
+      if(recall_recycling->source == source){
 	return;
+      }
 
       if(recall_recycling->source != NULL){
 	if((AGS_RECALL_TEMPLATE & (AGS_RECALL(recall_recycling)->flags)) == 0){
@@ -393,7 +396,7 @@ ags_recall_recycling_set_property(GObject *gobject,
 	    
 	    recall_recycling->source_remove_audio_signal_handler =
 	      g_signal_connect(gobject, "remove_audio_signal\0",
-			       G_CALLBACK(ags_recall_recycling_source_remove_audio_signal_callback), recall_recycling);
+	    		       G_CALLBACK(ags_recall_recycling_source_remove_audio_signal_callback), recall_recycling);
 	  }
 	}
       }
@@ -405,8 +408,9 @@ ags_recall_recycling_set_property(GObject *gobject,
 
       child_destination = (AgsAudioSignal *) g_value_get_object(value);
 
-      if(recall_recycling->child_destination == child_destination)
+      if(recall_recycling->child_destination == child_destination){
 	return;
+      }
 
       if(recall_recycling->child_destination != NULL){
 	g_object_unref(G_OBJECT(recall_recycling->child_destination));
@@ -425,8 +429,9 @@ ags_recall_recycling_set_property(GObject *gobject,
 
       child_source = (AgsAudioSignal *) g_value_get_object(value);
 
-      if(g_list_find(recall_recycling->child_source, child_source) != NULL)
+      if(g_list_find(recall_recycling->child_source, child_source) != NULL){
 	return;
+      }
 
       if(child_source != NULL){
 	g_object_ref(G_OBJECT(child_source));
@@ -477,24 +482,68 @@ ags_recall_recycling_get_property(GObject *gobject,
 }
 
 void
+ags_recall_recycling_dispose(GObject *gobject)
+{
+  AgsRecallRecycling *recall_recycling;
+
+  recall_recycling = AGS_RECALL_RECYCLING(gobject);
+
+  /* destination */
+  if(recall_recycling->destination != NULL){
+    g_object_unref(G_OBJECT(recall_recycling->destination));
+
+    recall_recycling->destination = NULL;
+  }
+
+  /* source */
+  if(recall_recycling->source != NULL){
+    g_object_unref(G_OBJECT(recall_recycling->source));
+
+    recall_recycling->source = NULL;
+  }
+
+  /* child destination */
+  if(recall_recycling->child_destination != NULL){
+    g_object_unref(G_OBJECT(recall_recycling->child_destination));
+
+    recall_recycling->child_destination = NULL;
+  }
+
+  /* child source */
+  if(recall_recycling->child_source != NULL){
+    g_list_free_full(recall_recycling->child_source,
+		     g_object_unref);
+
+    recall_recycling->child_source = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_recall_recycling_parent_class)->dispose(gobject);
+}
+
+void
 ags_recall_recycling_finalize(GObject *gobject)
 {
   AgsRecallRecycling *recall_recycling;
 
   recall_recycling = AGS_RECALL_RECYCLING(gobject);
 
+  /* destination */
   if(recall_recycling->destination != NULL){
     g_object_unref(G_OBJECT(recall_recycling->destination));
   }
-  
+
+  /* source */
   if(recall_recycling->source != NULL){
     g_object_unref(G_OBJECT(recall_recycling->source));
   }
-  
+
+  /* child destination */
   if(recall_recycling->child_destination != NULL){
     g_object_unref(G_OBJECT(recall_recycling->child_destination));
   }
-  
+
+  /* child source */
   if(recall_recycling->child_source != NULL){
     g_list_free_full(recall_recycling->child_source,
 		     g_object_unref);
@@ -543,13 +592,13 @@ ags_recall_recycling_connect_dynamic(AgsDynamicConnectable *dynamic_connectable)
   if(recall_recycling->destination != NULL){
     gobject = G_OBJECT(recall_recycling->destination);
 
-    recall_recycling->destination_add_audio_signal_handler =
-      g_signal_connect_after(gobject, "add_audio_signal\0",
-			     G_CALLBACK(ags_recall_recycling_destination_add_audio_signal_callback), recall_recycling);
+    //    recall_recycling->destination_add_audio_signal_handler =
+    //      g_signal_connect_after(gobject, "add_audio_signal\0",
+    //			     G_CALLBACK(ags_recall_recycling_destination_add_audio_signal_callback), recall_recycling);
       
-    recall_recycling->destination_remove_audio_signal_handler =
-      g_signal_connect(gobject, "remove_audio_signal\0",
-		       G_CALLBACK(ags_recall_recycling_destination_remove_audio_signal_callback), recall_recycling);
+    //    recall_recycling->destination_remove_audio_signal_handler =
+    //      g_signal_connect(gobject, "remove_audio_signal\0",
+    //    		       G_CALLBACK(ags_recall_recycling_destination_remove_audio_signal_callback), recall_recycling);
   }
 
   /* source */
@@ -561,7 +610,7 @@ ags_recall_recycling_connect_dynamic(AgsDynamicConnectable *dynamic_connectable)
 
   recall_recycling->source_remove_audio_signal_handler =
     g_signal_connect(gobject, "remove_audio_signal\0",
-		     G_CALLBACK(ags_recall_recycling_source_remove_audio_signal_callback), recall_recycling);
+  		     G_CALLBACK(ags_recall_recycling_source_remove_audio_signal_callback), recall_recycling);
 }
 
 void
@@ -582,9 +631,8 @@ ags_recall_recycling_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectab
 
     gobject = G_OBJECT(recall_recycling->destination);
     
-    g_signal_handler_disconnect(gobject, recall_recycling->destination_add_audio_signal_handler);
-    
-    g_signal_handler_disconnect(gobject, recall_recycling->destination_remove_audio_signal_handler);
+    //    g_signal_handler_disconnect(gobject, recall_recycling->destination_add_audio_signal_handler);
+    //    g_signal_handler_disconnect(gobject, recall_recycling->destination_remove_audio_signal_handler);
   }
 
   /* source */
@@ -762,13 +810,14 @@ ags_recall_recycling_source_add_audio_signal_callback(AgsRecycling *source,
     //		 NULL);
   }
 
+  pthread_mutex_unlock(mutex);
 
   if(AGS_RECALL(recall_recycling)->child_type != G_TYPE_NONE){
     recall_audio_signal = g_object_new(AGS_RECALL(recall_recycling)->child_type,
 				       "soundcard\0", recall->soundcard,
 				       "recall_id\0", audio_signal->recall_id,
 				       "audio_channel\0", recall_recycling->audio_channel,
-				       //"destination\0", recall_recycling->child_destination,
+				       //				       "destination\0", ((AGS_RECALL(recall_recycling)->child_type == AGS_TYPE_COPY_AUDIO_SIGNAL) ? recall_recycling->child_destination: NULL),
 				       "source\0", audio_signal,
 				       NULL);
 
@@ -778,8 +827,6 @@ ags_recall_recycling_source_add_audio_signal_callback(AgsRecycling *source,
     
     ags_recall_add_child(AGS_RECALL(recall_recycling), AGS_RECALL(recall_audio_signal));
   }
-
-  pthread_mutex_unlock(mutex);
 }
 
 void
@@ -794,7 +841,13 @@ ags_recall_recycling_source_remove_audio_signal_callback(AgsRecycling *source,
 
   AgsMutexManager *mutex_manager;
 
+  AgsConfig *config;
+  
   GList *list, *list_start;
+
+  gchar *str;
+  
+  gboolean performance_mode;
   
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *mutex;
@@ -836,9 +889,16 @@ ags_recall_recycling_source_remove_audio_signal_callback(AgsRecycling *source,
   if(AGS_RECALL_ID(audio_signal->recall_id)->recycling_context != recall->recall_id->recycling_context){
     if(AGS_IS_INPUT(channel)){
       if(channel->link != NULL){
-	if(AGS_RECALL_ID(audio_signal->recall_id)->recycling_context->parent != recall->recall_id->recycling_context){
-	  pthread_mutex_unlock(mutex);
-	  return;
+	if(AGS_RECALL_ID(audio_signal->recall_id)->recycling_context->parent != NULL){
+	  if(AGS_RECALL_ID(audio_signal->recall_id)->recycling_context->parent != recall->recall_id->recycling_context){
+	    pthread_mutex_unlock(mutex);
+	    return;
+	  }
+	}else{
+	  if(AGS_RECALL_ID(audio_signal->recall_id)->recycling_context != recall->recall_id->recycling_context){
+	    pthread_mutex_unlock(mutex);
+	    return;
+	  }
 	}
       }else{
 	pthread_mutex_unlock(mutex);
@@ -863,21 +923,35 @@ ags_recall_recycling_source_remove_audio_signal_callback(AgsRecycling *source,
 	    AGS_CHANNEL(recall_recycling->source->channel)->line);
 #endif
 
+  config = ags_config_get_instance();
+
+  str = ags_config_get_value(config,
+			     AGS_CONFIG_GENERIC,
+			     "engine-mode\0");
+
+  if(str != NULL &&
+     !g_ascii_strncasecmp(str,
+			  "performance\0",
+			  12)){
+    performance_mode = TRUE;
+  }else{
+    performance_mode = FALSE;
+  }
+  
   list_start = 
     list = ags_recall_get_children(recall);
-
+  
   while(list != NULL){
     recall_audio_signal = AGS_RECALL_AUDIO_SIGNAL(list->data);
 
     if((recall_audio_signal->source == audio_signal) &&
        (AGS_RECALL_DONE & (AGS_RECALL(recall_audio_signal)->flags)) == 0){
+      ags_recall_done(recall_audio_signal);
       //   	cancel_recall = ags_cancel_recall_new(AGS_RECALL(recall_audio_signal),
       //				      NULL);
 	
       //	ags_task_thread_append_task(AGS_TASK_THREAD(AGS_AUDIO_LOOP(AGS_MAIN(soundcard->application_context)->main_loop)->task_thread),
       //			    (AgsTask *) cancel_recall);
-
-      break;
     }
 
     list = list->next;
@@ -1072,6 +1146,7 @@ ags_recall_recycling_destination_remove_audio_signal_callback(AgsRecycling *dest
 
     if(recall_audio_signal->destination == audio_signal &&
        (AGS_RECALL_DONE & (AGS_RECALL(recall_audio_signal)->flags)) == 0){
+      //      ags_recall_done(recall_audio_signal);
       //	cancel_recall = ags_cancel_recall_new(AGS_RECALL(recall_audio_signal),
       //				      NULL);
 
diff --git a/ags/audio/ags_recall_recycling.h b/ags/audio/ags_recall_recycling.h
index c9f5dce..20fda32 100644
--- a/ags/audio/ags_recall_recycling.h
+++ b/ags/audio/ags_recall_recycling.h
@@ -41,9 +41,9 @@ typedef struct _AgsRecallRecyclingClass AgsRecallRecyclingClass;
 
 typedef enum{
   AGS_RECALL_RECYCLING_GARBAGE_COLLECTOR                = 1,
-  AGS_RECALL_RECYCLING_MAP_CHILD_DESTINATION            = 1 << 1,
-  AGS_RECALL_RECYCLING_MAP_CHILD_SOURCE                 = 1 << 2,
-  AGS_RECALL_RECYCLING_CREATE_DESTINATION_ON_MAP_SOURCE = 1 << 3,
+  AGS_RECALL_RECYCLING_MAP_CHILD_DESTINATION            = 1 <<  1,
+  AGS_RECALL_RECYCLING_MAP_CHILD_SOURCE                 = 1 <<  2,
+  AGS_RECALL_RECYCLING_CREATE_DESTINATION_ON_MAP_SOURCE = 1 <<  3,
 }AgsRecallRecyclingFlags;
 
 struct _AgsRecallRecycling
diff --git a/ags/audio/ags_recycling.c b/ags/audio/ags_recycling.c
index 1f74e14..90fc9b3 100644
--- a/ags/audio/ags_recycling.c
+++ b/ags/audio/ags_recycling.c
@@ -49,6 +49,7 @@ void ags_recycling_connect(AgsConnectable *connectable);
 void ags_recycling_disconnect(AgsConnectable *connectable);
 pthread_mutex_t* ags_recycling_get_lock(AgsConcurrentTree *concurrent_tree);
 pthread_mutex_t* ags_recycling_get_parent_lock(AgsConcurrentTree *concurrent_tree);
+void ags_recycling_dispose(GObject *gobject);
 void ags_recycling_finalize(GObject *gobject);
 
 void ags_recycling_real_add_audio_signal(AgsRecycling *recycling,
@@ -147,6 +148,7 @@ ags_recycling_class_init(AgsRecyclingClass *recycling)
   gobject->set_property = ags_recycling_set_property;
   gobject->get_property = ags_recycling_get_property;
 
+  gobject->dispose = ags_recycling_dispose;
   gobject->finalize = ags_recycling_finalize;
 
   /* properties */
@@ -481,10 +483,14 @@ ags_recycling_get_property(GObject *gobject,
   
   switch(prop_id){
   case PROP_SOUNDCARD:
-    g_value_set_object(value, recycling->soundcard);
+    {
+      g_value_set_object(value, recycling->soundcard);
+    }
     break;
   case PROP_CHANNEL:
-    g_value_set_object(value, recycling->channel);
+    {
+      g_value_set_object(value, recycling->channel);
+    }
     break;
   case PROP_PARENT:
     {
@@ -515,13 +521,51 @@ ags_recycling_get_property(GObject *gobject,
 void
 ags_recycling_connect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsRecycling *recycling;
+
+  GList *list;
+  
+  recycling = AGS_RECYCLING(connectable);
+
+  if((AGS_RECYCLING_CONNECTED & (recycling->flags)) != 0){
+    return;
+  }
+
+  recycling->flags |= AGS_RECYCLING_CONNECTED;
+
+  /* audio signal */
+  list = recycling->audio_signal;
+
+  while(list != NULL){
+    ags_connectable_connect(AGS_CONNECTABLE(list->data));
+    
+    list = list->next;
+  }
 }
 
 void
 ags_recycling_disconnect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsRecycling *recycling;
+
+  GList *list;
+  
+  recycling = AGS_RECYCLING(connectable);
+
+  if((AGS_RECYCLING_CONNECTED & (recycling->flags)) == 0){
+    return;
+  }
+
+  recycling->flags &= (~AGS_RECYCLING_CONNECTED);
+
+  /* audio signal */
+  list = recycling->audio_signal;
+
+  while(list != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
+    
+    list = list->next;
+  }
 }
 
 pthread_mutex_t*
@@ -574,14 +618,70 @@ ags_recycling_get_parent_lock(AgsConcurrentTree *concurrent_tree)
 }
 
 void
+ags_recycling_dispose(GObject *gobject)
+{
+  AgsRecycling *recycling;  
+
+  GList *list;
+
+  recycling = AGS_RECYCLING(gobject);
+
+  /* channel */
+  if(recycling->channel != NULL){
+    g_object_unref(recycling->channel);
+
+    recycling->channel = NULL;
+  }
+
+  /* soundcard */
+  if(recycling->soundcard != NULL){
+    g_object_unref(recycling->soundcard);
+
+    recycling->soundcard = NULL;
+  }
+
+  /* parent */
+  if(recycling->parent != NULL){
+    //    g_object_unref(recycling->parent);
+
+    recycling->parent = NULL;
+  }
+
+  /* next and prev */
+  if(recycling->next != NULL){
+    //    g_object_unref(recycling->next);
+
+    recycling->next = NULL;
+  }
+
+  if(recycling->prev != NULL){
+    //    g_object_unref(recycling->prev);
+
+    recycling->prev = NULL;
+  }
+
+  /* AgsAudioSignal */
+  list = recycling->audio_signal;
+
+  while(list != NULL){
+    g_object_run_dispose(list->data);
+    
+    list = list->next;
+  }
+  
+  g_list_free_full(recycling->audio_signal,
+		   g_object_unref);
+
+  recycling->audio_signal = NULL;
+}
+
+void
 ags_recycling_finalize(GObject *gobject)
 {
   AgsRecycling *recycling;  
 
   AgsMutexManager *mutex_manager;
   
-  GList *list, *list_next;
-
   pthread_mutex_t *application_mutex;
   
   //  g_warning("ags_recycling_finalize\0");
@@ -598,6 +698,30 @@ ags_recycling_finalize(GObject *gobject)
 
   recycling = AGS_RECYCLING(gobject);
 
+  /* channel */
+  if(recycling->channel != NULL){
+    g_object_unref(recycling->channel);
+  }
+
+  /* soundcard */
+  if(recycling->soundcard != NULL){
+    g_object_unref(recycling->soundcard);
+  }
+
+  /* parent */
+  if(recycling->parent != NULL){
+    g_object_unref(recycling->parent);
+  }
+
+  /* next and prev */
+  if(recycling->next != NULL){
+    g_object_unref(recycling->next);
+  }
+
+  if(recycling->prev != NULL){
+    g_object_unref(recycling->prev);
+  }
+
   /* AgsAudioSignal */
   g_list_free_full(recycling->audio_signal,
 		   g_object_unref);
@@ -619,15 +743,18 @@ void
 ags_recycling_set_soundcard(AgsRecycling *recycling, GObject *soundcard)
 {
   /* recycling */
-  if(recycling->soundcard == soundcard)
+  if(recycling->soundcard == soundcard){
     return;
+  }
 
-  if(recycling->soundcard != NULL)
+  if(recycling->soundcard != NULL){
     g_object_unref(recycling->soundcard);
-
-  if(soundcard != NULL)
+  }
+  
+  if(soundcard != NULL){
     g_object_ref(soundcard);
-
+  }
+  
   recycling->soundcard = (GObject *) soundcard;
 }
 
@@ -693,21 +820,27 @@ void
 ags_recycling_real_add_audio_signal(AgsRecycling *recycling,
 				    AgsAudioSignal *audio_signal)
 {
-  if((AGS_AUDIO_SIGNAL_TEMPLATE & (audio_signal->flags)) != 0){
-    AgsAudioSignal *old_template;
+  if(g_list_find(recycling->audio_signal,
+		 audio_signal) == NULL){
+    if((AGS_AUDIO_SIGNAL_TEMPLATE & (audio_signal->flags)) != 0){
+      AgsAudioSignal *old_template;
 
-    /* old template */
-    old_template = ags_audio_signal_get_template(recycling->audio_signal);
+      /* old template */
+      old_template = ags_audio_signal_get_template(recycling->audio_signal);
     
-    /* remove old template */
-    ags_recycling_remove_audio_signal(recycling,
-				      old_template);
+      /* remove old template */
+      ags_recycling_remove_audio_signal(recycling,
+					old_template);
+    }
+
+    recycling->audio_signal = g_list_prepend(recycling->audio_signal, (gpointer) audio_signal);
+    g_object_ref(audio_signal);
   }
   
-  recycling->audio_signal = g_list_prepend(recycling->audio_signal, (gpointer) audio_signal);
-  audio_signal->recycling = (GObject *) recycling;
-  g_object_ref(recycling);
-  g_object_ref(audio_signal);
+  if(audio_signal->recycling != recycling){
+    audio_signal->recycling = (GObject *) recycling;
+    g_object_ref(recycling);
+  }
 }
 
 /**
@@ -1215,6 +1348,68 @@ ags_recycling_position(AgsRecycling *start_region, AgsRecycling *end_region,
 }
 
 /**
+ * ags_recycling_is_active:
+ * @start_region: boundary start
+ * @end_region: boundary end
+ * @recall_id: the #AgsRecallID
+ * 
+ * Check if is active.
+ * 
+ * Returns: %TRUE if related audio signal to recall id is available, otherwise %FALSE
+ * 
+ * Since: 0.7.122.9
+ */
+gboolean
+ags_recycling_is_active(AgsRecycling *start_region, AgsRecycling *end_region,
+			GObject *recall_id)
+{
+  AgsRecycling *current;
+
+  AgsMutexManager *mutex_manager;
+  
+  pthread_mutex_t *application_mutex;
+  pthread_mutex_t *current_mutex;
+  
+  if(recall_id == NULL ||
+     AGS_RECALL_ID(recall_id)->recycling_context == NULL){
+    return(FALSE);
+  }
+
+  /* lookup mutex */
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  current = start_region;
+
+  while(current != end_region){
+    /* lock current */
+    pthread_mutex_lock(application_mutex);
+    
+    current_mutex = ags_mutex_manager_lookup(mutex_manager,
+					     (GObject *) current);
+
+    pthread_mutex_unlock(application_mutex);
+
+    /* is active */
+    pthread_mutex_lock(current_mutex);
+
+    if(ags_audio_signal_is_active(current->audio_signal,
+				  recall_id)){
+      pthread_mutex_unlock(current_mutex);
+      
+      return(TRUE);
+    }
+
+    
+    current = current->next;
+
+    pthread_mutex_unlock(current_mutex);
+  }
+
+  return(FALSE);
+}
+
+/**
  * ags_recycling_new:
  * @soundcard: the #GObject
  *
diff --git a/ags/audio/ags_recycling.h b/ags/audio/ags_recycling.h
index b80d85b..e5dc163 100644
--- a/ags/audio/ags_recycling.h
+++ b/ags/audio/ags_recycling.h
@@ -35,7 +35,8 @@ typedef struct _AgsRecycling AgsRecycling;
 typedef struct _AgsRecyclingClass AgsRecyclingClass;
 
 typedef enum{
-  AGS_RECYCLING_MUTED           =  1,
+  AGS_RECYCLING_CONNECTED       = 1,
+  AGS_RECYCLING_MUTED           = 1 <<  1,
 }AgsRecyclingFlags;
 
 struct _AgsRecycling
@@ -89,6 +90,9 @@ gint ags_recycling_position(AgsRecycling *start_region, AgsRecycling *end_region
 AgsRecycling* ags_recycling_find_next_channel(AgsRecycling *start_region, AgsRecycling *end_region,
 					      GObject *prev_channel);
 
+gboolean ags_recycling_is_active(AgsRecycling *start_region, AgsRecycling *end_region,
+				 GObject *recall_id);
+
 AgsRecycling* ags_recycling_new(GObject *soundcard);
 
 #endif /*__AGS_RECYCLING_H__*/
diff --git a/ags/audio/ags_recycling_context.c b/ags/audio/ags_recycling_context.c
index e4ccd60..923dda9 100644
--- a/ags/audio/ags_recycling_context.c
+++ b/ags/audio/ags_recycling_context.c
@@ -34,6 +34,7 @@ void ags_recycling_context_get_property(GObject *gobject,
 					guint prop_id,
 					GValue *value,
 					GParamSpec *param_spec);
+void ags_recycling_context_dispose(GObject *gobject);
 void ags_recycling_context_finalize(GObject *gobject);
 
 /**
@@ -96,6 +97,7 @@ ags_recycling_context_class_init(AgsRecyclingContextClass *recycling_context)
   gobject->set_property = ags_recycling_context_set_property;
   gobject->get_property = ags_recycling_context_get_property;
 
+  gobject->dispose = ags_recycling_context_dispose;
   gobject->finalize = ags_recycling_context_finalize;
 
   /* properties */
@@ -270,8 +272,88 @@ ags_recycling_context_get_property(GObject *gobject,
 }
 
 void
+ags_recycling_context_dispose(GObject *gobject)
+{
+  AgsRecyclingContext *recycling_context;
+
+  GList *list, *list_next;
+
+  guint i;
+  
+  recycling_context = AGS_RECYCLING_CONTEXT(gobject);
+
+  /* parent */
+  if(recycling_context->parent != NULL){
+    g_object_unref(recycling_context->parent);
+  }
+  
+  /* recall id */
+  if(recycling_context->recall_id != NULL){
+    g_object_unref(recycling_context->recall_id);
+  }
+
+  /* recycling */
+  if(recycling_context->recycling != NULL){
+    for(i = 0; i < recycling_context->length; i++){
+      g_object_unref(recycling_context->recycling[i]);
+    }
+
+    free(recycling_context->recycling);
+    
+    recycling_context->recycling = NULL;
+    recycling_context->length = 0;
+  }
+  
+  /* children */
+  list = recycling_context->children;
+
+  while(list != NULL){
+    list_next = list->next;
+    
+    ags_recycling_context_remove_child(recycling_context,
+				       list->data);
+    
+    list = list_next;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_recycling_context_parent_class)->dispose(gobject);
+}
+
+void
 ags_recycling_context_finalize(GObject *gobject)
 {
+  AgsRecyclingContext *recycling_context;
+
+  GList *list;
+
+  guint i;
+    
+  recycling_context = AGS_RECYCLING_CONTEXT(gobject);
+
+  /* parent */
+  if(recycling_context->parent != NULL){
+    g_object_unref(recycling_context->parent);
+  }
+  
+  /* recall id */
+  if(recycling_context->recall_id != NULL){
+    g_object_unref(recycling_context->recall_id);
+  }
+
+  /* recycling */
+  if(recycling_context->recycling != NULL){
+    for(i = 0; i < recycling_context->length; i++){
+      g_object_unref(recycling_context->recycling[i]);
+    }
+  
+    free(recycling_context->recycling);
+  }
+  
+  /* children */
+  g_list_free(recycling_context->children);
+
+  /* call parent */
   G_OBJECT_CLASS(ags_recycling_context_parent_class)->finalize(gobject);
 }
 
@@ -314,8 +396,10 @@ ags_recycling_context_add(AgsRecyclingContext *recycling_context,
 			  AgsRecycling *recycling)
 {
   AgsRecyclingContext *new_recycling_context;
-  gint new_length;
 
+  gint new_length;
+  guint i;
+  
   if(recycling_context == NULL){
     return(NULL);
   }
@@ -328,6 +412,11 @@ ags_recycling_context_add(AgsRecyclingContext *recycling_context,
   memcpy(new_recycling_context->recycling, recycling_context->recycling, new_length * sizeof(AgsRecycling *));
   new_recycling_context->recycling[new_length] = recycling;
 
+  /* ref count */
+  for(i = 0; i < new_recycling_context->length; i++){
+    g_object_ref(new_recycling_context->recycling[i]);
+  }
+
   return(new_recycling_context);
 }
 
@@ -347,9 +436,11 @@ ags_recycling_context_remove(AgsRecyclingContext *recycling_context,
 			     AgsRecycling *recycling)
 {
   AgsRecyclingContext *new_recycling_context;
+
   gint new_length;
   gint position;
-
+  guint i;
+  
   new_recycling_context = (AgsRecyclingContext *) g_object_new(AGS_TYPE_RECYCLING_CONTEXT,
 							       NULL);
 
@@ -362,6 +453,11 @@ ags_recycling_context_remove(AgsRecyclingContext *recycling_context,
   memcpy(new_recycling_context->recycling, recycling_context->recycling, (new_length - position) * sizeof(AgsRecycling *));
   memcpy(&(new_recycling_context->recycling[position + 1]), recycling_context->recycling, (-1 * (position - new_length)) * sizeof(AgsRecycling *));
 
+  /* ref count */
+  for(i = 0; i < new_recycling_context->length; i++){
+    g_object_ref(new_recycling_context->recycling[i]);
+  }
+
   return(new_recycling_context);
 }
 
@@ -383,7 +479,9 @@ ags_recycling_context_insert(AgsRecyclingContext *recycling_context,
 			     gint position)
 {
   AgsRecyclingContext *new_recycling_context;
+
   gint new_length;
+  guint i;
 
   new_recycling_context = (AgsRecyclingContext *) g_object_new(AGS_TYPE_RECYCLING_CONTEXT,
 							       NULL);
@@ -395,6 +493,11 @@ ags_recycling_context_insert(AgsRecyclingContext *recycling_context,
   memcpy(new_recycling_context->recycling, recycling_context->recycling, (new_length - position) * sizeof(AgsRecycling *));
   new_recycling_context->recycling[position] = recycling;
   memcpy(&(new_recycling_context->recycling[position + 1]), recycling_context->recycling, (-1 * (position - new_length)) * sizeof(AgsRecycling *));
+  
+  /* ref count */
+  for(i = 0; i < new_recycling_context->length; i++){
+    g_object_ref(new_recycling_context->recycling[i]);
+  }
 
   return(new_recycling_context);
 }
@@ -613,6 +716,7 @@ ags_recycling_context_reset_recycling(AgsRecyclingContext *recycling_context,
 {
   AgsRecyclingContext *new_recycling_context;
   AgsRecycling *recycling;
+
   gint new_length;
   gint first_index, last_index;
   guint i;
@@ -726,6 +830,11 @@ ags_recycling_context_reset_recycling(AgsRecyclingContext *recycling_context,
     }
   }
 
+  /* ref count */
+  for(i = 0; i < new_recycling_context->length; i++){
+    g_object_ref(new_recycling_context->recycling[i]);
+  }
+
   return(new_recycling_context);
 }
 
diff --git a/ags/audio/ags_recycling_context.h b/ags/audio/ags_recycling_context.h
index a726480..954a1a7 100644
--- a/ags/audio/ags_recycling_context.h
+++ b/ags/audio/ags_recycling_context.h
@@ -37,12 +37,13 @@ struct _AgsRecyclingContext
 {
   GObject object;
 
+  AgsRecyclingContext *parent;
+
   GObject *recall_id;
 
   AgsRecycling **recycling;
   guint64 length;
 
-  AgsRecyclingContext *parent;
   GList *children;
 };
 
@@ -53,6 +54,7 @@ struct _AgsRecyclingContextClass
 
 GType ags_recycling_context_get_type();
 
+/* replace, add, remove and insert */
 void ags_recycling_context_replace(AgsRecyclingContext *recycling_context,
 				   AgsRecycling *recycling,
 				   gint position);
@@ -65,6 +67,7 @@ AgsRecyclingContext* ags_recycling_context_insert(AgsRecyclingContext *recycling
 						  AgsRecycling *recycling,
 						  gint position);
 
+/* tolevel, find, find child and find parent */
 AgsRecyclingContext* ags_recycling_context_get_toplevel(AgsRecyclingContext *recycling_context);
 
 gint ags_recycling_context_find(AgsRecyclingContext *recycling_context,
@@ -74,17 +77,21 @@ gint ags_recycling_context_find_child(AgsRecyclingContext *recycling_context,
 gint ags_recycling_context_find_parent(AgsRecyclingContext *recycling_context,
 				       AgsRecycling *recycling);
 
+/* add and remove child */
 void ags_recycling_context_add_child(AgsRecyclingContext *parent,
 				     AgsRecyclingContext *child);
 void ags_recycling_context_remove_child(AgsRecyclingContext *parent,
 					AgsRecyclingContext *child);
 
+/* child recall id */
 GList* ags_recycling_context_get_child_recall_id(AgsRecyclingContext *recycling_context);
 
+/* instantiate - reset recycling */
 AgsRecyclingContext* ags_recycling_context_reset_recycling(AgsRecyclingContext *recycling_context,
 							   AgsRecycling *old_first_recycling, AgsRecycling *old_last_recycling,
 							   AgsRecycling *new_first_recycling, AgsRecycling *new_last_recycling);
 
+/* instantiate */
 AgsRecyclingContext* ags_recycling_context_new(guint64 length);
 
 #endif /*__AGS_RECYCLING_CONTEXT_H__*/
diff --git a/ags/audio/ags_synth_generator.c b/ags/audio/ags_synth_generator.c
index 06e781f..9c76c18 100644
--- a/ags/audio/ags_synth_generator.c
+++ b/ags/audio/ags_synth_generator.c
@@ -21,7 +21,9 @@
 
 #include <ags/util/ags_id_generator.h>
 
+#include <ags/object/ags_config.h>
 #include <ags/object/ags_plugin.h>
+#include <ags/object/ags_soundcard.h>
 
 #include <ags/thread/ags_timestamp.h>
 
@@ -310,6 +312,87 @@ ags_synth_generator_plugin_interface_init(AgsPluginInterface *plugin)
 void
 ags_synth_generator_init(AgsSynthGenerator *synth_generator)
 {
+  AgsConfig *config;
+  
+  gchar *str;
+  
+  /* config */
+  config = ags_config_get_instance();
+
+  /* base init */
+  synth_generator->flags = 0;
+
+  synth_generator->samplerate = AGS_SOUNDCARD_DEFAULT_SAMPLERATE;
+  synth_generator->buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
+  synth_generator->format = AGS_SOUNDCARD_DEFAULT_FORMAT;
+
+  /* samplerate */
+  str = ags_config_get_value(config,
+			     AGS_CONFIG_SOUNDCARD,
+			     "samplerate\0");
+
+  if(str == NULL){
+    str = ags_config_get_value(config,
+			       AGS_CONFIG_SOUNDCARD_0,
+			       "samplerate\0");
+  }
+  
+  if(str != NULL){
+    synth_generator->samplerate = g_ascii_strtoull(str,
+						   NULL,
+						   10);
+
+    free(str);
+  }
+
+  /* buffer size */
+  str = ags_config_get_value(config,
+			     AGS_CONFIG_SOUNDCARD,
+			     "buffer-size\0");
+
+  if(str == NULL){
+    str = ags_config_get_value(config,
+			       AGS_CONFIG_SOUNDCARD_0,
+			       "buffer-size\0");
+  }
+  
+  if(str != NULL){
+    synth_generator->buffer_size = g_ascii_strtoull(str,
+						    NULL,
+						    10);
+
+    free(str);
+  }
+
+  /* format */
+  str = ags_config_get_value(config,
+			     AGS_CONFIG_SOUNDCARD,
+			     "format\0");
+
+  if(str == NULL){
+    str = ags_config_get_value(config,
+			       AGS_CONFIG_SOUNDCARD_0,
+			       "format\0");
+  }
+  
+  if(str != NULL){
+    synth_generator->format = g_ascii_strtoull(str,
+					       NULL,
+					       10);
+
+    free(str);
+  }
+
+  /* more base init */
+  synth_generator->n_frames = 0;
+
+  synth_generator->oscillator = 0;
+  
+  synth_generator->frequency = 0.0;
+  synth_generator->phase = 0.0;
+  synth_generator->volume = 1.0;
+  
+  /* timestamp */
   synth_generator->timestamp = NULL;
 }
 
diff --git a/ags/audio/ags_synth_generator.h b/ags/audio/ags_synth_generator.h
index b0ad7d5..86ddf4c 100644
--- a/ags/audio/ags_synth_generator.h
+++ b/ags/audio/ags_synth_generator.h
@@ -45,6 +45,8 @@ typedef enum{
 struct _AgsSynthGenerator
 {
   AgsFunction function;
+
+  guint flags;
   
   guint samplerate;
   guint buffer_size;
diff --git a/ags/audio/jack/ags_jack_client.c b/ags/audio/jack/ags_jack_client.c
index 63ee845..972692d 100644
--- a/ags/audio/jack/ags_jack_client.c
+++ b/ags/audio/jack/ags_jack_client.c
@@ -59,6 +59,7 @@ void ags_jack_client_get_property(GObject *gobject,
 				  GParamSpec *param_spec);
 void ags_jack_client_connect(AgsConnectable *connectable);
 void ags_jack_client_disconnect(AgsConnectable *connectable);
+void ags_jack_client_dispose(GObject *gobject);
 void ags_jack_client_finalize(GObject *gobject);
 
 void ags_jack_client_shutdown(void *arg);
@@ -78,6 +79,8 @@ int ags_jack_client_xrun_callback(void *ptr);
 enum{
   PROP_0,
   PROP_JACK_SERVER,
+  PROP_DEVICE,
+  PROP_PORT,
 };
 
 static gpointer ags_jack_client_parent_class = NULL;
@@ -133,6 +136,7 @@ ags_jack_client_class_init(AgsJackClientClass *jack_client)
   gobject->set_property = ags_jack_client_set_property;
   gobject->get_property = ags_jack_client_get_property;
 
+  gobject->dispose = ags_jack_client_dispose;
   gobject->finalize = ags_jack_client_finalize;
 
   /* properties */
@@ -151,6 +155,38 @@ ags_jack_client_class_init(AgsJackClientClass *jack_client)
   g_object_class_install_property(gobject,
 				  PROP_JACK_SERVER,
 				  param_spec);
+
+  /**
+   * AgsJackClient:device:
+   *
+   * The assigned devices.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("device\0",
+				   "assigned device\0",
+				   "The assigned device.\0",
+				   G_TYPE_OBJECT,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_DEVICE,
+				  param_spec);
+
+  /**
+   * AgsJackClient:port:
+   *
+   * The assigned ports.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("port\0",
+				   "assigned port\0",
+				   "The assigned port.\0",
+				   G_TYPE_OBJECT,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_PORT,
+				  param_spec);
 }
 
 void
@@ -242,6 +278,44 @@ ags_jack_client_set_property(GObject *gobject,
       jack_client->jack_server = (GObject *) jack_server;
     }
     break;
+  case PROP_DEVICE:
+    {
+      GObject *device;
+
+      device = (GObject *) g_value_get_object(value);
+
+      if(g_list_find(jack_client->device,
+		     device) != NULL){
+	return;
+      }
+
+      if(device != NULL){
+	g_object_ref(device);
+	
+	jack_client->device = g_list_prepend(jack_client->device,
+					     device);
+      }
+    }
+    break;
+  case PROP_PORT:
+    {
+      GObject *port;
+
+      port = (GObject *) g_value_get_object(value);
+
+      if(g_list_find(jack_client->port,
+		     port) != NULL){
+	return;
+      }
+
+      if(port != NULL){
+	g_object_ref(port);
+	
+	jack_client->port = g_list_prepend(jack_client->port,
+					   port);
+      }
+    }
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
     break;
@@ -264,6 +338,18 @@ ags_jack_client_get_property(GObject *gobject,
       g_value_set_object(value, jack_client->jack_server);
     }
     break;
+  case PROP_DEVICE:
+    {
+      g_value_set_pointer(value,
+			  g_list_copy(jack_client->device));
+    }
+    break;
+  case PROP_PORT:
+    {
+      g_value_set_pointer(value,
+			  g_list_copy(jack_client->port));
+    }
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
     break;
@@ -273,13 +359,105 @@ ags_jack_client_get_property(GObject *gobject,
 void
 ags_jack_client_connect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsJackClient *jack_client;
+
+  GList *list;
+  
+  jack_client = AGS_JACK_CLIENT(connectable);
+
+  if((AGS_JACK_CLIENT_CONNECTED & (jack_client->flags)) != 0){
+    return;
+  }
+
+  jack_client->flags |= AGS_JACK_CLIENT_CONNECTED;
+
+  /* port */
+  list = jack_client->port;
+
+  while(list != NULL){
+    ags_connectable_connect(AGS_CONNECTABLE(list->data));
+    
+    list = list->next;
+  }
 }
 
 void
 ags_jack_client_disconnect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsJackClient *jack_client;
+
+  GList *list;
+  
+  jack_client = AGS_JACK_CLIENT(connectable);
+
+  if((AGS_JACK_CLIENT_CONNECTED & (jack_client->flags)) == 0){
+    return;
+  }
+
+  jack_client->flags &= (~AGS_JACK_CLIENT_CONNECTED);
+
+  /* port */
+  list = jack_client->port;
+
+  while(list != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
+    
+    list = list->next;
+  }
+}
+
+void
+ags_jack_client_dispose(GObject *gobject)
+{
+  AgsJackClient *jack_client;
+
+  GList *list;
+  
+  jack_client = AGS_JACK_CLIENT(gobject);
+
+  /* jack server */
+  if(jack_client->jack_server != NULL){
+    g_object_unref(jack_client->jack_server);
+
+    jack_client->jack_server = NULL;
+  }
+
+  /* device */
+  if(jack_client->device != NULL){
+    list = jack_client->device;
+
+    while(list != NULL){
+      g_object_set(G_OBJECT(list->data),
+		   "jack-client\0", NULL,
+		   NULL);
+
+      list = list->next;
+    }
+
+    g_list_free_full(jack_client->device,
+		     g_object_unref);
+
+    jack_client->device = NULL;
+  }
+
+  /* port */
+  if(jack_client->port != NULL){
+    list = jack_client->port;
+
+    while(list != NULL){
+      g_object_run_dispose(G_OBJECT(list->data));
+
+      list = list->next;
+    }
+    
+    g_list_free_full(jack_client->port,
+		     g_object_unref);
+
+    jack_client->port = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_jack_client_parent_class)->dispose(gobject);
 }
 
 void
@@ -288,11 +466,25 @@ ags_jack_client_finalize(GObject *gobject)
   AgsJackClient *jack_client;
 
   jack_client = AGS_JACK_CLIENT(gobject);
-  
+
+  /* jack server */
   if(jack_client->jack_server != NULL){
     g_object_unref(jack_client->jack_server);
   }
 
+  /* device */
+  if(jack_client->device != NULL){
+    g_list_free_full(jack_client->device,
+		     g_object_unref);
+  }
+
+  /* port */
+  if(jack_client->port != NULL){
+    g_list_free_full(jack_client->port,
+		     g_object_unref);
+  }
+  
+  /* call parent */
   G_OBJECT_CLASS(ags_jack_client_parent_class)->finalize(gobject);
 }
 
@@ -886,8 +1078,6 @@ ags_jack_client_process_callback(jack_nframes_t nframes, void *ptr)
       }
     
       if(!no_event){
-	memset(jack_devout->buffer[nth_buffer], 0, (size_t) jack_devout->pcm_channels * jack_devout->buffer_size * word_size);
-
 	/* signal finish */
 	pthread_mutex_lock(device_mutex);
 
diff --git a/ags/audio/jack/ags_jack_devout.c b/ags/audio/jack/ags_jack_devout.c
index 28b71d4..e96a613 100644
--- a/ags/audio/jack/ags_jack_devout.c
+++ b/ags/audio/jack/ags_jack_devout.c
@@ -40,6 +40,7 @@
 
 #include <ags/audio/task/ags_notify_soundcard.h>
 #include <ags/audio/task/ags_tic_device.h>
+#include <ags/audio/task/ags_clear_buffer.h>
 #include <ags/audio/task/ags_switch_buffer_flag.h>
 
 #include <ags/audio/thread/ags_audio_loop.h>
@@ -74,6 +75,7 @@ void ags_jack_devout_get_property(GObject *gobject,
 				  GParamSpec *param_spec);
 void ags_jack_devout_disconnect(AgsConnectable *connectable);
 void ags_jack_devout_connect(AgsConnectable *connectable);
+void ags_jack_devout_dispose(GObject *gobject);
 void ags_jack_devout_finalize(GObject *gobject);
 
 void ags_jack_devout_set_application_context(AgsSoundcard *soundcard,
@@ -176,6 +178,7 @@ enum{
   PROP_DELAY_FACTOR,
   PROP_ATTACK,
   PROP_JACK_CLIENT,
+  PROP_JACK_PORT,
   PROP_CHANNEL,
 };
 
@@ -247,6 +250,7 @@ ags_jack_devout_class_init(AgsJackDevoutClass *jack_devout)
   gobject->set_property = ags_jack_devout_set_property;
   gobject->get_property = ags_jack_devout_get_property;
 
+  gobject->dispose = ags_jack_devout_dispose;
   gobject->finalize = ags_jack_devout_finalize;
 
   /* properties */
@@ -470,6 +474,21 @@ ags_jack_devout_class_init(AgsJackDevoutClass *jack_devout)
 				  PROP_JACK_CLIENT,
 				  param_spec);
 
+  /**
+   * AgsJackDevout:jack-port:
+   *
+   * The assigned #AgsJackPort
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("jack-port\0",
+				   "jack port object\0",
+				   "The jack port object\0",
+				   AGS_TYPE_JACK_PORT,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_JACK_PORT,
+				  param_spec);
 
   /**
    * AgsJackDevout:channel:
@@ -980,9 +999,30 @@ ags_jack_devout_set_property(GObject *gobject,
 	g_object_unref(G_OBJECT(jack_devout->jack_client));
       }
 
+      if(jack_client != NULL){
+	g_object_ref(jack_client);
+      }
+      
       jack_devout->jack_client = (GObject *) jack_client;
     }
     break;
+  case PROP_JACK_PORT:
+    {
+      AgsJackPort *jack_port;
+
+      jack_port = (AgsJackPort *) g_value_get_object(value);
+
+      if(g_list_find(jack_devout->jack_port, jack_port) != NULL){
+	return;
+      }
+
+      if(jack_port != NULL){
+	g_object_ref(jack_port);
+	jack_devout->jack_port = g_list_append(jack_devout->jack_port,
+					       jack_port);
+      }
+    }
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
     break;
@@ -1065,6 +1105,12 @@ ags_jack_devout_get_property(GObject *gobject,
       g_value_set_object(value, jack_devout->jack_client);
     }
     break;
+  case PROP_JACK_PORT:
+    {
+      g_value_set_pointer(value,
+			  g_list_copy(jack_devout->jack_port));
+    }
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
     break;
@@ -1072,6 +1118,42 @@ ags_jack_devout_get_property(GObject *gobject,
 }
 
 void
+ags_jack_devout_dispose(GObject *gobject)
+{
+  AgsJackDevout *jack_devout;
+
+  GList *list;
+
+  jack_devout = AGS_JACK_DEVOUT(gobject);
+
+  /* application context */
+  if(jack_devout->application_context != NULL){
+    g_object_unref(jack_devout->application_context);
+
+    jack_devout->application_context = NULL;
+  }
+
+  /* unref audio */
+  if(jack_devout->audio != NULL){
+    list = jack_devout->audio;
+
+    while(list != NULL){
+      g_object_set(G_OBJECT(list->data),
+		   "soundcard\0", NULL,
+		   NULL);
+      
+      list = list->next;
+    }
+
+    g_list_free_full(jack_devout->audio,
+		     g_object_unref);
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_jack_devout_parent_class)->finalize(gobject);
+}
+
+void
 ags_jack_devout_finalize(GObject *gobject)
 {
   AgsJackDevout *jack_devout;
@@ -1104,14 +1186,33 @@ ags_jack_devout_finalize(GObject *gobject)
   /* free AgsAttack */
   free(jack_devout->attack);
 
+  /* unref notify soundcard */
   if(jack_devout->notify_soundcard != NULL){
-    ags_task_thread_remove_cyclic_task(ags_application_context_get_instance()->task_thread,
-				       jack_devout->notify_soundcard);
+    if(jack_devout->application_context != NULL){
+      ags_task_thread_remove_cyclic_task(AGS_APPLICATION_CONTEXT(jack_devout->application_context)->task_thread,
+					 jack_devout->notify_soundcard);
+    }
     
     g_object_unref(jack_devout->notify_soundcard);
   }
+
+  /* application context */
+  if(jack_devout->application_context != NULL){
+    g_object_unref(jack_devout->application_context);
+  }
   
+  /* unref audio */
   if(jack_devout->audio != NULL){
+    list = jack_devout->audio;
+
+    while(list != NULL){
+      g_object_set(G_OBJECT(list->data),
+		   "soundcard\0", NULL,
+		   NULL);
+      
+      list = list->next;
+    }
+
     g_list_free_full(jack_devout->audio,
 		     g_object_unref);
   }
@@ -1609,7 +1710,7 @@ ags_jack_devout_port_play(AgsSoundcard *soundcard,
 {
   AgsJackClient *jack_client;
   AgsJackDevout *jack_devout;
-
+  
   AgsMutexManager *mutex_manager;
   AgsTaskThread *task_thread;
 
@@ -1728,6 +1829,7 @@ ags_jack_devout_port_play(AgsSoundcard *soundcard,
 
   if(task_thread != NULL){
     AgsTicDevice *tic_device;
+    AgsClearBuffer *clear_buffer;
     AgsSwitchBufferFlag *switch_buffer_flag;
       
     GList *task;
@@ -1737,8 +1839,13 @@ ags_jack_devout_port_play(AgsSoundcard *soundcard,
     /* tic soundcard */
     tic_device = ags_tic_device_new((GObject *) jack_devout);
     task = g_list_append(task,
-			 tic_device);
-  
+    			 tic_device);
+
+    /* reset - clear buffer */
+    clear_buffer = ags_clear_buffer_new((GObject *) jack_devout);
+    task = g_list_append(task,
+			 clear_buffer); 
+    
     /* reset - switch buffer flags */
     switch_buffer_flag = ags_switch_buffer_flag_new((GObject *) jack_devout);
     task = g_list_append(task,
@@ -1748,9 +1855,57 @@ ags_jack_devout_port_play(AgsSoundcard *soundcard,
     ags_task_thread_append_tasks((AgsTaskThread *) task_thread,
 				 task);
   }else{
+    guint nth_buffer;
+    guint word_size;
+    
     /* tic */
     ags_soundcard_tic(AGS_SOUNDCARD(jack_devout));
-	  
+
+    switch(jack_devout->format){
+    case AGS_SOUNDCARD_SIGNED_8_BIT:
+      {
+	word_size = sizeof(signed char);
+      }
+      break;
+    case AGS_SOUNDCARD_SIGNED_16_BIT:
+      {
+	word_size = sizeof(signed short);
+      }
+      break;
+    case AGS_SOUNDCARD_SIGNED_24_BIT:
+      {
+	//NOTE:JK: The 24-bit linear samples use 32-bit physical space
+	word_size = sizeof(signed long);
+      }
+      break;
+    case AGS_SOUNDCARD_SIGNED_32_BIT:
+      {
+	word_size = sizeof(signed long);
+      }
+      break;
+    case AGS_SOUNDCARD_SIGNED_64_BIT:
+      {
+	word_size = sizeof(signed long long);
+      }
+      break;
+    default:
+      g_warning("ags_jack_devout_port_play(): unsupported word size\0");
+      return;
+    }
+        
+    /* reset - clear buffer */
+    if((AGS_JACK_DEVOUT_BUFFER0 & (jack_devout->flags)) != 0){
+      nth_buffer = 3;
+    }else if((AGS_JACK_DEVOUT_BUFFER1 & (jack_devout->flags)) != 0){
+      nth_buffer = 0;
+    }else if((AGS_JACK_DEVOUT_BUFFER2 & (jack_devout->flags)) != 0){
+      nth_buffer = 1;
+    }else if((AGS_JACK_DEVOUT_BUFFER3 & jack_devout->flags) != 0){
+      nth_buffer = 2;
+    }
+    
+    memset(jack_devout->buffer[nth_buffer], 0, (size_t) jack_devout->pcm_channels * jack_devout->buffer_size * word_size);
+    
     /* reset - switch buffer flags */
     ags_jack_devout_switch_buffer_flag(jack_devout);
   }
diff --git a/ags/audio/jack/ags_jack_midiin.c b/ags/audio/jack/ags_jack_midiin.c
index 860abf5..e700fc5 100644
--- a/ags/audio/jack/ags_jack_midiin.c
+++ b/ags/audio/jack/ags_jack_midiin.c
@@ -73,6 +73,7 @@ void ags_jack_midiin_get_property(GObject *gobject,
 				  GParamSpec *param_spec);
 void ags_jack_midiin_disconnect(AgsConnectable *connectable);
 void ags_jack_midiin_connect(AgsConnectable *connectable);
+void ags_jack_midiin_dispose(GObject *gobject);
 void ags_jack_midiin_finalize(GObject *gobject);
 
 void ags_jack_midiin_switch_buffer_flag(AgsJackMidiin *jack_midiin);
@@ -136,6 +137,7 @@ enum{
   PROP_DELAY_FACTOR,
   PROP_ATTACK,
   PROP_JACK_CLIENT,
+  PROP_JACK_PORT,
 };
 
 enum{
@@ -206,6 +208,7 @@ ags_jack_midiin_class_init(AgsJackMidiinClass *jack_midiin)
   gobject->set_property = ags_jack_midiin_set_property;
   gobject->get_property = ags_jack_midiin_get_property;
 
+  gobject->dispose = ags_jack_midiin_dispose;
   gobject->finalize = ags_jack_midiin_finalize;
 
   /* properties */
@@ -339,6 +342,22 @@ ags_jack_midiin_class_init(AgsJackMidiinClass *jack_midiin)
 				  PROP_JACK_CLIENT,
 				  param_spec);
 
+  /**
+   * AgsJackMidiin:jack-port:
+   *
+   * The assigned #AgsJackPort
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("jack-port\0",
+				   "jack port object\0",
+				   "The jack port object\0",
+				   AGS_TYPE_JACK_PORT,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_JACK_PORT,
+				  param_spec);
+
   /* AgsJackMidiinClass */
 }
 
@@ -602,9 +621,30 @@ ags_jack_midiin_set_property(GObject *gobject,
 	g_object_unref(G_OBJECT(jack_midiin->jack_client));
       }
 
+      if(jack_client != NULL){
+	g_object_ref(G_OBJECT(jack_client));
+      }
+
       jack_midiin->jack_client = (GObject *) jack_client;
     }
     break;
+  case PROP_JACK_PORT:
+    {
+      AgsJackPort *jack_port;
+
+      jack_port = (AgsJackPort *) g_value_get_object(value);
+
+      if(g_list_find(jack_midiin->jack_port, jack_port) != NULL){
+	return;
+      }
+
+      if(jack_port != NULL){
+	g_object_ref(jack_port);
+	jack_midiin->jack_port = g_list_append(jack_midiin->jack_port,
+					       jack_port);
+      }
+    }
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
     break;
@@ -657,6 +697,12 @@ ags_jack_midiin_get_property(GObject *gobject,
       g_value_set_object(value, jack_midiin->jack_client);
     }
     break;
+  case PROP_JACK_PORT:
+    {
+      g_value_set_pointer(value,
+			  g_list_copy(jack_midiin->jack_port));
+    }
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
     break;
@@ -664,13 +710,44 @@ ags_jack_midiin_get_property(GObject *gobject,
 }
 
 void
+ags_jack_midiin_dispose(GObject *gobject)
+{
+  AgsJackMidiin *jack_midiin;
+
+  GList *list;
+
+  jack_midiin = AGS_JACK_MIDIIN(gobject);
+
+  /* audio */
+  if(jack_midiin->audio != NULL){
+    list = jack_midiin->audio;
+
+    while(list != NULL){
+      g_object_set(list->data,
+		   "sequencer\0", NULL,
+		   NULL);
+
+      list = list->next;
+    }
+
+    g_list_free_full(jack_midiin->audio,
+		     g_object_unref);
+
+    jack_midiin->audio = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_jack_midiin_parent_class)->dispose(gobject);
+}
+
+void
 ags_jack_midiin_finalize(GObject *gobject)
 {
   AgsJackMidiin *jack_midiin;
 
   AgsMutexManager *mutex_manager;
   
-  GList *list, *list_next;
+  GList *list;
 
   jack_midiin = AGS_JACK_MIDIIN(gobject);
 
@@ -704,7 +781,18 @@ ags_jack_midiin_finalize(GObject *gobject)
   /* free buffer array */
   free(jack_midiin->buffer);
 
+  /* audio */
   if(jack_midiin->audio != NULL){
+    list = jack_midiin->audio;
+
+    while(list != NULL){
+      g_object_set(list->data,
+		   "sequencer\0", NULL,
+		   NULL);
+
+      list = list->next;
+    }
+
     g_list_free_full(jack_midiin->audio,
 		     g_object_unref);
   }
@@ -1231,6 +1319,8 @@ ags_jack_midiin_port_free(AgsSequencer *sequencer)
   pthread_mutex_t *mutex;
   pthread_mutex_t *callback_mutex;
   pthread_mutex_t *callback_finish_mutex;
+
+  jack_midiin = AGS_JACK_MIDIIN(sequencer);
   
   application_context = ags_sequencer_get_application_context(sequencer);
   
@@ -1245,8 +1335,6 @@ ags_jack_midiin_port_free(AgsSequencer *sequencer)
 
   pthread_mutex_lock(mutex);
 
-  jack_midiin = AGS_JACK_MIDIIN(sequencer);
-
   if((AGS_JACK_MIDIIN_INITIALIZED & (jack_midiin->flags)) == 0){
     pthread_mutex_unlock(mutex);
     
diff --git a/ags/audio/jack/ags_jack_port.c b/ags/audio/jack/ags_jack_port.c
index af841df..638f7ce 100644
--- a/ags/audio/jack/ags_jack_port.c
+++ b/ags/audio/jack/ags_jack_port.c
@@ -49,6 +49,7 @@ void ags_jack_port_get_property(GObject *gobject,
 				GParamSpec *param_spec);
 void ags_jack_port_connect(AgsConnectable *connectable);
 void ags_jack_port_disconnect(AgsConnectable *connectable);
+void ags_jack_port_dispose(GObject *gobject);
 void ags_jack_port_finalize(GObject *gobject);
 
 /**
@@ -121,6 +122,7 @@ ags_jack_port_class_init(AgsJackPortClass *jack_port)
   gobject->set_property = ags_jack_port_set_property;
   gobject->get_property = ags_jack_port_get_property;
 
+  gobject->dispose = ags_jack_port_dispose;
   gobject->finalize = ags_jack_port_finalize;
 
   /* properties */
@@ -269,13 +271,50 @@ ags_jack_port_get_property(GObject *gobject,
 void
 ags_jack_port_connect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsJackPort *jack_port;
+
+  jack_port = AGS_JACK_PORT(connectable);
+
+  if((AGS_JACK_PORT_CONNECTED & (jack_port->flags)) != 0){
+    return;
+  }
+
+  jack_port->flags |= AGS_JACK_PORT_CONNECTED;
 }
 
 void
 ags_jack_port_disconnect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsJackPort *jack_port;
+
+  jack_port = AGS_JACK_PORT(connectable);
+
+  if((AGS_JACK_PORT_CONNECTED & (jack_port->flags)) == 0){
+    return;
+  }
+
+  jack_port->flags &= (~AGS_JACK_PORT_CONNECTED);
+}
+
+void
+ags_jack_port_dispose(GObject *gobject)
+{
+  AgsJackPort *jack_port;
+
+  jack_port = AGS_JACK_PORT(gobject);
+
+  /* jack client */
+  if(jack_port->jack_client != NULL){
+    g_object_unref(jack_port->jack_client);
+
+    jack_port->jack_client = NULL;
+  }
+
+  /* name */
+  g_free(jack_port->name);
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_jack_port_parent_class)->dispose(gobject);
 }
 
 void
@@ -285,12 +324,15 @@ ags_jack_port_finalize(GObject *gobject)
 
   jack_port = AGS_JACK_PORT(gobject);
 
+  /* jack client */
   if(jack_port->jack_client != NULL){
     g_object_unref(jack_port->jack_client);
   }
-  
+
+  /* name */
   g_free(jack_port->name);
-  
+
+  /* call parent */
   G_OBJECT_CLASS(ags_jack_port_parent_class)->finalize(gobject);
 }
 
diff --git a/ags/audio/jack/ags_jack_server.c b/ags/audio/jack/ags_jack_server.c
index b0d657b..4893b9e 100644
--- a/ags/audio/jack/ags_jack_server.c
+++ b/ags/audio/jack/ags_jack_server.c
@@ -48,6 +48,7 @@ void ags_jack_server_get_property(GObject *gobject,
 				  GParamSpec *param_spec);
 void ags_jack_server_connect(AgsConnectable *connectable);
 void ags_jack_server_disconnect(AgsConnectable *connectable);
+void ags_jack_server_dispose(GObject *gobject);
 void ags_jack_server_finalize(GObject *gobject);
 
 void ags_jack_server_set_url(AgsDistributedManager *distributed_manager,
@@ -90,6 +91,9 @@ enum{
   PROP_0,
   PROP_APPLICATION_CONTEXT,
   PROP_URL,
+  PROP_DEFAULT_SOUNDCARD,
+  PROP_DEFAULT_JACK_CLIENT,
+  PROP_JACK_CLIENT,
 };
 
 static gpointer ags_jack_server_parent_class = NULL;
@@ -155,6 +159,7 @@ ags_jack_server_class_init(AgsJackServerClass *jack_server)
   gobject->set_property = ags_jack_server_set_property;
   gobject->get_property = ags_jack_server_get_property;
 
+  gobject->dispose = ags_jack_server_dispose;
   gobject->finalize = ags_jack_server_finalize;
 
   /* properties */
@@ -189,6 +194,54 @@ ags_jack_server_class_init(AgsJackServerClass *jack_server)
   g_object_class_install_property(gobject,
 				  PROP_URL,
 				  param_spec);
+
+  /**
+   * AgsJackServer:default-soundcard:
+   *
+   * The default soundcard.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("default-soundcard\0",
+				   "default soundcard\0",
+				   "The default soundcard\0",
+				   G_TYPE_OBJECT,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_DEFAULT_SOUNDCARD,
+				  param_spec);
+
+  /**
+   * AgsJackServer:default-jack-client:
+   *
+   * The default jack client.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("default-jack-client\0",
+				   "default jack client\0",
+				   "The default jack client\0",
+				   AGS_TYPE_JACK_CLIENT,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_DEFAULT_JACK_CLIENT,
+				  param_spec);
+
+  /**
+   * AgsJackServer:jack-client:
+   *
+   * The jack client list.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("jack-client\0",
+				   "jack client list\0",
+				   "The jack client list\0",
+				   AGS_TYPE_JACK_CLIENT,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_JACK_CLIENT,
+				  param_spec);
 }
 
 void
@@ -290,6 +343,66 @@ ags_jack_server_set_property(GObject *gobject,
       jack_server->url = g_strdup(url);
     }
     break;
+  case PROP_DEFAULT_SOUNDCARD:
+    {
+      GObject *default_soundcard;
+
+      default_soundcard = (GObject *) g_value_get_object(value);
+
+      if(jack_server->default_soundcard == (GObject *) default_soundcard){
+	return;
+      }
+
+      if(jack_server->default_soundcard != NULL){
+	g_object_unref(G_OBJECT(jack_server->default_soundcard));
+      }
+
+      if(default_soundcard != NULL){
+	g_object_ref(G_OBJECT(default_soundcard));
+      }
+
+      jack_server->default_soundcard = (GObject *) default_soundcard;
+    }
+    break;
+  case PROP_DEFAULT_JACK_CLIENT:
+    {
+      AgsJackClient *default_client;
+
+      default_client = (AgsJackClient *) g_value_get_object(value);
+
+      if(jack_server->default_client == (GObject *) default_client){
+	return;
+      }
+
+      if(jack_server->default_client != NULL){
+	g_object_unref(G_OBJECT(jack_server->default_client));
+      }
+
+      if(default_client != NULL){
+	g_object_ref(G_OBJECT(default_client));
+      }
+
+      jack_server->default_client = (GObject *) default_client;
+    }
+    break;
+  case PROP_JACK_CLIENT:
+    {
+      GObject *client;
+
+      client = (GObject *) g_value_get_object(value);
+
+      if(g_list_find(jack_server->client, client) != NULL){
+	return;
+      }
+
+      if(client != NULL){
+	g_object_ref(G_OBJECT(client));
+
+	jack_server->client = g_list_prepend(jack_server->client,
+					     client);
+      }
+    }
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
     break;
@@ -317,6 +430,22 @@ ags_jack_server_get_property(GObject *gobject,
       g_value_set_string(value, jack_server->url);
     }
     break;
+  case PROP_DEFAULT_SOUNDCARD:
+    {
+      g_value_set_object(value, jack_server->default_soundcard);
+    }
+    break;
+  case PROP_DEFAULT_JACK_CLIENT:
+    {
+      g_value_set_object(value, jack_server->default_soundcard);
+    }
+    break;
+  case PROP_JACK_CLIENT:
+    {
+      g_value_set_pointer(value,
+			  g_list_copy(jack_server->client));
+    }
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
     break;
@@ -326,28 +455,133 @@ ags_jack_server_get_property(GObject *gobject,
 void
 ags_jack_server_connect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsJackServer *jack_server;
+
+  GList *list;
+  
+  jack_server = AGS_JACK_SERVER(connectable);
+
+  if((AGS_JACK_SERVER_CONNECTED & (jack_server->flags)) != 0){
+    return;
+  }
+
+  jack_server->flags |= AGS_JACK_SERVER_CONNECTED;
+
+  list = jack_server->client;
+
+  while(list != NULL){
+    ags_connectable_connect(AGS_CONNECTABLE(list->data));
+
+    list = list->next;
+  }
 }
 
 void
 ags_jack_server_disconnect(AgsConnectable *connectable)
 {
-  /* empty */
+  AgsJackServer *jack_server;
+
+  GList *list;
+  
+  jack_server = AGS_JACK_SERVER(connectable);
+
+  if((AGS_JACK_SERVER_CONNECTED & (jack_server->flags)) != 0){
+    return;
+  }
+
+  jack_server->flags |= AGS_JACK_SERVER_CONNECTED;
+
+  list = jack_server->client;
+
+  while(list != NULL){
+    ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
+
+    list = list->next;
+  }
 }
 
 void
-ags_jack_server_finalize(GObject *gobject)
+ags_jack_server_dispose(GObject *gobject)
 {
   AgsJackServer *jack_server;
 
+  GList *list;
+  
   jack_server = AGS_JACK_SERVER(gobject);
 
+  /* application context */
   if(jack_server->application_context != NULL){
+    g_object_unref(G_OBJECT(jack_server->application_context));
+    
     jack_server->application_context = NULL;
   }
 
+  /* default soundcard */
+  if(jack_server->default_soundcard != NULL){
+    g_object_unref(G_OBJECT(jack_server->default_soundcard));
+
+    jack_server->default_soundcard = NULL;
+  }
+  
+  /* default client */
+  if(jack_server->default_client != NULL){
+    g_object_unref(G_OBJECT(jack_server->default_client));
+
+    jack_server->default_client = NULL;
+  }
+  
+  /* client */
+  if(jack_server->client != NULL){
+    list = jack_server->client;
+
+    while(list != NULL){
+      g_object_run_dispose(G_OBJECT(list->data));
+
+      list = list->next;
+    }
+    
+    g_list_free_full(jack_server->client,
+		     g_object_unref);
+
+    jack_server->client = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_jack_server_parent_class)->finalize(gobject);
+}
+
+void
+ags_jack_server_finalize(GObject *gobject)
+{
+  AgsJackServer *jack_server;
+
+  jack_server = AGS_JACK_SERVER(gobject);
+
+  /* application context */
+  if(jack_server->application_context != NULL){
+    g_object_unref(G_OBJECT(jack_server->application_context));
+  }
+
+  /* url */
   g_free(jack_server->url);
+
+  /* default soundcard */
+  if(jack_server->default_soundcard != NULL){
+    g_object_unref(G_OBJECT(jack_server->default_soundcard));
+  }
   
+  /* default client */
+  if(jack_server->default_client != NULL){
+    g_object_unref(G_OBJECT(jack_server->default_client));
+  }
+  
+  /* client */
+  if(jack_server->client != NULL){
+    g_list_free_full(jack_server->client,
+		     g_object_unref);
+  }
+  
+  /* call parent */
   G_OBJECT_CLASS(ags_jack_server_parent_class)->finalize(gobject);
 }
 
@@ -518,7 +752,9 @@ ags_jack_server_register_soundcard(AgsDistributedManager *distributed_manager,
   
   /* the default client */
   if(jack_server->default_client == NULL){
-    jack_server->default_client = ags_jack_client_new((GObject *) jack_server);
+    g_object_set(jack_server,
+		 "default-jack-client\0", ags_jack_client_new((GObject *) jack_server),
+		 NULL);
     ags_jack_server_add_client(jack_server,
 			       jack_server->default_client);
     
@@ -543,10 +779,10 @@ ags_jack_server_register_soundcard(AgsDistributedManager *distributed_manager,
 		 "device\0", str,
 		 NULL);
     g_free(str);
-    g_object_ref(jack_devout);
-    default_client->device = g_list_prepend(default_client->device,
-					    jack_devout);
-
+    g_object_set(default_client,
+		 "device\0", jack_devout,
+		 NULL);
+    
     if(initial_set &&
        default_client->client != NULL){
       rc = jack_set_buffer_size(default_client->client,
@@ -562,7 +798,7 @@ ags_jack_server_register_soundcard(AgsDistributedManager *distributed_manager,
       str = g_strdup_printf("ags-soundcard%d-%04d\0",
 			    jack_server->n_soundcards,
 			    i);
-
+      
 #ifdef AGS_DEBUG
       g_message("%s\0", str);
 #endif
@@ -571,8 +807,9 @@ ags_jack_server_register_soundcard(AgsDistributedManager *distributed_manager,
       ags_jack_client_add_port(default_client,
 			       (GObject *) jack_port);
 
-      jack_devout->jack_port = g_list_append(jack_devout->jack_port,
-					     jack_port);
+      g_object_set(jack_devout,
+		   "jack-port\0", jack_port,
+		   NULL);
       
       if(jack_devout->port_name == NULL){
 	jack_devout->port_name = (gchar **) malloc(2 * sizeof(gchar *));
@@ -630,6 +867,9 @@ ags_jack_server_unregister_soundcard(AgsDistributedManager *distributed_manager,
     list = list->next;
   }
 
+  ags_jack_client_remove_device(default_client,
+				soundcard);
+  
   if(default_client->port == NULL){
     jack_server->n_soundcards = 0;
   }
@@ -654,7 +894,9 @@ ags_jack_server_register_sequencer(AgsDistributedManager *distributed_manager,
   
   /* the default client */
   if(jack_server->default_client == NULL){
-    jack_server->default_client = (GObject *) ags_jack_client_new((GObject *) jack_server);
+    g_object_set(jack_server,
+		 "default-jack-client\0", (GObject *) ags_jack_client_new((GObject *) jack_server),
+		 NULL);
     ags_jack_server_add_client(jack_server,
 			       jack_server->default_client);
     
@@ -675,9 +917,9 @@ ags_jack_server_register_sequencer(AgsDistributedManager *distributed_manager,
 	       "jack-client\0", default_client,
 	       "device\0", str,
 	       NULL);
-  g_object_ref(jack_midiin);
-  default_client->device = g_list_prepend(default_client->device,
-					  jack_midiin);
+  g_object_set(default_client,
+	       "device\0", jack_midiin,
+	       NULL);
 
   /* register sequencer */
   str = g_strdup_printf("ags-sequencer%d\0",
@@ -691,8 +933,9 @@ ags_jack_server_register_sequencer(AgsDistributedManager *distributed_manager,
   ags_jack_client_add_port(default_client,
 			   (GObject *) jack_port);
 
-  jack_midiin->jack_port = g_list_append(jack_midiin->jack_port,
-					 jack_port);
+  g_object_set(jack_midiin,
+	       "jack-port\0", jack_port,
+	       NULL);
   
   ags_jack_port_register(jack_port,
 			 str,
@@ -735,6 +978,9 @@ ags_jack_server_unregister_sequencer(AgsDistributedManager *distributed_manager,
     list = list->next;
   }
 
+  ags_jack_client_remove_device(default_client,
+				sequencer);
+  
   if(default_client->port == NULL){
     jack_server->n_sequencers = 0;
   }
@@ -754,7 +1000,9 @@ ags_jack_server_register_default_soundcard(AgsJackServer *jack_server)
   
   /* the default client */
   if(jack_server->default_client == NULL){
-    jack_server->default_client = (GObject *) ags_jack_client_new((GObject *) jack_server);
+    g_object_set(jack_server,
+		 "default-jack-client\0", (GObject *) ags_jack_client_new((GObject *) jack_server),
+		 NULL);
     ags_jack_server_add_client(jack_server,
 			       jack_server->default_client);
     
@@ -776,8 +1024,9 @@ ags_jack_server_register_default_soundcard(AgsJackServer *jack_server)
 	       "jack-client\0", default_client,
 	       "device\0", "ags-default-devout\0",
 	       NULL);
-  default_client->device = g_list_prepend(default_client->device,
-					  jack_devout);
+  g_object_set(default_client,
+	       "device\0", jack_devout,
+	       NULL);
 
   if(default_client->client != NULL){
     rc = jack_set_buffer_size(default_client->client,
@@ -801,8 +1050,9 @@ ags_jack_server_register_default_soundcard(AgsJackServer *jack_server)
     ags_jack_client_add_port(default_client,
 			     (GObject *) jack_port);
 
-    jack_devout->jack_port = g_list_prepend(jack_devout->jack_port,
-					    jack_port);
+    g_object_set(jack_devout,
+		 "jack-port\0", jack_port,
+		 NULL);
 
     if(jack_devout->port_name == NULL){
       jack_devout->port_name = (gchar **) malloc(2 * sizeof(gchar *));
diff --git a/ags/audio/midi/ags_midi_builder.h b/ags/audio/midi/ags_midi_builder.h
index 152c18f..82c8076 100644
--- a/ags/audio/midi/ags_midi_builder.h
+++ b/ags/audio/midi/ags_midi_builder.h
@@ -46,7 +46,7 @@ typedef struct _AgsMidiBuilderTrack AgsMidiBuilderTrack;
 
 typedef enum{
   AGS_MIDI_BUILDER_EOF            = 1,
-  AGS_MIDI_PARSER_EOT             = 1 << 1,
+  AGS_MIDI_BUILDER_EOT            = 1 << 1,
 }AgsMidiBuilderFlags;
 
 struct _AgsMidiBuilder
diff --git a/ags/audio/recall/ags_buffer_audio_signal.c b/ags/audio/recall/ags_buffer_audio_signal.c
index 8b1a05f..a9cd054 100644
--- a/ags/audio/recall/ags_buffer_audio_signal.c
+++ b/ags/audio/recall/ags_buffer_audio_signal.c
@@ -164,10 +164,6 @@ ags_buffer_audio_signal_init(AgsBufferAudioSignal *buffer_audio_signal)
 void
 ags_buffer_audio_signal_finalize(GObject *gobject)
 {
-  if(AGS_RECALL_AUDIO_SIGNAL(gobject)->destination != NULL){
-    g_object_unref(AGS_RECALL_AUDIO_SIGNAL(gobject)->destination);
-  }
-  
   /* call parent */
   G_OBJECT_CLASS(ags_buffer_audio_signal_parent_class)->finalize(gobject); 
 }
@@ -350,11 +346,16 @@ ags_buffer_audio_signal_run_inter(AgsRecall *recall)
   //FIXME:JK: attack probably needs to be removed
   destination = AGS_RECALL_AUDIO_SIGNAL(buffer_audio_signal)->destination;
 
-  g_value_init(&value, G_TYPE_BOOLEAN);
+  g_value_init(&value, G_TYPE_FLOAT);
   ags_port_safe_read(buffer_channel->muted,
 		     &value);
 
-  muted = g_value_get_boolean(&value);
+  if(g_value_get_float(&value) == 0.0){
+    muted = FALSE;
+  }else{
+    muted = TRUE;
+  }
+  
   g_value_unset(&value);
 
   if(muted){
diff --git a/ags/audio/recall/ags_buffer_audio_signal.h b/ags/audio/recall/ags_buffer_audio_signal.h
index c069f62..bd6c28c 100644
--- a/ags/audio/recall/ags_buffer_audio_signal.h
+++ b/ags/audio/recall/ags_buffer_audio_signal.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/audio/recall/ags_buffer_channel.c b/ags/audio/recall/ags_buffer_channel.c
index cc89437..456404c 100644
--- a/ags/audio/recall/ags_buffer_channel.c
+++ b/ags/audio/recall/ags_buffer_channel.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -23,6 +23,8 @@
 #include <ags/object/ags_mutable.h>
 #include <ags/object/ags_plugin.h>
 
+#include <ags/plugin/ags_base_plugin.h>
+
 void ags_buffer_channel_class_init(AgsBufferChannelClass *buffer_channel);
 void ags_buffer_channel_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_buffer_channel_mutable_interface_init(AgsMutableInterface *mutable);
@@ -39,10 +41,13 @@ void ags_buffer_channel_get_property(GObject *gobject,
 void ags_buffer_channel_connect(AgsConnectable *connectable);
 void ags_buffer_channel_disconnect(AgsConnectable *connectable);
 void ags_buffer_channel_set_ports(AgsPlugin *plugin, GList *port);
+void ags_buffer_channel_dispose(GObject *gobject);
 void ags_buffer_channel_finalize(GObject *gobject);
 
 void ags_buffer_channel_set_muted(AgsMutable *mutable, gboolean muted);
 
+static AgsPortDescriptor* ags_buffer_channel_get_muted_port_descriptor();
+
 /**
  * SECTION:ags_buffer_channel
  * @short_description: buffers channel
@@ -168,9 +173,17 @@ ags_buffer_channel_class_init(AgsBufferChannelClass *buffer_channel)
   gobject->set_property = ags_buffer_channel_set_property;
   gobject->get_property = ags_buffer_channel_get_property;
 
+  gobject->dispose = ags_buffer_channel_dispose;
   gobject->finalize = ags_buffer_channel_finalize;
 
   /* properties */
+  /**
+   * AgsBufferChannel:muted:
+   *
+   * The mute port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("muted\0",
 				   "mute channel\0",
 				   "Mute the channel\0",
@@ -198,13 +211,19 @@ ags_buffer_channel_init(AgsBufferChannel *buffer_channel)
 				     "specifier\0", ags_buffer_channel_plugin_specifier[0],
 				     "control-port\0", ags_buffer_channel_plugin_control_port[0],
 				     "port-value-is-pointer\0", FALSE,
-				     "port-value-type\0", G_TYPE_BOOLEAN,
-				     "port-value-size\0", sizeof(gboolean),
+				     "port-value-type\0", G_TYPE_FLOAT,
+				     "port-value-size\0", sizeof(gfloat),
 				     "port-value-length\0", 1,
 				     NULL);
-  buffer_channel->muted->port_value.ags_port_boolean = FALSE;
+  g_object_ref(buffer_channel->muted);
+  buffer_channel->muted->port_value.ags_port_float = (float) FALSE;
 
+  /* port descriptor */
+  buffer_channel->muted->port_descriptor = ags_buffer_channel_get_muted_port_descriptor();
+
+  /* add to port */
   port = g_list_prepend(port, buffer_channel->muted);
+  g_object_ref(buffer_channel->muted);
 
   /* set port */
   AGS_RECALL(buffer_channel)->port = port;
@@ -273,6 +292,23 @@ ags_buffer_channel_get_property(GObject *gobject,
 }
 
 void
+ags_buffer_channel_dispose(GObject *gobject)
+{
+  AgsBufferChannel *buffer_channel;
+
+  buffer_channel = AGS_BUFFER_CHANNEL(gobject);
+
+  if(buffer_channel->muted != NULL){
+    g_object_unref(G_OBJECT(buffer_channel->muted));
+
+    buffer_channel->muted = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_buffer_channel_parent_class)->dispose(gobject);
+}
+
+void
 ags_buffer_channel_finalize(GObject *gobject)
 {
   AgsBufferChannel *buffer_channel;
@@ -290,9 +326,20 @@ ags_buffer_channel_finalize(GObject *gobject)
 void
 ags_buffer_channel_connect(AgsConnectable *connectable)
 {
-  ags_buffer_channel_parent_connectable_interface->connect(connectable);
+  AgsRecall *recall;
+  
+  recall = AGS_RECALL(connectable);
+  
+  if((AGS_RECALL_CONNECTED & (recall->flags)) != 0){
+    return;
+  }
 
-  /* empty */
+  /* load automation */
+  ags_recall_load_automation(recall,
+			     g_list_copy(recall->port));
+
+  /* call parent */
+  ags_buffer_channel_parent_connectable_interface->connect(connectable);
 }
 
 void
@@ -324,12 +371,45 @@ ags_buffer_channel_set_muted(AgsMutable *mutable, gboolean muted)
 {
   GValue value = {0,};
 
-  g_value_init(&value, G_TYPE_BOOLEAN);
-  g_value_set_boolean(&value, muted);
+  g_value_init(&value, G_TYPE_FLOAT);
+  g_value_set_float(&value, (float) muted);
 
   ags_port_safe_write(AGS_BUFFER_CHANNEL(mutable)->muted, &value);
 }
 
+static AgsPortDescriptor*
+ags_buffer_channel_get_muted_port_descriptor()
+{
+  static AgsPortDescriptor *port_descriptor = NULL;
+
+  if(port_descriptor == NULL){
+    port_descriptor = ags_port_descriptor_alloc();
+
+    port_descriptor->flags |= (AGS_PORT_DESCRIPTOR_INPUT |
+			       AGS_PORT_DESCRIPTOR_CONTROL |
+			       AGS_PORT_DESCRIPTOR_TOGGLED);
+
+    port_descriptor->port_index = 0;
+
+    /* range */
+    g_value_init(port_descriptor->default_value,
+		 G_TYPE_FLOAT);
+    g_value_init(port_descriptor->lower_value,
+		 G_TYPE_FLOAT);
+    g_value_init(port_descriptor->upper_value,
+		 G_TYPE_FLOAT);
+
+    g_value_set_float(port_descriptor->default_value,
+		      0.0);
+    g_value_set_float(port_descriptor->lower_value,
+		      0.0);
+    g_value_set_float(port_descriptor->upper_value,
+		      1.0);
+  }
+  
+  return(port_descriptor);
+}
+
 /**
  * ags_buffer_channel_new:
  *
diff --git a/ags/audio/recall/ags_buffer_channel.h b/ags/audio/recall/ags_buffer_channel.h
index 4f8a31f..2998ebf 100644
--- a/ags/audio/recall/ags_buffer_channel.h
+++ b/ags/audio/recall/ags_buffer_channel.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/audio/recall/ags_buffer_channel_run.c b/ags/audio/recall/ags_buffer_channel_run.c
index 864c81a..93a253c 100644
--- a/ags/audio/recall/ags_buffer_channel_run.c
+++ b/ags/audio/recall/ags_buffer_channel_run.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/audio/recall/ags_buffer_channel_run.h b/ags/audio/recall/ags_buffer_channel_run.h
index a5629f1..ac31454 100644
--- a/ags/audio/recall/ags_buffer_channel_run.h
+++ b/ags/audio/recall/ags_buffer_channel_run.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/audio/recall/ags_buffer_recycling.c b/ags/audio/recall/ags_buffer_recycling.c
index c6f39a6..626fa37 100644
--- a/ags/audio/recall/ags_buffer_recycling.c
+++ b/ags/audio/recall/ags_buffer_recycling.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/audio/recall/ags_copy_audio_signal.c b/ags/audio/recall/ags_copy_audio_signal.c
index 4e0bddb..5d4fd7a 100644
--- a/ags/audio/recall/ags_copy_audio_signal.c
+++ b/ags/audio/recall/ags_copy_audio_signal.c
@@ -18,6 +18,8 @@
  */
 
 #include <ags/audio/recall/ags_copy_audio_signal.h>
+#include <ags/audio/recall/ags_copy_channel.h>
+#include <ags/audio/recall/ags_copy_recycling.h>
 
 #include <ags/object/ags_connectable.h>
 #include <ags/object/ags_dynamic_connectable.h>
@@ -47,6 +49,8 @@ void ags_copy_audio_signal_connect_dynamic(AgsDynamicConnectable *dynamic_connec
 void ags_copy_audio_signal_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
 void ags_copy_audio_signal_finalize(GObject *gobject);
 
+void ags_copy_audio_signal_run_init_pre(AgsRecall *recall);
+void ags_copy_audio_signal_run_pre(AgsRecall *recall);
 void ags_copy_audio_signal_run_inter(AgsRecall *recall);
 AgsRecall* ags_copy_audio_signal_duplicate(AgsRecall *recall,
 					   AgsRecallID *recall_id,
@@ -129,6 +133,8 @@ ags_copy_audio_signal_class_init(AgsCopyAudioSignalClass *copy_audio_signal)
   /* AgsRecallClass */
   recall = (AgsRecallClass *) copy_audio_signal;
 
+  recall->run_init_pre = ags_copy_audio_signal_run_init_pre;
+  recall->run_pre = ags_copy_audio_signal_run_pre;
   recall->run_inter = ags_copy_audio_signal_run_inter;  
   recall->duplicate = ags_copy_audio_signal_duplicate;
 }
@@ -201,11 +207,113 @@ ags_copy_audio_signal_disconnect_dynamic(AgsDynamicConnectable *dynamic_connecta
 
 void
 ags_copy_audio_signal_finalize(GObject *gobject)
+{  
+  /* call parent */
+  G_OBJECT_CLASS(ags_copy_audio_signal_parent_class)->finalize(gobject);
+}
+void
+ags_copy_audio_signal_run_init_pre(AgsRecall *recall)
 {
-  /* empty */
+  GObject *soundcard;
+  AgsRecycling *recycling;
+  AgsAudioSignal *destination;
+  AgsRecallID *parent_recall_id;
+  AgsRecyclingContext *recycling_context;
+  
+  AgsCopyRecycling *copy_recycling;
+  AgsCopyAudioSignal *copy_audio_signal;
+
+  AgsMutexManager *mutex_manager;
+  
+  GList *stream;
+
+  gdouble delay;
+  guint attack;
+  guint length;
+  
+  pthread_mutex_t *application_mutex;
+  pthread_mutex_t *recycling_mutex;
+  
+  copy_audio_signal = AGS_COPY_AUDIO_SIGNAL(recall);
+  copy_recycling = AGS_COPY_RECYCLING(recall->parent);
+
+  soundcard = AGS_RECALL(copy_audio_signal)->soundcard;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+  
+  /* recycling */
+  recall->flags &= (~AGS_RECALL_PERSISTENT);
+  recycling = AGS_RECALL_RECYCLING(copy_recycling)->destination;
+
+  pthread_mutex_lock(application_mutex);
 
+  recycling_mutex = ags_mutex_manager_lookup(mutex_manager,
+					     (GObject *) recycling);
+	
+  pthread_mutex_unlock(application_mutex);
+
+  /* recycling context */
+  recycling_context = recall->recall_id->recycling_context;
+
+  parent_recall_id = ags_recall_id_find_recycling_context(AGS_RECALL_CHANNEL_RUN(recall->parent->parent)->destination->recall_id,
+							  recycling_context->parent);
+
+  //TODO:JK: unclear
+  attack = 0;
+  delay = 0.0;
+
+  /* create new audio signal */
+  destination = ags_audio_signal_new((GObject *) soundcard,
+				     (GObject *) recycling,
+				     (GObject *) parent_recall_id);
+  
+  g_object_set(copy_audio_signal,
+	       "destination\0", destination,
+	       NULL);  
+  ags_recycling_create_audio_signal_with_defaults(recycling,
+						  destination,
+						  delay, attack);
+  length = 1; // (guint) (2.0 * soundcard->delay[soundcard->tic_counter]) + 1;
+  ags_audio_signal_stream_resize(destination,
+				 length);
+
+  ags_connectable_connect(AGS_CONNECTABLE(destination));
+  
+  destination->stream_current = destination->stream_beginning;
+
+  pthread_mutex_lock(recycling_mutex);
+
+  ags_recycling_add_audio_signal(recycling,
+				 destination);
+
+  pthread_mutex_unlock(recycling_mutex);
+
+#ifdef AGS_DEBUG
+  g_message("copy %x to %x\0", destination, parent_recall_id);
+  g_message("creating destination\0");
+#endif
+  
   /* call parent */
-  G_OBJECT_CLASS(ags_copy_audio_signal_parent_class)->finalize(gobject);
+  AGS_RECALL_CLASS(ags_copy_audio_signal_parent_class)->run_init_pre(recall);
+}
+
+void
+ags_copy_audio_signal_run_pre(AgsRecall *recall)
+{
+  AGS_RECALL_CLASS(ags_copy_audio_signal_parent_class)->run_pre(recall);
+
+  if(AGS_RECALL_AUDIO_SIGNAL(recall)->source->stream_current != NULL){
+    void *buffer;
+
+    guint buffer_size;
+
+    buffer = (signed short *) AGS_RECALL_AUDIO_SIGNAL(recall)->destination->stream_current->data;
+    buffer_size = AGS_RECALL_AUDIO_SIGNAL(recall)->destination->buffer_size;
+
+    ags_audio_buffer_util_clear_buffer(buffer, 1,
+				       buffer_size, ags_audio_buffer_util_format_from_soundcard(AGS_RECALL_AUDIO_SIGNAL(recall)->destination->format));
+  }
 }
 
 void
@@ -230,14 +338,27 @@ ags_copy_audio_signal_run_inter(AgsRecall *recall)
 
   source = AGS_RECALL_AUDIO_SIGNAL(copy_audio_signal)->source;
   stream_source = source->stream_current;
+
+  destination = AGS_RECALL_AUDIO_SIGNAL(copy_audio_signal)->destination;
   
   if(stream_source == NULL){
+    if(destination != NULL){
+      ags_recycling_remove_audio_signal(destination->recycling,
+					destination);
+      g_object_run_dispose(destination);
+      g_object_unref(destination);
+    }
+
     ags_recall_done(recall);
+
+    ags_recycling_remove_audio_signal(source->recycling,
+				      source);
+    g_object_unref(source);
+    
     return;
   }
 
   //FIXME:JK: attack probably needs to be removed
-  destination = AGS_RECALL_AUDIO_SIGNAL(copy_audio_signal)->destination;
 
   if(destination == NULL){
     g_warning("no destination\0");
diff --git a/ags/audio/recall/ags_copy_channel.c b/ags/audio/recall/ags_copy_channel.c
index 71ab02b..1ed38c9 100644
--- a/ags/audio/recall/ags_copy_channel.c
+++ b/ags/audio/recall/ags_copy_channel.c
@@ -39,6 +39,7 @@ void ags_copy_channel_get_property(GObject *gobject,
 void ags_copy_channel_connect(AgsConnectable *connectable);
 void ags_copy_channel_disconnect(AgsConnectable *connectable);
 void ags_copy_channel_set_ports(AgsPlugin *plugin, GList *port);
+void ags_copy_channel_dispose(GObject *gobject);
 void ags_copy_channel_finalize(GObject *gobject);
 
 void ags_copy_channel_set_muted(AgsMutable *mutable, gboolean muted);
@@ -167,9 +168,17 @@ ags_copy_channel_class_init(AgsCopyChannelClass *copy_channel)
   gobject->set_property = ags_copy_channel_set_property;
   gobject->get_property = ags_copy_channel_get_property;
 
+  gobject->dispose = ags_copy_channel_dispose;
   gobject->finalize = ags_copy_channel_finalize;
 
   /* properties */
+  /**
+   * AgsCopyChannel:muted:
+   *
+   * The mute port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("muted\0",
 				   "mute channel\0",
 				   "Mute the channel\0",
@@ -201,9 +210,12 @@ ags_copy_channel_init(AgsCopyChannel *copy_channel)
 				     "port-value-size\0", sizeof(gboolean),
 				     "port-value-length\0", 1,
 				     NULL);
+  g_object_ref(copy_channel->muted);
   copy_channel->muted->port_value.ags_port_boolean = FALSE;
 
+  /* add to port */
   port = g_list_prepend(port, copy_channel->muted);
+  g_object_ref(copy_channel->muted);
 
   /* set port */
   AGS_RECALL(copy_channel)->port = port;
@@ -270,6 +282,23 @@ ags_copy_channel_get_property(GObject *gobject,
 }
 
 void
+ags_copy_channel_dispose(GObject *gobject)
+{
+  AgsCopyChannel *copy_channel;
+
+  copy_channel = AGS_COPY_CHANNEL(gobject);
+
+  if(copy_channel->muted != NULL){
+    g_object_unref(G_OBJECT(copy_channel->muted));
+
+    copy_channel->muted = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_copy_channel_parent_class)->dispose(gobject);
+}
+
+void
 ags_copy_channel_finalize(GObject *gobject)
 {
   AgsCopyChannel *copy_channel;
diff --git a/ags/audio/recall/ags_copy_channel.h b/ags/audio/recall/ags_copy_channel.h
index cbd1c3c..d97d94e 100644
--- a/ags/audio/recall/ags_copy_channel.h
+++ b/ags/audio/recall/ags_copy_channel.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/audio/recall/ags_copy_notation_audio.c b/ags/audio/recall/ags_copy_notation_audio.c
index 5672b99..87a5617 100644
--- a/ags/audio/recall/ags_copy_notation_audio.c
+++ b/ags/audio/recall/ags_copy_notation_audio.c
@@ -29,6 +29,7 @@ void ags_copy_notation_audio_get_property(GObject *gobject,
 					  guint prop_id,
 					  GValue *value,
 					  GParamSpec *param_spec);
+void ags_copy_notation_audio_dispose(GObject *gobject);
 void ags_copy_notation_audio_finalize(GObject *gobject);
 
 /**
@@ -43,7 +44,6 @@ void ags_copy_notation_audio_finalize(GObject *gobject);
 
 enum{
   PROP_0,
-  PROP_DEVOUT,
   PROP_NOTATION,
   PROP_AUDIO_CHANNEL,
 };
@@ -94,6 +94,13 @@ ags_copy_notation_audio_class_init(AgsCopyNotationAudioClass *copy_notation_audi
   gobject->finalize = ags_copy_notation_audio_finalize;
 
   /* properties */
+  /**
+   * AgsCopyNotationAudio:notation:
+   *
+   * The notation.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("notation\0",
 				   "the assigned notation\0",
 				   "The AgsNotation it is assigned to\0",
@@ -103,6 +110,13 @@ ags_copy_notation_audio_class_init(AgsCopyNotationAudioClass *copy_notation_audi
 				  PROP_NOTATION,
 				  param_spec);
 
+  /**
+   * AgsCopyNotationAudio:audio-channel:
+   *
+   * The audio channel.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_uint("audio_channel\0",
 				 "the audio channel to play\0",
 				 "The audio channel to play of audio object\0",
@@ -136,24 +150,6 @@ ags_copy_notation_audio_set_property(GObject *gobject,
   copy_notation_audio = AGS_COPY_NOTATION_AUDIO(gobject);
 
   switch(prop_id){
-  case PROP_DEVOUT:
-    {
-      GObject *soundcard;
-
-      soundcard = (GObject *) g_value_get_object(value);
-
-      if(copy_notation_audio->soundcard != soundcard)
-	return;
-
-      if(copy_notation_audio->soundcard != NULL)
-	g_object_unref(copy_notation_audio->soundcard);
-
-      if(soundcard != NULL)
-	g_object_ref(soundcard);
-
-      copy_notation_audio->soundcard = soundcard;
-    }
-    break;
   case PROP_NOTATION:
     {
       AgsNotation *notation;
@@ -197,11 +193,6 @@ ags_copy_notation_audio_get_property(GObject *gobject,
   copy_notation_audio = AGS_COPY_NOTATION_AUDIO(gobject);
 
   switch(prop_id){
-  case PROP_DEVOUT:
-    {
-      g_value_set_object(value, copy_notation_audio->soundcard);
-    }
-    break;
   case PROP_NOTATION:
     {
       g_value_set_object(value, copy_notation_audio->notation);
@@ -218,8 +209,35 @@ ags_copy_notation_audio_get_property(GObject *gobject,
 }
 
 void
+ags_copy_notation_audio_dispose(GObject *gobject)
+{
+  AgsCopyNotationAudio *copy_notation_audio;
+
+  copy_notation_audio = AGS_COPY_NOTATION_AUDIO(gobject);
+  
+  /* notation */
+  if(copy_notation_audio->notation != NULL){
+    g_object_unref(copy_notation_audio->notation);
+
+    copy_notation_audio->notation = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_copy_notation_audio_parent_class)->dispose(gobject);
+}
+
+void
 ags_copy_notation_audio_finalize(GObject *gobject)
 {
+  AgsCopyNotationAudio *copy_notation_audio;
+
+  copy_notation_audio = AGS_COPY_NOTATION_AUDIO(gobject);
+  
+  /* notation */
+  if(copy_notation_audio->notation != NULL){
+    g_object_unref(copy_notation_audio->notation);
+  }
+
   /* call parent */
   G_OBJECT_CLASS(ags_copy_notation_audio_parent_class)->finalize(gobject);
 }
diff --git a/ags/audio/recall/ags_copy_notation_audio.h b/ags/audio/recall/ags_copy_notation_audio.h
index 6311197..3974f82 100644
--- a/ags/audio/recall/ags_copy_notation_audio.h
+++ b/ags/audio/recall/ags_copy_notation_audio.h
@@ -46,8 +46,6 @@ struct _AgsCopyNotationAudio
 
   guint flags;
 
-  GObject *soundcard;
-
   AgsNotation *notation;
   guint audio_channel;
 };
diff --git a/ags/audio/recall/ags_copy_notation_audio_run.c b/ags/audio/recall/ags_copy_notation_audio_run.c
index d0885a6..40f0f24 100644
--- a/ags/audio/recall/ags_copy_notation_audio_run.c
+++ b/ags/audio/recall/ags_copy_notation_audio_run.c
@@ -42,6 +42,7 @@ void ags_copy_notation_audio_run_connect(AgsConnectable *connectable);
 void ags_copy_notation_audio_run_disconnect(AgsConnectable *connectable);
 void ags_copy_notation_audio_run_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
 void ags_copy_notation_audio_run_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+void ags_copy_notation_audio_run_dispose(GObject *gobject);
 void ags_copy_notation_audio_run_finalize(GObject *gobject);
 
 void ags_copy_notation_audio_run_resolve_dependencies(AgsRecall *recall);
@@ -135,6 +136,7 @@ ags_copy_notation_audio_run_class_init(AgsCopyNotationAudioRunClass *copy_notati
   gobject->set_property = ags_copy_notation_audio_run_set_property;
   gobject->get_property = ags_copy_notation_audio_run_get_property;
 
+  gobject->dispose = ags_copy_notation_audio_run_dispose;
   gobject->finalize = ags_copy_notation_audio_run_finalize;
 
   /* properties */
@@ -259,15 +261,35 @@ ags_copy_notation_audio_run_get_property(GObject *gobject,
 }
 
 void
-ags_copy_notation_audio_run_finalize(GObject *gobject)
+ags_copy_notation_audio_run_dispose(GObject *gobject)
 {
   AgsCopyNotationAudioRun *copy_notation_audio_run;
 
   copy_notation_audio_run = AGS_COPY_NOTATION_AUDIO_RUN(gobject);
 
-  if(copy_notation_audio_run->count_beats_audio_run != NULL)
+  /* count beats audio run */
+  if(copy_notation_audio_run->count_beats_audio_run != NULL){
     g_object_unref(copy_notation_audio_run->count_beats_audio_run);
 
+    copy_notation_audio_run->count_beats_audio_run = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_copy_notation_audio_run_parent_class)->dispose(gobject);
+}
+
+void
+ags_copy_notation_audio_run_finalize(GObject *gobject)
+{
+  AgsCopyNotationAudioRun *copy_notation_audio_run;
+
+  copy_notation_audio_run = AGS_COPY_NOTATION_AUDIO_RUN(gobject);
+
+  /* count beats audio run */
+  if(copy_notation_audio_run->count_beats_audio_run != NULL){
+    g_object_unref(copy_notation_audio_run->count_beats_audio_run);
+  }
+  
   /* call parent */
   G_OBJECT_CLASS(ags_copy_notation_audio_run_parent_class)->finalize(gobject);
 }
@@ -434,12 +456,12 @@ ags_copy_notation_audio_run_tic_alloc_input_callback(AgsDelayAudioRun *delay_aud
 
 	while(recycling != last_recycling->next){
 	  if((AGS_COPY_NOTATION_AUDIO_FIT_AUDIO_SIGNAL & (copy_notation_audio->flags)) != 0){
-	    audio_signal = ags_audio_signal_new_with_length((GObject *) copy_notation_audio->soundcard,
+	    audio_signal = ags_audio_signal_new_with_length((GObject *) AGS_RECALL(copy_notation_audio)->soundcard,
 							    (GObject *) recycling,
 							    (GObject *) AGS_RECALL(copy_notation_audio_run)->recall_id,
 							    length);
 	  }else{
-	    audio_signal = ags_audio_signal_new((GObject *) copy_notation_audio->soundcard,
+	    audio_signal = ags_audio_signal_new((GObject *) AGS_RECALL(copy_notation_audio)->soundcard,
 						(GObject *) recycling,
 						(GObject *) AGS_RECALL(copy_notation_audio_run)->recall_id);
 	  }
diff --git a/ags/audio/recall/ags_copy_pattern_audio.c b/ags/audio/recall/ags_copy_pattern_audio.c
index ba87cf4..3ce2a02 100644
--- a/ags/audio/recall/ags_copy_pattern_audio.c
+++ b/ags/audio/recall/ags_copy_pattern_audio.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -36,6 +36,7 @@ void ags_copy_pattern_audio_get_property(GObject *gobject,
 					 GValue *value,
 					 GParamSpec *param_spec);
 void ags_copy_pattern_audio_set_ports(AgsPlugin *plugin, GList *port);
+void ags_copy_pattern_audio_dispose(GObject *gobject);
 void ags_copy_pattern_audio_finalize(GObject *gobject);
 
 /**
@@ -123,9 +124,17 @@ ags_copy_pattern_audio_class_init(AgsCopyPatternAudioClass *copy_pattern_audio)
   gobject->set_property = ags_copy_pattern_audio_set_property;
   gobject->get_property = ags_copy_pattern_audio_get_property;
 
+  gobject->dispose = ags_copy_pattern_audio_dispose;
   gobject->finalize = ags_copy_pattern_audio_finalize;
 
   /* properties */
+  /**
+   * AgsCopyPatternAudio:bank-index-0:
+   *
+   * The bank index 0 port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("bank-index-0\0",
 				   "current bank index 0\0",
 				   "The current bank index 0 of the AgsPattern\0",
@@ -135,6 +144,13 @@ ags_copy_pattern_audio_class_init(AgsCopyPatternAudioClass *copy_pattern_audio)
 				  PROP_BANK_INDEX_0,
 				  param_spec);
 
+  /**
+   * AgsCopyPatternAudio:bank-index-1:
+   *
+   * The bank index 1 port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("bank-index-1\0",
 				   "current bank index 1\0",
 				   "The current bank index 1 of the AgsPattern\0",
@@ -157,6 +173,7 @@ ags_copy_pattern_audio_init(AgsCopyPatternAudio *copy_pattern_audio)
 
   port = NULL;
 
+  /* bank index 0 */
   copy_pattern_audio->bank_index_0 = g_object_new(AGS_TYPE_PORT,
 						  "plugin-name\0", ags_copy_pattern_audio_plugin_name,
 						  "specifier\0", ags_copy_pattern_audio_specifier[0],
@@ -166,10 +183,15 @@ ags_copy_pattern_audio_init(AgsCopyPatternAudio *copy_pattern_audio)
 						  "port-value-size\0", sizeof(guint),
 						  "port-value-length\0", 1,
 						  NULL);
+  g_object_ref(copy_pattern_audio->bank_index_0);
+
   copy_pattern_audio->bank_index_0->port_value.ags_port_uint = 0;
 
+  /* add to port */
   port = g_list_prepend(port, copy_pattern_audio->bank_index_0);
+  g_object_ref(copy_pattern_audio->bank_index_0);
 
+  /* bank index 1 */
   copy_pattern_audio->bank_index_1 = g_object_new(AGS_TYPE_PORT,
 						  "plugin-name\0", ags_copy_pattern_audio_plugin_name,
 						  "specifier\0", ags_copy_pattern_audio_specifier[1],
@@ -179,10 +201,15 @@ ags_copy_pattern_audio_init(AgsCopyPatternAudio *copy_pattern_audio)
 						  "port-value-size\0", sizeof(guint),
 						  "port-value-length\0", 1,
 						  NULL);
+  g_object_ref(copy_pattern_audio->bank_index_1);
+
   copy_pattern_audio->bank_index_1->port_value.ags_port_uint = 0;
 
+  /* add to port */
   port = g_list_prepend(port, copy_pattern_audio->bank_index_1);
+  g_object_ref(copy_pattern_audio->bank_index_1);
 
+  /* set port */
   AGS_RECALL(copy_pattern_audio)->port = port;
 }
 
@@ -295,6 +322,31 @@ ags_copy_pattern_audio_set_ports(AgsPlugin *plugin, GList *port)
 }
 
 void
+ags_copy_pattern_audio_dispose(GObject *gobject)
+{
+  AgsCopyPatternAudio *copy_pattern_audio;
+  
+  copy_pattern_audio = AGS_COPY_PATTERN_AUDIO(gobject);
+
+  /* bank index 0 */
+  if(copy_pattern_audio->bank_index_0 != NULL){
+    g_object_unref(copy_pattern_audio->bank_index_0);
+
+    copy_pattern_audio->bank_index_0 = NULL;
+  }
+
+  /* bank index 1 */
+  if(copy_pattern_audio->bank_index_1 != NULL){
+    g_object_unref(copy_pattern_audio->bank_index_1);
+
+    copy_pattern_audio->bank_index_1 = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_copy_pattern_audio_parent_class)->dispose(gobject);
+}
+
+void
 ags_copy_pattern_audio_finalize(GObject *gobject)
 {
   AgsCopyPatternAudio *copy_pattern_audio;
@@ -335,12 +387,27 @@ ags_copy_pattern_audio_new(GObject *soundcard,
 {
   AgsCopyPatternAudio *copy_pattern_audio;
 
+  GValue *value;
+  
   copy_pattern_audio = (AgsCopyPatternAudio *) g_object_new(AGS_TYPE_COPY_PATTERN_AUDIO,
 							    "soundcard\0", soundcard,
 							    "tact\0", tact,
-							    "bank_index_0\0", i,
-							    "bank_index_1\0", j,
 							    NULL);
 
+  value = g_new0(GValue,
+		 1);
+  g_value_init(value, G_TYPE_UINT);
+
+  g_value_set_uint(value, i);
+  ags_port_safe_write(copy_pattern_audio->bank_index_0,
+		      value);
+
+  g_value_set_uint(value, j);
+  ags_port_safe_write(copy_pattern_audio->bank_index_1,
+		      value);
+
+  g_value_unset(value);
+  g_free(value);
+  
   return(copy_pattern_audio);
 }
diff --git a/ags/audio/recall/ags_copy_pattern_audio.h b/ags/audio/recall/ags_copy_pattern_audio.h
index ebbcba8..bca7a8b 100644
--- a/ags/audio/recall/ags_copy_pattern_audio.h
+++ b/ags/audio/recall/ags_copy_pattern_audio.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/audio/recall/ags_copy_pattern_audio_run.c b/ags/audio/recall/ags_copy_pattern_audio_run.c
index 5dafe56..30b9503 100644
--- a/ags/audio/recall/ags_copy_pattern_audio_run.c
+++ b/ags/audio/recall/ags_copy_pattern_audio_run.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -45,6 +45,7 @@ void ags_copy_pattern_audio_run_get_property(GObject *gobject,
 					     guint prop_id,
 					     GValue *value,
 					     GParamSpec *param_spec);
+void ags_copy_pattern_audio_run_dispose(GObject *gobject);
 void ags_copy_pattern_audio_run_finalize(GObject *gobject);
 void ags_copy_pattern_audio_run_connect(AgsConnectable *connectable);
 void ags_copy_pattern_audio_run_disconnect(AgsConnectable *connectable);
@@ -157,9 +158,17 @@ ags_copy_pattern_audio_run_class_init(AgsCopyPatternAudioRunClass *copy_pattern_
   gobject->set_property = ags_copy_pattern_audio_run_set_property;
   gobject->get_property = ags_copy_pattern_audio_run_get_property;
 
+  gobject->dispose = ags_copy_pattern_audio_run_dispose;
   gobject->finalize = ags_copy_pattern_audio_run_finalize;
 
   /* properties */
+  /**
+   * AgsCopyPatternAudioRun:delay-audio-run:
+   *
+   * The delay audio run dependency.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("delay-audio-run\0",
 				   "assigned AgsDelayAudioRun\0",
 				   "the AgsDelayAudioRun which emits alloc signal\0",
@@ -169,6 +178,13 @@ ags_copy_pattern_audio_run_class_init(AgsCopyPatternAudioRunClass *copy_pattern_
 				  PROP_DELAY_AUDIO_RUN,
 				  param_spec);
 
+  /**
+   * AgsCopyPatternAudioRun:count-beats-audio-run:
+   *
+   * The count beats audio run dependency.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("count-beats-audio-run\0",
 				   "assigned AgsCountBeatsAudioRun\0",
 				   "the AgsCountBeatsAudioRun which emits beat signal\0",
@@ -285,8 +301,9 @@ ags_copy_pattern_audio_run_set_property(GObject *gobject,
 
       count_beats_audio_run = (AgsCountBeatsAudioRun *) g_value_get_object(value);
 
-      if(copy_pattern_audio_run->count_beats_audio_run == count_beats_audio_run)
+      if(copy_pattern_audio_run->count_beats_audio_run == count_beats_audio_run){
 	return;
+      }
 
       if(count_beats_audio_run != NULL &&
 	 (AGS_RECALL_TEMPLATE & (AGS_RECALL(count_beats_audio_run)->flags)) != 0){
@@ -350,16 +367,43 @@ ags_copy_pattern_audio_run_get_property(GObject *gobject,
 }
 
 void
+ags_copy_pattern_audio_run_dispose(GObject *gobject)
+{
+  AgsCopyPatternAudioRun *copy_pattern_audio_run;
+
+  copy_pattern_audio_run = AGS_COPY_PATTERN_AUDIO_RUN(gobject);
+
+  /* delay audio run */
+  if(copy_pattern_audio_run->delay_audio_run != NULL){
+    g_object_unref(copy_pattern_audio_run->delay_audio_run);
+
+    copy_pattern_audio_run->delay_audio_run = NULL;
+  }
+  
+  /* count beats audio run */
+  if(copy_pattern_audio_run->count_beats_audio_run != NULL){
+    g_object_unref(copy_pattern_audio_run->count_beats_audio_run);
+
+    copy_pattern_audio_run->count_beats_audio_run = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_copy_pattern_audio_run_parent_class)->dispose(gobject);
+}
+
+void
 ags_copy_pattern_audio_run_finalize(GObject *gobject)
 {
   AgsCopyPatternAudioRun *copy_pattern_audio_run;
 
   copy_pattern_audio_run = AGS_COPY_PATTERN_AUDIO_RUN(gobject);
 
+  /* delay audio run */
   if(copy_pattern_audio_run->delay_audio_run != NULL){
     g_object_unref(copy_pattern_audio_run->delay_audio_run);
   }
   
+  /* count beats audio run */
   if(copy_pattern_audio_run->count_beats_audio_run != NULL){
     g_object_unref(copy_pattern_audio_run->count_beats_audio_run);
   }
diff --git a/ags/audio/recall/ags_copy_pattern_audio_run.h b/ags/audio/recall/ags_copy_pattern_audio_run.h
index d08672e..e3b2783 100644
--- a/ags/audio/recall/ags_copy_pattern_audio_run.h
+++ b/ags/audio/recall/ags_copy_pattern_audio_run.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/audio/recall/ags_copy_pattern_channel.c b/ags/audio/recall/ags_copy_pattern_channel.c
index 4c2fe79..9080b9c 100644
--- a/ags/audio/recall/ags_copy_pattern_channel.c
+++ b/ags/audio/recall/ags_copy_pattern_channel.c
@@ -36,6 +36,7 @@ void ags_copy_pattern_channel_get_property(GObject *gobject,
 					   GValue *value,
 					   GParamSpec *param_spec);
 void ags_copy_pattern_channel_set_ports(AgsPlugin *plugin, GList *port);
+void ags_copy_pattern_channel_dispose(GObject *gobject);
 void ags_copy_pattern_channel_finalize(GObject *gobject);
 
 /**
@@ -120,9 +121,17 @@ ags_copy_pattern_channel_class_init(AgsCopyPatternChannelClass *copy_pattern_cha
   gobject->set_property = ags_copy_pattern_channel_set_property;
   gobject->get_property = ags_copy_pattern_channel_get_property;
 
+  gobject->dispose = ags_copy_pattern_channel_dispose;
   gobject->finalize = ags_copy_pattern_channel_finalize;
 
   /* properties */
+  /**
+   * AgsCopyPatternChannel:pattern:
+   *
+   * The pattern port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("pattern\0",
 				   "pattern to play\0",
 				   "The pattern which has to be played\0",
@@ -145,6 +154,7 @@ ags_copy_pattern_channel_init(AgsCopyPatternChannel *copy_pattern_channel)
   
   port = NULL;
 
+  /* pattern */
   copy_pattern_channel->pattern = g_object_new(AGS_TYPE_PORT,
 					       "plugin-name\0", ags_copy_pattern_channel_plugin_name,
 					       "specifier\0", ags_copy_pattern_channel_specifier[0],
@@ -152,11 +162,15 @@ ags_copy_pattern_channel_init(AgsCopyPatternChannel *copy_pattern_channel)
 					       "port-value-is-pointer\0", FALSE,
 					       "port-value-type\0", G_TYPE_OBJECT,
 					       NULL);
-
+  g_object_ref(copy_pattern_channel->pattern);
+  
   copy_pattern_channel->pattern->port_value.ags_port_object = NULL;
 
+  /* add to port */
   port = g_list_prepend(port, copy_pattern_channel->pattern);
+  g_object_ref(copy_pattern_channel->pattern);
 
+  /* set port */
   AGS_RECALL(copy_pattern_channel)->port = port;
 }
 
@@ -237,16 +251,36 @@ ags_copy_pattern_channel_set_ports(AgsPlugin *plugin, GList *port)
 }
 
 void
+ags_copy_pattern_channel_dispose(GObject *gobject)
+{
+  AgsCopyPatternChannel *copy_pattern_channel;
+
+  copy_pattern_channel = AGS_COPY_PATTERN_CHANNEL(gobject);
+
+  /* pattern */
+  if(copy_pattern_channel->pattern != NULL){
+    g_object_unref(copy_pattern_channel->pattern);
+
+    copy_pattern_channel->pattern = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_copy_pattern_channel_parent_class)->dispose(gobject);
+}
+
+void
 ags_copy_pattern_channel_finalize(GObject *gobject)
 {
   AgsCopyPatternChannel *copy_pattern_channel;
 
   copy_pattern_channel = AGS_COPY_PATTERN_CHANNEL(gobject);
 
+  /* pattern */
   if(copy_pattern_channel->pattern != NULL){
     g_object_unref(copy_pattern_channel->pattern);
   }
 
+  /* call parent */
   G_OBJECT_CLASS(ags_copy_pattern_channel_parent_class)->finalize(gobject);
 }
 
diff --git a/ags/audio/recall/ags_copy_pattern_channel_run.c b/ags/audio/recall/ags_copy_pattern_channel_run.c
index 577dcc5..5083633 100644
--- a/ags/audio/recall/ags_copy_pattern_channel_run.c
+++ b/ags/audio/recall/ags_copy_pattern_channel_run.c
@@ -315,8 +315,6 @@ ags_copy_pattern_channel_run_done(AgsRecall *recall)
   AgsCopyPatternChannelRun *copy_pattern_channel_run;
   AgsCopyPatternAudioRun *copy_pattern_audio_run;
 
-  AGS_RECALL_CLASS(ags_copy_pattern_channel_run_parent_class)->done(recall);
-
   copy_pattern_channel_run = AGS_COPY_PATTERN_CHANNEL_RUN(recall);
 
   /* get AgsCopyPatternAudioRun */
@@ -325,6 +323,9 @@ ags_copy_pattern_channel_run_done(AgsRecall *recall)
   /* denotify dependency */
   ags_recall_notify_dependency(AGS_RECALL(copy_pattern_audio_run->count_beats_audio_run),
  			       AGS_RECALL_NOTIFY_CHANNEL_RUN, -1);
+
+  /* call parent */
+  AGS_RECALL_CLASS(ags_copy_pattern_channel_run_parent_class)->done(recall);
 }
 
 void
@@ -364,7 +365,7 @@ ags_copy_pattern_channel_run_sequencer_alloc_callback(AgsDelayAudioRun *delay_au
 						      gdouble delay, guint attack,
 						      AgsCopyPatternChannelRun *copy_pattern_channel_run)
 {
-  AgsChannel *output, *source;
+  AgsChannel *source;
   AgsPattern *pattern;
   AgsCopyPatternAudio *copy_pattern_audio;
   AgsCopyPatternAudioRun *copy_pattern_audio_run;
@@ -380,7 +381,8 @@ ags_copy_pattern_channel_run_sequencer_alloc_callback(AgsDelayAudioRun *delay_au
 
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *pattern_mutex;
-
+  pthread_mutex_t *source_mutex;
+  
   if(delay != 0.0){
     return;
   }
@@ -440,34 +442,66 @@ ags_copy_pattern_channel_run_sequencer_alloc_callback(AgsDelayAudioRun *delay_au
 
   /*  */
   if(current_bit){
+    AgsChannel *link;
     AgsRecycling *recycling;
+    AgsRecycling *end_recycling;
     AgsAudioSignal *audio_signal;
 
     gdouble delay;
     guint attack;
   
+    pthread_mutex_t *link_mutex;
+    
     //    g_message("ags_copy_pattern_channel_run_sequencer_alloc_callback - playing channel: %u; playing pattern: %u\0",
     //	      AGS_RECALL_CHANNEL(copy_pattern_channel)->source->line,
     //	      copy_pattern_audio_run->count_beats_audio_run->sequencer_counter);
 
     /* get source */
     source = AGS_RECALL_CHANNEL(copy_pattern_channel)->source;
+
+    pthread_mutex_lock(application_mutex);
+  
+    source_mutex = ags_mutex_manager_lookup(mutex_manager,
+					    (GObject *) source);
+    
+    pthread_mutex_unlock(application_mutex);
+    
+    /* source fields */
+    pthread_mutex_lock(source_mutex);
+
+    link = source->link;
     
-    /* create new audio signals */
     recycling = source->first_recycling;
+
+    if(recycling != NULL){
+      end_recycling = source->last_recycling->next;
+    }
     
-    //TODO:JK: unclear
+    pthread_mutex_unlock(source_mutex);
+
+    /* link */
+    if(link != NULL){
+      pthread_mutex_lock(application_mutex);
+      
+      link_mutex = ags_mutex_manager_lookup(mutex_manager,
+					    (GObject *) link);
+      
+      pthread_mutex_unlock(application_mutex);
+    }
 
+    /* create audio signals */
     if(recycling != NULL){
       AgsRecallID *child_recall_id;
 
-      while(recycling != source->last_recycling->next){
-	if(source->link == NULL){
+      while(recycling != end_recycling){
+	if(link == NULL){
 	  child_recall_id = AGS_RECALL(copy_pattern_channel_run)->recall_id;
 	}else{
 	  GList *list;
 
-	  list = source->link->recall_id;
+	  pthread_mutex_lock(link_mutex);
+	  
+	  list = link->recall_id;
 
 	  while(list != NULL){
 	    if(AGS_RECALL_ID(list->data)->recycling_context->parent == AGS_RECALL(copy_pattern_channel_run)->recall_id->recycling_context){
@@ -481,6 +515,8 @@ ags_copy_pattern_channel_run_sequencer_alloc_callback(AgsDelayAudioRun *delay_au
 	  if(list == NULL){
 	    child_recall_id = NULL;
 	  }
+
+	  pthread_mutex_unlock(link_mutex);
 	}
 
 	audio_signal = ags_audio_signal_new(AGS_RECALL(copy_pattern_audio)->soundcard,
@@ -508,7 +544,7 @@ ags_copy_pattern_channel_run_sequencer_alloc_callback(AgsDelayAudioRun *delay_au
 	 * unref AgsAudioSignal because AgsCopyPatternChannelRun has no need for it
 	 * if you need a valid reference to audio_signal you have to g_object_ref(audio_signal)
 	 */
-	g_object_unref(audio_signal);
+	//	g_object_unref(audio_signal);
 		
 	recycling = recycling->next;
       }
diff --git a/ags/audio/recall/ags_copy_recycling.c b/ags/audio/recall/ags_copy_recycling.c
index 88abbdb..3a6c4ea 100644
--- a/ags/audio/recall/ags_copy_recycling.c
+++ b/ags/audio/recall/ags_copy_recycling.c
@@ -156,7 +156,7 @@ ags_copy_recycling_init(AgsCopyRecycling *copy_recycling)
   AGS_RECALL(copy_recycling)->port = NULL;
 
   AGS_RECALL(copy_recycling)->child_type = AGS_TYPE_COPY_AUDIO_SIGNAL;
-  AGS_RECALL_RECYCLING(copy_recycling)->flags |= AGS_RECALL_RECYCLING_MAP_CHILD_DESTINATION;
+  AGS_RECALL_RECYCLING(copy_recycling)->flags |= (AGS_RECALL_RECYCLING_MAP_CHILD_DESTINATION);
 }
 
 void
diff --git a/ags/audio/recall/ags_count_beats_audio.c b/ags/audio/recall/ags_count_beats_audio.c
index 951b353..d801847 100644
--- a/ags/audio/recall/ags_count_beats_audio.c
+++ b/ags/audio/recall/ags_count_beats_audio.c
@@ -39,6 +39,7 @@ void ags_count_beats_audio_get_property(GObject *gobject,
 					GValue *value,
 					GParamSpec *param_spec);
 void ags_count_beats_audio_set_ports(AgsPlugin *plugin, GList *port);
+void ags_count_beats_audio_dispose(GObject *gobject);
 void ags_count_beats_audio_finalize(GObject *gobject);
 void ags_count_beats_audio_connect(AgsConnectable *connectable);
 void ags_count_beats_audio_disconnect(AgsConnectable *connectable);
@@ -184,6 +185,7 @@ ags_count_beats_audio_class_init(AgsCountBeatsAudioClass *count_beats_audio)
   gobject->set_property = ags_count_beats_audio_set_property;
   gobject->get_property = ags_count_beats_audio_get_property;
 
+  gobject->dispose = ags_count_beats_audio_dispose;
   gobject->finalize = ags_count_beats_audio_finalize;
 
   /* properties */
@@ -306,10 +308,13 @@ ags_count_beats_audio_init(AgsCountBeatsAudio *count_beats_audio)
 						   "port-value-size\0", sizeof(gboolean),
 						   "port-value-length", 1,
 						   NULL);
-
+  g_object_ref(count_beats_audio->sequencer_loop);
+  
   count_beats_audio->sequencer_loop->port_value.ags_port_boolean = FALSE;
 
+  /* add to port */
   port = g_list_prepend(port, count_beats_audio->sequencer_loop);
+  g_object_ref(count_beats_audio->sequencer_loop);
 
   /* notation loop */
   count_beats_audio->notation_loop = g_object_new(AGS_TYPE_PORT,
@@ -321,10 +326,13 @@ ags_count_beats_audio_init(AgsCountBeatsAudio *count_beats_audio)
 						   "port-value-size\0", sizeof(gboolean),
 						   "port-value-length", 1,
 						   NULL);
-
+  g_object_ref(count_beats_audio->notation_loop);
+  
   count_beats_audio->notation_loop->port_value.ags_port_boolean = FALSE;
 
+  /* add to port */
   port = g_list_prepend(port, count_beats_audio->notation_loop);
+  g_object_ref(count_beats_audio->notation_loop);
   
   /* sequencer-loop-start  */
   count_beats_audio->sequencer_loop_start = g_object_new(AGS_TYPE_PORT,
@@ -336,10 +344,13 @@ ags_count_beats_audio_init(AgsCountBeatsAudio *count_beats_audio)
 							 "port-value-size\0", sizeof(gdouble),
 							 "port-value-length", 1,
 							 NULL);
-
+  g_object_ref(count_beats_audio->sequencer_loop_start);
+  
   count_beats_audio->sequencer_loop_start->port_value.ags_port_double = 0.0;
 
+  /* add to port */
   port = g_list_prepend(port, count_beats_audio->sequencer_loop_start);
+  g_object_ref(count_beats_audio->sequencer_loop_start);
 
   /* notation-loop-start */
   count_beats_audio->notation_loop_start = g_object_new(AGS_TYPE_PORT,
@@ -351,11 +362,14 @@ ags_count_beats_audio_init(AgsCountBeatsAudio *count_beats_audio)
 							"port-value-size\0", sizeof(gdouble),
 							"port-value-length", 1,
 							NULL);
-
+  g_object_ref(count_beats_audio->notation_loop_start);
+  
   count_beats_audio->notation_loop_start->port_value.ags_port_double = 0.0;
 
+  /* add to port */
   port = g_list_prepend(port, count_beats_audio->notation_loop_start);
-
+  g_object_ref(count_beats_audio->notation_loop_start);
+  
   /* sequencer-loop-end */
   count_beats_audio->sequencer_loop_end = g_object_new(AGS_TYPE_PORT,
 						       "plugin-name\0", ags_count_beats_audio_plugin_name,
@@ -366,11 +380,14 @@ ags_count_beats_audio_init(AgsCountBeatsAudio *count_beats_audio)
 						       "port-value-size\0", sizeof(gdouble),
 						       "port-value-length", 1,
 						       NULL);
-
+  g_object_ref(count_beats_audio->sequencer_loop_end);
+  
   count_beats_audio->sequencer_loop_end->port_value.ags_port_double = 16.0;
 
+  /* add to port */
   port = g_list_prepend(port, count_beats_audio->sequencer_loop_end);
-
+  g_object_ref(count_beats_audio->sequencer_loop_end);
+  
   /* notation-loop-end */
   count_beats_audio->notation_loop_end = g_object_new(AGS_TYPE_PORT,
 						      "plugin-name\0", ags_count_beats_audio_plugin_name,
@@ -381,10 +398,13 @@ ags_count_beats_audio_init(AgsCountBeatsAudio *count_beats_audio)
 						      "port-value-size\0", sizeof(gdouble),
 						      "port-value-length", 1,
 						      NULL);
-
+  g_object_ref(count_beats_audio->notation_loop_end);
+  
   count_beats_audio->notation_loop_end->port_value.ags_port_double = 64.0;
 
+  /* add to port */
   port = g_list_prepend(port, count_beats_audio->notation_loop_end);
+  g_object_ref(count_beats_audio->notation_loop_end);
 
   /* port */
   AGS_RECALL(count_beats_audio)->port = port;
@@ -626,7 +646,54 @@ ags_count_beats_audio_set_ports(AgsPlugin *plugin, GList *port)
   }
 }
 
-  void
+void
+ags_count_beats_audio_dispose(GObject *gobject)
+{
+  AgsCountBeatsAudio *count_beats_audio;
+
+  count_beats_audio = AGS_COUNT_BEATS_AUDIO(gobject);
+
+  if(count_beats_audio->notation_loop != NULL){
+    g_object_unref(G_OBJECT(count_beats_audio->notation_loop));
+
+    count_beats_audio->notation_loop = NULL;
+  }
+
+  if(count_beats_audio->notation_loop_start != NULL){
+    g_object_unref(G_OBJECT(count_beats_audio->notation_loop_start));
+
+    count_beats_audio->notation_loop_start = NULL;
+  }
+
+  if(count_beats_audio->notation_loop_end != NULL){
+    g_object_unref(G_OBJECT(count_beats_audio->notation_loop_end));
+
+    count_beats_audio->notation_loop_end = NULL;
+  }
+
+  if(count_beats_audio->sequencer_loop != NULL){
+    g_object_unref(G_OBJECT(count_beats_audio->sequencer_loop));
+
+    count_beats_audio->sequencer_loop = NULL;
+  }
+
+  if(count_beats_audio->sequencer_loop_start != NULL){
+    g_object_unref(G_OBJECT(count_beats_audio->sequencer_loop_start));
+
+    count_beats_audio->sequencer_loop_start = NULL;
+  }
+
+  if(count_beats_audio->sequencer_loop_end != NULL){
+    g_object_unref(G_OBJECT(count_beats_audio->sequencer_loop_end));
+
+    count_beats_audio->sequencer_loop_end = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_count_beats_audio_parent_class)->dispose(gobject);
+}
+
+void
 ags_count_beats_audio_finalize(GObject *gobject)
 {
   AgsCountBeatsAudio *count_beats_audio;
diff --git a/ags/audio/recall/ags_count_beats_audio_run.c b/ags/audio/recall/ags_count_beats_audio_run.c
index 86fd47e..031e70b 100644
--- a/ags/audio/recall/ags_count_beats_audio_run.c
+++ b/ags/audio/recall/ags_count_beats_audio_run.c
@@ -65,6 +65,7 @@ void ags_count_beats_audio_run_get_property(GObject *gobject,
 					    guint prop_id,
 					    GValue *value,
 					    GParamSpec *param_spec);
+void ags_count_beats_audio_run_dispose(GObject *gobject);
 void ags_count_beats_audio_run_finalize(GObject *gobject);
 void ags_count_beats_audio_run_connect(AgsConnectable *connectable);
 void ags_count_beats_audio_run_disconnect(AgsConnectable *connectable);
@@ -311,6 +312,7 @@ ags_count_beats_audio_run_class_init(AgsCountBeatsAudioRunClass *count_beats_aud
   gobject->set_property = ags_count_beats_audio_run_set_property;
   gobject->get_property = ags_count_beats_audio_run_get_property;
 
+  gobject->dispose = ags_count_beats_audio_run_dispose;
   gobject->finalize = ags_count_beats_audio_run_finalize;
 
   /* properties */
@@ -529,8 +531,9 @@ ags_count_beats_audio_run_set_property(GObject *gobject,
 
       delay_audio_run = (AgsDelayAudioRun *) g_value_get_object(value);
 
-      if(count_beats_audio_run->delay_audio_run == delay_audio_run)
+      if(count_beats_audio_run->delay_audio_run == delay_audio_run){
 	return;
+      }
 
       if(delay_audio_run != NULL &&
 	 (AGS_RECALL_TEMPLATE & (AGS_RECALL(delay_audio_run)->flags)) != 0){
@@ -648,12 +651,31 @@ ags_count_beats_audio_run_get_property(GObject *gobject,
 }
 
 void
+ags_count_beats_audio_run_dispose(GObject *gobject)
+{
+  AgsCountBeatsAudioRun *count_beats_audio_run;
+
+  count_beats_audio_run = AGS_COUNT_BEATS_AUDIO_RUN(gobject);
+
+  /* delay audio run */
+  if(count_beats_audio_run->delay_audio_run != NULL){
+    g_object_unref(count_beats_audio_run->delay_audio_run);
+
+    count_beats_audio_run->delay_audio_run = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_count_beats_audio_run_parent_class)->dispose(gobject);
+}
+
+void
 ags_count_beats_audio_run_finalize(GObject *gobject)
 {
   AgsCountBeatsAudioRun *count_beats_audio_run;
 
   count_beats_audio_run = AGS_COUNT_BEATS_AUDIO_RUN(gobject);
 
+  /* delay audio run */
   if(count_beats_audio_run->delay_audio_run != NULL){
     g_object_unref(count_beats_audio_run->delay_audio_run);
   }
@@ -742,7 +764,6 @@ ags_count_beats_audio_run_seek(AgsSeekable *seekable,
 			       guint steps,
 			       gboolean move_forward)
 {
-  GObject *soundcard;
   AgsDelayAudio *delay_audio;
   AgsDelayAudioRun *delay_audio_run;
   AgsCountBeatsAudioRun *count_beats_audio_run;
@@ -752,9 +773,7 @@ ags_count_beats_audio_run_seek(AgsSeekable *seekable,
   count_beats_audio_run = AGS_COUNT_BEATS_AUDIO_RUN(seekable);
   delay_audio_run = count_beats_audio_run->delay_audio_run;
   delay_audio = (AgsDelayAudio *) AGS_RECALL_AUDIO_RUN(delay_audio_run)->recall_audio;
-
-  soundcard = AGS_RECALL(count_beats_audio_run)->soundcard;
-    
+  
   if(delay_audio->sequencer_duration->port_value.ags_port_double != 0.0){
     seq_steps = (steps % (guint) delay_audio->sequencer_duration->port_value.ags_port_double);
   }else{
@@ -927,6 +946,10 @@ ags_count_beats_audio_run_resolve_dependencies(AgsRecall *recall)
 
   guint i, i_stop;
 
+  if(recall->soundcard == NULL){
+    return;
+  }
+
   template = AGS_RECALL(ags_recall_find_template(AGS_RECALL_CONTAINER(recall->container)->recall_audio_run)->data);
 
   list = template->dependencies;
@@ -1031,11 +1054,13 @@ ags_count_beats_audio_run_run_init_pre(AgsRecall *recall)
 void
 ags_count_beats_audio_run_done(AgsRecall *recall)
 {
-  GObject *soundcard;
-
+  AgsAudio *audio;
+  AgsRecallID *recall_id;
+  
   AgsCountBeatsAudio *count_beats_audio;
   AgsCountBeatsAudioRun *count_beats_audio_run;
-
+  AgsDelayAudioRun *delay_audio_run;
+  
   AgsCancelAudio *cancel_audio;
 
   AgsMutexManager *mutex_manager;
@@ -1043,22 +1068,27 @@ ags_count_beats_audio_run_done(AgsRecall *recall)
   AgsThread *async_queue;
 
   AgsApplicationContext *application_context;
+
+  GObject *soundcard;
   
   gboolean sequencer, notation;
   
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *soundcard_mutex;
   
-  AGS_RECALL_CLASS(ags_count_beats_audio_run_parent_class)->done(recall);
-
   count_beats_audio_run = AGS_COUNT_BEATS_AUDIO_RUN(recall);
   count_beats_audio = AGS_COUNT_BEATS_AUDIO(AGS_RECALL_AUDIO_RUN(count_beats_audio_run)->recall_audio);
 
-  soundcard = AGS_RECALL_AUDIO(count_beats_audio)->audio->soundcard;
-
+  delay_audio_run = count_beats_audio_run->delay_audio_run;
+  
+  audio = AGS_RECALL_AUDIO(count_beats_audio)->audio;
+  recall_id = AGS_RECALL(count_beats_audio_run)->recall_id;
+  
   mutex_manager = ags_mutex_manager_get_instance();
   application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
   
+  soundcard = AGS_RECALL_AUDIO(count_beats_audio)->audio->soundcard;
+
   /* lookup soundcard mutex */
   pthread_mutex_lock(application_mutex);
   
@@ -1085,11 +1115,7 @@ ags_count_beats_audio_run_done(AgsRecall *recall)
   async_queue = (AgsThread *) ags_thread_find_type(main_loop,
 						   AGS_TYPE_TASK_THREAD);
 
-  ags_recall_done((AgsRecall *) count_beats_audio_run->delay_audio_run);
-  ags_audio_done(AGS_RECALL_AUDIO(count_beats_audio)->audio,
-		 AGS_RECALL(count_beats_audio_run)->recall_id);
-
-  if((AGS_RECALL_ID_SEQUENCER & (recall->recall_id->flags)) != 0){
+  if((AGS_RECALL_ID_SEQUENCER & (recall_id->flags)) != 0){
     sequencer = TRUE;
   }else{
     sequencer = FALSE;
@@ -1108,6 +1134,14 @@ ags_count_beats_audio_run_done(AgsRecall *recall)
   /* append AgsCancelAudio */
   ags_task_thread_append_task((AgsTaskThread *) async_queue,
 			      (AgsTask *) cancel_audio);  
+
+  /* call parent */
+  AGS_RECALL_CLASS(ags_count_beats_audio_run_parent_class)->done(recall);
+
+  ags_recall_done((AgsRecall *) delay_audio_run);
+  ags_audio_done(audio,
+		 recall_id);
+
 }
 
 /**
@@ -1446,38 +1480,87 @@ ags_count_beats_audio_run_sequencer_count_callback(AgsDelayAudioRun *delay_audio
   }else{      
     if(count_beats_audio_run->sequencer_counter >= (guint) loop_end - 1.0){
       AgsAudio *audio;
+
+      AgsMutexManager *mutex_manager;
+
       GList *playback;
 
+      pthread_mutex_t *application_mutex;
+      pthread_mutex_t *audio_mutex;
+      
+      audio = AGS_RECALL_AUDIO_RUN(count_beats_audio_run)->recall_audio->audio;
+
+      mutex_manager = ags_mutex_manager_get_instance();
+      application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+  
+      /* lookup audio mutex */
+      pthread_mutex_lock(application_mutex);
+  
+      audio_mutex = ags_mutex_manager_lookup(mutex_manager,
+					     audio);
+  
+      pthread_mutex_unlock(application_mutex);
+
+      /* reset sequencer counter */
       count_beats_audio_run->sequencer_counter = 0;
 
-      audio = AGS_RECALL_AUDIO_RUN(count_beats_audio_run)->recall_audio->audio;
+      /* get playback */
+      pthread_mutex_lock(audio_mutex);
+      
       playback = AGS_PLAYBACK_DOMAIN(audio->playback_domain)->playback;
 
+      pthread_mutex_unlock(audio_mutex);
+      
       /* emit stop signals */
       ags_count_beats_audio_run_sequencer_stop(count_beats_audio_run,
 					       FALSE);
 
       /* set done flag in soundcard play */
       while(playback != NULL){
-	if(AGS_PLAYBACK(playback->data)->recall_id[1] != NULL &&
-	   AGS_PLAYBACK(playback->data)->recall_id[1]->recycling_context == AGS_RECALL(count_beats_audio_run)->recall_id->recycling_context){
-	  AgsChannel *channel;
+	AgsChannel *channel;
+	AgsRecyclingContext *recycling_context;
+	
+	pthread_mutex_lock(audio_mutex);
+
+	channel = audio->output;
+	
+	if(AGS_PLAYBACK(playback->data)->recall_id[1] != NULL){
+	  recycling_context = AGS_PLAYBACK(playback->data)->recall_id[1]->recycling_context;
+	}else{
+	  recycling_context = NULL;
+	}
+
+	pthread_mutex_unlock(audio_mutex);
+
+	if(recycling_context == AGS_RECALL(count_beats_audio_run)->recall_id->recycling_context){
 	  AgsStreamChannelRun *stream_channel_run;
+	  
 	  GList *list;
 	  GList *recall_recycling_list, *recall_audio_signal_list;
+	  
 	  gboolean found;
 
+	  pthread_mutex_t *channel_mutex;
+
 	  //	    AGS_PLAYBACK(playback->data)->flags |= AGS_PLAYBACK_DONE;
 
+	  /* lookup channel mutex */
+	  pthread_mutex_lock(application_mutex);
+	  
+	  channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+						   channel);
+	  
+	  pthread_mutex_unlock(application_mutex);
+
 	  /* check if to stop audio processing */
-	  channel = audio->output;
 	  found = FALSE;
 
+	  pthread_mutex_lock(channel_mutex);
+	  
 	  list = channel->play;
-
 	  list = ags_recall_find_type_with_recycling_context(list,
 							     AGS_TYPE_STREAM_CHANNEL_RUN,
-							     (GObject *) AGS_RECALL(count_beats_audio_run)->recall_id->recycling_context);
+							     (GObject *) recycling_context);
 
 	  if(list != NULL){
 	    stream_channel_run = AGS_STREAM_CHANNEL_RUN(list->data);
@@ -1500,6 +1583,8 @@ ags_count_beats_audio_run_sequencer_count_callback(AgsDelayAudioRun *delay_audio
 	    }
 	  }
 
+	  pthread_mutex_unlock(channel_mutex);
+
 	  /* stop audio processing*/
 	  if(!found){
 	    ags_count_beats_audio_run_stop(count_beats_audio_run,
@@ -1509,7 +1594,12 @@ ags_count_beats_audio_run_sequencer_count_callback(AgsDelayAudioRun *delay_audio
 	  break;
 	}
 
-	playback = playback->next;
+	/* iterate playback */
+	pthread_mutex_lock(audio_mutex);
+	
+      	playback = playback->next;
+
+	pthread_mutex_unlock(audio_mutex);
       }
 
       return;
diff --git a/ags/audio/recall/ags_delay_audio.c b/ags/audio/recall/ags_delay_audio.c
index 4afebe1..cc853ba 100644
--- a/ags/audio/recall/ags_delay_audio.c
+++ b/ags/audio/recall/ags_delay_audio.c
@@ -40,12 +40,23 @@ void ags_delay_audio_get_property(GObject *gobject,
 				  GValue *value,
 				  GParamSpec *param_spec);
 void ags_delay_audio_set_ports(AgsPlugin *plugin, GList *port);
+void ags_delay_audio_dispose(GObject *gobject);
 void ags_delay_audio_finalize(GObject *gobject);
 
+void ags_delay_audio_notify_audio_callback(GObject *gobject,
+					   GParamSpec *pspec,
+					   gpointer user_data);
 void ags_delay_audio_notify_soundcard_callback(GObject *gobject,
 					       GParamSpec *pspec,
 					       gpointer user_data);
 
+void ags_delay_audio_notify_samplerate_callback(GObject *gobject,
+						GParamSpec *pspec,
+						gpointer user_data);
+void ags_delay_audio_notify_buffer_size_callback(GObject *gobject,
+						 GParamSpec *pspec,
+						 gpointer user_data);
+
 gdouble ags_delay_audio_get_bpm(AgsTactable *tactable);
 gdouble ags_delay_audio_get_tact(AgsTactable *tactable);
 gdouble ags_delay_audio_get_sequencer_duration(AgsTactable *tactable);
@@ -55,6 +66,8 @@ void ags_delay_audio_change_tact(AgsTactable *tactable, gdouble new_tact, gdoubl
 void ags_delay_audio_change_sequencer_duration(AgsTactable *tactable, gdouble duration);
 void ags_delay_audio_change_notation_duration(AgsTactable *tactable, gdouble duration);
 
+void ags_delay_audio_refresh_delay(AgsDelayAudio *delay_audio);
+
 /**
  * SECTION:ags_delay_audio
  * @short_description: delay audio 
@@ -164,6 +177,7 @@ ags_delay_audio_class_init(AgsDelayAudioClass *delay_audio)
   gobject->set_property = ags_delay_audio_set_property;
   gobject->get_property = ags_delay_audio_get_property;
 
+  gobject->dispose = ags_delay_audio_dispose;
   gobject->finalize = ags_delay_audio_finalize;
 
   /* properties */
@@ -321,12 +335,137 @@ ags_delay_audio_plugin_interface_init(AgsPluginInterface *plugin)
 void
 ags_delay_audio_init(AgsDelayAudio *delay_audio)
 {
+  GList *port;
+
+  gdouble bpm;
+  gdouble delay;
+
   AGS_RECALL(delay_audio)->name = "ags-delay\0";
   AGS_RECALL(delay_audio)->version = AGS_RECALL_DEFAULT_VERSION;
   AGS_RECALL(delay_audio)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
   AGS_RECALL(delay_audio)->xml_type = "ags-delay-audio\0";
 
-  g_signal_connect_after(delay_audio, "notify::soundcard",
+  port = NULL;
+
+  bpm = AGS_SOUNDCARD_DEFAULT_BPM;
+  delay = AGS_SOUNDCARD_DEFAULT_DELAY;
+
+  /* bpm */
+  delay_audio->bpm = g_object_new(AGS_TYPE_PORT,
+				  "plugin-name\0", ags_delay_audio_plugin_name,
+				  "specifier\0", ags_delay_audio_specifier[0],
+				  "control-port\0", ags_delay_audio_control_port[0],
+				  "port-value-is-pointer\0", FALSE,
+				  "port-value-type\0", G_TYPE_DOUBLE,
+				  "port-value-size\0", sizeof(gdouble),
+				  "port-value-length", 1,
+				  NULL);
+  g_object_ref(delay_audio->bpm);
+  
+  delay_audio->bpm->port_value.ags_port_double = bpm;
+
+  /* add port */
+  port = g_list_prepend(port, delay_audio->bpm);
+  g_object_ref(delay_audio->bpm);
+  
+  /* tact */
+  delay_audio->tact = g_object_new(AGS_TYPE_PORT,
+				   "plugin-name\0", ags_delay_audio_plugin_name,
+				   "specifier\0", ags_delay_audio_specifier[1],
+				   "control-port\0", ags_delay_audio_control_port[1],
+				   "port-value-is-pointer\0", FALSE,
+				   "port-value-type\0", G_TYPE_DOUBLE,
+				   "port-value-size\0", sizeof(gdouble),
+				   "port-value-length", 1,
+				   NULL);
+  g_object_ref(delay_audio->tact);
+  
+  delay_audio->tact->port_value.ags_port_double = AGS_SOUNDCARD_DEFAULT_TACT;
+
+  /* add port */
+  port = g_list_prepend(port, delay_audio->tact);
+  g_object_ref(delay_audio->tact);
+  
+  /* sequencer delay */
+  delay_audio->sequencer_delay = g_object_new(AGS_TYPE_PORT,
+					      "plugin-name\0", ags_delay_audio_plugin_name,
+					      "specifier\0", ags_delay_audio_specifier[2],
+					      "control-port\0", ags_delay_audio_control_port[2],
+					      "port-value-is-pointer\0", FALSE,
+					      "port-value-type\0", G_TYPE_DOUBLE,
+					      "port-value-size\0", sizeof(gdouble),
+					      "port-value-length", 1,
+					      NULL);
+  g_object_ref(delay_audio->sequencer_delay);
+  
+  delay_audio->sequencer_delay->port_value.ags_port_double = delay;
+
+  /* add port */
+  port = g_list_prepend(port, delay_audio->sequencer_delay);
+  g_object_ref(delay_audio->sequencer_delay);
+  
+  /* notation delay */
+  delay_audio->notation_delay = g_object_new(AGS_TYPE_PORT,
+					     "plugin-name\0", ags_delay_audio_plugin_name,
+					     "specifier\0", ags_delay_audio_specifier[3],
+					     "control-port\0", ags_delay_audio_control_port[3],
+					     "port-value-is-pointer\0", FALSE,
+					     "port-value-type\0", G_TYPE_DOUBLE,
+					     "port-value-size\0", sizeof(gdouble),
+					     "port-value-length", 1,
+					     NULL);
+  g_object_ref(delay_audio->notation_delay);
+  
+  delay_audio->notation_delay->port_value.ags_port_double = delay;
+
+  /* add port */
+  port = g_list_prepend(port, delay_audio->notation_delay);
+  g_object_ref(delay_audio->notation_delay);
+  
+  /* sequencer duration */
+  delay_audio->sequencer_duration = g_object_new(AGS_TYPE_PORT,
+						 "plugin-name\0", ags_delay_audio_plugin_name,
+						 "specifier\0", ags_delay_audio_specifier[4],
+						 "control-port\0", ags_delay_audio_control_port[4],
+						 "port-value-is-pointer\0", FALSE,
+						 "port-value-type\0", G_TYPE_DOUBLE,
+						 "port-value-size\0", sizeof(gdouble),
+						 "port-value-length", 1,
+						 NULL);
+  g_object_ref(delay_audio->sequencer_duration);
+  
+  delay_audio->sequencer_duration->port_value.ags_port_double = ceil(16.0 * delay);
+
+  /* add port */
+  port = g_list_prepend(port, delay_audio->sequencer_duration);
+  g_object_ref(delay_audio->sequencer_duration);
+  
+  /* notation duration */
+  delay_audio->notation_duration = g_object_new(AGS_TYPE_PORT,
+						"plugin-name\0", ags_delay_audio_plugin_name,
+						"specifier\0", ags_delay_audio_specifier[5],
+						"control-port\0", ags_delay_audio_control_port[5],
+						"port-value-is-pointer\0", FALSE,
+						"port-value-type\0", G_TYPE_DOUBLE,
+						"port-value-size\0", sizeof(gdouble),
+						"port-value-length", 1,
+						NULL);
+  g_object_ref(delay_audio->notation_duration);
+  
+  delay_audio->notation_duration->port_value.ags_port_double = ceil(AGS_NOTATION_DEFAULT_DURATION * delay);
+
+  /* add port */
+  port = g_list_prepend(port, delay_audio->notation_duration);
+  g_object_ref(delay_audio->notation_duration);
+  
+  /* set port */
+  AGS_RECALL(delay_audio)->port = port;
+  
+  /* notify some properties to do final configuration */
+  g_signal_connect_after(delay_audio, "notify::audio\0",
+			 G_CALLBACK(ags_delay_audio_notify_audio_callback), NULL);
+
+  g_signal_connect_after(delay_audio, "notify::soundcard\0",
 			 G_CALLBACK(ags_delay_audio_notify_soundcard_callback), NULL);
 }
 
@@ -555,6 +694,56 @@ ags_delay_audio_set_ports(AgsPlugin *plugin, GList *port)
 }
 
 void
+ags_delay_audio_dispose(GObject *gobject)
+{
+  AgsDelayAudio *delay_audio;
+
+  delay_audio = AGS_DELAY_AUDIO(gobject);
+
+  /* bpm and tact */
+  if(delay_audio->bpm != NULL){
+    g_object_unref(G_OBJECT(delay_audio->bpm));
+
+    delay_audio->bpm = NULL;
+  }
+
+  if(delay_audio->tact != NULL){
+    g_object_unref(G_OBJECT(delay_audio->tact));
+
+    delay_audio->tact = NULL;
+  }
+
+  /* delay */
+  if(delay_audio->notation_delay != NULL){
+    g_object_unref(G_OBJECT(delay_audio->notation_delay));
+
+    delay_audio->notation_delay = NULL;
+  }
+
+  if(delay_audio->sequencer_delay != NULL){
+    g_object_unref(G_OBJECT(delay_audio->sequencer_delay));
+
+    delay_audio->sequencer_delay = NULL;
+  }
+
+  /* duration */
+  if(delay_audio->notation_duration != NULL){
+    g_object_unref(G_OBJECT(delay_audio->notation_duration));
+
+    delay_audio->notation_duration = NULL;
+  }
+
+  if(delay_audio->sequencer_duration != NULL){
+    g_object_unref(G_OBJECT(delay_audio->sequencer_duration));
+
+    delay_audio->sequencer_duration = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_delay_audio_parent_class)->dispose(gobject);
+}
+
+void
 ags_delay_audio_finalize(GObject *gobject)
 {
   AgsDelayAudio *delay_audio;
@@ -590,13 +779,35 @@ ags_delay_audio_finalize(GObject *gobject)
 }
 
 void
+ags_delay_audio_notify_audio_callback(GObject *gobject,
+				      GParamSpec *pspec,
+				      gpointer user_data)
+{
+  AgsDelayAudio *delay_audio;
+  
+  AgsAudio *audio;
+  
+  delay_audio = AGS_DELAY_AUDIO(gobject);
+
+  audio = AGS_RECALL_AUDIO(delay_audio)->audio;
+
+  if(audio == NULL){
+    return;
+  }
+
+  g_signal_connect_after(audio, "notify::samplerate\0",
+			 G_CALLBACK(ags_delay_audio_notify_samplerate_callback), delay_audio);
+
+  g_signal_connect_after(audio, "notify::buffer-size\0",
+			 G_CALLBACK(ags_delay_audio_notify_buffer_size_callback), delay_audio);
+}
+
+void
 ags_delay_audio_notify_soundcard_callback(GObject *gobject,
 					  GParamSpec *pspec,
 					  gpointer user_data)
 {
   AgsDelayAudio *delay_audio;
-  
-  GList *port;
 
   GObject *soundcard;
   gdouble bpm;
@@ -606,104 +817,56 @@ ags_delay_audio_notify_soundcard_callback(GObject *gobject,
   delay_audio = AGS_DELAY_AUDIO(gobject);
 
   soundcard = AGS_RECALL(delay_audio)->soundcard;
-  port = NULL;
 
+  if(soundcard == NULL){
+    return;
+  }
+  
   /*  */
   bpm = ags_soundcard_get_bpm(AGS_SOUNDCARD(soundcard));
   delay = ags_soundcard_get_delay(AGS_SOUNDCARD(soundcard));
 
   /* bpm */
-  delay_audio->bpm = g_object_new(AGS_TYPE_PORT,
-				  "plugin-name\0", ags_delay_audio_plugin_name,
-				  "specifier\0", ags_delay_audio_specifier[0],
-				  "control-port\0", ags_delay_audio_control_port[0],
-				  "port-value-is-pointer\0", FALSE,
-				  "port-value-type\0", G_TYPE_DOUBLE,
-				  "port-value-size\0", sizeof(gdouble),
-				  "port-value-length", 1,
-				  NULL);
-
   delay_audio->bpm->port_value.ags_port_double = bpm;
 
-  port = g_list_prepend(port, delay_audio->bpm);
-
   /* tact */
-  delay_audio->tact = g_object_new(AGS_TYPE_PORT,
-				   "plugin-name\0", ags_delay_audio_plugin_name,
-				   "specifier\0", ags_delay_audio_specifier[1],
-				   "control-port\0", ags_delay_audio_control_port[1],
-				   "port-value-is-pointer\0", FALSE,
-				   "port-value-type\0", G_TYPE_DOUBLE,
-				   "port-value-size\0", sizeof(gdouble),
-				   "port-value-length", 1,
-				   NULL);
-
   delay_audio->tact->port_value.ags_port_double = AGS_SOUNDCARD_DEFAULT_TACT;
 
-  port = g_list_prepend(port, delay_audio->tact);
-
   /* sequencer delay */
-  delay_audio->sequencer_delay = g_object_new(AGS_TYPE_PORT,
-					      "plugin-name\0", ags_delay_audio_plugin_name,
-					      "specifier\0", ags_delay_audio_specifier[2],
-					      "control-port\0", ags_delay_audio_control_port[2],
-					      "port-value-is-pointer\0", FALSE,
-					      "port-value-type\0", G_TYPE_DOUBLE,
-					      "port-value-size\0", sizeof(gdouble),
-					      "port-value-length", 1,
-					      NULL);
-
   delay_audio->sequencer_delay->port_value.ags_port_double = delay;
-
-  port = g_list_prepend(port, delay_audio->sequencer_delay);
-
+  
   /* notation delay */
-  delay_audio->notation_delay = g_object_new(AGS_TYPE_PORT,
-					     "plugin-name\0", ags_delay_audio_plugin_name,
-					     "specifier\0", ags_delay_audio_specifier[3],
-					     "control-port\0", ags_delay_audio_control_port[3],
-					     "port-value-is-pointer\0", FALSE,
-					     "port-value-type\0", G_TYPE_DOUBLE,
-					     "port-value-size\0", sizeof(gdouble),
-					     "port-value-length", 1,
-					     NULL);
-
   delay_audio->notation_delay->port_value.ags_port_double = delay;
 
-  port = g_list_prepend(port, delay_audio->notation_delay);
-
   /* sequencer duration */
-  delay_audio->sequencer_duration = g_object_new(AGS_TYPE_PORT,
-						 "plugin-name\0", ags_delay_audio_plugin_name,
-						 "specifier\0", ags_delay_audio_specifier[4],
-						 "control-port\0", ags_delay_audio_control_port[4],
-						 "port-value-is-pointer\0", FALSE,
-						 "port-value-type\0", G_TYPE_DOUBLE,
-						 "port-value-size\0", sizeof(gdouble),
-						 "port-value-length", 1,
-						 NULL);
-
   delay_audio->sequencer_duration->port_value.ags_port_double = ceil(16.0 * delay);
 
-  port = g_list_prepend(port, delay_audio->sequencer_duration);
+  /* notation duration */  
+  delay_audio->notation_duration->port_value.ags_port_double = ceil(AGS_NOTATION_DEFAULT_DURATION * delay);
+}
 
-  /* notation duration */
-  delay_audio->notation_duration = g_object_new(AGS_TYPE_PORT,
-						"plugin-name\0", ags_delay_audio_plugin_name,
-						"specifier\0", ags_delay_audio_specifier[5],
-						"control-port\0", ags_delay_audio_control_port[5],
-						"port-value-is-pointer\0", FALSE,
-						"port-value-type\0", G_TYPE_DOUBLE,
-						"port-value-size\0", sizeof(gdouble),
-						"port-value-length", 1,
-						NULL);
+void
+ags_delay_audio_notify_samplerate_callback(GObject *gobject,
+					   GParamSpec *pspec,
+					   gpointer user_data)
+{
+  AgsDelayAudio *delay_audio;
+  
+  delay_audio = AGS_DELAY_AUDIO(user_data);
 
-  delay_audio->notation_duration->port_value.ags_port_double = ceil(AGS_NOTATION_DEFAULT_DURATION * delay);
+  ags_delay_audio_refresh_delay(delay_audio);
+}
 
-  port = g_list_prepend(port, delay_audio->notation_duration);
+void
+ags_delay_audio_notify_buffer_size_callback(GObject *gobject,
+					    GParamSpec *pspec,
+					    gpointer user_data)
+{
+  AgsDelayAudio *delay_audio;
+  
+  delay_audio = AGS_DELAY_AUDIO(user_data);
 
-  /*  */
-  AGS_RECALL(delay_audio)->port = port;
+  ags_delay_audio_refresh_delay(delay_audio);
 }
 
 gdouble
@@ -901,6 +1064,59 @@ ags_delay_audio_change_tact(AgsTactable *tactable, gdouble new_tact, gdouble old
 }
 
 void
+ags_delay_audio_refresh_delay(AgsDelayAudio *delay_audio)
+{
+  GObject *soundcard;
+
+  gdouble delay;
+  
+  GValue value = {0,};
+  
+  soundcard = AGS_RECALL(delay_audio)->soundcard;
+
+  if(soundcard == NULL){
+    return;
+  }
+  
+  delay = ags_soundcard_get_delay(AGS_SOUNDCARD(soundcard));
+  g_value_init(&value, G_TYPE_DOUBLE);
+
+  /* -- start adjust -- */
+  /* notation-delay */
+  g_value_reset(&value);
+
+  g_value_set_double(&value, delay);
+  ags_port_safe_write(delay_audio->notation_delay, &value);
+
+  //  g_message("notation delay = %f\0", notation_delay * (old_tact / new_tact));
+  
+  /* sequencer-delay */
+  g_value_reset(&value);
+
+  g_value_set_double(&value, delay);
+  ags_port_safe_write(delay_audio->sequencer_delay, &value);
+
+  //  g_message("sequencer delay = %f\0", sequencer_delay * (old_tact / new_tact));
+
+  /* notation-duration */
+  g_value_reset(&value);
+
+  g_value_set_double(&value, ceil(AGS_NOTATION_DEFAULT_DURATION * delay));
+  ags_port_safe_write(delay_audio->notation_duration, &value);
+
+  /* sequencer-duration */
+  g_value_reset(&value);
+
+  g_value_set_double(&value, ceil(16.0 * delay));
+  ags_port_safe_write(delay_audio->sequencer_duration, &value);
+
+  /* -- finish adjust -- */
+
+  /* emit changed */
+  ags_delay_audio_sequencer_duration_changed(delay_audio);
+}
+
+void
 ags_delay_audio_change_sequencer_duration(AgsTactable *tactable, gdouble duration)
 {
   AgsDelayAudio *delay_audio;
diff --git a/ags/audio/recall/ags_delay_audio_run.c b/ags/audio/recall/ags_delay_audio_run.c
index b0c1950..29ccafd 100644
--- a/ags/audio/recall/ags_delay_audio_run.c
+++ b/ags/audio/recall/ags_delay_audio_run.c
@@ -26,6 +26,8 @@
 #include <ags/object/ags_soundcard.h>
 #include <ags/object/ags_plugin.h>
 
+#include <ags/thread/ags_mutex_manager.h>
+
 #include <ags/file/ags_file_stock.h>
 #include <ags/file/ags_file_id_ref.h>
 #include <ags/file/ags_file_lookup.h>
@@ -441,16 +443,24 @@ ags_delay_audio_run_run_pre(AgsRecall *recall)
   AgsDelayAudio *delay_audio;
   AgsDelayAudioRun *delay_audio_run;
 
+  AgsMutexManager *mutex_manager;
+  
   gdouble notation_delay, sequencer_delay;
+  gdouble delay;
+  guint attack;
 
   GValue value = { 0, };
 
+  pthread_mutex_t *application_mutex;
+  pthread_mutex_t *soundcard_mutex;
+  
   AGS_RECALL_CLASS(ags_delay_audio_run_parent_class)->run_pre(recall);
 
   //  g_message("ags_delay_audio_run_run_pre()\0");
   
   delay_audio_run = AGS_DELAY_AUDIO_RUN(recall);
 
+  /* check done */  
   if((AGS_RECALL_PERSISTENT & (recall->flags)) == 0 &&
      delay_audio_run->dependency_ref == 0){
     delay_audio_run->notation_counter = 0;
@@ -463,6 +473,17 @@ ags_delay_audio_run_run_pre(AgsRecall *recall)
 
   delay_audio = AGS_DELAY_AUDIO(AGS_RECALL_AUDIO_RUN(delay_audio_run)->recall_audio);
 
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+  
+  /* lookup soundcard mutex */
+  pthread_mutex_lock(application_mutex);
+  
+  soundcard_mutex = ags_mutex_manager_lookup(mutex_manager,
+					     recall->soundcard);
+  
+  pthread_mutex_unlock(application_mutex);
+
   /* read notation-delay port */
   g_value_init(&value, G_TYPE_DOUBLE);
 
@@ -489,22 +510,22 @@ ags_delay_audio_run_run_pre(AgsRecall *recall)
   }else{
     delay_audio_run->sequencer_counter += 1;
   }
+  
+  /* delay and attack */
+  pthread_mutex_lock(soundcard_mutex);
+
+  attack = ags_soundcard_get_attack(AGS_SOUNDCARD(recall->soundcard));
+  
+  pthread_mutex_unlock(soundcard_mutex);
+  
+  delay = 0.0;
 
+  /* notation */
   if(delay_audio_run->notation_counter == 0){    
     guint run_order;
-    gdouble delay;
-    guint attack;
 
     run_order = 0; //NOTE:JK: old hide_ref style
 
-    /* delay and attack */
-    //TODO:JK: unclear
-    attack = ags_soundcard_get_attack(AGS_SOUNDCARD(recall->soundcard));
-      
-    delay = 0.0; // soundcard->delay[((soundcard->tic_counter + 1 == AGS_NOTATION_TICS_PER_BEAT) ?
-      //		   0:
-      //		   soundcard->tic_counter + 1)];
-
     //    g_message("ags_delay_audio_run_run_pre@%llu: alloc notation[%u]\0",
     //	      delay_audio_run,
     //	      run_order);
@@ -521,8 +542,6 @@ ags_delay_audio_run_run_pre(AgsRecall *recall)
 				       delay, attack);
   }else{
     guint run_order;
-    gdouble delay;
-    guint attack;
 
     run_order = 0;
     
@@ -541,17 +560,9 @@ ags_delay_audio_run_run_pre(AgsRecall *recall)
 				       delay, attack);
   }
 
+  /* sequencer */
   if(delay_audio_run->sequencer_counter == 0){
     guint run_order;
-    gdouble delay;
-    guint attack;
-
-    /* delay and attack */
-    //TODO:JK: unclear
-    attack = ags_soundcard_get_attack(AGS_SOUNDCARD(recall->soundcard));
-    delay = 0.0; // soundcard->delay[((soundcard->tic_counter + 1 == AGS_NOTATION_TICS_PER_BEAT) ?
-      //		   0:
-      //		   soundcard->tic_counter + 1)];
 
     run_order = 0;
 
@@ -572,8 +583,6 @@ ags_delay_audio_run_run_pre(AgsRecall *recall)
 					delay, attack);
   }else{
     guint run_order;
-    gdouble delay;
-    guint attack;
 
     run_order = 0;
     
diff --git a/ags/audio/recall/ags_envelope_channel.c b/ags/audio/recall/ags_envelope_channel.c
index c1331d2..b2b04a2 100644
--- a/ags/audio/recall/ags_envelope_channel.c
+++ b/ags/audio/recall/ags_envelope_channel.c
@@ -37,6 +37,7 @@ void ags_envelope_channel_get_property(GObject *gobject,
 void ags_envelope_channel_connect(AgsConnectable *connectable);
 void ags_envelope_channel_disconnect(AgsConnectable *connectable);
 void ags_envelope_channel_set_ports(AgsPlugin *plugin, GList *port);
+void ags_envelope_channel_dispose(GObject *gobject);
 void ags_envelope_channel_finalize(GObject *gobject);
 
 /**
@@ -137,9 +138,17 @@ ags_envelope_channel_class_init(AgsEnvelopeChannelClass *envelope_channel)
   gobject->set_property = ags_envelope_channel_set_property;
   gobject->get_property = ags_envelope_channel_get_property;
 
+  gobject->dispose = ags_envelope_channel_dispose;
   gobject->finalize = ags_envelope_channel_finalize;
 
   /* properties */
+  /**
+   * AgsEnvelopeChannel:attack:
+   *
+   * The attack of envelope.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("attack\0",
 				   "attack channel\0",
 				   "Attack of the channel\0",
@@ -149,6 +158,13 @@ ags_envelope_channel_class_init(AgsEnvelopeChannelClass *envelope_channel)
 				  PROP_ATTACK,
 				  param_spec);
 
+  /**
+   * AgsEnvelopeChannel:decay:
+   *
+   * The decay of envelope.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("decay\0",
 				   "decay channel\0",
 				   "Decay of the channel\0",
@@ -158,6 +174,13 @@ ags_envelope_channel_class_init(AgsEnvelopeChannelClass *envelope_channel)
 				  PROP_DECAY,
 				  param_spec);
 
+  /**
+   * AgsEnvelopeChannel:sustain:
+   *
+   * The sustain of envelope.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("sustain\0",
 				   "sustain channel\0",
 				   "Sustain of the channel\0",
@@ -167,6 +190,13 @@ ags_envelope_channel_class_init(AgsEnvelopeChannelClass *envelope_channel)
 				  PROP_SUSTAIN,
 				  param_spec);
 
+  /**
+   * AgsEnvelopeChannel:release:
+   *
+   * The release of envelope.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("release\0",
 				   "release channel\0",
 				   "Release of the channel\0",
@@ -176,6 +206,13 @@ ags_envelope_channel_class_init(AgsEnvelopeChannelClass *envelope_channel)
 				  PROP_RELEASE,
 				  param_spec);
 
+  /**
+   * AgsEnvelopeChannel:ratio:
+   *
+   * The ratio of envelope.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("ratio\0",
 				   "envelope ratio\0",
 				   "The ratio of the envelope\0",
@@ -199,6 +236,7 @@ ags_envelope_channel_init(AgsEnvelopeChannel *envelope_channel)
   /* ports */
   port = NULL;
 
+  /* attack */
   envelope_channel->attack = g_object_new(AGS_TYPE_PORT,
 					  "plugin-name\0", g_strdup("ags-envelope\0"),
 					  "specifier\0", "./attack[0]\0",
@@ -208,10 +246,15 @@ ags_envelope_channel_init(AgsEnvelopeChannel *envelope_channel)
 					  "port-value-size\0", sizeof(gdouble),
 					  "port-value-length\0", 1,
 					  NULL);
+  g_object_ref(envelope_channel->attack);
+  
   envelope_channel->attack->port_value.ags_port_double = 1.0;
 
+  /* add to port */
   port = g_list_prepend(port, envelope_channel->attack);
+  g_object_ref(envelope_channel->attack);
 
+  /* decay */
   envelope_channel->decay = g_object_new(AGS_TYPE_PORT,
 					 "plugin-name\0", g_strdup("ags-envelope\0"),
 					 "specifier\0", "./decay[0]\0",
@@ -221,10 +264,15 @@ ags_envelope_channel_init(AgsEnvelopeChannel *envelope_channel)
 					 "port-value-size\0", sizeof(gdouble),
 					 "port-value-length\0", 1,
 					 NULL);
+  g_object_ref(envelope_channel->decay);
+
   envelope_channel->decay->port_value.ags_port_double = 1.0;
 
+  /* add to port */
   port = g_list_prepend(port, envelope_channel->decay);
+  g_object_ref(envelope_channel->decay);
 
+  /* sustain */
   envelope_channel->sustain = g_object_new(AGS_TYPE_PORT,
 					   "plugin-name\0", g_strdup("ags-envelope\0"),
 					   "specifier\0", "./sustain[0]\0",
@@ -234,10 +282,15 @@ ags_envelope_channel_init(AgsEnvelopeChannel *envelope_channel)
 					   "port-value-size\0", sizeof(gdouble),
 					   "port-value-length\0", 1,
 					   NULL);
-  envelope_channel->sustain->port_value.ags_port_double = 1.0;
+  g_object_ref(envelope_channel->sustain);
 
+  envelope_channel->sustain->port_value.ags_port_double = 1.0;
+  
+  /* add to port */
   port = g_list_prepend(port, envelope_channel->sustain);
+  g_object_ref(envelope_channel->sustain);
 
+  /* release */
   envelope_channel->release = g_object_new(AGS_TYPE_PORT,
 					   "plugin-name\0", g_strdup("ags-envelope\0"),
 					   "specifier\0", "./release[0]\0",
@@ -247,10 +300,15 @@ ags_envelope_channel_init(AgsEnvelopeChannel *envelope_channel)
 					   "port-value-size\0", sizeof(gdouble),
 					   "port-value-length\0", 1,
 					   NULL);
+  g_object_ref(envelope_channel->release);
+  
   envelope_channel->release->port_value.ags_port_boolean = 1.0;
-
+  
+  /* add to port */
   port = g_list_prepend(port, envelope_channel->release);
+  g_object_ref(envelope_channel->release);
 
+  /* ratio */  
   envelope_channel->ratio = g_object_new(AGS_TYPE_PORT,
 					 "plugin-name\0", g_strdup("ags-envelope\0"),
 					 "specifier\0", "./ratio[0]\0",
@@ -260,9 +318,13 @@ ags_envelope_channel_init(AgsEnvelopeChannel *envelope_channel)
 					 "port-value-size\0", sizeof(gdouble),
 					 "port-value-length\0", 1,
 					 NULL);
+  g_object_ref(envelope_channel->ratio);
+  
   envelope_channel->ratio->port_value.ags_port_boolean = 1.0;
 
+  /* add to port */
   port = g_list_prepend(port, envelope_channel->ratio);
+  g_object_ref(envelope_channel->ratio);
 
   /* set ports */
   AGS_RECALL(envelope_channel)->port = port;
@@ -490,6 +552,47 @@ ags_envelope_channel_set_ports(AgsPlugin *plugin, GList *port)
 }
 
 void
+ags_envelope_channel_dispose(GObject *gobject)
+{
+  AgsEnvelopeChannel *envelope_channel;
+
+  envelope_channel = AGS_ENVELOPE_CHANNEL(gobject);
+
+  if(envelope_channel->attack != NULL){
+    g_object_unref(G_OBJECT(envelope_channel->attack));
+
+    envelope_channel->attack = NULL;
+  }
+
+  if(envelope_channel->decay != NULL){
+    g_object_unref(G_OBJECT(envelope_channel->decay));
+
+    envelope_channel->decay = NULL;
+  }
+
+  if(envelope_channel->sustain != NULL){
+    g_object_unref(G_OBJECT(envelope_channel->sustain));
+
+    envelope_channel->sustain = NULL;
+  }
+
+  if(envelope_channel->release != NULL){
+    g_object_unref(G_OBJECT(envelope_channel->release));
+
+    envelope_channel->release = NULL;
+  }
+
+  if(envelope_channel->ratio != NULL){
+    g_object_unref(G_OBJECT(envelope_channel->ratio));
+
+    envelope_channel->ratio = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_envelope_channel_parent_class)->dispose(gobject);
+}
+
+void
 ags_envelope_channel_finalize(GObject *gobject)
 {
   AgsEnvelopeChannel *envelope_channel;
diff --git a/ags/audio/recall/ags_loop_channel.c b/ags/audio/recall/ags_loop_channel.c
index 4ffd557..96fbfd2 100644
--- a/ags/audio/recall/ags_loop_channel.c
+++ b/ags/audio/recall/ags_loop_channel.c
@@ -44,6 +44,7 @@ void ags_loop_channel_get_property(GObject *gobject,
 				   GParamSpec *param_spec);
 void ags_loop_channel_connect(AgsConnectable *connectable);
 void ags_loop_channel_disconnect(AgsConnectable *connectable);
+void ags_loop_channel_dispose(GObject *gobject);
 void ags_loop_channel_finalize(GObject *gobject);
 
 void ags_loop_channel_sequencer_duration_changed_callback(AgsDelayAudio *delay_audio,
@@ -130,12 +131,20 @@ ags_loop_channel_class_init(AgsLoopChannelClass *loop_channel)
   gobject->set_property = ags_loop_channel_set_property;
   gobject->get_property = ags_loop_channel_get_property;
 
+  gobject->dispose = ags_loop_channel_dispose;
   gobject->finalize = ags_loop_channel_finalize;
 
   /* properties */
+  /**
+   * AgsLoopChannel:delay-audio:
+   *
+   * The assigned #AgsDelayAudio.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("delay-audio\0",
-				   "assigned delay-audio\0",
-				   "The delay-audio it is assigned with\0",
+				   "assigned delay audio\0",
+				   "The delay audio it is assigned with\0",
 				   AGS_TYPE_DELAY_AUDIO,
 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
   g_object_class_install_property(gobject,
@@ -187,8 +196,9 @@ ags_loop_channel_set_property(GObject *gobject,
 
       delay_audio = (AgsDelayAudio *) g_value_get_object(value);
 
-      if(loop_channel->delay_audio == delay_audio)
+      if(loop_channel->delay_audio == delay_audio){
 	return;
+      }
 
       if(loop_channel->delay_audio != NULL){
 	g_object_disconnect(G_OBJECT(loop_channel->delay_audio),
@@ -225,10 +235,12 @@ ags_loop_channel_get_property(GObject *gobject,
   AgsLoopChannel *loop_channel;
 
   loop_channel = AGS_LOOP_CHANNEL(gobject);
-
+  
   switch(prop_id){
   case PROP_DELAY_AUDIO:
-    g_value_set_object(value, loop_channel->delay_audio);
+    {
+      g_value_set_object(value, loop_channel->delay_audio);
+    }
     break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
@@ -237,12 +249,31 @@ ags_loop_channel_get_property(GObject *gobject,
 }
 
 void
+ags_loop_channel_dispose(GObject *gobject)
+{
+  AgsLoopChannel *loop_channel;
+
+  loop_channel = AGS_LOOP_CHANNEL(gobject);
+
+  /* delay audio */
+  if(loop_channel->delay_audio != NULL){
+    g_object_unref(G_OBJECT(loop_channel->delay_audio));
+
+    loop_channel->delay_audio = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_loop_channel_parent_class)->dispose(gobject);
+}
+
+void
 ags_loop_channel_finalize(GObject *gobject)
 {
   AgsLoopChannel *loop_channel;
 
   loop_channel = AGS_LOOP_CHANNEL(gobject);
 
+  /* delay audio */
   if(loop_channel->delay_audio != NULL){
     g_object_unref(G_OBJECT(loop_channel->delay_audio));
   }
diff --git a/ags/audio/recall/ags_loop_channel_run.c b/ags/audio/recall/ags_loop_channel_run.c
index 6112983..b2a793c 100644
--- a/ags/audio/recall/ags_loop_channel_run.c
+++ b/ags/audio/recall/ags_loop_channel_run.c
@@ -52,6 +52,7 @@ void ags_loop_channel_run_get_property(GObject *gobject,
 				       guint prop_id,
 				       GValue *value,
 				       GParamSpec *param_spec);
+void ags_loop_channel_run_dispose(GObject *gobject);
 void ags_loop_channel_run_finalize(GObject *gobject);
 void ags_loop_channel_run_connect(AgsConnectable *connectable);
 void ags_loop_channel_run_disconnect(AgsConnectable *connectable);
@@ -171,9 +172,17 @@ ags_loop_channel_run_class_init(AgsLoopChannelRunClass *loop_channel_run)
   gobject->set_property = ags_loop_channel_run_set_property;
   gobject->get_property = ags_loop_channel_run_get_property;
 
+  gobject->dispose = ags_loop_channel_run_dispose;
   gobject->finalize = ags_loop_channel_run_finalize;
 
   /* properties */
+  /**
+   * AgsLoopChannelRun:count-beats-audio-run:
+   *
+   * The count beats audio run dependency.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("count-beats-audio-run\0",
 				   "assigned AgsCountBeatsAudioRun\0",
 				   "The pointer to a counter object which indicates when looping should happen\0",
@@ -335,12 +344,31 @@ ags_loop_channel_run_get_property(GObject *gobject,
 }
 
 void
+ags_loop_channel_run_dispose(GObject *gobject)
+{
+  AgsLoopChannelRun *loop_channel_run;
+
+  loop_channel_run = AGS_LOOP_CHANNEL_RUN(gobject);
+
+  /* count beats audio run */
+  if(loop_channel_run->count_beats_audio_run != NULL){
+    g_object_unref(G_OBJECT(loop_channel_run->count_beats_audio_run));
+
+    loop_channel_run->count_beats_audio_run = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_loop_channel_run_parent_class)->dispose(gobject);
+}
+
+void
 ags_loop_channel_run_finalize(GObject *gobject)
 {
   AgsLoopChannelRun *loop_channel_run;
 
   loop_channel_run = AGS_LOOP_CHANNEL_RUN(gobject);
 
+  /* count beats audio run */
   if(loop_channel_run->count_beats_audio_run != NULL){
     g_object_unref(G_OBJECT(loop_channel_run->count_beats_audio_run));
   }
diff --git a/ags/audio/recall/ags_mute_audio.c b/ags/audio/recall/ags_mute_audio.c
index 4bc783d..3ce8a0b 100644
--- a/ags/audio/recall/ags_mute_audio.c
+++ b/ags/audio/recall/ags_mute_audio.c
@@ -23,6 +23,8 @@
 #include <ags/object/ags_mutable.h>
 #include <ags/object/ags_plugin.h>
 
+#include <ags/plugin/ags_base_plugin.h>
+
 void ags_mute_audio_class_init(AgsMuteAudioClass *mute_audio);
 void ags_mute_audio_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_mute_audio_mutable_interface_init(AgsMutableInterface *mutable);
@@ -39,10 +41,13 @@ void ags_mute_audio_get_property(GObject *gobject,
 void ags_mute_audio_connect(AgsConnectable *connectable);
 void ags_mute_audio_disconnect(AgsConnectable *connectable);
 void ags_mute_audio_set_ports(AgsPlugin *plugin, GList *port);
+void ags_mute_audio_dispose(GObject *gobject);
 void ags_mute_audio_finalize(GObject *gobject);
 
 void ags_mute_audio_set_muted(AgsMutable *mutable, gboolean muted);
 
+static AgsPortDescriptor* ags_mute_audio_get_muted_port_descriptor();
+
 /**
  * SECTION:ags_mute_audio
  * @short_description: mute audio 
@@ -133,9 +138,17 @@ ags_mute_audio_class_init(AgsMuteAudioClass *mute_audio)
   gobject->set_property = ags_mute_audio_set_property;
   gobject->get_property = ags_mute_audio_get_property;
 
+  gobject->dispose = ags_mute_audio_dispose;
   gobject->finalize = ags_mute_audio_finalize;
 
   /* properties */
+  /**
+   * AgsMuteAudio:muted:
+   *
+   * The mute port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("muted\0",
 				   "mute audio\0",
 				   "Mute the audio\0",
@@ -181,20 +194,28 @@ ags_mute_audio_init(AgsMuteAudio *mute_audio)
 
   port = NULL;
 
+  /* muted */
   mute_audio->muted = g_object_new(AGS_TYPE_PORT,
 				   "plugin-name\0", "ags-mute\0",
 				   "specifier\0", "./muted[0]\0",
 				   "control-port\0", "1/1\0",
 				   "port-value-is-pointer\0", FALSE,
-				   "port-value-type\0", G_TYPE_BOOLEAN,
-				   "port-value-size\0", sizeof(gboolean),
+				   "port-value-type\0", G_TYPE_FLOAT,
+				   "port-value-size\0", sizeof(gfloat),
 				   "port-value-length\0", 1,
 				   NULL);
-  mute_audio->muted->port_value.ags_port_boolean = FALSE;
+  g_object_ref(mute_audio->muted);
+
+  mute_audio->muted->port_value.ags_port_float = (float) FALSE;
+
+  /* port descriptor */
+  mute_audio->muted->port_descriptor = ags_mute_audio_get_muted_port_descriptor();
 
+  /* add to port */
   port = g_list_prepend(port, mute_audio->muted);
+  g_object_ref(mute_audio->muted);
 
-  /*  */
+  /* set port */
   AGS_RECALL(mute_audio)->port = port;
 }
 
@@ -262,9 +283,20 @@ ags_mute_audio_get_property(GObject *gobject,
 void
 ags_mute_audio_connect(AgsConnectable *connectable)
 {
-  ags_mute_audio_parent_connectable_interface->connect(connectable);
+  AgsRecall *recall;
+  
+  recall = AGS_RECALL(connectable);
+  
+  if((AGS_RECALL_CONNECTED & (recall->flags)) != 0){
+    return;
+  }
 
-  /* empty */
+  /* load automation */
+  ags_recall_load_automation(recall,
+			     g_list_copy(recall->port));
+
+  /* call parent */
+  ags_mute_audio_parent_connectable_interface->connect(connectable);
 }
 
 void
@@ -292,12 +324,31 @@ ags_mute_audio_set_ports(AgsPlugin *plugin, GList *port)
 }
 
 void
+ags_mute_audio_dispose(GObject *gobject)
+{
+  AgsMuteAudio *mute_audio;
+
+  mute_audio = AGS_MUTE_AUDIO(gobject);
+
+  /* muted */
+  if(mute_audio->muted != NULL){
+    g_object_unref(G_OBJECT(mute_audio->muted));
+
+    mute_audio->muted = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_mute_audio_parent_class)->dispose(gobject);
+}
+
+void
 ags_mute_audio_finalize(GObject *gobject)
 {
   AgsMuteAudio *mute_audio;
 
   mute_audio = AGS_MUTE_AUDIO(gobject);
 
+  /* muted */
   if(mute_audio->muted != NULL){
     g_object_unref(G_OBJECT(mute_audio->muted));
   }
@@ -311,12 +362,45 @@ ags_mute_audio_set_muted(AgsMutable *mutable, gboolean muted)
 {
   GValue value = {0,};
 
-  g_value_init(&value, G_TYPE_BOOLEAN);
-  g_value_set_boolean(&value, muted);
+  g_value_init(&value, G_TYPE_FLOAT);
+  g_value_set_float(&value, (float) muted);
 
   ags_port_safe_write(AGS_MUTE_AUDIO(mutable)->muted, &value);
 }
 
+static AgsPortDescriptor*
+ags_mute_audio_get_muted_port_descriptor()
+{
+  static AgsPortDescriptor *port_descriptor = NULL;
+
+  if(port_descriptor == NULL){
+    port_descriptor = ags_port_descriptor_alloc();
+
+    port_descriptor->flags |= (AGS_PORT_DESCRIPTOR_INPUT |
+			       AGS_PORT_DESCRIPTOR_CONTROL |
+			       AGS_PORT_DESCRIPTOR_TOGGLED);
+
+    port_descriptor->port_index = 0;
+
+    /* range */
+    g_value_init(port_descriptor->default_value,
+		 G_TYPE_FLOAT);
+    g_value_init(port_descriptor->lower_value,
+		 G_TYPE_FLOAT);
+    g_value_init(port_descriptor->upper_value,
+		 G_TYPE_FLOAT);
+
+    g_value_set_float(port_descriptor->default_value,
+		      0.0);
+    g_value_set_float(port_descriptor->lower_value,
+		      0.0);
+    g_value_set_float(port_descriptor->upper_value,
+		      1.0);
+  }
+  
+  return(port_descriptor);
+}
+
 /**
  * ags_mute_audio_new:
  *
diff --git a/ags/audio/recall/ags_mute_audio_signal.c b/ags/audio/recall/ags_mute_audio_signal.c
index 9ed472f..8953542 100644
--- a/ags/audio/recall/ags_mute_audio_signal.c
+++ b/ags/audio/recall/ags_mute_audio_signal.c
@@ -245,21 +245,21 @@ ags_mute_audio_signal_run_inter(AgsRecall *recall)
   /* check channel */
   mute_channel = AGS_MUTE_CHANNEL(AGS_RECALL_CHANNEL_RUN(recall->parent->parent)->recall_channel);
 
-  g_value_init(&channel_value, G_TYPE_BOOLEAN);
+  g_value_init(&channel_value, G_TYPE_FLOAT);
   ags_port_safe_read(mute_channel->muted,
 		     &channel_value);
 
-  channel_muted = g_value_get_boolean(&channel_value);
+  channel_muted = (gboolean) g_value_get_float(&channel_value);
   g_value_unset(&channel_value);
 
   /* check audio */
   mute_audio = AGS_MUTE_AUDIO(AGS_RECALL_CONTAINER(AGS_RECALL(mute_channel)->container)->recall_audio);
 
-  g_value_init(&audio_value, G_TYPE_BOOLEAN);
+  g_value_init(&audio_value, G_TYPE_FLOAT);
   ags_port_safe_read(mute_audio->muted,
 		     &audio_value);
 
-  audio_muted = g_value_get_boolean(&audio_value);
+  audio_muted = (gboolean) g_value_get_float(&audio_value);
   g_value_unset(&audio_value);
 
   /* if not muted return */
diff --git a/ags/audio/recall/ags_mute_channel.c b/ags/audio/recall/ags_mute_channel.c
index 84ed09d..13632d7 100644
--- a/ags/audio/recall/ags_mute_channel.c
+++ b/ags/audio/recall/ags_mute_channel.c
@@ -23,6 +23,8 @@
 #include <ags/object/ags_mutable.h>
 #include <ags/object/ags_plugin.h>
 
+#include <ags/plugin/ags_base_plugin.h>
+
 void ags_mute_channel_class_init(AgsMuteChannelClass *mute_channel);
 void ags_mute_channel_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_mute_channel_mutable_interface_init(AgsMutableInterface *mutable);
@@ -39,10 +41,13 @@ void ags_mute_channel_get_property(GObject *gobject,
 void ags_mute_channel_connect(AgsConnectable *connectable);
 void ags_mute_channel_disconnect(AgsConnectable *connectable);
 void ags_mute_channel_set_ports(AgsPlugin *plugin, GList *port);
+void ags_mute_channel_dispose(GObject *gobject);
 void ags_mute_channel_finalize(GObject *gobject);
 
 void ags_mute_channel_set_muted(AgsMutable *mutable, gboolean muted);
 
+static AgsPortDescriptor* ags_mute_channel_get_muted_port_descriptor();
+
 /**
  * SECTION:ags_mute_channel
  * @short_description: mutes channel
@@ -156,9 +161,17 @@ ags_mute_channel_class_init(AgsMuteChannelClass *mute_channel)
   gobject->set_property = ags_mute_channel_set_property;
   gobject->get_property = ags_mute_channel_get_property;
 
+  gobject->dispose = ags_mute_channel_dispose;
   gobject->finalize = ags_mute_channel_finalize;
 
   /* properties */
+  /**
+   * AgsMuteChannel:muted:
+   *
+   * The mute port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("muted\0",
 				   "mute channel\0",
 				   "Mute the channel\0",
@@ -181,19 +194,28 @@ ags_mute_channel_init(AgsMuteChannel *mute_channel)
 
   port = NULL;
 
+  /* muted */
   mute_channel->muted = g_object_new(AGS_TYPE_PORT,
 				     "plugin-name\0", "ags-mute\0",
 				     "specifier\0", "./muted[0]\0",
 				     "control-port\0", "1/1\0",
 				     "port-value-is-pointer\0", FALSE,
-				     "port-value-type\0", G_TYPE_BOOLEAN,
-				     "port-value-size\0", sizeof(gboolean),
+				     "port-value-type\0", G_TYPE_FLOAT,
+				     "port-value-size\0", sizeof(gfloat),
 				     "port-value-length\0", 1,
 				     NULL);
-  mute_channel->muted->port_value.ags_port_boolean = FALSE;
+  g_object_ref(mute_channel->muted);
+
+  mute_channel->muted->port_value.ags_port_float = (float) FALSE;
+
+  /* port descriptor */
+  mute_channel->muted->port_descriptor = ags_mute_channel_get_muted_port_descriptor();
 
+  /* add to port */
   port = g_list_prepend(port, mute_channel->muted);
+  g_object_ref(mute_channel->muted);
 
+  /* set port */
   AGS_RECALL(mute_channel)->port = port;
 }
 
@@ -260,9 +282,20 @@ ags_mute_channel_get_property(GObject *gobject,
 void
 ags_mute_channel_connect(AgsConnectable *connectable)
 {
-  ags_mute_channel_parent_connectable_interface->connect(connectable);
+  AgsRecall *recall;
+  
+  recall = AGS_RECALL(connectable);
+  
+  if((AGS_RECALL_CONNECTED & (recall->flags)) != 0){
+    return;
+  }
 
-  /* empty */
+  /* load automation */
+  ags_recall_load_automation(recall,
+			     g_list_copy(recall->port));
+
+  /* call parent */
+  ags_mute_channel_parent_connectable_interface->connect(connectable);
 }
 
 void
@@ -290,12 +323,31 @@ ags_mute_channel_set_ports(AgsPlugin *plugin, GList *port)
 }
 
 void
+ags_mute_channel_dispose(GObject *gobject)
+{
+  AgsMuteChannel *mute_channel;
+
+  mute_channel = AGS_MUTE_CHANNEL(gobject);
+
+  /* muted */
+  if(mute_channel->muted != NULL){
+    g_object_unref(G_OBJECT(mute_channel->muted));
+
+    mute_channel->muted = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_mute_channel_parent_class)->dispose(gobject);
+}
+
+void
 ags_mute_channel_finalize(GObject *gobject)
 {
   AgsMuteChannel *mute_channel;
 
   mute_channel = AGS_MUTE_CHANNEL(gobject);
 
+  /* muted */
   if(mute_channel->muted != NULL){
     g_object_unref(G_OBJECT(mute_channel->muted));
   }
@@ -309,12 +361,45 @@ ags_mute_channel_set_muted(AgsMutable *mutable, gboolean muted)
 {
   GValue value = {0,};
 
-  g_value_init(&value, G_TYPE_BOOLEAN);
-  g_value_set_boolean(&value, muted);
+  g_value_init(&value, G_TYPE_FLOAT);
+  g_value_set_float(&value, (float) muted);
 
   ags_port_safe_write(AGS_MUTE_CHANNEL(mutable)->muted, &value);
 }
 
+static AgsPortDescriptor*
+ags_mute_channel_get_muted_port_descriptor()
+{
+  static AgsPortDescriptor *port_descriptor = NULL;
+
+  if(port_descriptor == NULL){
+    port_descriptor = ags_port_descriptor_alloc();
+
+    port_descriptor->flags |= (AGS_PORT_DESCRIPTOR_INPUT |
+			       AGS_PORT_DESCRIPTOR_CONTROL |
+			       AGS_PORT_DESCRIPTOR_TOGGLED);
+
+    port_descriptor->port_index = 0;
+
+    /* range */
+    g_value_init(port_descriptor->default_value,
+		 G_TYPE_FLOAT);
+    g_value_init(port_descriptor->lower_value,
+		 G_TYPE_FLOAT);
+    g_value_init(port_descriptor->upper_value,
+		 G_TYPE_FLOAT);
+
+    g_value_set_float(port_descriptor->default_value,
+		      0.0);
+    g_value_set_float(port_descriptor->lower_value,
+		      0.0);
+    g_value_set_float(port_descriptor->upper_value,
+		      1.0);
+  }
+  
+  return(port_descriptor);
+}
+
 /**
  * ags_mute_channel_new:
  *
diff --git a/ags/audio/recall/ags_peak_channel.c b/ags/audio/recall/ags_peak_channel.c
index 873d2de..44da823 100644
--- a/ags/audio/recall/ags_peak_channel.c
+++ b/ags/audio/recall/ags_peak_channel.c
@@ -25,6 +25,8 @@
 #include <ags/object/ags_mutable.h>
 #include <ags/object/ags_plugin.h>
 
+#include <ags/plugin/ags_base_plugin.h>
+
 #include <ags/audio/ags_audio.h>
 #include <ags/audio/ags_output.h>
 #include <ags/audio/ags_input.h>
@@ -47,8 +49,11 @@ void ags_peak_channel_get_property(GObject *gobject,
 void ags_peak_channel_connect(AgsConnectable *connectable);
 void ags_peak_channel_disconnect(AgsConnectable *connectable);
 void ags_peak_channel_set_ports(AgsPlugin *plugin, GList *port);
+void ags_peak_channel_dispose(GObject *gobject);
 void ags_peak_channel_finalize(GObject *gobject);
 
+static AgsPortDescriptor* ags_peak_channel_get_peak_port_descriptor();
+
 /**
  * SECTION:ags_peak_channel
  * @short_description: peaks channel
@@ -154,9 +159,17 @@ ags_peak_channel_class_init(AgsPeakChannelClass *peak_channel)
   gobject->set_property = ags_peak_channel_set_property;
   gobject->get_property = ags_peak_channel_get_property;
 
+  gobject->dispose = ags_peak_channel_dispose;
   gobject->finalize = ags_peak_channel_finalize;
 
   /* properties */
+  /**
+   * AgsPeakChannel:peak:
+   * 
+   * The peak of the channel.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("peak\0",
 				   "peak of channel\0",
 				   "The peak of channel\0",
@@ -171,6 +184,8 @@ void
 ags_peak_channel_init(AgsPeakChannel *peak_channel)
 {
   GList *port;
+  
+  AGS_RECALL(peak_channel)->flags |= AGS_RECALL_HAS_OUTPUT_PORT;
 
   AGS_RECALL(peak_channel)->name = "ags-peak\0";
   AGS_RECALL(peak_channel)->version = AGS_RECALL_DEFAULT_VERSION;
@@ -179,18 +194,27 @@ ags_peak_channel_init(AgsPeakChannel *peak_channel)
 
   port = NULL;
 
+  /* peak */
   peak_channel->peak = g_object_new(AGS_TYPE_PORT,
-				     "plugin-name\0", ags_peak_channel_plugin_name,
-				     "specifier\0", ags_peak_channel_plugin_specifier[0],
-				     "control-port\0", ags_peak_channel_plugin_control_port[0],
-				     "port-value-is-pointer\0", FALSE,
-				     "port-value-type\0", G_TYPE_DOUBLE,
-				     "port-value-size\0", sizeof(gdouble),
-				     "port-value-length\0", 1,
-				     NULL);
-  peak_channel->peak->port_value.ags_port_double = FALSE;
+				    "plugin-name\0", ags_peak_channel_plugin_name,
+				    "specifier\0", ags_peak_channel_plugin_specifier[0],
+				    "control-port\0", ags_peak_channel_plugin_control_port[0],
+				    "port-value-is-pointer\0", FALSE,
+				    "port-value-type\0", G_TYPE_FLOAT,
+				    "port-value-size\0", sizeof(gfloat),
+				    "port-value-length\0", 1,
+				    NULL);
+  g_object_ref(peak_channel->peak);
+  
+  peak_channel->peak->flags |= AGS_PORT_IS_OUTPUT;
+  peak_channel->peak->port_value.ags_port_float = FALSE;
+  
+  /* port descriptor */
+  peak_channel->peak->port_descriptor = ags_peak_channel_get_peak_port_descriptor();
 
+  /* add to port */  
   port = g_list_prepend(port, peak_channel->peak);
+  g_object_ref(peak_channel->peak);
 
   /* set port */
   AGS_RECALL(peak_channel)->port = port;
@@ -257,12 +281,31 @@ ags_peak_channel_get_property(GObject *gobject,
 }
 
 void
+ags_peak_channel_dispose(GObject *gobject)
+{
+  AgsPeakChannel *peak_channel;
+
+  peak_channel = AGS_PEAK_CHANNEL(gobject);
+
+  /* peak */
+  if(peak_channel->peak != NULL){
+    g_object_unref(G_OBJECT(peak_channel->peak));
+
+    peak_channel->peak = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_peak_channel_parent_class)->dispose(gobject);
+}
+
+void
 ags_peak_channel_finalize(GObject *gobject)
 {
   AgsPeakChannel *peak_channel;
 
   peak_channel = AGS_PEAK_CHANNEL(gobject);
 
+  /* peak */
   if(peak_channel->peak != NULL){
     g_object_unref(G_OBJECT(peak_channel->peak));
   }
@@ -313,8 +356,6 @@ ags_peak_channel_retrieve_peak(AgsPeakChannel *peak_channel,
 {
   AgsChannel *source;
   AgsRecycling *recycling;
-
-  AgsConfig *config;
   
   GList *audio_signal;
 
@@ -329,37 +370,17 @@ ags_peak_channel_retrieve_peak(AgsPeakChannel *peak_channel,
   guint i;
   guint copy_mode;
   
-  GValue value = {0,};
+  GValue *value;
 
   if(peak_channel == NULL){
     return;
   }
-
-  config = ags_config_get_instance();
-  
-  str = ags_config_get_value(config,
-			     AGS_CONFIG_SOUNDCARD,
-			     "buffer-size\0");
-
-  if(str == NULL){
-    str = ags_config_get_value(config,
-			       AGS_CONFIG_SOUNDCARD_0,
-			       "buffer-size\0");
-  }
-
   
-  if(str != NULL){
-    buffer_size = g_ascii_strtoull(str,
-				   NULL,
-				   10);
-    free(str);
-  }else{
-    buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
-  }
-
   source = AGS_RECALL_CHANNEL(peak_channel)->source;
   recycling = source->first_recycling;
-  
+
+  buffer_size = source->buffer_size;
+
   /* initialize buffer */
   buffer = (signed short *) malloc(buffer_size * sizeof(signed short));
   memset(buffer,
@@ -451,24 +472,59 @@ ags_peak_channel_retrieve_peak(AgsPeakChannel *peak_channel,
   if(current_value != 0.0){
     current_value = scale_precision * (atan(1.0 / 440.0) / sin(current_value / 22000.0));
   }
-  
-  g_value_init(&value, G_TYPE_DOUBLE);
+
+  value = g_new0(GValue,
+		 1);
+  g_value_init(value, G_TYPE_FLOAT);
 
   if(current_value < 0.0){
     current_value *= -1.0;
   }
 
-  g_value_set_double(&value,
-		     current_value);
+  g_value_set_float(value,
+		    current_value);
 
   ags_port_safe_write(peak_channel->peak,
-		      &value);
-  g_value_unset(&value);
-
+		      value);
+  g_value_unset(value);
+  g_free(value);
+  
   /* free buffer */
   free(buffer);
 }
 
+static AgsPortDescriptor*
+ags_peak_channel_get_peak_port_descriptor()
+{
+  static AgsPortDescriptor *port_descriptor = NULL;
+
+  if(port_descriptor == NULL){
+    port_descriptor = ags_port_descriptor_alloc();
+
+    port_descriptor->flags |= (AGS_PORT_DESCRIPTOR_INPUT |
+			       AGS_PORT_DESCRIPTOR_CONTROL);
+
+    port_descriptor->port_index = 0;
+
+    /* range */
+    g_value_init(port_descriptor->default_value,
+		 G_TYPE_FLOAT);
+    g_value_init(port_descriptor->lower_value,
+		 G_TYPE_FLOAT);
+    g_value_init(port_descriptor->upper_value,
+		 G_TYPE_FLOAT);
+
+    g_value_set_float(port_descriptor->default_value,
+		      0.0);
+    g_value_set_float(port_descriptor->lower_value,
+		      0.0);
+    g_value_set_float(port_descriptor->upper_value,
+		      10.0);
+  }
+  
+  return(port_descriptor);
+}
+
 /**
  * ags_peak_channel_new:
  * @source: the #AgsChannel as source
diff --git a/ags/audio/recall/ags_play_audio_signal.c b/ags/audio/recall/ags_play_audio_signal.c
index 63f326c..1d5db88 100644
--- a/ags/audio/recall/ags_play_audio_signal.c
+++ b/ags/audio/recall/ags_play_audio_signal.c
@@ -277,6 +277,10 @@ ags_play_audio_signal_run_inter(AgsRecall *recall)
     pthread_mutex_unlock(soundcard_mutex);
 
     ags_recall_done(recall);
+  
+    ags_recycling_remove_audio_signal(source->recycling,
+				      source);
+    g_object_unref(source);
 
     return;
   }
diff --git a/ags/audio/recall/ags_play_channel.c b/ags/audio/recall/ags_play_channel.c
index e165613..219e7ae 100644
--- a/ags/audio/recall/ags_play_channel.c
+++ b/ags/audio/recall/ags_play_channel.c
@@ -45,6 +45,7 @@ void ags_play_channel_get_property(GObject *gobject,
 void ags_play_channel_connect(AgsConnectable *connectable);
 void ags_play_channel_disconnect(AgsConnectable *connectable);
 void ags_play_channel_set_ports(AgsPlugin *plugin, GList *port);
+void ags_play_channel_dispose(GObject *gobject);
 void ags_play_channel_finalize(GObject *gobject);
 
 void ags_play_channel_set_muted(AgsMutable *mutable, gboolean muted);
@@ -152,9 +153,17 @@ ags_play_channel_class_init(AgsPlayChannelClass *play_channel)
   gobject->set_property = ags_play_channel_set_property;
   gobject->get_property = ags_play_channel_get_property;
 
+  gobject->dispose = ags_play_channel_dispose;
   gobject->finalize = ags_play_channel_finalize;
 
   /* properties */
+  /**
+   * AgsPlayChannel:audio-channel:
+   * 
+   * The audio channel port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("audio-channel\0",
 				   "assigned audio channel\0",
 				   "The audio channel this recall does output to\0",
@@ -164,6 +173,13 @@ ags_play_channel_class_init(AgsPlayChannelClass *play_channel)
 				  PROP_AUDIO_CHANNEL,
 				  param_spec);
 
+  /**
+   * AgsPlayChannel:muted:
+   * 
+   * The muted port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("muted\0",
 				   "mute channel\0",
 				   "Mute the channel\0",
@@ -211,6 +227,7 @@ ags_play_channel_init(AgsPlayChannel *play_channel)
 
   port = NULL;
 
+  /* audio channel */
   play_channel->audio_channel = g_object_new(AGS_TYPE_PORT,
 					     "plugin-name\0", ags_play_channel_plugin_name,
 					     "specifier\0", ags_play_channel_specifier[0],
@@ -220,10 +237,15 @@ ags_play_channel_init(AgsPlayChannel *play_channel)
 					     "port-value-size\0", sizeof(guint64),
 					     "port-value-length\0", 1,
 					     NULL);
+  g_object_ref(play_channel->audio_channel);
+
   play_channel->audio_channel->port_value.ags_port_uint = 0;
 
+  /* add to port */
   port = g_list_prepend(port, play_channel->audio_channel);
+  g_object_ref(play_channel->audio_channel);
 
+  /* muted */
   play_channel->muted = g_object_new(AGS_TYPE_PORT,
 				     "plugin-name\0", ags_play_channel_plugin_name,
 				     "specifier\0", ags_play_channel_specifier[1],
@@ -233,9 +255,13 @@ ags_play_channel_init(AgsPlayChannel *play_channel)
 				     "port-value-size\0", sizeof(gboolean),
 				     "port-value-length\0", 1,
 				     NULL);
+  g_object_ref(play_channel->muted);
+
   play_channel->muted->port_value.ags_port_boolean = FALSE;
 
+  /* add to port */
   port = g_list_prepend(port, play_channel->muted);
+  g_object_ref(play_channel->muted);
 
   /* set port */
   AGS_RECALL(play_channel)->port = port;
@@ -328,16 +354,43 @@ ags_play_channel_get_property(GObject *gobject,
 }
 
 void
+ags_play_channel_dispose(GObject *gobject)
+{
+  AgsPlayChannel *play_channel;
+
+  play_channel = AGS_PLAY_CHANNEL(gobject);
+
+  /* audio channel */
+  if(play_channel->audio_channel != NULL){
+    g_object_unref(G_OBJECT(play_channel->audio_channel));
+
+    play_channel->audio_channel = NULL;
+  }
+
+  /* muted */
+  if(play_channel->muted != NULL){
+    g_object_unref(G_OBJECT(play_channel->muted));
+
+    play_channel->muted = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_play_channel_parent_class)->dispose(gobject);
+}
+
+void
 ags_play_channel_finalize(GObject *gobject)
 {
   AgsPlayChannel *play_channel;
 
   play_channel = AGS_PLAY_CHANNEL(gobject);
 
+  /* audio channel */
   if(play_channel->audio_channel != NULL){
     g_object_unref(G_OBJECT(play_channel->audio_channel));
   }
 
+  /* muted */
   if(play_channel->muted != NULL){
     g_object_unref(G_OBJECT(play_channel->muted));
   }
diff --git a/ags/audio/recall/ags_play_channel_run.c b/ags/audio/recall/ags_play_channel_run.c
index 4239ad1..7a4d211 100644
--- a/ags/audio/recall/ags_play_channel_run.c
+++ b/ags/audio/recall/ags_play_channel_run.c
@@ -65,12 +65,12 @@ void ags_play_channel_run_connect(AgsConnectable *connectable);
 void ags_play_channel_run_disconnect(AgsConnectable *connectable);
 void ags_play_channel_run_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
 void ags_play_channel_run_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+void ags_play_channel_run_dispose(GObject *gobject);
 void ags_play_channel_run_finalize(GObject *gobject);
 
 void ags_play_channel_run_run_init_inter(AgsRecall *recall);
 void ags_play_channel_run_run_pre(AgsRecall *recall);
 void ags_play_channel_run_run_post(AgsRecall *recall);
-void ags_play_channel_run_done(AgsRecall *recall);
 void ags_play_channel_run_remove(AgsRecall *recall);
 void ags_play_channel_run_cancel(AgsRecall *recall);
 void ags_play_channel_run_resolve_dependencies(AgsRecall *recall);
@@ -176,9 +176,17 @@ ags_play_channel_run_class_init(AgsPlayChannelRunClass *play_channel_run)
   gobject->set_property = ags_play_channel_run_set_property;
   gobject->get_property = ags_play_channel_run_get_property;
 
+  gobject->dispose = ags_play_channel_run_dispose;
   gobject->finalize = ags_play_channel_run_finalize;
 
   /* properties */
+  /**
+   * AgsPlayChannelRun:stream-channel-run:
+   * 
+   * The stream channel run dependency.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("stream-channel-run\0",
 				   "assigned AgsStreamChannelRun\0",
 				   "the assigned AgsStreamChannelRun\0",
@@ -194,7 +202,7 @@ ags_play_channel_run_class_init(AgsPlayChannelRunClass *play_channel_run)
   recall->run_init_inter = ags_play_channel_run_run_init_inter;
   recall->run_pre = ags_play_channel_run_run_pre;
   recall->run_post = ags_play_channel_run_run_post;
-  recall->done = ags_play_channel_run_done;
+  recall->remove = ags_play_channel_run_remove;
   recall->cancel = ags_play_channel_run_cancel;
   recall->resolve_dependencies = ags_play_channel_run_resolve_dependencies;
   recall->duplicate = ags_play_channel_run_duplicate;
@@ -319,12 +327,33 @@ ags_play_channel_run_get_property(GObject *gobject,
 }
 
 void
+ags_play_channel_run_dispose(GObject *gobject)
+{
+  AgsPlayChannelRun *play_channel_run;
+
+  play_channel_run = AGS_PLAY_CHANNEL_RUN(gobject);
+
+  /* stream channel run */
+  if(play_channel_run->stream_channel_run != NULL){
+    g_object_unref(G_OBJECT(play_channel_run->stream_channel_run));
+
+    play_channel_run->stream_channel_run = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_play_channel_run_parent_class)->dispose(gobject);
+}
+
+void
 ags_play_channel_run_finalize(GObject *gobject)
 {
   AgsPlayChannelRun *play_channel_run;
 
   play_channel_run = AGS_PLAY_CHANNEL_RUN(gobject);
 
+  ags_play_channel_run_stop((AgsPlayChannelRun *) gobject);
+
+  /* stream channel run */
   if(play_channel_run->stream_channel_run != NULL){
     g_object_unref(G_OBJECT(play_channel_run->stream_channel_run));
   }
@@ -395,57 +424,61 @@ ags_play_channel_run_run_post(AgsRecall *recall)
   GList *list;
   GList *recall_recycling_list, *recall_audio_signal_list;
   gboolean found;
-
+  
   AGS_RECALL_CLASS(ags_play_channel_run_parent_class)->run_post(recall);
 
-  if((AGS_PLAY_CHANNEL_RUN_INITIAL_RUN & (AGS_PLAY_CHANNEL_RUN(recall)->flags)) == 0){
-    return;
-  }
-
-  AGS_PLAY_CHANNEL_RUN(recall)->flags &= (~AGS_PLAY_CHANNEL_RUN_INITIAL_RUN);
-
   /* connect done */
   source = AGS_RECALL_CHANNEL_RUN(recall)->source;
   found = FALSE;
 
-  list = ags_recall_find_type_with_recycling_context(source->play,
-						     AGS_TYPE_STREAM_CHANNEL_RUN,
-						     (GObject *) recall->recall_id->recycling_context);
-  stream_channel_run = AGS_STREAM_CHANNEL_RUN(list->data);
-  
-  recall_recycling_list = AGS_RECALL(stream_channel_run)->children;
+  list = source->play;
 
-  while(recall_recycling_list != NULL){
-    recall_audio_signal_list = AGS_RECALL(recall_recycling_list->data)->children;
-      
-    while(recall_audio_signal_list != NULL){
-      found = TRUE;
-      g_signal_connect_after(G_OBJECT(recall_audio_signal_list->data), "done\0",
-			     G_CALLBACK(ags_play_channel_run_stream_audio_signal_done_callback), recall);
+  while((list = ags_recall_find_type_with_recycling_context(list,
+							    AGS_TYPE_STREAM_CHANNEL_RUN,
+							    (GObject *) recall->recall_id->recycling_context)) != NULL){
+    stream_channel_run = AGS_STREAM_CHANNEL_RUN(list->data);
 
+    if((AGS_RECALL_TEMPLATE & (AGS_RECALL(stream_channel_run)->flags)) != 0){
+      list = list->next;
 
-      recall_audio_signal_list = recall_audio_signal_list->next;
+      continue;
     }
+    
+    recall_recycling_list = AGS_RECALL(stream_channel_run)->children;
 
-    recall_recycling_list = recall_recycling_list->next;
-  }
+    while(recall_recycling_list != NULL){
+      recall_audio_signal_list = AGS_RECALL(recall_recycling_list->data)->children;
+      
+      while(recall_audio_signal_list != NULL &&
+	    (AGS_RECALL_DONE & (AGS_RECALL(recall_audio_signal_list->data)->flags)) == 0 &&
+	    (AGS_RECALL_TEMPLATE & (AGS_RECALL(recall_audio_signal_list->data)->flags)) == 0){
+	found = TRUE;
+	break;
+	
+	recall_audio_signal_list = recall_audio_signal_list->next;
+      }
+
+      recall_recycling_list = recall_recycling_list->next;
+    }
 
+    list = list->next;
+  }
+  
   if(!found){
     ags_play_channel_run_stop((AgsPlayChannelRun *) recall);
   }
 }
 
 void
-ags_play_channel_run_done(AgsRecall *recall)
+ags_play_channel_run_remove(AgsRecall *recall)
 {
-  AGS_RECALL_CLASS(ags_play_channel_run_parent_class)->done(recall);
-
   /* empty */
+  AGS_RECALL_CLASS(ags_play_channel_run_parent_class)->remove(recall);
 }
 
 void 
 ags_play_channel_run_cancel(AgsRecall *recall)
-{
+{  
   AGS_RECALL_CLASS(ags_play_channel_run_parent_class)->cancel(recall);
 
   /* empty */
@@ -507,7 +540,7 @@ ags_play_channel_run_duplicate(AgsRecall *recall,
 void
 ags_play_channel_run_stream_audio_signal_done_callback(AgsRecall *recall,
 						       AgsPlayChannelRun *play_channel_run)
-{
+{  
   ags_play_channel_run_stop(play_channel_run);
 }
 
@@ -526,7 +559,7 @@ ags_play_channel_run_stop(AgsPlayChannelRun *play_channel_run)
 
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *soundcard_mutex;
-
+  
   channel = AGS_RECALL_CHANNEL_RUN(play_channel_run)->source;
 
   soundcard = AGS_AUDIO(channel->audio)->soundcard;
diff --git a/ags/audio/recall/ags_play_channel_run_master.c b/ags/audio/recall/ags_play_channel_run_master.c
index 78d27d4..de7d604 100644
--- a/ags/audio/recall/ags_play_channel_run_master.c
+++ b/ags/audio/recall/ags_play_channel_run_master.c
@@ -54,6 +54,7 @@ void ags_play_channel_run_master_connect(AgsConnectable *connectable);
 void ags_play_channel_run_master_disconnect(AgsConnectable *connectable);
 void ags_play_channel_run_master_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
 void ags_play_channel_run_master_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+void ags_play_channel_run_master_dispose(GObject *gobject);
 void ags_play_channel_run_master_finalize(GObject *gobject);
 
 void ags_play_channel_run_master_run_init_pre(AgsRecall *recall);
@@ -173,9 +174,17 @@ ags_play_channel_run_master_class_init(AgsPlayChannelRunMasterClass *play_channe
   gobject->set_property = ags_play_channel_run_master_set_property;
   gobject->get_property = ags_play_channel_run_master_get_property;
 
+  gobject->dispose = ags_play_channel_run_master_dispose;
   gobject->finalize = ags_play_channel_run_master_finalize;
 
   /* properties */
+  /**
+   * AgsPlayChannelRunMaster:stream-channel-run:
+   * 
+   * The assigned stream channel run.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("stream-channel-run\0",
 				   "assigned AgsStreamChannelRun\0",
 				   "an assigned AgsStreamChannelRun\0",
@@ -324,10 +333,37 @@ ags_play_channel_run_master_get_property(GObject *gobject,
 }
 
 void
+ags_play_channel_run_master_dispose(GObject *gobject)
+{
+  AgsPlayChannelRunMaster *play_channel_run_master;
+
+  play_channel_run_master = AGS_PLAY_CHANNEL_RUN_MASTER(gobject);
+
+  /* streamer */
+  if(play_channel_run_master->streamer != NULL){
+    g_list_free_full(play_channel_run_master->streamer,
+		     ags_play_channel_run_master_streamer_free);
+
+    play_channel_run_master->streamer = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_play_channel_run_master_parent_class)->dispose(gobject);
+}
+
+void
 ags_play_channel_run_master_finalize(GObject *gobject)
 {
-  /* empty */
+  AgsPlayChannelRunMaster *play_channel_run_master;
 
+  play_channel_run_master = AGS_PLAY_CHANNEL_RUN_MASTER(gobject);
+  
+  /* streamer */
+  if(play_channel_run_master->streamer != NULL){
+    g_list_free_full(play_channel_run_master->streamer,
+		     ags_play_channel_run_master_streamer_free);
+  }
+  
   /* call parent */
   G_OBJECT_CLASS(ags_play_channel_run_master_parent_class)->finalize(gobject);
 }
@@ -657,6 +693,13 @@ ags_play_channel_run_master_stream_channel_done_callback(AgsRecall *recall,
 void
 ags_play_channel_run_master_streamer_free(AgsPlayChannelRunMasterStreamer *streamer)
 {
+  if(streamer == NULL){
+    return;
+  }
+  
+  g_object_unref(streamer->play_channel_run_master);
+  g_object_unref(streamer->stream_channel_run);
+  
   free(streamer);
 }
 
@@ -666,11 +709,19 @@ ags_play_channel_run_master_streamer_alloc(AgsPlayChannelRunMaster *play_channel
 {
   AgsPlayChannelRunMasterStreamer *streamer;
 
+  if(play_channel_run_master == NULL ||
+     stream_channel_run == NULL){
+    return;
+  }
+  
   streamer = (AgsPlayChannelRunMasterStreamer *) malloc(sizeof(AgsPlayChannelRunMasterStreamer));
 
   streamer->play_channel_run_master = play_channel_run_master;
+  g_object_ref(play_channel_run_master);
+  
   streamer->stream_channel_run = stream_channel_run;
-
+  g_object_ref(stream_channel_run);
+  
   return(streamer);
 }
 
diff --git a/ags/audio/recall/ags_play_notation_audio_run.c b/ags/audio/recall/ags_play_notation_audio_run.c
index 1c777c8..0d1611c 100644
--- a/ags/audio/recall/ags_play_notation_audio_run.c
+++ b/ags/audio/recall/ags_play_notation_audio_run.c
@@ -57,6 +57,7 @@ void ags_play_notation_audio_run_get_property(GObject *gobject,
 					      guint prop_id,
 					      GValue *value,
 					      GParamSpec *param_spec);
+void ags_play_notation_audio_run_dispose(GObject *gobject);
 void ags_play_notation_audio_run_finalize(GObject *gobject);
 void ags_play_notation_audio_run_connect(AgsConnectable *connectable);
 void ags_play_notation_audio_run_disconnect(AgsConnectable *connectable);
@@ -94,6 +95,7 @@ enum{
   PROP_0,
   PROP_DELAY_AUDIO_RUN,
   PROP_COUNT_BEATS_AUDIO_RUN,
+  PROP_NOTATION,
 };
 
 static gpointer ags_play_notation_audio_run_parent_class = NULL;
@@ -173,9 +175,17 @@ ags_play_notation_audio_run_class_init(AgsPlayNotationAudioRunClass *play_notati
   gobject->set_property = ags_play_notation_audio_run_set_property;
   gobject->get_property = ags_play_notation_audio_run_get_property;
 
+  gobject->dispose = ags_play_notation_audio_run_dispose;
   gobject->finalize = ags_play_notation_audio_run_finalize;
 
   /* properties */
+  /**
+   * AgsPlayNotationAudioRun:delay-audio-run:
+   *
+   * The delay audio run dependency.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("delay-audio-run\0",
 				   "assigned AgsDelayAudioRun\0",
 				   "the AgsDelayAudioRun which emits notation_alloc_input signal\0",
@@ -185,6 +195,13 @@ ags_play_notation_audio_run_class_init(AgsPlayNotationAudioRunClass *play_notati
 				  PROP_DELAY_AUDIO_RUN,
 				  param_spec);
 
+  /**
+   * AgsPlayNotationAudioRun:count-beats-audio-run:
+   *
+   * The count beats audio run dependency.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("count-beats-audio-run\0",
 				   "assigned AgsCountBeatsAudioRun\0",
 				   "the AgsCountBeatsAudioRun which just counts\0",
@@ -194,6 +211,22 @@ ags_play_notation_audio_run_class_init(AgsPlayNotationAudioRunClass *play_notati
 				  PROP_COUNT_BEATS_AUDIO_RUN,
 				  param_spec);
 
+  /**
+   * AgsPlayNotationAudioRun:notation:
+   *
+   * The notation containing the notes.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("notation\0",
+				   "assigned AgsNotation\0",
+				   "The AgsNotation containing notes\0",
+				   AGS_TYPE_NOTATION,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_NOTATION,
+				  param_spec);
+
   /* AgsRecallClass */
   recall = (AgsRecallClass *) play_notation_audio_run;
 
@@ -346,6 +379,27 @@ ags_play_notation_audio_run_set_property(GObject *gobject,
       play_notation_audio_run->count_beats_audio_run = count_beats_audio_run;
     }
     break;
+  case PROP_NOTATION:
+    {
+      AgsNotation *notation;
+
+      notation = (AgsNotation *) g_value_get_object(value);
+
+      if(play_notation_audio_run->notation == notation){
+	return;
+      }
+
+      if(play_notation_audio_run->notation != NULL){
+	g_object_unref(play_notation_audio_run->notation);
+      }
+
+      if(notation != NULL){
+	g_object_ref(notation);
+      }
+
+      play_notation_audio_run->notation = notation;
+    }
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
     break;
@@ -373,6 +427,11 @@ ags_play_notation_audio_run_get_property(GObject *gobject,
       g_value_set_object(value, G_OBJECT(play_notation_audio_run->count_beats_audio_run));
     }
     break;
+  case PROP_NOTATION:
+    {
+      g_value_set_object(value, play_notation_audio_run->notation);
+    }
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
     break;
@@ -380,20 +439,60 @@ ags_play_notation_audio_run_get_property(GObject *gobject,
 }
 
 void
+ags_play_notation_audio_run_dispose(GObject *gobject)
+{
+  AgsPlayNotationAudioRun *play_notation_audio_run;
+
+  play_notation_audio_run = AGS_PLAY_NOTATION_AUDIO_RUN(gobject);
+
+  /* delay audio run */
+  if(play_notation_audio_run->delay_audio_run != NULL){
+    g_object_unref(G_OBJECT(play_notation_audio_run->delay_audio_run));
+
+    play_notation_audio_run->delay_audio_run = NULL;
+  }
+
+  /* count beats audio run */
+  if(play_notation_audio_run->count_beats_audio_run != NULL){
+    g_object_unref(G_OBJECT(play_notation_audio_run->count_beats_audio_run));
+
+    play_notation_audio_run->count_beats_audio_run = NULL;
+  }
+
+  /* notation */
+  if(play_notation_audio_run->notation != NULL){
+    g_object_unref(G_OBJECT(play_notation_audio_run->notation));
+
+    play_notation_audio_run->notation = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_play_notation_audio_run_parent_class)->dispose(gobject);
+}
+
+void
 ags_play_notation_audio_run_finalize(GObject *gobject)
 {
   AgsPlayNotationAudioRun *play_notation_audio_run;
 
   play_notation_audio_run = AGS_PLAY_NOTATION_AUDIO_RUN(gobject);
 
+  /* delay audio run */
   if(play_notation_audio_run->delay_audio_run != NULL){
     g_object_unref(G_OBJECT(play_notation_audio_run->delay_audio_run));
   }
 
+  /* count beats audio run */
   if(play_notation_audio_run->count_beats_audio_run != NULL){
     g_object_unref(G_OBJECT(play_notation_audio_run->count_beats_audio_run));
   }
 
+  /* notation */
+  if(play_notation_audio_run->notation != NULL){
+    g_object_unref(G_OBJECT(play_notation_audio_run->notation));
+  }
+
+  /* call parent */
   G_OBJECT_CLASS(ags_play_notation_audio_run_parent_class)->finalize(gobject);
 }
 
@@ -435,8 +534,7 @@ ags_play_notation_audio_run_connect_dynamic(AgsDynamicConnectable *dynamic_conne
 
   /* connect */
   g_signal_connect(G_OBJECT(play_notation_audio_run->delay_audio_run), "notation-alloc-input\0",
-		   G_CALLBACK(ags_play_notation_audio_run_alloc_input_callback), play_notation_audio_run);
-  
+		   G_CALLBACK(ags_play_notation_audio_run_alloc_input_callback), play_notation_audio_run);  
 }
 
 void
@@ -778,10 +876,10 @@ ags_play_notation_audio_run_alloc_input_callback(AgsDelayAudioRun *delay_audio_r
   current_position = notation->notes; // start_loop
   notation_counter = play_notation_audio_run->count_beats_audio_run->notation_counter;
 
-  if(play_notation_audio_run->offset != NULL &&
-     notation_counter > AGS_NOTE(play_notation_audio_run->offset->data)->x[0]){
-    current_position = play_notation_audio_run->offset;
-  }
+  //  if(play_notation_audio_run->offset != NULL &&
+  //     notation_counter > AGS_NOTE(play_notation_audio_run->offset->data)->x[0]){
+  //    current_position = play_notation_audio_run->offset;
+  //  }
   
   pthread_mutex_unlock(audio_mutex);
 
@@ -911,7 +1009,7 @@ ags_play_notation_audio_run_alloc_input_callback(AgsDelayAudioRun *delay_audio_r
 
 	ags_recycling_add_audio_signal(recycling,
 				       audio_signal);
-	g_object_unref(audio_signal);
+	//	g_object_unref(audio_signal);
 
 	/* iterate */
 	recycling = recycling->next;
@@ -931,10 +1029,10 @@ ags_play_notation_audio_run_alloc_input_callback(AgsDelayAudioRun *delay_audio_r
 
   pthread_mutex_lock(audio_mutex);
 
-  if(reset_current &&
-     current_position != NULL){
-    play_notation_audio_run->offset = current_position->prev;
-  }
+  //  if(reset_current &&
+  //     current_position != NULL){
+  //    play_notation_audio_run->offset = current_position->prev;
+  //  }
   
   pthread_mutex_unlock(audio_mutex);
 }
diff --git a/ags/audio/recall/ags_prepare_audio_signal.c b/ags/audio/recall/ags_prepare_audio_signal.c
new file mode 100644
index 0000000..3bc23e7
--- /dev/null
+++ b/ags/audio/recall/ags_prepare_audio_signal.c
@@ -0,0 +1,336 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/audio/recall/ags_prepare_audio_signal.h>
+#include <ags/audio/recall/ags_prepare_channel.h>
+#include <ags/audio/recall/ags_prepare_recycling.h>
+
+#include <ags/lib/ags_parameter.h>
+
+#include <ags/object/ags_connectable.h>
+#include <ags/object/ags_dynamic_connectable.h>
+#include <ags/object/ags_soundcard.h>
+
+#include <ags/thread/ags_mutex_manager.h>
+
+#include <ags/audio/ags_recycling.h>
+#include <ags/audio/ags_audio_signal.h>
+#include <ags/audio/ags_recall_channel.h>
+#include <ags/audio/ags_recall_channel_run.h>
+#include <ags/audio/ags_recall_recycling.h>
+#include <ags/audio/ags_audio_buffer_util.h>
+
+void ags_prepare_audio_signal_class_init(AgsPrepareAudioSignalClass *prepare_audio_signal);
+void ags_prepare_audio_signal_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_prepare_audio_signal_dynamic_connectable_interface_init(AgsDynamicConnectableInterface *dynamic_connectable);
+void ags_prepare_audio_signal_init(AgsPrepareAudioSignal *prepare_audio_signal);
+void ags_prepare_audio_signal_connect(AgsConnectable *connectable);
+void ags_prepare_audio_signal_disconnect(AgsConnectable *connectable);
+void ags_prepare_audio_signal_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+void ags_prepare_audio_signal_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+void ags_prepare_audio_signal_finalize(GObject *gobject);
+
+void ags_prepare_audio_signal_run_init_pre(AgsRecall *recall);
+void ags_prepare_audio_signal_run_pre(AgsRecall *recall);
+AgsRecall* ags_prepare_audio_signal_duplicate(AgsRecall *recall,
+					      AgsRecallID *recall_id,
+					      guint *n_params, GParameter *parameter);
+
+/**
+ * SECTION:ags_prepare_audio_signal
+ * @short_description: prepares audio signal
+ * @title: AgsPrepareAudioSignal
+ * @section_id:
+ * @include: ags/audio/recall/ags_prepare_audio_signal.h
+ *
+ * The #AgsPrepareAudioSignal class prepares the audio signal.
+ */
+
+static gpointer ags_prepare_audio_signal_parent_class = NULL;
+static AgsConnectableInterface *ags_prepare_audio_signal_parent_connectable_interface;
+static AgsDynamicConnectableInterface *ags_prepare_audio_signal_parent_dynamic_connectable_interface;
+
+GType
+ags_prepare_audio_signal_get_type()
+{
+  static GType ags_type_prepare_audio_signal = 0;
+
+  if(!ags_type_prepare_audio_signal){
+    static const GTypeInfo ags_prepare_audio_signal_info = {
+      sizeof (AgsPrepareAudioSignalClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_prepare_audio_signal_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof (AgsPrepareAudioSignal),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_prepare_audio_signal_init,
+    };
+
+    static const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_prepare_audio_signal_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    static const GInterfaceInfo ags_dynamic_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_prepare_audio_signal_dynamic_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    ags_type_prepare_audio_signal = g_type_register_static(AGS_TYPE_RECALL_AUDIO_SIGNAL,
+							   "AgsPrepareAudioSignal\0",
+							   &ags_prepare_audio_signal_info,
+							   0);
+
+    g_type_add_interface_static(ags_type_prepare_audio_signal,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+
+    g_type_add_interface_static(ags_type_prepare_audio_signal,
+				AGS_TYPE_DYNAMIC_CONNECTABLE,
+				&ags_dynamic_connectable_interface_info);
+  }
+
+  return (ags_type_prepare_audio_signal);
+}
+
+void
+ags_prepare_audio_signal_class_init(AgsPrepareAudioSignalClass *prepare_audio_signal)
+{
+  GObjectClass *gobject;
+  AgsRecallClass *recall;
+  GParamSpec *param_spec;
+
+  ags_prepare_audio_signal_parent_class = g_type_class_peek_parent(prepare_audio_signal);
+
+  /* GObjectClass */
+  gobject = (GObjectClass *) prepare_audio_signal;
+
+  gobject->finalize = ags_prepare_audio_signal_finalize;
+
+  /* AgsRecallClass */
+  recall = (AgsRecallClass *) prepare_audio_signal;
+
+  recall->run_init_pre = ags_prepare_audio_signal_run_init_pre;
+  recall->run_pre = ags_prepare_audio_signal_run_pre;
+}
+
+void
+ags_prepare_audio_signal_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  ags_prepare_audio_signal_parent_connectable_interface = g_type_interface_peek_parent(connectable);
+
+  connectable->connect = ags_prepare_audio_signal_connect;
+  connectable->disconnect = ags_prepare_audio_signal_disconnect;
+}
+
+void
+ags_prepare_audio_signal_dynamic_connectable_interface_init(AgsDynamicConnectableInterface *dynamic_connectable)
+{
+  ags_prepare_audio_signal_parent_dynamic_connectable_interface = g_type_interface_peek_parent(dynamic_connectable);
+
+  dynamic_connectable->connect_dynamic = ags_prepare_audio_signal_connect_dynamic;
+  dynamic_connectable->disconnect_dynamic = ags_prepare_audio_signal_disconnect_dynamic;
+}
+
+void
+ags_prepare_audio_signal_init(AgsPrepareAudioSignal *prepare_audio_signal)
+{
+  AGS_RECALL(prepare_audio_signal)->name = "ags-prepare\0";
+  AGS_RECALL(prepare_audio_signal)->version = AGS_RECALL_DEFAULT_VERSION;
+  AGS_RECALL(prepare_audio_signal)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
+  AGS_RECALL(prepare_audio_signal)->xml_type = "ags-prepare-audio-signal\0";
+  AGS_RECALL(prepare_audio_signal)->port = NULL;
+}
+
+void
+ags_prepare_audio_signal_finalize(GObject *gobject)
+{
+  /* call parent */
+  G_OBJECT_CLASS(ags_prepare_audio_signal_parent_class)->finalize(gobject);
+
+  /* empty */
+}
+
+void
+ags_prepare_audio_signal_connect(AgsConnectable *connectable)
+{
+  /* call parent */
+  ags_prepare_audio_signal_parent_connectable_interface->connect(connectable);
+
+  /* empty */
+}
+
+void
+ags_prepare_audio_signal_disconnect(AgsConnectable *connectable)
+{
+  /* call parent */
+  ags_prepare_audio_signal_parent_connectable_interface->disconnect(connectable);
+
+  /* empty */
+}
+
+void
+ags_prepare_audio_signal_connect_dynamic(AgsDynamicConnectable *dynamic_connectable)
+{
+  /* call parent */
+  ags_prepare_audio_signal_parent_dynamic_connectable_interface->connect_dynamic(dynamic_connectable);
+
+  /* empty */
+}
+
+void
+ags_prepare_audio_signal_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable)
+{
+  /* call parent */
+  ags_prepare_audio_signal_parent_dynamic_connectable_interface->disconnect_dynamic(dynamic_connectable);
+
+  /* empty */
+}
+
+void
+ags_prepare_audio_signal_run_init_pre(AgsRecall *recall)
+{
+  GObject *soundcard;
+  AgsRecycling *recycling;
+  AgsAudioSignal *destination;
+  AgsRecallID *parent_recall_id;
+  AgsRecyclingContext *recycling_context;
+  
+  AgsPrepareRecycling *prepare_recycling;
+  AgsPrepareAudioSignal *prepare_audio_signal;
+
+  AgsMutexManager *mutex_manager;
+  
+  GList *stream;
+
+  gdouble delay;
+  guint attack;
+  guint length;
+  
+  pthread_mutex_t *application_mutex;
+  pthread_mutex_t *recycling_mutex;
+  
+  prepare_audio_signal = AGS_PREPARE_AUDIO_SIGNAL(recall);
+  prepare_recycling = AGS_PREPARE_RECYCLING(recall->parent);
+
+  soundcard = AGS_RECALL(prepare_audio_signal)->soundcard;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+  
+  /* recycling */
+  recall->flags &= (~AGS_RECALL_PERSISTENT);
+  recycling = AGS_RECALL_RECYCLING(prepare_recycling)->destination;
+
+  pthread_mutex_lock(application_mutex);
+
+  recycling_mutex = ags_mutex_manager_lookup(mutex_manager,
+					     (GObject *) recycling);
+	
+  pthread_mutex_unlock(application_mutex);
+
+  /* recycling context */
+  recycling_context = recall->recall_id->recycling_context;
+
+  parent_recall_id = ags_recall_id_find_recycling_context(AGS_RECALL_CHANNEL_RUN(recall->parent->parent)->destination->recall_id,
+							  recycling_context->parent);
+
+  //TODO:JK: unclear
+  attack = 0;
+  delay = 0.0;
+
+  /* create new audio signal */
+  destination = ags_audio_signal_new((GObject *) soundcard,
+				     (GObject *) recycling,
+				     (GObject *) parent_recall_id);
+  
+  g_object_set(prepare_audio_signal,
+	       "destination\0", destination,
+	       NULL);  
+  ags_recycling_create_audio_signal_with_defaults(recycling,
+						  destination,
+						  delay, attack);
+  length = 1; // (guint) (2.0 * soundcard->delay[soundcard->tic_counter]) + 1;
+  ags_audio_signal_stream_resize(destination,
+				 length);
+
+  ags_connectable_connect(AGS_CONNECTABLE(destination));
+  
+  destination->stream_current = destination->stream_beginning;
+
+  pthread_mutex_lock(recycling_mutex);
+
+  ags_recycling_add_audio_signal(recycling,
+				 destination);
+
+  pthread_mutex_unlock(recycling_mutex);
+
+#ifdef AGS_DEBUG
+  g_message("prepare %x to %x\0", destination, parent_recall_id);
+  g_message("creating destination\0");
+#endif
+  
+  /* call parent */
+  AGS_RECALL_CLASS(ags_prepare_audio_signal_parent_class)->run_init_pre(recall);
+}
+
+void
+ags_prepare_audio_signal_run_pre(AgsRecall *recall)
+{
+  AGS_RECALL_CLASS(ags_prepare_audio_signal_parent_class)->run_pre(recall);
+
+  if(AGS_RECALL_AUDIO_SIGNAL(recall)->source->stream_current != NULL){
+    void *buffer;
+
+    guint buffer_size;
+
+    buffer = (signed short *) AGS_RECALL_AUDIO_SIGNAL(recall)->destination->stream_current->data;
+    buffer_size = AGS_RECALL_AUDIO_SIGNAL(recall)->destination->buffer_size;
+
+    ags_audio_buffer_util_clear_buffer(buffer, 1,
+				       buffer_size, ags_audio_buffer_util_format_from_soundcard(AGS_RECALL_AUDIO_SIGNAL(recall)->destination->format));
+  }else{
+    ags_recall_done(recall);
+  }
+}
+
+/**
+ * ags_prepare_audio_signal_new:
+ * @audio_signal: an #AgsAudioSignal
+ *
+ * Creates an #AgsPrepareAudioSignal
+ *
+ * Returns: a new #AgsPrepareAudioSignal
+ *
+ * Since: 0.7.122.8
+ */
+AgsPrepareAudioSignal*
+ags_prepare_audio_signal_new(AgsAudioSignal *audio_signal)
+{
+  AgsPrepareAudioSignal *prepare_audio_signal;
+
+  prepare_audio_signal = (AgsPrepareAudioSignal *) g_object_new(AGS_TYPE_PREPARE_AUDIO_SIGNAL,
+								NULL);
+
+  return(prepare_audio_signal);
+}
diff --git a/ags/audio/recall/ags_prepare_audio_signal.h b/ags/audio/recall/ags_prepare_audio_signal.h
new file mode 100644
index 0000000..2b6d139
--- /dev/null
+++ b/ags/audio/recall/ags_prepare_audio_signal.h
@@ -0,0 +1,52 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_PREPARE_AUDIO_SIGNAL_H__
+#define __AGS_PREPARE_AUDIO_SIGNAL_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <ags/audio/ags_recall_audio_signal.h>
+
+#define AGS_TYPE_PREPARE_AUDIO_SIGNAL                (ags_prepare_audio_signal_get_type())
+#define AGS_PREPARE_AUDIO_SIGNAL(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_PREPARE_AUDIO_SIGNAL, AgsPrepareAudioSignal))
+#define AGS_PREPARE_AUDIO_SIGNAL_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_PREPARE_AUDIO_SIGNAL, AgsPrepareAudioSignalClass))
+#define AGS_IS_PREPARE_AUDIO_SIGNAL(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_PREPARE_AUDIO_SIGNAL))
+#define AGS_IS_PREPARE_AUDIO_SIGNAL_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_PREPARE_AUDIO_SIGNAL))
+#define AGS_PREPARE_AUDIO_SIGNAL_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), AGS_TYPE_PREPARE_AUDIO_SIGNAL, AgsPrepareAudioSignalClass))
+
+typedef struct _AgsPrepareAudioSignal AgsPrepareAudioSignal;
+typedef struct _AgsPrepareAudioSignalClass AgsPrepareAudioSignalClass;
+
+struct _AgsPrepareAudioSignal
+{
+  AgsRecallAudioSignal recall_audio_signal;
+};
+
+struct _AgsPrepareAudioSignalClass
+{
+  AgsRecallAudioSignalClass recall_audio_signal;
+};
+
+GType ags_prepare_audio_signal_get_type();
+
+AgsPrepareAudioSignal* ags_prepare_audio_signal_new(AgsAudioSignal *audio_signal);
+
+#endif /*__AGS_PREPARE_AUDIO_SIGNAL_H__*/
diff --git a/ags/audio/recall/ags_prepare_channel.c b/ags/audio/recall/ags_prepare_channel.c
new file mode 100644
index 0000000..36e7b91
--- /dev/null
+++ b/ags/audio/recall/ags_prepare_channel.c
@@ -0,0 +1,188 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/audio/recall/ags_prepare_channel.h>
+
+#include <ags/object/ags_connectable.h>
+#include <ags/object/ags_plugin.h>
+
+void ags_prepare_channel_class_init(AgsPrepareChannelClass *prepare_channel);
+void ags_prepare_channel_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_prepare_channel_plugin_interface_init(AgsPluginInterface *plugin);
+void ags_prepare_channel_init(AgsPrepareChannel *prepare_channel);
+void ags_prepare_channel_connect(AgsConnectable *connectable);
+void ags_prepare_channel_disconnect(AgsConnectable *connectable);
+void ags_prepare_channel_dispose(GObject *gobject);
+void ags_prepare_channel_finalize(GObject *gobject);
+
+/**
+ * SECTION:ags_prepare_channel
+ * @short_description: prepares channel
+ * @title: AgsPrepareChannel
+ * @section_id:
+ * @include: ags/audio/recall/ags_prepare_channel.h
+ *
+ * The #AgsPrepareChannel class provides ports to the effect processor.
+ */
+
+static gpointer ags_prepare_channel_parent_class = NULL;
+static AgsConnectableInterface *ags_prepare_channel_parent_connectable_interface;
+static AgsPluginInterface *ags_prepare_channel_parent_plugin_interface;
+
+static const gchar *ags_prepare_channel_plugin_name = "ags-prepare\0";
+
+GType
+ags_prepare_channel_get_type()
+{
+  static GType ags_type_prepare_channel = 0;
+
+  if(!ags_type_prepare_channel){
+    static const GTypeInfo ags_prepare_channel_info = {
+      sizeof (AgsPrepareChannelClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_prepare_channel_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof (AgsPrepareChannel),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_prepare_channel_init,
+    };
+
+    static const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_prepare_channel_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    static const GInterfaceInfo ags_plugin_interface_info = {
+      (GInterfaceInitFunc) ags_prepare_channel_plugin_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    ags_type_prepare_channel = g_type_register_static(AGS_TYPE_RECALL_CHANNEL,
+						      "AgsPrepareChannel\0",
+						      &ags_prepare_channel_info,
+						      0);
+
+    g_type_add_interface_static(ags_type_prepare_channel,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+
+    g_type_add_interface_static(ags_type_prepare_channel,
+				AGS_TYPE_PLUGIN,
+				&ags_plugin_interface_info);
+  }
+
+  return (ags_type_prepare_channel);
+}
+
+void
+ags_prepare_channel_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  ags_prepare_channel_parent_connectable_interface = g_type_interface_peek_parent(connectable);
+
+  connectable->connect = ags_prepare_channel_connect;
+  connectable->disconnect = ags_prepare_channel_disconnect;
+}
+
+void
+ags_prepare_channel_plugin_interface_init(AgsPluginInterface *plugin)
+{
+  ags_prepare_channel_parent_plugin_interface = g_type_interface_peek_parent(plugin);
+}
+
+void
+ags_prepare_channel_class_init(AgsPrepareChannelClass *prepare_channel)
+{
+  GObjectClass *gobject;
+  AgsRecallClass *recall;
+
+  GParamSpec *param_spec;
+
+  ags_prepare_channel_parent_class = g_type_class_peek_parent(prepare_channel);
+
+  /* GObjectClass */
+  gobject = (GObjectClass *) prepare_channel;
+
+  gobject->dispose = ags_prepare_channel_dispose;
+  gobject->finalize = ags_prepare_channel_finalize;
+}
+
+void
+ags_prepare_channel_init(AgsPrepareChannel *prepare_channel)
+{
+  AGS_RECALL(prepare_channel)->name = "ags-prepare\0";
+  AGS_RECALL(prepare_channel)->version = AGS_RECALL_DEFAULT_VERSION;
+  AGS_RECALL(prepare_channel)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
+  AGS_RECALL(prepare_channel)->xml_type = "ags-prepare-channel\0";
+}
+
+void
+ags_prepare_channel_dispose(GObject *gobject)
+{
+  /* call parent */
+  G_OBJECT_CLASS(ags_prepare_channel_parent_class)->dispose(gobject);
+}
+
+void
+ags_prepare_channel_finalize(GObject *gobject)
+{
+  /* call parent */
+  G_OBJECT_CLASS(ags_prepare_channel_parent_class)->finalize(gobject);
+}
+
+void
+ags_prepare_channel_connect(AgsConnectable *connectable)
+{
+  /* call parent */
+  ags_prepare_channel_parent_connectable_interface->connect(connectable);
+
+  /* empty */
+}
+
+void
+ags_prepare_channel_disconnect(AgsConnectable *connectable)
+{
+  /* call parent */
+  ags_prepare_channel_parent_connectable_interface->disconnect(connectable);
+
+  /* empty */
+}
+
+/**
+ * ags_prepare_channel_new:
+ *
+ * Creates an #AgsPrepareChannel
+ *
+ * Returns: a new #AgsPrepareChannel
+ *
+ * Since: 0.7.122.8
+ */
+AgsPrepareChannel*
+ags_prepare_channel_new()
+{
+  AgsPrepareChannel *prepare_channel;
+
+  prepare_channel = (AgsPrepareChannel *) g_object_new(AGS_TYPE_PREPARE_CHANNEL,
+						       NULL);
+
+  return(prepare_channel);
+}
diff --git a/ags/audio/recall/ags_prepare_channel.h b/ags/audio/recall/ags_prepare_channel.h
new file mode 100644
index 0000000..485eddb
--- /dev/null
+++ b/ags/audio/recall/ags_prepare_channel.h
@@ -0,0 +1,53 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_PREPARE_CHANNEL_H__
+#define __AGS_PREPARE_CHANNEL_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <ags/audio/ags_recall_channel.h>
+#include <ags/audio/ags_channel.h>
+
+#define AGS_TYPE_PREPARE_CHANNEL                (ags_prepare_channel_get_type())
+#define AGS_PREPARE_CHANNEL(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_PREPARE_CHANNEL, AgsPrepareChannel))
+#define AGS_PREPARE_CHANNEL_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_PREPARE_CHANNEL, AgsPrepareChannel))
+#define AGS_IS_PREPARE_CHANNEL(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_PREPARE_CHANNEL))
+#define AGS_IS_PREPARE_CHANNEL_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_PREPARE_CHANNEL))
+#define AGS_PREPARE_CHANNEL_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), AGS_TYPE_PREPARE_CHANNEL, AgsPrepareChannelClass))
+
+typedef struct _AgsPrepareChannel AgsPrepareChannel;
+typedef struct _AgsPrepareChannelClass AgsPrepareChannelClass;
+
+struct _AgsPrepareChannel
+{
+  AgsRecallChannel recall_channel;
+};
+
+struct _AgsPrepareChannelClass
+{
+  AgsRecallChannelClass recall_channel;
+};
+
+GType ags_prepare_channel_get_type();
+
+AgsPrepareChannel* ags_prepare_channel_new();
+
+#endif /*__AGS_PREPARE_CHANNEL_H__*/
diff --git a/ags/audio/recall/ags_prepare_channel_run.c b/ags/audio/recall/ags_prepare_channel_run.c
new file mode 100644
index 0000000..dbb1a9d
--- /dev/null
+++ b/ags/audio/recall/ags_prepare_channel_run.c
@@ -0,0 +1,254 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/audio/recall/ags_prepare_channel_run.h>
+#include <ags/audio/recall/ags_prepare_recycling.h>
+
+#include <ags/object/ags_connectable.h>
+#include <ags/object/ags_dynamic_connectable.h>
+#include <ags/object/ags_plugin.h>
+#include <ags/object/ags_soundcard.h>
+
+#include <ags/audio/ags_audio.h>
+#include <ags/audio/ags_recycling.h>
+#include <ags/audio/ags_recall_id.h>
+
+#include <ags/audio/task/ags_cancel_recall.h>
+
+void ags_prepare_channel_run_class_init(AgsPrepareChannelRunClass *prepare_channel_run);
+void ags_prepare_channel_run_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_prepare_channel_run_dynamic_connectable_interface_init(AgsDynamicConnectableInterface *dynamic_connectable);
+void ags_prepare_channel_run_plugin_interface_init(AgsPluginInterface *plugin);
+void ags_prepare_channel_run_init(AgsPrepareChannelRun *prepare_channel_run);
+void ags_prepare_channel_run_connect(AgsConnectable *connectable);
+void ags_prepare_channel_run_disconnect(AgsConnectable *connectable);
+void ags_prepare_channel_run_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+void ags_prepare_channel_run_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+void ags_prepare_channel_run_finalize(GObject *gobject);
+
+AgsRecall* ags_prepare_channel_run_duplicate(AgsRecall *recall,
+					     AgsRecallID *recall_id,
+					     guint *n_params, GParameter *parameter);
+
+/**
+ * SECTION:ags_prepare_channel_run
+ * @short_description: prepares channel
+ * @title: AgsPrepareChannelRun
+ * @section_id:
+ * @include: ags/audio/recall/ags_prepare_channel_run.h
+ *
+ * The #AgsPrepareChannelRun class prepares the channel.
+ */
+
+static gpointer ags_prepare_channel_run_parent_class = NULL;
+static AgsConnectableInterface *ags_prepare_channel_run_parent_connectable_interface;
+static AgsDynamicConnectableInterface *ags_prepare_channel_run_parent_dynamic_connectable_interface;
+static AgsPluginInterface *ags_prepare_channel_run_parent_plugin_interface;
+
+GType
+ags_prepare_channel_run_get_type()
+{
+  static GType ags_type_prepare_channel_run = 0;
+
+  if(!ags_type_prepare_channel_run){
+    static const GTypeInfo ags_prepare_channel_run_info = {
+      sizeof (AgsPrepareChannelRunClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_prepare_channel_run_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof (AgsPrepareChannelRun),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_prepare_channel_run_init,
+    };
+
+    static const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_prepare_channel_run_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    static const GInterfaceInfo ags_dynamic_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_prepare_channel_run_dynamic_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    static const GInterfaceInfo ags_plugin_interface_info = {
+      (GInterfaceInitFunc) ags_prepare_channel_run_plugin_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    ags_type_prepare_channel_run = g_type_register_static(AGS_TYPE_RECALL_CHANNEL_RUN,
+							  "AgsPrepareChannelRun\0",
+							  &ags_prepare_channel_run_info,
+							  0);
+
+    g_type_add_interface_static(ags_type_prepare_channel_run,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+
+    g_type_add_interface_static(ags_type_prepare_channel_run,
+				AGS_TYPE_DYNAMIC_CONNECTABLE,
+				&ags_dynamic_connectable_interface_info);
+
+    g_type_add_interface_static(ags_type_prepare_channel_run,
+				AGS_TYPE_PLUGIN,
+				&ags_plugin_interface_info);
+  }
+
+  return (ags_type_prepare_channel_run);
+}
+
+void
+ags_prepare_channel_run_class_init(AgsPrepareChannelRunClass *prepare_channel_run)
+{
+  GObjectClass *gobject;
+  AgsRecallClass *recall;
+
+  ags_prepare_channel_run_parent_class = g_type_class_peek_parent(prepare_channel_run);
+
+  /* GObjectClass */
+  gobject = (GObjectClass *) prepare_channel_run;
+
+  gobject->finalize = ags_prepare_channel_run_finalize;
+
+  /* AgsRecallClass */
+  recall = (AgsRecallClass *) prepare_channel_run;
+
+  recall->duplicate = ags_prepare_channel_run_duplicate;
+}
+
+void
+ags_prepare_channel_run_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  ags_prepare_channel_run_parent_connectable_interface = g_type_interface_peek_parent(connectable);
+
+  connectable->connect = ags_prepare_channel_run_connect;
+  connectable->disconnect = ags_prepare_channel_run_disconnect;
+}
+
+void
+ags_prepare_channel_run_dynamic_connectable_interface_init(AgsDynamicConnectableInterface *dynamic_connectable)
+{
+  ags_prepare_channel_run_parent_dynamic_connectable_interface = g_type_interface_peek_parent(dynamic_connectable);
+
+  dynamic_connectable->connect_dynamic = ags_prepare_channel_run_connect_dynamic;
+  dynamic_connectable->disconnect_dynamic = ags_prepare_channel_run_disconnect_dynamic;
+}
+
+void
+ags_prepare_channel_run_plugin_interface_init(AgsPluginInterface *plugin)
+{
+  ags_prepare_channel_run_parent_plugin_interface = g_type_interface_peek_parent(plugin);
+}
+
+void
+ags_prepare_channel_run_init(AgsPrepareChannelRun *prepare_channel_run)
+{
+  AGS_RECALL(prepare_channel_run)->name = "ags-prepare\0";
+  AGS_RECALL(prepare_channel_run)->version = AGS_RECALL_DEFAULT_VERSION;
+  AGS_RECALL(prepare_channel_run)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
+  AGS_RECALL(prepare_channel_run)->xml_type = "ags-prepare-channel-run\0";
+  AGS_RECALL(prepare_channel_run)->port = NULL;
+
+  AGS_RECALL(prepare_channel_run)->flags |= AGS_RECALL_INPUT_ORIENTATED;
+  AGS_RECALL(prepare_channel_run)->child_type = AGS_TYPE_PREPARE_RECYCLING;
+}
+
+void
+ags_prepare_channel_run_finalize(GObject *gobject)
+{
+  /* empty */
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_prepare_channel_run_parent_class)->finalize(gobject);
+}
+
+void
+ags_prepare_channel_run_connect(AgsConnectable *connectable)
+{
+  /* call parent */
+  ags_prepare_channel_run_parent_connectable_interface->connect(connectable);
+
+  /* empty */
+}
+
+void
+ags_prepare_channel_run_disconnect(AgsConnectable *connectable)
+{
+  /* call parent */
+  ags_prepare_channel_run_parent_connectable_interface->disconnect(connectable);
+
+  /* empty */
+}
+
+void
+ags_prepare_channel_run_connect_dynamic(AgsDynamicConnectable *dynamic_connectable)
+{
+  /* call parent */
+  ags_prepare_channel_run_parent_dynamic_connectable_interface->connect_dynamic(dynamic_connectable);
+
+  /* empty */
+}
+
+void
+ags_prepare_channel_run_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable)
+{
+  /* call parent */
+  ags_prepare_channel_run_parent_dynamic_connectable_interface->disconnect_dynamic(dynamic_connectable);
+
+  /* empty */
+}
+
+AgsRecall*
+ags_prepare_channel_run_duplicate(AgsRecall *recall,
+				  AgsRecallID *recall_id,
+				  guint *n_params, GParameter *parameter)
+{
+  AgsPrepareChannelRun *copy;
+
+  copy = (AgsPrepareChannelRun *) AGS_RECALL_CLASS(ags_prepare_channel_run_parent_class)->duplicate(recall,
+												    recall_id,
+												    n_params, parameter);
+
+  return((AgsRecall *) copy);
+}
+
+/**
+ * ags_prepare_channel_run_new:
+ *
+ * Creates an #AgsPrepareChannelRun
+ *
+ * Returns: a new #AgsPrepareChannelRun
+ *
+ * Since: 0.7.122.8
+ */
+AgsPrepareChannelRun*
+ags_prepare_channel_run_new()
+{
+  AgsPrepareChannelRun *prepare_channel_run;
+
+  prepare_channel_run = (AgsPrepareChannelRun *) g_object_new(AGS_TYPE_PREPARE_CHANNEL_RUN,
+							      NULL);
+  
+  return(prepare_channel_run);
+}
diff --git a/ags/audio/recall/ags_prepare_channel_run.h b/ags/audio/recall/ags_prepare_channel_run.h
new file mode 100644
index 0000000..890c3a7
--- /dev/null
+++ b/ags/audio/recall/ags_prepare_channel_run.h
@@ -0,0 +1,54 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_PREPARE_CHANNEL_RUN_H__
+#define __AGS_PREPARE_CHANNEL_RUN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <ags/audio/ags_recall_channel_run.h>
+
+#include <ags/audio/recall/ags_prepare_channel.h>
+
+#define AGS_TYPE_PREPARE_CHANNEL_RUN                (ags_prepare_channel_run_get_type())
+#define AGS_PREPARE_CHANNEL_RUN(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_PREPARE_CHANNEL_RUN, AgsPrepareChannelRun))
+#define AGS_PREPARE_CHANNEL_RUN_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_PREPARE_CHANNEL_RUN, AgsPrepareChannelRunClass))
+#define AGS_IS_PREPARE_CHANNEL_RUN(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), AGS_TYPE_PREPARE_CHANNEL_RUN))
+#define AGS_IS_PREPARE_CHANNEL_RUN_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_PREPARE_CHANNEL_RUN))
+#define AGS_PREPARE_CHANNEL_RUN_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_PREPARE_CHANNEL_RUN, AgsPrepareChannelRunClass))
+
+typedef struct _AgsPrepareChannelRun AgsPrepareChannelRun;
+typedef struct _AgsPrepareChannelRunClass AgsPrepareChannelRunClass;
+
+struct _AgsPrepareChannelRun
+{
+  AgsRecallChannelRun recall_channel_run;
+};
+
+struct _AgsPrepareChannelRunClass
+{
+  AgsRecallChannelRunClass recall_channel_run;
+};
+
+GType ags_prepare_channel_run_get_type();
+
+AgsPrepareChannelRun* ags_prepare_channel_run_new();
+
+#endif /*__AGS_PREPARE_CHANNEL_RUN_H__*/
diff --git a/ags/audio/recall/ags_prepare_recycling.c b/ags/audio/recall/ags_prepare_recycling.c
new file mode 100644
index 0000000..0622388
--- /dev/null
+++ b/ags/audio/recall/ags_prepare_recycling.c
@@ -0,0 +1,234 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/audio/recall/ags_prepare_recycling.h>
+#include <ags/audio/recall/ags_prepare_audio_signal.h>
+
+#include <ags/object/ags_connectable.h>
+#include <ags/object/ags_dynamic_connectable.h>
+
+void ags_prepare_recycling_class_init(AgsPrepareRecyclingClass *prepare_recycling);
+void ags_prepare_recycling_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_prepare_recycling_dynamic_connectable_interface_init(AgsDynamicConnectableInterface *dynamic_connectable);
+void ags_prepare_recycling_init(AgsPrepareRecycling *prepare_recycling);
+void ags_prepare_recycling_connect(AgsConnectable *connectable);
+void ags_prepare_recycling_disconnect(AgsConnectable *connectable);
+void ags_prepare_recycling_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+void ags_prepare_recycling_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+void ags_prepare_recycling_finalize(GObject *gobject);
+
+AgsRecall* ags_prepare_recycling_duplicate(AgsRecall *recall,
+					   AgsRecallID *recall_id,
+					   guint *n_params, GParameter *parameter);
+void ags_prepare_recycling_remove(AgsRecall *recall);
+
+/**
+ * SECTION:ags_prepare_recycling
+ * @short_description: prepares recycling
+ * @title: AgsPrepareRecycling
+ * @section_id:
+ * @include: ags/audio/recall/ags_prepare_recycling.h
+ *
+ * The #AgsPrepareRecycling class prepares the recycling.
+ */
+
+static gpointer ags_prepare_recycling_parent_class = NULL;
+static AgsConnectableInterface *ags_prepare_recycling_parent_connectable_interface;
+static AgsDynamicConnectableInterface *ags_prepare_recycling_parent_dynamic_connectable_interface;
+
+GType
+ags_prepare_recycling_get_type()
+{
+  static GType ags_type_prepare_recycling = 0;
+
+  if(!ags_type_prepare_recycling){
+    static const GTypeInfo ags_prepare_recycling_info = {
+      sizeof (AgsPrepareRecyclingClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_prepare_recycling_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof (AgsPrepareRecycling),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_prepare_recycling_init,
+    };
+
+    static const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_prepare_recycling_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    static const GInterfaceInfo ags_dynamic_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_prepare_recycling_dynamic_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    ags_type_prepare_recycling = g_type_register_static(AGS_TYPE_RECALL_RECYCLING,
+							"AgsPrepareRecycling\0",
+							&ags_prepare_recycling_info,
+							0);
+
+    g_type_add_interface_static(ags_type_prepare_recycling,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+
+    g_type_add_interface_static(ags_type_prepare_recycling,
+				AGS_TYPE_DYNAMIC_CONNECTABLE,
+				&ags_dynamic_connectable_interface_info);
+  }
+
+  return (ags_type_prepare_recycling);
+}
+
+void
+ags_prepare_recycling_class_init(AgsPrepareRecyclingClass *prepare_recycling)
+{
+  GObjectClass *gobject;
+  AgsRecallClass *recall;
+  GParamSpec *param_spec;
+
+  ags_prepare_recycling_parent_class = g_type_class_peek_parent(prepare_recycling);
+
+  /* GObjectClass */
+  gobject = (GObjectClass *) prepare_recycling;
+
+  gobject->finalize = ags_prepare_recycling_finalize;
+
+  /* AgsRecallClass */
+  recall = (AgsRecallClass *) prepare_recycling;
+
+  recall->duplicate = ags_prepare_recycling_duplicate;
+}
+
+void
+ags_prepare_recycling_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  ags_prepare_recycling_parent_connectable_interface = g_type_interface_peek_parent(connectable);
+
+  connectable->connect = ags_prepare_recycling_connect;
+  connectable->disconnect = ags_prepare_recycling_disconnect;
+}
+
+void
+ags_prepare_recycling_dynamic_connectable_interface_init(AgsDynamicConnectableInterface *dynamic_connectable)
+{
+  ags_prepare_recycling_parent_dynamic_connectable_interface = g_type_interface_peek_parent(dynamic_connectable);
+
+  dynamic_connectable->connect_dynamic = ags_prepare_recycling_connect_dynamic;
+  dynamic_connectable->disconnect_dynamic = ags_prepare_recycling_disconnect_dynamic;
+}
+
+void
+ags_prepare_recycling_init(AgsPrepareRecycling *prepare_recycling)
+{
+  AGS_RECALL(prepare_recycling)->name = "ags-prepare\0";
+  AGS_RECALL(prepare_recycling)->version = AGS_RECALL_DEFAULT_VERSION;
+  AGS_RECALL(prepare_recycling)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
+  AGS_RECALL(prepare_recycling)->xml_type = "ags-prepare-recycling\0";
+  AGS_RECALL(prepare_recycling)->port = NULL;
+
+  AGS_RECALL(prepare_recycling)->child_type = AGS_TYPE_PREPARE_AUDIO_SIGNAL;
+
+  AGS_RECALL_RECYCLING(prepare_recycling)->flags |= (AGS_RECALL_RECYCLING_MAP_CHILD_SOURCE);
+}
+
+void
+ags_prepare_recycling_finalize(GObject *gobject)
+{
+  /* empty */
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_prepare_recycling_parent_class)->finalize(gobject);
+}
+
+void
+ags_prepare_recycling_connect(AgsConnectable *connectable)
+{
+  if((AGS_RECALL_CONNECTED & (AGS_RECALL(connectable)->flags)) != 0){
+    return;
+  }
+
+  ags_prepare_recycling_parent_connectable_interface->connect(connectable);
+
+  /* empty */
+}
+
+void
+ags_prepare_recycling_disconnect(AgsConnectable *connectable)
+{
+  ags_prepare_recycling_parent_connectable_interface->disconnect(connectable);
+
+  /* empty */
+}
+
+void
+ags_prepare_recycling_connect_dynamic(AgsDynamicConnectable *dynamic_connectable)
+{
+  if((AGS_RECALL_DYNAMIC_CONNECTED & (AGS_RECALL(dynamic_connectable)->flags)) != 0){
+    return;
+  }
+
+  ags_prepare_recycling_parent_dynamic_connectable_interface->connect_dynamic(dynamic_connectable);
+}
+
+void
+ags_prepare_recycling_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable)
+{
+  ags_prepare_recycling_parent_dynamic_connectable_interface->disconnect_dynamic(dynamic_connectable);
+}
+
+AgsRecall*
+ags_prepare_recycling_duplicate(AgsRecall *recall,
+				AgsRecallID *recall_id,
+				guint *n_params, GParameter *parameter)
+{
+  AgsPrepareRecycling *copy;
+
+  copy = (AgsPrepareRecycling *) AGS_RECALL_CLASS(ags_prepare_recycling_parent_class)->duplicate(recall,
+												 recall_id,
+												 n_params, parameter);
+
+
+  return((AgsRecall *) copy);
+}
+
+/**
+ * ags_prepare_recycling_new:
+ * @recycling: an #AgsRecycling
+ *
+ * Creates an #AgsPrepareRecycling
+ *
+ * Returns: a new #AgsPrepareRecycling
+ *
+ * Since: 0.7.122.8
+ */
+AgsPrepareRecycling*
+ags_prepare_recycling_new(AgsRecycling *recycling)
+{
+  AgsPrepareRecycling *prepare_recycling;
+
+  prepare_recycling = (AgsPrepareRecycling *) g_object_new(AGS_TYPE_PREPARE_RECYCLING,
+							   "source\0", recycling,
+							   NULL);
+
+  return(prepare_recycling);
+}
diff --git a/ags/audio/recall/ags_prepare_recycling.h b/ags/audio/recall/ags_prepare_recycling.h
new file mode 100644
index 0000000..a52ec3e
--- /dev/null
+++ b/ags/audio/recall/ags_prepare_recycling.h
@@ -0,0 +1,52 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_PREPARE_RECYCLING_H__
+#define __AGS_PREPARE_RECYCLING_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <ags/audio/ags_recall_recycling.h>
+
+#define AGS_TYPE_PREPARE_RECYCLING                (ags_prepare_recycling_get_type())
+#define AGS_PREPARE_RECYCLING(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_PREPARE_RECYCLING, AgsPrepareRecycling))
+#define AGS_PREPARE_RECYCLING_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_PREPARE_RECYCLING, AgsPrepareRecyclingClass))
+#define AGS_IS_PREPARE_RECYCLING(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_PREPARE_RECYCLING))
+#define AGS_IS_PREPARE_RECYCLING_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_PREPARE_RECYCLING))
+#define AGS_PREPARE_RECYCLING_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), AGS_TYPE_PREPARE_RECYCLING, AgsPrepareRecyclingClass))
+
+typedef struct _AgsPrepareRecycling AgsPrepareRecycling;
+typedef struct _AgsPrepareRecyclingClass AgsPrepareRecyclingClass;
+
+struct _AgsPrepareRecycling
+{
+  AgsRecallRecycling recall_recycling;
+};
+
+struct _AgsPrepareRecyclingClass
+{
+  AgsRecallRecyclingClass recall_recycling;
+};
+
+GType ags_prepare_recycling_get_type();
+
+AgsPrepareRecycling* ags_prepare_recycling_new(AgsRecycling *recycling);
+
+#endif /*__AGS_PREPARE_RECYCLING_H__*/
diff --git a/ags/audio/recall/ags_record_midi_audio.c b/ags/audio/recall/ags_record_midi_audio.c
index 56f5314..819a44a 100644
--- a/ags/audio/recall/ags_record_midi_audio.c
+++ b/ags/audio/recall/ags_record_midi_audio.c
@@ -32,6 +32,7 @@ void ags_record_midi_audio_get_property(GObject *gobject,
 					guint prop_id,
 					GValue *value,
 					GParamSpec *param_spec);
+void ags_record_midi_audio_dispose(GObject *gobject);
 void ags_record_midi_audio_finalize(GObject *gobject);
 void ags_record_midi_audio_set_ports(AgsPlugin *plugin, GList *port);
 
@@ -127,9 +128,17 @@ ags_record_midi_audio_class_init(AgsRecordMidiAudioClass *record_midi_audio)
   gobject->set_property = ags_record_midi_audio_set_property;
   gobject->get_property = ags_record_midi_audio_get_property;
 
+  gobject->dispose = ags_record_midi_audio_dispose;
   gobject->finalize = ags_record_midi_audio_finalize;
 
   /* properties */
+  /**
+   * AgsRecordMidiAudio:playback:
+   * 
+   * The playback port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("playback\0",
 				   "if do playback\0",
 				   "If playback should be performed\0",
@@ -139,6 +148,13 @@ ags_record_midi_audio_class_init(AgsRecordMidiAudioClass *record_midi_audio)
 				  PROP_PLAYBACK,
 				  param_spec);
 
+  /**
+   * AgsRecordMidiAudio:record:
+   * 
+   * The record port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("record\0",
 				   "if do record\0",
 				   "If record data for later use should be done\0",
@@ -148,6 +164,13 @@ ags_record_midi_audio_class_init(AgsRecordMidiAudioClass *record_midi_audio)
 				  PROP_RECORD,
 				  param_spec);
 
+  /**
+   * AgsRecordMidiAudio:filename:
+   * 
+   * The filename port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("filename\0",
 				   "filename of record\0",
 				   "The filename of record\0",
@@ -157,6 +180,13 @@ ags_record_midi_audio_class_init(AgsRecordMidiAudioClass *record_midi_audio)
 				  PROP_FILENAME,
 				  param_spec);
 
+  /**
+   * AgsRecordMidiAudio:division:
+   * 
+   * The division port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("division\0",
 				   "division of record\0",
 				   "The division of record\0",
@@ -166,6 +196,13 @@ ags_record_midi_audio_class_init(AgsRecordMidiAudioClass *record_midi_audio)
 				  PROP_DIVISION,
 				  param_spec);
 
+  /**
+   * AgsRecordMidiAudio:tempo:
+   * 
+   * The tempo port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("tempo\0",
 				   "tempo of record\0",
 				   "The tempo of record\0",
@@ -175,6 +212,13 @@ ags_record_midi_audio_class_init(AgsRecordMidiAudioClass *record_midi_audio)
 				  PROP_TEMPO,
 				  param_spec);
 
+  /**
+   * AgsRecordMidiAudio:bpm:
+   * 
+   * The bpm port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("bpm\0",
 				   "bpm of record\0",
 				   "The bpm of record\0",
@@ -213,11 +257,14 @@ ags_record_midi_audio_init(AgsRecordMidiAudio *record_midi_audio)
 					     "port-value-is-pointer\0", FALSE,
 					     "port-value-type\0", G_TYPE_BOOLEAN,
 					     NULL);
-
+  g_object_ref(record_midi_audio->playback);
+  
   record_midi_audio->playback->port_value.ags_port_boolean = TRUE;
 
+  /* add to port */
   port = g_list_prepend(port, record_midi_audio->playback);
-
+  g_object_ref(record_midi_audio->playback);
+  
   /* record */
   record_midi_audio->record = g_object_new(AGS_TYPE_PORT,
 					   "plugin-name\0", ags_record_midi_audio_plugin_name,
@@ -226,10 +273,13 @@ ags_record_midi_audio_init(AgsRecordMidiAudio *record_midi_audio)
 					   "port-value-is-pointer\0", FALSE,
 					   "port-value-type\0", G_TYPE_BOOLEAN,
 					   NULL);
-
+  g_object_ref(record_midi_audio->record);
+  
   record_midi_audio->record->port_value.ags_port_boolean = FALSE;
 
+  /* add to port */
   port = g_list_prepend(port, record_midi_audio->record);
+  g_object_ref(record_midi_audio->record);
 
   /* filename */
   record_midi_audio->filename = g_object_new(AGS_TYPE_PORT,
@@ -239,10 +289,13 @@ ags_record_midi_audio_init(AgsRecordMidiAudio *record_midi_audio)
 					     "port-value-is-pointer\0", FALSE,
 					     "port-value-type\0", G_TYPE_BOOLEAN,
 					     NULL);
+  g_object_ref(record_midi_audio->filename);
 
   record_midi_audio->filename->port_value.ags_port_boolean = TRUE;
 
+  /* add to port */
   port = g_list_prepend(port, record_midi_audio->filename);
+  g_object_ref(record_midi_audio->filename);
 
   /* division */
   record_midi_audio->division = g_object_new(AGS_TYPE_PORT,
@@ -252,10 +305,13 @@ ags_record_midi_audio_init(AgsRecordMidiAudio *record_midi_audio)
 					     "port-value-is-pointer\0", FALSE,
 					     "port-value-type\0", G_TYPE_INT64,
 					     NULL);
+  g_object_ref(record_midi_audio->division);
 
   record_midi_audio->division->port_value.ags_port_int = 0;
 
+  /* add to port */
   port = g_list_prepend(port, record_midi_audio->division);
+  g_object_ref(record_midi_audio->division);
 
   /* tempo */
   record_midi_audio->tempo = g_object_new(AGS_TYPE_PORT,
@@ -265,10 +321,13 @@ ags_record_midi_audio_init(AgsRecordMidiAudio *record_midi_audio)
 					  "port-value-is-pointer\0", FALSE,
 					  "port-value-type\0", G_TYPE_INT64,
 					  NULL);
+  g_object_ref(record_midi_audio->tempo);
 
   record_midi_audio->tempo->port_value.ags_port_int = 0;
 
+  /* add to port */
   port = g_list_prepend(port, record_midi_audio->tempo);
+  g_object_ref(record_midi_audio->tempo);
 
   /* bpm */
   record_midi_audio->bpm = g_object_new(AGS_TYPE_PORT,
@@ -278,10 +337,13 @@ ags_record_midi_audio_init(AgsRecordMidiAudio *record_midi_audio)
 					"port-value-is-pointer\0", FALSE,
 					"port-value-type\0", G_TYPE_INT64,
 					NULL);
+  g_object_ref(record_midi_audio->bpm);
 
   record_midi_audio->bpm->port_value.ags_port_int = 120;
 
+  /* add to port */
   port = g_list_prepend(port, record_midi_audio->bpm);
+  g_object_ref(record_midi_audio->bpm);
 
   /* set port */
   AGS_RECALL(record_midi_audio)->port = port;
@@ -478,12 +540,95 @@ ags_record_midi_audio_get_property(GObject *gobject,
 }
 
 void
+ags_record_midi_audio_dispose(GObject *gobject)
+{
+  AgsRecordMidiAudio *record_midi_audio;
+
+  record_midi_audio = AGS_RECORD_MIDI_AUDIO(gobject);
+
+  /* playback */
+  if(record_midi_audio->playback != NULL){
+    g_object_unref(record_midi_audio->playback);
+
+    record_midi_audio->playback = NULL;
+  }
+
+  /* record */
+  if(record_midi_audio->record != NULL){
+    g_object_unref(record_midi_audio->record);
+
+    record_midi_audio->record = NULL;
+  }
+
+  /* filename */
+  if(record_midi_audio->filename != NULL){
+    g_object_unref(record_midi_audio->filename);
+
+    record_midi_audio->filename = NULL;
+  }
+
+  /* division */
+  if(record_midi_audio->division != NULL){
+    g_object_unref(record_midi_audio->division);
+
+    record_midi_audio->division = NULL;
+  }
+
+  /* tempo */
+  if(record_midi_audio->tempo != NULL){
+    g_object_unref(record_midi_audio->tempo);
+
+    record_midi_audio->tempo = NULL;
+  }
+
+  /* bpm */
+  if(record_midi_audio->bpm != NULL){
+    g_object_unref(record_midi_audio->bpm);
+
+    record_midi_audio->bpm = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_record_midi_audio_parent_class)->dispose(gobject);
+}
+
+void
 ags_record_midi_audio_finalize(GObject *gobject)
 {
   AgsRecordMidiAudio *record_midi_audio;
 
   record_midi_audio = AGS_RECORD_MIDI_AUDIO(gobject);
 
+  /* playback */
+  if(record_midi_audio->playback != NULL){
+    g_object_unref(record_midi_audio->playback);
+  }
+
+  /* record */
+  if(record_midi_audio->record != NULL){
+    g_object_unref(record_midi_audio->record);
+  }
+
+  /* filename */
+  if(record_midi_audio->filename != NULL){
+    g_object_unref(record_midi_audio->filename);
+  }
+
+  /* division */
+  if(record_midi_audio->division != NULL){
+    g_object_unref(record_midi_audio->division);
+  }
+
+  /* tempo */
+  if(record_midi_audio->tempo != NULL){
+    g_object_unref(record_midi_audio->tempo);
+  }
+
+  /* bpm */
+  if(record_midi_audio->bpm != NULL){
+    g_object_unref(record_midi_audio->bpm);
+  }
+
   /* call parent */
   G_OBJECT_CLASS(ags_record_midi_audio_parent_class)->finalize(gobject);
 }
diff --git a/ags/audio/recall/ags_record_midi_audio_run.c b/ags/audio/recall/ags_record_midi_audio_run.c
index 33cfe81..4a05fac 100644
--- a/ags/audio/recall/ags_record_midi_audio_run.c
+++ b/ags/audio/recall/ags_record_midi_audio_run.c
@@ -60,6 +60,7 @@ void ags_record_midi_audio_run_get_property(GObject *gobject,
 					    guint prop_id,
 					    GValue *value,
 					    GParamSpec *param_spec);
+void ags_record_midi_audio_run_dispose(GObject *gobject);
 void ags_record_midi_audio_run_finalize(GObject *gobject);
 void ags_record_midi_audio_run_connect(AgsConnectable *connectable);
 void ags_record_midi_audio_run_disconnect(AgsConnectable *connectable);
@@ -87,7 +88,7 @@ void ags_record_midi_audio_run_read_resolve_dependency(AgsFileLookup *file_looku
  * @section_id:
  * @include: ags/audio/recall/ags_record_midi_audio_run.h
  *
- * The #AgsRecordMidiAudioRun class record midi.
+ * The #AgsRecordMidiAudioRun does record midi.
  */
 
 enum{
@@ -173,9 +174,17 @@ ags_record_midi_audio_run_class_init(AgsRecordMidiAudioRunClass *record_midi_aud
   gobject->set_property = ags_record_midi_audio_run_set_property;
   gobject->get_property = ags_record_midi_audio_run_get_property;
 
+  gobject->dispose = ags_record_midi_audio_run_dispose;
   gobject->finalize = ags_record_midi_audio_run_finalize;
 
   /* properties */
+  /**
+   * AgsRecordMidiAudioRun:delay-audio-run:
+   * 
+   * The delay audio run dependency.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("delay-audio-run\0",
 				   "assigned AgsDelayAudioRun\0",
 				   "the AgsDelayAudioRun which emits midi_alloc_input signal\0",
@@ -185,6 +194,13 @@ ags_record_midi_audio_run_class_init(AgsRecordMidiAudioRunClass *record_midi_aud
 				  PROP_DELAY_AUDIO_RUN,
 				  param_spec);
 
+  /**
+   * AgsRecordMidiAudioRun:count-beats-audio-run:
+   * 
+   * The count beats audio run dependency.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("count-beats-audio-run\0",
 				   "assigned AgsCountBeatsAudioRun\0",
 				   "the AgsCountBeatsAudioRun which just counts\0",
@@ -370,20 +386,48 @@ ags_record_midi_audio_run_get_property(GObject *gobject,
 }
 
 void
+ags_record_midi_audio_run_dispose(GObject *gobject)
+{
+  AgsRecordMidiAudioRun *record_midi_audio_run;
+
+  record_midi_audio_run = AGS_RECORD_MIDI_AUDIO_RUN(gobject);
+
+  /* delay audio run */
+  if(record_midi_audio_run->delay_audio_run != NULL){
+    g_object_unref(G_OBJECT(record_midi_audio_run->delay_audio_run));
+
+    record_midi_audio_run->delay_audio_run = NULL;
+  }
+
+  /* count beats audio run */
+  if(record_midi_audio_run->count_beats_audio_run != NULL){
+    g_object_unref(G_OBJECT(record_midi_audio_run->count_beats_audio_run));
+
+    record_midi_audio_run->count_beats_audio_run = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_record_midi_audio_run_parent_class)->dispose(gobject);
+}
+
+void
 ags_record_midi_audio_run_finalize(GObject *gobject)
 {
   AgsRecordMidiAudioRun *record_midi_audio_run;
 
   record_midi_audio_run = AGS_RECORD_MIDI_AUDIO_RUN(gobject);
 
+  /* delay audio run */
   if(record_midi_audio_run->delay_audio_run != NULL){
     g_object_unref(G_OBJECT(record_midi_audio_run->delay_audio_run));
   }
 
+  /* count beats audio run */
   if(record_midi_audio_run->count_beats_audio_run != NULL){
     g_object_unref(G_OBJECT(record_midi_audio_run->count_beats_audio_run));
   }
 
+  /* call parent */
   G_OBJECT_CLASS(ags_record_midi_audio_run_parent_class)->finalize(gobject);
 }
 
@@ -610,7 +654,7 @@ ags_record_midi_audio_run_duplicate(AgsRecall *recall,
 				    AgsRecallID *recall_id,
 				    guint *n_params, GParameter *parameter)
 {
-  AgsRecordMidiAudioRun *copy, *record_midi_audio_run;
+  AgsRecordMidiAudioRun *copy;
 
   copy = AGS_RECORD_MIDI_AUDIO_RUN(AGS_RECALL_CLASS(ags_record_midi_audio_run_parent_class)->duplicate(recall,
 												       recall_id,
@@ -687,8 +731,10 @@ ags_record_midi_audio_run_run_pre(AgsRecall *recall)
 
   glong division, tempo, bpm;
   guint notation_counter;
+  gboolean reverse_mapping;
   gboolean pattern_mode;
   gboolean playback, record;
+  guint midi_channel;
   guint audio_start_mapping;
   guint midi_start_mapping, midi_end_mapping;
   guint input_pads;
@@ -703,22 +749,15 @@ ags_record_midi_audio_run_run_pre(AgsRecall *recall)
   pthread_mutex_t *audio_mutex;
   pthread_mutex_t *channel_mutex;
 
+  /*  */
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+
+  /* get defaults */
   record_midi_audio_run = AGS_RECORD_MIDI_AUDIO_RUN(recall);
   record_midi_audio = AGS_RECORD_MIDI_AUDIO(AGS_RECALL_AUDIO_RUN(recall)->recall_audio);
 
-  delay_audio_run = record_midi_audio_run->delay_audio_run;
-  count_beats_audio_run = AGS_COUNT_BEATS_AUDIO_RUN(record_midi_audio_run->count_beats_audio_run);
-  
   audio = AGS_RECALL_AUDIO(record_midi_audio)->audio;
-  sequencer = audio->sequencer;
-
-  if(sequencer == NULL){
-    return;
-  }
-
-  /*  */
-  mutex_manager = ags_mutex_manager_get_instance();
-  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
 
   /* get audio mutex */
   pthread_mutex_lock(application_mutex);
@@ -728,10 +767,29 @@ ags_record_midi_audio_run_run_pre(AgsRecall *recall)
 
   pthread_mutex_unlock(application_mutex);
 
+  /*  */
+  pthread_mutex_lock(audio_mutex);
+  
+  delay_audio_run = record_midi_audio_run->delay_audio_run;
+  count_beats_audio_run = AGS_COUNT_BEATS_AUDIO_RUN(record_midi_audio_run->count_beats_audio_run);
+  
+  sequencer = audio->sequencer;
+
+  pthread_mutex_unlock(audio_mutex);
+
+  if(sequencer == NULL){
+    return;
+  }
+
   /* get audio fields */
   pthread_mutex_lock(audio_mutex);
 
+  reverse_mapping = ((AGS_AUDIO_REVERSE_MAPPING & (audio->flags)) != 0) ? TRUE: FALSE;
+  
   pattern_mode = ((AGS_AUDIO_PATTERN_MODE & (audio->flags)) != 0) ? TRUE: FALSE;
+
+  midi_channel = audio->midi_channel;
+  
   audio_start_mapping = audio->audio_start_mapping;
 
   midi_start_mapping = audio->midi_start_mapping;
@@ -785,10 +843,10 @@ ags_record_midi_audio_run_run_pre(AgsRecall *recall)
     notation = NULL;
   }
   
-  pthread_mutex_unlock(audio_mutex);
-
   /*  */
   notation_counter = count_beats_audio_run->notation_counter;
+  
+  pthread_mutex_unlock(audio_mutex);
 
   /* get mode */
   g_value_init(&value,
@@ -852,18 +910,20 @@ ags_record_midi_audio_run_run_pre(AgsRecall *recall)
 	  AgsNote *current_note;
 	  
 	  /* key on - check within mapping */
-	  if(audio->midi_channel == (0x0f & midi_iter[0])){
+	  if(midi_channel == (0x0f & midi_iter[0])){
 	    if(midi_start_mapping <= (0x7f & midi_iter[1]) &&
-	       (((AGS_AUDIO_REVERSE_MAPPING & (audio->flags)) != 0 &&
+	       ((reverse_mapping &&
 		 input_pads - ((0x7f & midi_iter[1]) - midi_start_mapping) - 1 > 0) ||
-		((AGS_AUDIO_REVERSE_MAPPING & (audio->flags)) == 0 &&
+		(!reverse_mapping &&
 		 (0x7f & midi_iter[1]) - midi_start_mapping < midi_end_mapping))){
 	      current_note = NULL;
 	      note = record_midi_audio_run->note;
 
+	      pthread_mutex_lock(audio_mutex);
+	      
 	      while(note != NULL){
 		/* check current notes */
-		if((AGS_AUDIO_REVERSE_MAPPING & (audio->flags)) != 0){
+		if(reverse_mapping){
 		  if(AGS_NOTE(note->data)->y == input_pads - ((0x7f & midi_iter[1]) - midi_start_mapping) - 1){
 		    current_note = note->data;
 
@@ -879,7 +939,9 @@ ags_record_midi_audio_run_run_pre(AgsRecall *recall)
 	    
 		note = note->next;
 	      }
-	    
+
+	      pthread_mutex_unlock(audio_mutex);
+
 	      /* add note */
 	      if(current_note == NULL){
 		if((0x7f & (midi_iter[2])) != 0){
@@ -888,7 +950,7 @@ ags_record_midi_audio_run_run_pre(AgsRecall *recall)
 		  current_note->x[0] = notation_counter;
 		  current_note->x[1] = notation_counter + 1;
 	      
-		  if((AGS_AUDIO_REVERSE_MAPPING & (audio->flags)) != 0){
+		  if(reverse_mapping){
 		    current_note->y = input_pads - ((0x7f & midi_iter[1]) - midi_start_mapping) - 1;
 		  }else{
 		    current_note->y = (0x7f & midi_iter[1]) - midi_start_mapping;
@@ -946,10 +1008,12 @@ ags_record_midi_audio_run_run_pre(AgsRecall *recall)
 	    /* key off - find matching note */
 	    current_note = NULL;
 	    note = record_midi_audio_run->note;
-
+	    
+	    pthread_mutex_lock(audio_mutex);
+	    
 	    while(note != NULL){
 	      /* check current notes */
-	      if((AGS_AUDIO_REVERSE_MAPPING & (audio->flags)) != 0){
+	      if(reverse_mapping){
 		if(AGS_NOTE(note->data)->y == input_pads - ((0x7f & midi_iter[1]) - midi_start_mapping) - 1){
 		  current_note = note->data;
 
@@ -965,7 +1029,9 @@ ags_record_midi_audio_run_run_pre(AgsRecall *recall)
 	    
 	      note = note->next;
 	    }
-	  
+
+	    pthread_mutex_unlock(audio_mutex);
+	    
 	    /* remove current note */
 	    if(current_note != NULL){
 	      pthread_mutex_lock(audio_mutex);
@@ -992,9 +1058,11 @@ ags_record_midi_audio_run_run_pre(AgsRecall *recall)
 	    current_note = NULL;
 	    note = record_midi_audio_run->note;
 
+	    pthread_mutex_lock(audio_mutex);
+
 	    while(note != NULL){
 	      /* check current notes */
-	      if((AGS_AUDIO_REVERSE_MAPPING & (audio->flags)) != 0){
+	      if(reverse_mapping){
 		if(AGS_NOTE(note->data)->y == input_pads - ((0x7f & midi_iter[1]) - midi_start_mapping) - 1){
 		  current_note = note->data;
 
@@ -1010,7 +1078,9 @@ ags_record_midi_audio_run_run_pre(AgsRecall *recall)
 	    
 	      note = note->next;
 	    }
-	    
+
+	    pthread_mutex_unlock(audio_mutex);
+
 	    /* feed note */
 	    if(current_note != NULL){
 	      current_note->x[1] = notation_counter + 1;
@@ -1116,6 +1186,7 @@ ags_record_midi_audio_run_run_pre(AgsRecall *recall)
     }
   }
 
+  /* call parent */
   AGS_RECALL_CLASS(ags_record_midi_audio_run_parent_class)->run_pre(recall);
 }
 
diff --git a/ags/audio/recall/ags_route_dssi_audio.c b/ags/audio/recall/ags_route_dssi_audio.c
index 1cf7e20..285529d 100644
--- a/ags/audio/recall/ags_route_dssi_audio.c
+++ b/ags/audio/recall/ags_route_dssi_audio.c
@@ -34,6 +34,7 @@ void ags_route_dssi_audio_get_property(GObject *gobject,
 				       GValue *value,
 				       GParamSpec *param_spec);
 void ags_route_dssi_audio_set_ports(AgsPlugin *plugin, GList *port);
+void ags_route_dssi_audio_dispose(GObject *gobject);
 void ags_route_dssi_audio_finalize(GObject *gobject);
 
 /**
@@ -120,6 +121,7 @@ ags_route_dssi_audio_class_init(AgsRouteDssiAudioClass *route_dssi_audio)
   gobject->set_property = ags_route_dssi_audio_set_property;
   gobject->get_property = ags_route_dssi_audio_get_property;
 
+  gobject->dispose = ags_route_dssi_audio_dispose;
   gobject->finalize = ags_route_dssi_audio_finalize;
 
   /* properties */
@@ -178,10 +180,13 @@ ags_route_dssi_audio_init(AgsRouteDssiAudio *route_dssi_audio)
 						  "port-value-size\0", sizeof(gboolean),
 						  "port-value-length", 1,
 						  NULL);
-
+  g_object_ref(route_dssi_audio->notation_input);
+  
   route_dssi_audio->notation_input->port_value.ags_port_boolean = FALSE;
 
+  /* add to port */
   port = g_list_prepend(port, route_dssi_audio->notation_input);
+  g_object_ref(route_dssi_audio->notation_input);
 
   /* sequencer input */
   route_dssi_audio->sequencer_input = g_object_new(AGS_TYPE_PORT,
@@ -193,10 +198,13 @@ ags_route_dssi_audio_init(AgsRouteDssiAudio *route_dssi_audio)
 						  "port-value-size\0", sizeof(gboolean),
 						  "port-value-length", 1,
 						  NULL);
+  g_object_ref(route_dssi_audio->sequencer_input);
 
   route_dssi_audio->sequencer_input->port_value.ags_port_boolean = FALSE;
 
+  /* add to port */
   port = g_list_prepend(port, route_dssi_audio->sequencer_input);
+  g_object_ref(route_dssi_audio->sequencer_input);
 
   /* port */
   AGS_RECALL(route_dssi_audio)->port = port;
@@ -311,6 +319,31 @@ ags_route_dssi_audio_set_ports(AgsPlugin *plugin, GList *port)
 }
 
 void
+ags_route_dssi_audio_dispose(GObject *gobject)
+{
+  AgsRouteDssiAudio *route_dssi_audio;
+
+  route_dssi_audio = AGS_ROUTE_DSSI_AUDIO(gobject);
+
+  /* notation input */
+  if(route_dssi_audio->notation_input != NULL){
+    g_object_unref(G_OBJECT(route_dssi_audio->notation_input));
+
+    route_dssi_audio->notation_input = NULL;
+  }
+
+  /* sequencer input */
+  if(route_dssi_audio->sequencer_input != NULL){
+    g_object_unref(G_OBJECT(route_dssi_audio->sequencer_input));
+
+    route_dssi_audio->sequencer_input = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_route_dssi_audio_parent_class)->dispose(gobject);
+}
+
+void
 ags_route_dssi_audio_finalize(GObject *gobject)
 {
   AgsRouteDssiAudio *route_dssi_audio;
diff --git a/ags/audio/recall/ags_route_dssi_audio_run.c b/ags/audio/recall/ags_route_dssi_audio_run.c
index 193b3d9..5ca09d7 100644
--- a/ags/audio/recall/ags_route_dssi_audio_run.c
+++ b/ags/audio/recall/ags_route_dssi_audio_run.c
@@ -63,6 +63,7 @@ void ags_route_dssi_audio_run_get_property(GObject *gobject,
 					   guint prop_id,
 					   GValue *value,
 					   GParamSpec *param_spec);
+void ags_route_dssi_audio_run_dispose(GObject *gobject);
 void ags_route_dssi_audio_run_finalize(GObject *gobject);
 void ags_route_dssi_audio_run_connect(AgsConnectable *connectable);
 void ags_route_dssi_audio_run_disconnect(AgsConnectable *connectable);
@@ -211,9 +212,17 @@ ags_route_dssi_audio_run_class_init(AgsRouteDssiAudioRunClass *route_dssi_audio_
   gobject->set_property = ags_route_dssi_audio_run_set_property;
   gobject->get_property = ags_route_dssi_audio_run_get_property;
 
+  gobject->dispose = ags_route_dssi_audio_run_dispose;
   gobject->finalize = ags_route_dssi_audio_run_finalize;
 
   /* properties */
+  /**
+   * AgsRouteDssiAudioRun:delay-audio-run:
+   * 
+   * The delay audio run dependency.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("delay-audio-run\0",
 				   "assigned AgsDelayAudioRun\0",
 				   "the AgsDelayAudioRun which emits notation_alloc_input signal\0",
@@ -223,6 +232,13 @@ ags_route_dssi_audio_run_class_init(AgsRouteDssiAudioRunClass *route_dssi_audio_
 				  PROP_DELAY_AUDIO_RUN,
 				  param_spec);
 
+  /**
+   * AgsRouteDssiAudioRun:count-beats-audio-run:
+   * 
+   * The count beats audio run dependency.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("count-beats-audio-run\0",
 				   "assigned AgsCountBeatsAudioRun\0",
 				   "the AgsCountBeatsAudioRun which just counts\0",
@@ -392,20 +408,48 @@ ags_route_dssi_audio_run_get_property(GObject *gobject,
 }
 
 void
+ags_route_dssi_audio_run_dispose(GObject *gobject)
+{
+  AgsRouteDssiAudioRun *route_dssi_audio_run;
+
+  route_dssi_audio_run = AGS_ROUTE_DSSI_AUDIO_RUN(gobject);
+
+  /* delay audio run */
+  if(route_dssi_audio_run->delay_audio_run != NULL){
+    g_object_unref(G_OBJECT(route_dssi_audio_run->delay_audio_run));
+
+    route_dssi_audio_run->delay_audio_run = NULL;
+  }
+
+  /* count beats audio run */
+  if(route_dssi_audio_run->count_beats_audio_run != NULL){
+    g_object_unref(G_OBJECT(route_dssi_audio_run->count_beats_audio_run));
+
+    route_dssi_audio_run->count_beats_audio_run = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_route_dssi_audio_run_parent_class)->finalize(gobject);
+}
+
+void
 ags_route_dssi_audio_run_finalize(GObject *gobject)
 {
   AgsRouteDssiAudioRun *route_dssi_audio_run;
 
   route_dssi_audio_run = AGS_ROUTE_DSSI_AUDIO_RUN(gobject);
 
+  /* delay audio run */
   if(route_dssi_audio_run->delay_audio_run != NULL){
     g_object_unref(G_OBJECT(route_dssi_audio_run->delay_audio_run));
   }
 
+  /* count beats audio run */
   if(route_dssi_audio_run->count_beats_audio_run != NULL){
     g_object_unref(G_OBJECT(route_dssi_audio_run->count_beats_audio_run));
   }
 
+  /* call parent */
   G_OBJECT_CLASS(ags_route_dssi_audio_run_parent_class)->finalize(gobject);
 }
 
@@ -848,8 +892,8 @@ ags_route_dssi_audio_run_feed_midi(AgsRecall *recall,
 	    
 	      if(recall_dssi_run->event_buffer == NULL){
 		/* prepend note */
-		route_dssi_audio_run->feed_midi = g_list_prepend(route_dssi_audio_run->feed_midi,
-								 note);
+		//		route_dssi_audio_run->feed_midi = g_list_prepend(route_dssi_audio_run->feed_midi,
+		//						 note);
 	      
 		recall_dssi_run->route_dssi_audio_run = (GObject *) route_dssi_audio_run;
 	      
diff --git a/ags/audio/recall/ags_route_lv2_audio.c b/ags/audio/recall/ags_route_lv2_audio.c
index 4cdcc09..796f372 100644
--- a/ags/audio/recall/ags_route_lv2_audio.c
+++ b/ags/audio/recall/ags_route_lv2_audio.c
@@ -34,6 +34,7 @@ void ags_route_lv2_audio_get_property(GObject *gobject,
 				      GValue *value,
 				      GParamSpec *param_spec);
 void ags_route_lv2_audio_set_ports(AgsPlugin *plugin, GList *port);
+void ags_route_lv2_audio_dispose(GObject *gobject);
 void ags_route_lv2_audio_finalize(GObject *gobject);
 
 /**
@@ -120,6 +121,7 @@ ags_route_lv2_audio_class_init(AgsRouteLv2AudioClass *route_lv2_audio)
   gobject->set_property = ags_route_lv2_audio_set_property;
   gobject->get_property = ags_route_lv2_audio_get_property;
 
+  gobject->dispose = ags_route_lv2_audio_dispose;
   gobject->finalize = ags_route_lv2_audio_finalize;
 
   /* properties */
@@ -178,10 +180,13 @@ ags_route_lv2_audio_init(AgsRouteLv2Audio *route_lv2_audio)
 						 "port-value-size\0", sizeof(gboolean),
 						 "port-value-length", 1,
 						 NULL);
-
+  g_object_ref(route_lv2_audio->notation_input);
+  
   route_lv2_audio->notation_input->port_value.ags_port_boolean = FALSE;
 
+  /* add to port */
   port = g_list_prepend(port, route_lv2_audio->notation_input);
+  g_object_ref(route_lv2_audio->notation_input);
 
   /* sequencer input */
   route_lv2_audio->sequencer_input = g_object_new(AGS_TYPE_PORT,
@@ -193,12 +198,15 @@ ags_route_lv2_audio_init(AgsRouteLv2Audio *route_lv2_audio)
 						  "port-value-size\0", sizeof(gboolean),
 						  "port-value-length", 1,
 						  NULL);
+  g_object_ref(route_lv2_audio->sequencer_input);
 
   route_lv2_audio->sequencer_input->port_value.ags_port_boolean = FALSE;
 
+  /* add to port */
   port = g_list_prepend(port, route_lv2_audio->sequencer_input);
+  g_object_ref(route_lv2_audio->sequencer_input);
 
-  /* port */
+  /* set port */
   AGS_RECALL(route_lv2_audio)->port = port;
 }
 
@@ -311,16 +319,43 @@ ags_route_lv2_audio_set_ports(AgsPlugin *plugin, GList *port)
 }
 
 void
+ags_route_lv2_audio_dispose(GObject *gobject)
+{
+  AgsRouteLv2Audio *route_lv2_audio;
+
+  route_lv2_audio = AGS_ROUTE_LV2_AUDIO(gobject);
+
+  /* notation input */
+  if(route_lv2_audio->notation_input != NULL){
+    g_object_unref(G_OBJECT(route_lv2_audio->notation_input));
+
+    route_lv2_audio->notation_input = NULL;
+  }
+
+  /* sequencer input */
+  if(route_lv2_audio->sequencer_input != NULL){
+    g_object_unref(G_OBJECT(route_lv2_audio->sequencer_input));
+
+    route_lv2_audio->sequencer_input = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_route_lv2_audio_parent_class)->dispose(gobject);
+}
+
+void
 ags_route_lv2_audio_finalize(GObject *gobject)
 {
   AgsRouteLv2Audio *route_lv2_audio;
 
   route_lv2_audio = AGS_ROUTE_LV2_AUDIO(gobject);
 
+  /* notation input */
   if(route_lv2_audio->notation_input != NULL){
     g_object_unref(G_OBJECT(route_lv2_audio->notation_input));
   }
 
+  /* sequencer input */
   if(route_lv2_audio->sequencer_input != NULL){
     g_object_unref(G_OBJECT(route_lv2_audio->sequencer_input));
   }
diff --git a/ags/audio/recall/ags_route_lv2_audio_run.c b/ags/audio/recall/ags_route_lv2_audio_run.c
index f5fa26a..db2ffbf 100644
--- a/ags/audio/recall/ags_route_lv2_audio_run.c
+++ b/ags/audio/recall/ags_route_lv2_audio_run.c
@@ -867,11 +867,11 @@ ags_route_lv2_audio_run_feed_midi(AgsRecall *recall,
 	    
 	      if(recall_lv2_run->note == NULL){
 		/* prepend note */
-		route_lv2_audio_run->feed_midi = g_list_prepend(route_lv2_audio_run->feed_midi,
-								note);
+		//		route_lv2_audio_run->feed_midi = g_list_prepend(route_lv2_audio_run->feed_midi,
+		//						note);
   
 		recall_lv2_run->route_lv2_audio_run = (GObject *) route_lv2_audio_run;
-	      
+		
 		/* key on */
 		seq_event = (snd_seq_event_t *) malloc(sizeof(snd_seq_event_t));
 		memset(seq_event, 0, sizeof(snd_seq_event_t));
diff --git a/ags/audio/recall/ags_stream_audio_signal.c b/ags/audio/recall/ags_stream_audio_signal.c
index 208bfb6..564e9ed 100644
--- a/ags/audio/recall/ags_stream_audio_signal.c
+++ b/ags/audio/recall/ags_stream_audio_signal.c
@@ -37,6 +37,7 @@ void ags_stream_audio_signal_connect(AgsConnectable *connectable);
 void ags_stream_audio_signal_disconnect(AgsConnectable *connectable);
 void ags_stream_audio_signal_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
 void ags_stream_audio_signal_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+void ags_stream_audio_signal_dispose(GObject *gobject);
 void ags_stream_audio_signal_finalize(GObject *gobject);
 
 void ags_stream_audio_signal_run_init_pre(AgsRecall *recall);
@@ -118,6 +119,7 @@ ags_stream_audio_signal_class_init(AgsStreamAudioSignalClass *stream_audio_signa
   /* GObjectClass */
   gobject = (GObjectClass *) stream_audio_signal;
 
+  gobject->dispose = ags_stream_audio_signal_dispose;
   gobject->finalize = ags_stream_audio_signal_finalize;
 
   /* AgsRecallClass */
@@ -156,15 +158,38 @@ ags_stream_audio_signal_init(AgsStreamAudioSignal *stream_audio_signal)
   AGS_RECALL(stream_audio_signal)->port = NULL;
 
   AGS_RECALL(stream_audio_signal)->child_type = G_TYPE_NONE;
+
+  stream_audio_signal->dispose_source = NULL;
+}
+
+void
+ags_stream_audio_signal_dispose(GObject *gobject)
+{
+  AGS_STREAM_AUDIO_SIGNAL(gobject)->dispose_source = AGS_RECALL_AUDIO_SIGNAL(gobject)->source;
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_stream_audio_signal_parent_class)->dispose(gobject); 
 }
 
 void
 ags_stream_audio_signal_finalize(GObject *gobject)
 {
-  if(AGS_RECALL_AUDIO_SIGNAL(gobject)->source != NULL &&
-     AGS_RECALL_AUDIO_SIGNAL(gobject)->source->recycling != NULL){
-    ags_recycling_remove_audio_signal((AgsRecycling *) AGS_RECALL_AUDIO_SIGNAL(gobject)->source->recycling,
-				      AGS_RECALL_AUDIO_SIGNAL(gobject)->source);
+  AgsAudioSignal *audio_signal;
+
+  audio_signal = AGS_STREAM_AUDIO_SIGNAL(gobject)->dispose_source;
+  
+  if(audio_signal != NULL){
+    AgsRecycling *recycling;
+
+    recycling = audio_signal->recycling;
+    
+    if(recycling != NULL){
+      ags_recycling_remove_audio_signal(recycling,
+					audio_signal);
+    }
+    
+    g_object_run_dispose(audio_signal);
+    g_object_unref(audio_signal);
   }
 
   /* call parent */
@@ -316,10 +341,10 @@ ags_stream_audio_signal_run_post(AgsRecall *recall)
 
     /* call parent */
     AGS_RECALL_CLASS(ags_stream_audio_signal_parent_class)->run_post(recall);
-  }else{
+  }else{    
     /* call parent */
     AGS_RECALL_CLASS(ags_stream_audio_signal_parent_class)->run_post(recall);
-    
+
     ags_recall_done(recall);
   }
 }
diff --git a/ags/audio/recall/ags_stream_audio_signal.h b/ags/audio/recall/ags_stream_audio_signal.h
index 1b0c01f..7fb54cc 100644
--- a/ags/audio/recall/ags_stream_audio_signal.h
+++ b/ags/audio/recall/ags_stream_audio_signal.h
@@ -38,6 +38,8 @@ typedef struct _AgsStreamAudioSignalClass AgsStreamAudioSignalClass;
 struct _AgsStreamAudioSignal
 {
   AgsRecallAudioSignal recall_audio_signal;
+
+  GObject *dispose_source;
 };
 
 struct _AgsStreamAudioSignalClass
diff --git a/ags/audio/recall/ags_stream_channel.c b/ags/audio/recall/ags_stream_channel.c
index a669326..5dfa0f1 100644
--- a/ags/audio/recall/ags_stream_channel.c
+++ b/ags/audio/recall/ags_stream_channel.c
@@ -38,6 +38,7 @@ void ags_stream_channel_get_property(GObject *gobject,
 void ags_stream_channel_connect(AgsConnectable *connectable);
 void ags_stream_channel_disconnect(AgsConnectable *connectable);
 void ags_stream_channel_set_ports(AgsPlugin *plugin, GList *port);
+void ags_stream_channel_dispose(GObject *gobject);
 void ags_stream_channel_finalize(GObject *gobject);
 
 /**
@@ -129,9 +130,17 @@ ags_stream_channel_class_init(AgsStreamChannelClass *stream_channel)
   gobject->set_property = ags_stream_channel_set_property;
   gobject->get_property = ags_stream_channel_get_property;
 
+  gobject->dispose = ags_stream_channel_dispose;
   gobject->finalize = ags_stream_channel_finalize;
 
   /* properties */
+  /**
+   * AgsStreamChannel:auto-sense:
+   * 
+   * The auto-sense port.
+   * 
+   * Since: 0.7.122.7
+   */
   param_spec = g_param_spec_object("auto-sense\0",
 				   "mute channel\0",
 				   "Mute the channel\0",
@@ -174,8 +183,10 @@ ags_stream_channel_init(AgsStreamChannel *stream_channel)
   AGS_RECALL(stream_channel)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
   AGS_RECALL(stream_channel)->xml_type = "ags-stream-channel\0";
 
+  /* initialize port */
   port = NULL;
 
+  /* auto-sense */
   stream_channel->auto_sense = g_object_new(AGS_TYPE_PORT,
 				     "plugin-name\0", ags_stream_channel_plugin_name,
 				     "specifier\0", ags_stream_channel_plugin_specifier[0],
@@ -185,7 +196,8 @@ ags_stream_channel_init(AgsStreamChannel *stream_channel)
 				     "port-value-size\0", sizeof(gboolean),
 				     "port-value-length\0", 1,
 				     NULL);
-
+  g_object_ref(stream_channel->auto_sense);
+  
   config = ags_config_get_instance();
   
   str = ags_config_get_value(config,
@@ -194,9 +206,11 @@ ags_stream_channel_init(AgsStreamChannel *stream_channel)
   stream_channel->auto_sense->port_value.ags_port_boolean = ((!g_strcmp0(str, "true\0")
 							      ) ? TRUE: FALSE);
   free(str);
-  
-  port = g_list_prepend(port, stream_channel->auto_sense);
 
+  /* add to port */
+  port = g_list_prepend(port, stream_channel->auto_sense);
+  g_object_ref(stream_channel->auto_sense);
+  
   /* set port */
   AGS_RECALL(stream_channel)->port = port;
 
@@ -264,12 +278,31 @@ ags_stream_channel_get_property(GObject *gobject,
 }
 
 void
+ags_stream_channel_dispose(GObject *gobject)
+{
+  AgsStreamChannel *stream_channel;
+
+  stream_channel = AGS_STREAM_CHANNEL(gobject);
+
+  /* auto-sense */
+  if(stream_channel->auto_sense != NULL){
+    g_object_unref(G_OBJECT(stream_channel->auto_sense));
+
+    stream_channel->auto_sense = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_stream_channel_parent_class)->dispose(gobject);
+}
+
+void
 ags_stream_channel_finalize(GObject *gobject)
 {
   AgsStreamChannel *stream_channel;
 
   stream_channel = AGS_STREAM_CHANNEL(gobject);
 
+  /* auto-sense */
   if(stream_channel->auto_sense != NULL){
     g_object_unref(G_OBJECT(stream_channel->auto_sense));
   }
diff --git a/ags/audio/recall/ags_volume_audio_signal.c b/ags/audio/recall/ags_volume_audio_signal.c
index d2563eb..b2ba8ad 100644
--- a/ags/audio/recall/ags_volume_audio_signal.c
+++ b/ags/audio/recall/ags_volume_audio_signal.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -31,14 +31,6 @@ void ags_volume_audio_signal_class_init(AgsVolumeAudioSignalClass *volume_audio_
 void ags_volume_audio_signal_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_volume_audio_signal_dynamic_connectable_interface_init(AgsDynamicConnectableInterface *dynamic_connectable);
 void ags_volume_audio_signal_init(AgsVolumeAudioSignal *volume_audio_signal);
-void ags_volume_audio_signal_set_property(GObject *gobject,
-					  guint prop_id,
-					  const GValue *value,
-					  GParamSpec *param_spec);
-void ags_volume_audio_signal_get_property(GObject *gobject,
-					  guint prop_id,
-					  GValue *value,
-					  GParamSpec *param_spec);
 void ags_volume_audio_signal_connect(AgsConnectable *connectable);
 void ags_volume_audio_signal_disconnect(AgsConnectable *connectable);
 void ags_volume_audio_signal_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
@@ -60,11 +52,6 @@ AgsRecall* ags_volume_audio_signal_duplicate(AgsRecall *recall,
  * The #AgsVolumeAudioSignal class volumes the audio signal.
  */
 
-enum{
-  PROP_0,
-  PROP_VOLUME,
-};
-
 static gpointer ags_volume_audio_signal_parent_class = NULL;
 static AgsConnectableInterface *ags_volume_audio_signal_parent_connectable_interface;
 static AgsDynamicConnectableInterface *ags_volume_audio_signal_parent_dynamic_connectable_interface;
@@ -231,44 +218,17 @@ ags_volume_audio_signal_run_inter(AgsRecall *recall)
     buffer = (signed short *) AGS_RECALL_AUDIO_SIGNAL(recall)->source->stream_current->data;
     buffer_size = AGS_RECALL_AUDIO_SIGNAL(recall)->source->buffer_size;
 
-    g_value_init(&value, G_TYPE_DOUBLE);
+    g_value_init(&value, G_TYPE_FLOAT);
     ags_port_safe_read(volume_channel->volume, &value);
 
-    volume = g_value_get_double(&value);
-
-    for(i = 0; i < buffer_size; i++){
-      switch(AGS_RECALL_AUDIO_SIGNAL(recall)->source->format){
-      case AGS_SOUNDCARD_SIGNED_8_BIT:
-	{
-	  ((signed char *) buffer)[i] = (signed char) ((0xff) & (signed short) ((gdouble) volume * (gdouble) ((signed char *) buffer)[i]));
-	}
-	break;
-      case AGS_SOUNDCARD_SIGNED_16_BIT:
-	{
-	  ((signed short *) buffer)[i] = (signed short) ((0xffff) & (signed long) ((gdouble) volume * (gdouble) ((signed short *) buffer)[i]));
-	}
-	break;
-      case AGS_SOUNDCARD_SIGNED_24_BIT:
-	{
-	  ((signed long *) buffer)[i] = (signed long) ((0xffffff) & (signed long) ((gdouble) volume * (gdouble) ((signed long *) buffer)[i]));
-	}
-	break;
-      case AGS_SOUNDCARD_SIGNED_32_BIT:
-	{
-	  ((signed long *) buffer)[i] = (signed long) ((0xffffffff) & (signed long long) ((gdouble) volume * (gdouble) ((signed long *) buffer)[i]));
-	}
-	break;
-      case AGS_SOUNDCARD_SIGNED_64_BIT:
-	{
-	  ((signed long long *) buffer)[i] = (signed long long) ((0xffffffffffffffff) & (signed long long) ((gdouble)volume * (gdouble)((signed long long *) buffer)[i]));
-	}
-	break;
-      default:
-	g_critical("unsupported soundcard format\0");
-      }
-    }
-
+    volume = g_value_get_float(&value);
     g_value_unset(&value);
+
+    ags_audio_buffer_util_volume(buffer, 1,
+				 ags_audio_buffer_util_format_from_soundcard(AGS_RECALL_AUDIO_SIGNAL(recall)->source->format),
+				 buffer_size,
+				 volume);
+
   }else{
     ags_recall_done(recall);
   }
diff --git a/ags/audio/recall/ags_volume_channel.c b/ags/audio/recall/ags_volume_channel.c
index 5cacf3a..f53d31c 100644
--- a/ags/audio/recall/ags_volume_channel.c
+++ b/ags/audio/recall/ags_volume_channel.c
@@ -20,9 +20,10 @@
 #include <ags/audio/recall/ags_volume_channel.h>
 
 #include <ags/object/ags_connectable.h>
-
 #include <ags/object/ags_plugin.h>
 
+#include <ags/plugin/ags_base_plugin.h>
+
 void ags_volume_channel_class_init(AgsVolumeChannelClass *volume_channel);
 void ags_volume_channel_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_volume_channel_plugin_interface_init(AgsPluginInterface *plugin);
@@ -38,8 +39,11 @@ void ags_volume_channel_get_property(GObject *gobject,
 void ags_volume_channel_connect(AgsConnectable *connectable);
 void ags_volume_channel_disconnect(AgsConnectable *connectable);
 void ags_volume_channel_set_ports(AgsPlugin *plugin, GList *port);
+void ags_volume_channel_dispose(GObject *gobject);
 void ags_volume_channel_finalize(GObject *gobject);
 
+static AgsPortDescriptor* ags_volume_channel_get_volume_port_descriptor();
+
 /**
  * SECTION:ags_volume_channel
  * @short_description: volumes channel
@@ -143,9 +147,17 @@ ags_volume_channel_class_init(AgsVolumeChannelClass *volume_channel)
   gobject->set_property = ags_volume_channel_set_property;
   gobject->get_property = ags_volume_channel_get_property;
 
+  gobject->dispose = ags_volume_channel_dispose;
   gobject->finalize = ags_volume_channel_finalize;
 
   /* properties */
+  /**
+   * AgsVolumeChannel:volume:
+   * 
+   * The volume port.
+   * 
+   * Since: 0.7.122.7 
+   */
   param_spec = g_param_spec_object("volume\0",
 				   "volume to apply\0",
 				   "The volume to apply on the channel\0",
@@ -166,6 +178,7 @@ ags_volume_channel_init(AgsVolumeChannel *volume_channel)
   AGS_RECALL(volume_channel)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
   AGS_RECALL(volume_channel)->xml_type = "ags-volume-channel\0";
 
+  /* initialize the port */
   port = NULL;
 
   /* volume */
@@ -174,15 +187,22 @@ ags_volume_channel_init(AgsVolumeChannel *volume_channel)
 					"specifier\0", "./volume[0]\0",
 					"control-port\0", "1/1\0",
 					"port-value-is-pointer\0", FALSE,
-					"port-value-type\0", G_TYPE_DOUBLE,
-					"port-value-size\0", sizeof(gdouble),
+					"port-value-type\0", G_TYPE_FLOAT,
+					"port-value-size\0", sizeof(gfloat),
 					"port-value-length", 1,
 					NULL);
+  g_object_ref(volume_channel->volume);
+  
+  volume_channel->volume->port_value.ags_port_float = 1.0;
 
-  volume_channel->volume->port_value.ags_port_double = 1.0;
+  /* port descriptor */
+  volume_channel->volume->port_descriptor = ags_volume_channel_get_volume_port_descriptor();
 
+  /* add to port */  
   port = g_list_prepend(port, volume_channel->volume);
-
+  g_object_ref(volume_channel->volume);
+  
+  /* set port */
   AGS_RECALL(volume_channel)->port = port;
 }
 
@@ -249,9 +269,20 @@ ags_volume_channel_get_property(GObject *gobject,
 void
 ags_volume_channel_connect(AgsConnectable *connectable)
 {
-  ags_volume_channel_parent_connectable_interface->connect(connectable);
+  AgsRecall *recall;
+  
+  recall = AGS_RECALL(connectable);
+  
+  if((AGS_RECALL_CONNECTED & (recall->flags)) != 0){
+    return;
+  }
 
-  /* empty */
+  /* load automation */
+  ags_recall_load_automation(recall,
+			     g_list_copy(recall->port));
+
+  /* call parent */
+  ags_volume_channel_parent_connectable_interface->connect(connectable);
 }
 
 void
@@ -279,12 +310,29 @@ ags_volume_channel_set_ports(AgsPlugin *plugin, GList *port)
 }
 
 void
+ags_volume_channel_dispose(GObject *gobject)
+{
+  AgsVolumeChannel *volume_channel;
+
+  volume_channel = AGS_VOLUME_CHANNEL(gobject);
+
+  /* volume */
+  if(volume_channel->volume != NULL){
+    g_object_unref(G_OBJECT(volume_channel->volume));
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_volume_channel_parent_class)->dispose(gobject);
+}
+
+void
 ags_volume_channel_finalize(GObject *gobject)
 {
   AgsVolumeChannel *volume_channel;
 
   volume_channel = AGS_VOLUME_CHANNEL(gobject);
 
+  /* volume */
   if(volume_channel->volume != NULL){
     g_object_unref(G_OBJECT(volume_channel->volume));
   }
@@ -293,6 +341,38 @@ ags_volume_channel_finalize(GObject *gobject)
   G_OBJECT_CLASS(ags_volume_channel_parent_class)->finalize(gobject);
 }
 
+static AgsPortDescriptor*
+ags_volume_channel_get_volume_port_descriptor()
+{
+  static AgsPortDescriptor *port_descriptor = NULL;
+
+  if(port_descriptor == NULL){
+    port_descriptor = ags_port_descriptor_alloc();
+
+    port_descriptor->flags |= (AGS_PORT_DESCRIPTOR_INPUT |
+			       AGS_PORT_DESCRIPTOR_CONTROL);
+
+    port_descriptor->port_index = 0;
+
+    /* range */
+    g_value_init(port_descriptor->default_value,
+		 G_TYPE_FLOAT);
+    g_value_init(port_descriptor->lower_value,
+		 G_TYPE_FLOAT);
+    g_value_init(port_descriptor->upper_value,
+		 G_TYPE_FLOAT);
+
+    g_value_set_float(port_descriptor->default_value,
+		      1.0);
+    g_value_set_float(port_descriptor->lower_value,
+		      0.0);
+    g_value_set_float(port_descriptor->upper_value,
+		      2.0);
+  }
+  
+  return(port_descriptor);
+}
+
 /**
  * ags_volume_channel_new:
  *
diff --git a/ags/audio/task/ags_apply_synth.c b/ags/audio/task/ags_apply_synth.c
index 284b74c..e7f6eaa 100644
--- a/ags/audio/task/ags_apply_synth.c
+++ b/ags/audio/task/ags_apply_synth.c
@@ -621,6 +621,26 @@ ags_apply_synth_launch(AgsTask *task)
 
   factor = 1.0;
 
+  /* clear */
+  for(i = 0; channel != NULL && i < apply_synth->count; i++){
+    audio_signal = ags_audio_signal_get_template(channel->first_recycling->audio_signal);
+
+    /* clear the stream */
+    stream = audio_signal->stream_beginning;
+
+    while(stream != NULL){
+      ags_audio_buffer_util_clear_buffer(stream->data, 1,
+					 audio_signal->buffer_size, ags_audio_buffer_util_format_from_soundcard(audio_signal->format));
+      
+      stream = stream->next;
+    }
+
+    channel = channel->next;
+  }
+
+  /* fill */
+  channel = apply_synth->start_channel;
+
   for(i = 0; channel != NULL && i < apply_synth->count; i++){
     audio_signal = ags_audio_signal_get_template(channel->first_recycling->audio_signal);
 
@@ -665,7 +685,7 @@ ags_apply_synth_launch(AgsTask *task)
     
     audio_signal->loop_start = (guint) ((double) apply_synth->loop_start) * factor;
     audio_signal->loop_end = (guint) ((double) apply_synth->loop_end) * factor;
-
+    
     /* fill in the stream */
     stream = g_list_nth(audio_signal->stream_beginning, stream_start);
     
diff --git a/ags/audio/task/ags_clear_buffer.c b/ags/audio/task/ags_clear_buffer.c
new file mode 100644
index 0000000..92b993c
--- /dev/null
+++ b/ags/audio/task/ags_clear_buffer.c
@@ -0,0 +1,379 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2015 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/audio/task/ags_clear_buffer.h>
+
+#include <ags/object/ags_connectable.h>
+#include <ags/object/ags_soundcard.h>
+
+#include <ags/audio/ags_devout.h>
+#include <ags/audio/ags_midiin.h>
+
+#include <ags/audio/jack/ags_jack_devout.h>
+#include <ags/audio/jack/ags_jack_midiin.h>
+
+void ags_clear_buffer_class_init(AgsClearBufferClass *clear_buffer);
+void ags_clear_buffer_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_clear_buffer_init(AgsClearBuffer *clear_buffer);
+void ags_clear_buffer_set_property(GObject *gobject,
+					 guint prop_id,
+					 const GValue *value,
+					 GParamSpec *param_spec);
+void ags_clear_buffer_get_property(GObject *gobject,
+					 guint prop_id,
+					 GValue *value,
+					 GParamSpec *param_spec);
+void ags_clear_buffer_connect(AgsConnectable *connectable);
+void ags_clear_buffer_disconnect(AgsConnectable *connectable);
+void ags_clear_buffer_finalize(GObject *gobject);
+
+void ags_clear_buffer_launch(AgsTask *task);
+
+/**
+ * SECTION:ags_clear_buffer
+ * @short_description: switch buffer flag of device
+ * @title: AgsClearBuffer
+ * @section_id:
+ * @include: ags/audio/task/ags_clear_buffer.h
+ *
+ * The #AgsClearBuffer task switches the buffer flag of device.
+ */
+
+static gpointer ags_clear_buffer_parent_class = NULL;
+static AgsConnectableInterface *ags_clear_buffer_parent_connectable_interface;
+
+enum{
+  PROP_0,
+  PROP_DEVICE,
+};
+
+GType
+ags_clear_buffer_get_type()
+{
+  static GType ags_type_clear_buffer = 0;
+
+  if(!ags_type_clear_buffer){
+    static const GTypeInfo ags_clear_buffer_info = {
+      sizeof (AgsClearBufferClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_clear_buffer_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof (AgsClearBuffer),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_clear_buffer_init,
+    };
+
+    static const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_clear_buffer_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    ags_type_clear_buffer = g_type_register_static(AGS_TYPE_TASK,
+							 "AgsClearBuffer\0",
+							 &ags_clear_buffer_info,
+							 0);
+
+    g_type_add_interface_static(ags_type_clear_buffer,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+  }
+  
+  return (ags_type_clear_buffer);
+}
+
+void
+ags_clear_buffer_class_init(AgsClearBufferClass *clear_buffer)
+{
+  GObjectClass *gobject;
+  AgsTaskClass *task;
+  GParamSpec *param_spec;
+
+  ags_clear_buffer_parent_class = g_type_class_peek_parent(clear_buffer);
+
+  /* gobject */
+  gobject = (GObjectClass *) clear_buffer;
+
+  gobject->set_property = ags_clear_buffer_set_property;
+  gobject->get_property = ags_clear_buffer_get_property;
+
+  gobject->finalize = ags_clear_buffer_finalize;
+
+  /* properties */
+  /**
+   * AgsClearBuffer:device:
+   *
+   * The assigned #AgsSoundcard or #AgsSequencer
+   * 
+   * Since: 0.7.124
+   */
+  param_spec = g_param_spec_object("device\0",
+				   "device of change device\0",
+				   "The device of change device task\0",
+				   G_TYPE_OBJECT,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_DEVICE,
+				  param_spec);
+
+  /* task */
+  task = (AgsTaskClass *) clear_buffer;
+
+  task->launch = ags_clear_buffer_launch;
+}
+
+void
+ags_clear_buffer_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  ags_clear_buffer_parent_connectable_interface = g_type_interface_peek_parent(connectable);
+
+  connectable->connect = ags_clear_buffer_connect;
+  connectable->disconnect = ags_clear_buffer_disconnect;
+}
+
+void
+ags_clear_buffer_init(AgsClearBuffer *clear_buffer)
+{
+  clear_buffer->device = NULL;
+}
+
+void
+ags_clear_buffer_set_property(GObject *gobject,
+				    guint prop_id,
+				    const GValue *value,
+				    GParamSpec *param_spec)
+{
+  AgsClearBuffer *clear_buffer;
+
+  clear_buffer = AGS_CLEAR_BUFFER(gobject);
+
+  switch(prop_id){
+  case PROP_DEVICE:
+    {
+      GObject *device;
+
+      device = (GObject *) g_value_get_object(value);
+
+      if(clear_buffer->device == (GObject *) device){
+	return;
+      }
+
+      if(clear_buffer->device != NULL){
+	g_object_unref(clear_buffer->device);
+      }
+
+      if(device != NULL){
+	g_object_ref(device);
+      }
+
+      clear_buffer->device = (GObject *) device;
+    }
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  }
+}
+
+void
+ags_clear_buffer_get_property(GObject *gobject,
+				    guint prop_id,
+				    GValue *value,
+				    GParamSpec *param_spec)
+{
+  AgsClearBuffer *clear_buffer;
+
+  clear_buffer = AGS_CLEAR_BUFFER(gobject);
+
+  switch(prop_id){
+  case PROP_DEVICE:
+    {
+      g_value_set_object(value, clear_buffer->device);
+    }
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  }
+}
+
+void
+ags_clear_buffer_connect(AgsConnectable *connectable)
+{
+  ags_clear_buffer_parent_connectable_interface->connect(connectable);
+
+  /* empty */
+}
+
+void
+ags_clear_buffer_disconnect(AgsConnectable *connectable)
+{
+  ags_clear_buffer_parent_connectable_interface->disconnect(connectable);
+
+  /* empty */
+}
+
+void
+ags_clear_buffer_finalize(GObject *gobject)
+{
+  G_OBJECT_CLASS(ags_clear_buffer_parent_class)->finalize(gobject);
+
+  /* empty */
+}
+
+void
+ags_clear_buffer_launch(AgsTask *task)
+{
+  AgsClearBuffer *clear_buffer;
+
+  guint nth_buffer;
+  guint word_size;
+  
+  clear_buffer = AGS_CLEAR_BUFFER(task);
+
+  if(AGS_IS_DEVOUT(clear_buffer->device)){
+    AgsDevout *devout;
+
+    devout = clear_buffer->device;
+
+    /* retrieve word size */
+    switch(devout->format){
+    case AGS_SOUNDCARD_SIGNED_8_BIT:
+      {
+	word_size = sizeof(signed char);
+      }
+      break;
+    case AGS_SOUNDCARD_SIGNED_16_BIT:
+      {
+	word_size = sizeof(signed short);
+      }
+      break;
+    case AGS_SOUNDCARD_SIGNED_24_BIT:
+      {
+	word_size = sizeof(signed long);
+      }
+      break;
+    case AGS_SOUNDCARD_SIGNED_32_BIT:
+      {
+	word_size = sizeof(signed long);
+      }
+      break;
+    case AGS_SOUNDCARD_SIGNED_64_BIT:
+      {
+	word_size = sizeof(signed long long);
+      }
+      break;
+    default:
+      g_warning("ags_clear_buffer_launch(): unsupported word size\0");
+
+      return;
+    }
+
+    
+    if((AGS_DEVOUT_BUFFER0 & (devout->flags)) != 0){
+      nth_buffer = 0;
+    }else if((AGS_DEVOUT_BUFFER1 & (devout->flags)) != 0){
+      nth_buffer = 1;
+    }else if((AGS_DEVOUT_BUFFER2 & (devout->flags)) != 0){
+      nth_buffer = 2;
+    }else if((AGS_DEVOUT_BUFFER3 & devout->flags) != 0){
+      nth_buffer = 3;
+    }
+    
+    memset(devout->buffer[nth_buffer], 0, (size_t) devout->pcm_channels * devout->buffer_size * word_size);
+  }else if(AGS_IS_JACK_DEVOUT(clear_buffer->device)){
+    AgsJackDevout *jack_devout;
+    
+    jack_devout = clear_buffer->device;
+
+    switch(jack_devout->format){
+    case AGS_SOUNDCARD_SIGNED_8_BIT:
+      {
+	word_size = sizeof(signed char);
+      }
+      break;
+    case AGS_SOUNDCARD_SIGNED_16_BIT:
+      {
+	word_size = sizeof(signed short);
+      }
+      break;
+    case AGS_SOUNDCARD_SIGNED_24_BIT:
+      {      
+	//NOTE:JK: The 24-bit linear samples use 32-bit physical space
+	word_size = sizeof(signed long);
+      }
+      break;
+    case AGS_SOUNDCARD_SIGNED_32_BIT:
+      {
+	word_size = sizeof(signed long);
+      }
+      break;
+    case AGS_SOUNDCARD_SIGNED_64_BIT:
+      {
+	word_size = sizeof(signed long long);
+      }
+      break;
+    default:    
+      g_warning("ags_clear_buffer_launch(): unsupported word size\0");
+    
+      return;
+    }
+    
+    if((AGS_JACK_DEVOUT_BUFFER0 & (jack_devout->flags)) != 0){
+      nth_buffer = 3;
+    }else if((AGS_JACK_DEVOUT_BUFFER1 & (jack_devout->flags)) != 0){
+      nth_buffer = 0;
+    }else if((AGS_JACK_DEVOUT_BUFFER2 & (jack_devout->flags)) != 0){
+      nth_buffer = 1;
+    }else if((AGS_JACK_DEVOUT_BUFFER3 & jack_devout->flags) != 0){
+      nth_buffer = 2;
+    }
+      
+    memset(jack_devout->buffer[nth_buffer], 0, (size_t) jack_devout->pcm_channels * jack_devout->buffer_size * word_size);
+  }else if(AGS_IS_MIDIIN(clear_buffer->device)){
+    //TODO:JK: implement me
+  }else if(AGS_IS_JACK_MIDIIN(clear_buffer->device)){
+    //TODO:JK: implement me
+  }
+}
+
+/**
+ * ags_clear_buffer_new:
+ * @device: the #AgsSoundcard or #AgsSequencer
+ *
+ * Creates an #AgsClearBuffer.
+ *
+ * Returns: an new #AgsClearBuffer.
+ *
+ * Since: 0.7.124
+ */
+AgsClearBuffer*
+ags_clear_buffer_new(GObject *device)
+{
+  AgsClearBuffer *clear_buffer;
+
+  clear_buffer = (AgsClearBuffer *) g_object_new(AGS_TYPE_CLEAR_BUFFER,
+							    NULL);
+
+  clear_buffer->device = device;
+
+  return(clear_buffer);
+}
diff --git a/ags/audio/task/ags_clear_buffer.h b/ags/audio/task/ags_clear_buffer.h
new file mode 100644
index 0000000..342ff77
--- /dev/null
+++ b/ags/audio/task/ags_clear_buffer.h
@@ -0,0 +1,54 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2015 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_CLEAR_BUFFER_H__
+#define __AGS_CLEAR_BUFFER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <ags/thread/ags_task.h>
+
+#define AGS_TYPE_CLEAR_BUFFER                (ags_clear_buffer_get_type())
+#define AGS_CLEAR_BUFFER(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_CLEAR_BUFFER, AgsClearBuffer))
+#define AGS_CLEAR_BUFFER_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_CLEAR_BUFFER, AgsClearBufferClass))
+#define AGS_IS_CLEAR_BUFFER(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), AGS_TYPE_CLEAR_BUFFER))
+#define AGS_IS_CLEAR_BUFFER_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_CLEAR_BUFFER))
+#define AGS_CLEAR_BUFFER_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_CLEAR_BUFFER, AgsClearBufferClass))
+
+typedef struct _AgsClearBuffer AgsClearBuffer;
+typedef struct _AgsClearBufferClass AgsClearBufferClass;
+
+struct _AgsClearBuffer
+{
+  AgsTask task;
+
+  GObject *device;
+};
+
+struct _AgsClearBufferClass
+{
+  AgsTaskClass task;
+};
+
+GType ags_clear_buffer_get_type();
+
+AgsClearBuffer* ags_clear_buffer_new(GObject *device);
+
+#endif /*__AGS_CLEAR_BUFFER_H__*/
diff --git a/ags/audio/task/ags_remove_audio.c b/ags/audio/task/ags_remove_audio.c
index 469dd57..052ff3b 100644
--- a/ags/audio/task/ags_remove_audio.c
+++ b/ags/audio/task/ags_remove_audio.c
@@ -314,6 +314,7 @@ ags_remove_audio_launch(AgsTask *task)
   ags_soundcard_set_audio(AGS_SOUNDCARD(remove_audio->soundcard),
 			  list);
 
+  g_object_run_dispose(remove_audio->audio);
   g_object_unref(remove_audio->audio);
 }
 
diff --git a/ags/audio/task/ags_reset_audio_connection.c b/ags/audio/task/ags_reset_audio_connection.c
index c46c106..1ee040e 100644
--- a/ags/audio/task/ags_reset_audio_connection.c
+++ b/ags/audio/task/ags_reset_audio_connection.c
@@ -448,7 +448,6 @@ ags_reset_audio_connection_launch(AgsTask *task)
     audio_connection = list->data;
   }else{
     audio_connection = g_object_new(AGS_TYPE_AUDIO_CONNECTION,
-				    "data-object\0", reset_audio_connection->soundcard,
 				    NULL);
     ags_audio_add_audio_connection(audio,
 				   (GObject *) audio_connection);
@@ -457,6 +456,7 @@ ags_reset_audio_connection_launch(AgsTask *task)
   }
 
   g_object_set(audio_connection,
+	       "data-object\0", reset_audio_connection->soundcard,
 	       "audio\0", audio,
 	       "channel-type\0", reset_audio_connection->channel_type,
 	       "pad\0", reset_audio_connection->pad,
diff --git a/ags/audio/task/ags_set_buffer_size.c b/ags/audio/task/ags_set_buffer_size.c
index 982c1d0..98d0e94 100644
--- a/ags/audio/task/ags_set_buffer_size.c
+++ b/ags/audio/task/ags_set_buffer_size.c
@@ -20,6 +20,7 @@
 #include <ags/audio/task/ags_set_buffer_size.h>
 
 #include <ags/object/ags_application_context.h>
+#include <ags/object/ags_main_loop.h>
 #include <ags/object/ags_connectable.h>
 #include <ags/object/ags_soundcard.h>
 
@@ -371,6 +372,7 @@ ags_set_buffer_size_soundcard(AgsSetBufferSize *set_buffer_size, GObject *soundc
   
   GList *list;
 
+  gdouble thread_frequency;
   guint channels;
   guint samplerate;
   guint buffer_size;
@@ -378,46 +380,56 @@ ags_set_buffer_size_soundcard(AgsSetBufferSize *set_buffer_size, GObject *soundc
 
   application_context = ags_soundcard_get_application_context(AGS_SOUNDCARD(soundcard));
   
-  /*  */
   ags_soundcard_get_presets(AGS_SOUNDCARD(soundcard),
 			    &channels,
 			    &samplerate,
 			    &buffer_size,
 			    &format);
-
-  ags_soundcard_set_presets(AGS_SOUNDCARD(soundcard),
-			    channels,
-			    samplerate,
-			    set_buffer_size->buffer_size,
-			    format);
-
+    
   /* reset soundcards */
   list = ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context));
 
-  while(list != NULL){
-    if(list->data != soundcard){
-      guint target_channels;
-      guint target_samplerate;
-      guint target_buffer_size;
-      guint target_format;
-
-      ags_soundcard_get_presets(AGS_SOUNDCARD(list->data),
-				&target_channels,
-				&target_samplerate,
-				&target_buffer_size,
-				&target_format);
+  if(soundcard == list->data){
+    /* reset soundcards if applied to first soundcard */
+    ags_soundcard_set_presets(AGS_SOUNDCARD(soundcard),
+			      channels,
+			      samplerate,
+			      set_buffer_size->buffer_size,
+			      format);
+
+    while(list != NULL){
+      if(list->data != soundcard){
+	guint target_channels;
+	guint target_samplerate;
+	guint target_buffer_size;
+	guint target_format;
+
+	ags_soundcard_get_presets(AGS_SOUNDCARD(list->data),
+				  &target_channels,
+				  &target_samplerate,
+				  &target_buffer_size,
+				  &target_format);
       
 
-      ags_soundcard_set_presets(AGS_SOUNDCARD(soundcard),
-				target_channels,
-				target_samplerate,
-				set_buffer_size->buffer_size * (target_samplerate / samplerate),
-				target_format);
+	ags_soundcard_set_presets(AGS_SOUNDCARD(soundcard),
+				  target_channels,
+				  target_samplerate,
+				  set_buffer_size->buffer_size * (target_samplerate / samplerate),
+				  target_format);
+      }
+
+      list = list->next;
     }
+    
+    /* reset thread frequency */
+    thread_frequency = samplerate / set_buffer_size->buffer_size + AGS_SOUNDCARD_DEFAULT_OVERCLOCK;
 
-    list = list->next;
+    ags_main_loop_change_frequency(AGS_MAIN_LOOP(application_context->main_loop),
+				   thread_frequency);
+  }else{
+    g_warning("buffer size can only adjusted of your very first soundcard\0");
   }
-
+  
   /* AgsAudio */
   list = ags_soundcard_get_audio(AGS_SOUNDCARD(soundcard));
 
diff --git a/ags/audio/task/ags_set_samplerate.c b/ags/audio/task/ags_set_samplerate.c
index ebd8570..5b24a89 100644
--- a/ags/audio/task/ags_set_samplerate.c
+++ b/ags/audio/task/ags_set_samplerate.c
@@ -20,6 +20,7 @@
 #include <ags/audio/task/ags_set_samplerate.h>
 
 #include <ags/object/ags_application_context.h>
+#include <ags/object/ags_main_loop.h>
 #include <ags/object/ags_connectable.h>
 #include <ags/object/ags_soundcard.h>
 
@@ -366,11 +367,12 @@ ags_set_samplerate_audio(AgsSetSamplerate *set_samplerate, AgsAudio *audio)
 
 void
 ags_set_samplerate_soundcard(AgsSetSamplerate *set_samplerate, GObject *soundcard)
-{
+{  
   AgsApplicationContext *application_context;
   
   GList *list;
 
+  gdouble thread_frequency;
   guint channels;
   guint samplerate;
   guint buffer_size;
@@ -378,46 +380,62 @@ ags_set_samplerate_soundcard(AgsSetSamplerate *set_samplerate, GObject *soundcar
 
   application_context = ags_soundcard_get_application_context(AGS_SOUNDCARD(soundcard));
 
-  /*  */
   ags_soundcard_get_presets(AGS_SOUNDCARD(soundcard),
 			    &channels,
 			    &samplerate,
 			    &buffer_size,
 			    &format);
-  
-  ags_soundcard_set_presets(AGS_SOUNDCARD(soundcard),
-			    channels,
-			    set_samplerate->samplerate,
-			    buffer_size,
-			    format);
 
   /* reset soundcards */
   list = ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context));
 
-  while(list != NULL){
-    if(list->data != soundcard){
-      guint target_channels;
-      guint target_samplerate;
-      guint target_buffer_size;
-      guint target_format;
-
-      ags_soundcard_get_presets(AGS_SOUNDCARD(list->data),
-				&target_channels,
-				&target_samplerate,
-				&target_buffer_size,
-				&target_format);
+  if(soundcard == list->data){
+    /* reset soundcards if applied to first soundcard */
+    ags_soundcard_set_presets(AGS_SOUNDCARD(soundcard),
+			      channels,
+			      set_samplerate->samplerate,
+			      buffer_size,
+			      format);
+
+    /* reset depending soundcards */
+    while(list != NULL){
+      if(list->data != soundcard){
+	guint target_channels;
+	guint target_samplerate;
+	guint target_buffer_size;
+	guint target_format;
+
+	ags_soundcard_get_presets(AGS_SOUNDCARD(list->data),
+				  &target_channels,
+				  &target_samplerate,
+				  &target_buffer_size,
+				  &target_format);
       
 
-      ags_soundcard_set_presets(AGS_SOUNDCARD(soundcard),
-				target_channels,
-				target_samplerate,
-				buffer_size * (target_samplerate / set_samplerate->samplerate),
-				target_format);
-    }
+	ags_soundcard_set_presets(AGS_SOUNDCARD(soundcard),
+				  target_channels,
+				  target_samplerate,
+				  buffer_size * (target_samplerate / set_samplerate->samplerate),
+				  target_format);
+      }
 
-    list = list->next;
+      list = list->next;
+    }
+    
+    /* reset thread frequency */
+    thread_frequency = set_samplerate->samplerate / buffer_size + AGS_SOUNDCARD_DEFAULT_OVERCLOCK;
+
+    ags_main_loop_change_frequency(AGS_MAIN_LOOP(application_context->main_loop),
+				   thread_frequency);
+  }else{
+    /* it is not first soundcard */
+    ags_soundcard_set_presets(AGS_SOUNDCARD(soundcard),
+			      channels,
+			      set_samplerate->samplerate,
+			      buffer_size * (samplerate / set_samplerate->samplerate),
+			      format);
   }
-
+  
   /* AgsAudio */
   list = ags_soundcard_get_audio(AGS_SOUNDCARD(soundcard));
 
diff --git a/ags/audio/task/ags_tic_device.c b/ags/audio/task/ags_tic_device.c
index 881b8e0..530403b 100644
--- a/ags/audio/task/ags_tic_device.c
+++ b/ags/audio/task/ags_tic_device.c
@@ -149,9 +149,19 @@ ags_tic_device_launch(AgsTask *task)
   tic_device = AGS_TIC_DEVICE(task);
 
   if(AGS_IS_SOUNDCARD(tic_device->device)){
-    ags_soundcard_tic(AGS_SOUNDCARD(tic_device->device));
+    AgsSoundcardInterface *soundcard_interface;
+    
+    soundcard_interface = AGS_SOUNDCARD_GET_INTERFACE(AGS_SOUNDCARD(tic_device->device));
+  
+    soundcard_interface->tic(AGS_SOUNDCARD(tic_device->device));
+    //    ags_soundcard_tic(AGS_SOUNDCARD(tic_device->device));
   }else if(AGS_IS_SEQUENCER(AGS_SEQUENCER(tic_device->device))){
-    ags_sequencer_tic(AGS_SEQUENCER(tic_device->device));
+    AgsSequencerInterface *sequencer_interface;
+    
+    sequencer_interface = AGS_SEQUENCER_GET_INTERFACE(AGS_SEQUENCER(tic_device->device));
+  
+    sequencer_interface->tic(AGS_SEQUENCER(tic_device->device));
+    //    ags_sequencer_tic(AGS_SEQUENCER(tic_device->device));
   }
 }
 
diff --git a/ags/audio/thread/ags_audio_loop.c b/ags/audio/thread/ags_audio_loop.c
index 64ae6a4..458aead 100644
--- a/ags/audio/thread/ags_audio_loop.c
+++ b/ags/audio/thread/ags_audio_loop.c
@@ -42,6 +42,8 @@
 #include <ags/audio/thread/ags_export_thread.h>
 #include <ags/audio/thread/ags_audio_thread.h>
 #include <ags/audio/thread/ags_channel_thread.h>
+#include <ags/audio/thread/ags_recycling_thread.h>
+#include <ags/audio/thread/ags_iterator_thread.h>
 
 #include <fontconfig/fontconfig.h>
 
@@ -68,6 +70,9 @@ void ags_audio_loop_set_last_sync(AgsMainLoop *main_loop, guint last_sync);
 guint ags_audio_loop_get_last_sync(AgsMainLoop *main_loop);
 gboolean ags_audio_loop_monitor(AgsMainLoop *main_loop,
 				guint time_cycle, guint *time_spent);
+void ags_audio_loop_change_frequency(AgsMainLoop *main_loop,
+				     gdouble frequency);
+void ags_audio_loop_dispose(GObject *gobject);
 void ags_audio_loop_finalize(GObject *gobject);
 
 void ags_audio_loop_start(AgsThread *thread);
@@ -103,6 +108,7 @@ void ags_audio_loop_sync_audio_super_threaded(AgsAudioLoop *audio_loop,
 
 enum{
   PROP_0,
+  PROP_APPLICATION_CONTEXT,
   PROP_SOUNDCARD,
   PROP_PLAY_RECALL,
   PROP_PLAY_CHANNEL,
@@ -174,10 +180,27 @@ ags_audio_loop_class_init(AgsAudioLoopClass *audio_loop)
   gobject->set_property = ags_audio_loop_set_property;
   gobject->get_property = ags_audio_loop_get_property;
 
+  gobject->dispose = ags_audio_loop_dispose;
   gobject->finalize = ags_audio_loop_finalize;
 
   /* properties */
   /**
+   * AgsDevout:application-context:
+   *
+   * The assigned #AgsApplicationContext
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_object("application-context\0",
+				   "the application context object\0",
+				   "The application context object\0",
+				   AGS_TYPE_APPLICATION_CONTEXT,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_APPLICATION_CONTEXT,
+				  param_spec);
+
+  /**
    * AgsAudioLoop:soundcard:
    *
    * The assigned #AgsAudio.
@@ -271,6 +294,7 @@ ags_audio_loop_main_loop_interface_init(AgsMainLoopInterface *main_loop)
   main_loop->get_last_sync = ags_audio_loop_get_last_sync;
   main_loop->interrupt = NULL;
   main_loop->monitor = ags_audio_loop_monitor;
+  main_loop->change_frequency = ags_audio_loop_change_frequency;
 }
 
 void
@@ -409,6 +433,27 @@ ags_audio_loop_set_property(GObject *gobject,
   audio_loop = AGS_AUDIO_LOOP(gobject);
 
   switch(prop_id){
+  case PROP_APPLICATION_CONTEXT:
+    {
+      AgsApplicationContext *application_context;
+
+      application_context = (AgsApplicationContext *) g_value_get_object(value);
+
+      if(audio_loop->application_context == (GObject *) application_context){
+	return;
+      }
+
+      if(audio_loop->application_context != NULL){
+	g_object_unref(G_OBJECT(audio_loop->application_context));
+      }
+
+      if(application_context != NULL){
+	g_object_ref(G_OBJECT(application_context));
+      }
+      
+      audio_loop->application_context = (GObject *) application_context;
+    }
+    break;
   case PROP_SOUNDCARD:
     {
       GObject *soundcard;
@@ -479,6 +524,11 @@ ags_audio_loop_get_property(GObject *gobject,
   audio_loop = AGS_AUDIO_LOOP(gobject);
 
   switch(prop_id){
+  case PROP_APPLICATION_CONTEXT:
+    {
+      g_value_set_object(value, audio_loop->application_context);
+    }
+    break;
   case PROP_SOUNDCARD:
     {
       g_value_set_object(value, audio_loop->soundcard);
@@ -593,12 +643,165 @@ ags_audio_loop_monitor(AgsMainLoop *main_loop,
 }
 
 void
+ags_audio_loop_change_frequency(AgsMainLoop *main_loop,
+				gdouble frequency)
+{
+  AgsThread *audio_loop, *thread;
+
+  audio_loop = AGS_THREAD(main_loop);
+  
+  g_object_set(audio_loop,
+	       "frequency\0", frequency,
+	       NULL);
+
+  /* reset soundcard thread */
+  thread = audio_loop;
+
+  while(ags_thread_find_type(thread, AGS_TYPE_SOUNDCARD_THREAD) != NULL){
+    g_object_set(thread,
+		 "frequency\0", frequency,
+		 NULL);
+
+    thread = g_atomic_pointer_get(&(thread->next));
+  }
+
+  /* reset sequencer thread */
+  thread = audio_loop;
+
+  while(ags_thread_find_type(thread, AGS_TYPE_SEQUENCER_THREAD) != NULL){
+    g_object_set(thread,
+		 "frequency\0", frequency,
+		 NULL);
+
+    thread = g_atomic_pointer_get(&(thread->next));
+  }
+
+  /* reset export thread */
+  thread = audio_loop;
+
+  while(ags_thread_find_type(thread, AGS_TYPE_EXPORT_THREAD) != NULL){
+    g_object_set(thread,
+		 "frequency\0", frequency,
+		 NULL);
+
+    thread = g_atomic_pointer_get(&(thread->next));
+  }
+
+  /* reset audio thread */
+  thread = audio_loop;
+
+  while(ags_thread_find_type(thread, AGS_TYPE_AUDIO_THREAD) != NULL){
+    g_object_set(thread,
+		 "frequency\0", frequency,
+		 NULL);
+
+    thread = g_atomic_pointer_get(&(thread->next));
+  }
+
+  /* reset channel thread */
+  thread = audio_loop;
+
+  while(ags_thread_find_type(thread, AGS_TYPE_CHANNEL_THREAD) != NULL){
+    g_object_set(thread,
+		 "frequency\0", frequency,
+		 NULL);
+
+    thread = g_atomic_pointer_get(&(thread->next));
+  }
+}
+
+void
+ags_audio_loop_dispose(GObject *gobject)
+{
+  AgsAudioLoop *audio_loop;
+
+  audio_loop = AGS_AUDIO_LOOP(gobject);
+
+  /* application context */
+  if(audio_loop->application_context != NULL){
+    g_object_unref(audio_loop->application_context);
+
+    audio_loop->application_context = NULL;
+  }
+
+  /* soundcard */
+  if(audio_loop->soundcard != NULL){
+    g_object_unref(audio_loop->soundcard);
+
+    audio_loop->soundcard = NULL;
+  }
+
+  /* async queue */
+  if(audio_loop->async_queue != NULL){
+    g_object_unref(audio_loop->async_queue);
+
+    audio_loop->async_queue = NULL;
+  }
+
+  /* unref AgsPlayback lists */
+  if(audio_loop->play_recall != NULL){
+    g_list_free_full(audio_loop->play_recall,
+		     g_object_unref);
+    
+    audio_loop->play_recall = NULL;
+  }
+
+  if(audio_loop->play_channel != NULL){
+    g_list_free_full(audio_loop->play_channel,
+		     g_object_unref);
+    
+    audio_loop->play_channel = NULL;
+  }
+
+  if(audio_loop->play_audio != NULL){
+    g_list_free_full(audio_loop->play_audio,
+		     g_object_unref);
+    
+    audio_loop->play_audio = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_audio_loop_parent_class)->dispose(gobject);
+}
+
+void
 ags_audio_loop_finalize(GObject *gobject)
 {
   AgsAudioLoop *audio_loop;
 
   audio_loop = AGS_AUDIO_LOOP(gobject);
 
+  /* application context */
+  if(audio_loop->application_context != NULL){
+    g_object_unref(audio_loop->application_context);
+  }
+
+  /* soundcard */
+  if(audio_loop->soundcard != NULL){
+    g_object_unref(audio_loop->soundcard);
+  }
+
+  /* async queue */
+  if(audio_loop->async_queue != NULL){
+    g_object_unref(audio_loop->async_queue);
+  }
+
+  /* tree lock and recall mutex */
+  pthread_mutex_destroy(audio_loop->tree_lock);
+  free(audio_loop->tree_lock);
+
+  pthread_mutex_destroy(audio_loop->recall_mutex);
+  free(audio_loop->recall_mutex);
+
+  /* timing mutex and cond */
+  pthread_mutex_destroy(audio_loop->timing_mutex);
+  free(audio_loop->timing_mutex);
+
+  pthread_cond_destroy(audio_loop->timing_cond);
+  free(audio_loop->timing_cond);
+
+  //FIXME:JK: destroy timing thread
+  
   /* unref AgsPlayback lists */
   g_list_free_full(audio_loop->play_recall,
 		   g_object_unref);
@@ -1233,18 +1436,18 @@ ags_audio_loop_play_audio(AgsAudioLoop *audio_loop)
 
 	  /* super threaded recycling level */
 	  if((AGS_PLAYBACK_PLAYBACK & (g_atomic_int_get(&(playback->flags)))) != 0){
-	    playback->iterator_thread[0]->flags |= AGS_ITERATOR_THREAD_DONE;
-	    pthread_cond_signal(playback->iterator_thread[0]->tic_cond);
+	    AGS_ITERATOR_THREAD(playback->iterator_thread[0])->flags |= AGS_ITERATOR_THREAD_DONE;
+	    pthread_cond_signal(AGS_ITERATOR_THREAD(playback->iterator_thread[0])->tic_cond);
 	  }
 
 	  if((AGS_PLAYBACK_SEQUENCER & (g_atomic_int_get(&(playback->flags)))) != 0){
-	    playback->iterator_thread[1]->flags |= AGS_ITERATOR_THREAD_DONE;
-	    pthread_cond_signal(playback->iterator_thread[1]->tic_cond);
+	    AGS_ITERATOR_THREAD(playback->iterator_thread[1])->flags |= AGS_ITERATOR_THREAD_DONE;
+	    pthread_cond_signal(AGS_ITERATOR_THREAD(playback->iterator_thread[1])->tic_cond);
 	  }
 
 	  if((AGS_PLAYBACK_NOTATION & (g_atomic_int_get(&(playback->flags)))) != 0){
-	    playback->iterator_thread[2]->flags |= AGS_ITERATOR_THREAD_DONE;
-	    pthread_cond_signal(playback->iterator_thread[2]->tic_cond);
+	    AGS_ITERATOR_THREAD(playback->iterator_thread[2])->flags |= AGS_ITERATOR_THREAD_DONE;
+	    pthread_cond_signal(AGS_ITERATOR_THREAD(playback->iterator_thread[2])->tic_cond);
 	  }
 	}else{
 	  gboolean remove_domain;
diff --git a/ags/audio/thread/ags_audio_thread.c b/ags/audio/thread/ags_audio_thread.c
index cc2a114..8fb1615 100644
--- a/ags/audio/thread/ags_audio_thread.c
+++ b/ags/audio/thread/ags_audio_thread.c
@@ -47,6 +47,7 @@ void ags_audio_thread_get_property(GObject *gobject,
 				   GParamSpec *param_spec);
 void ags_audio_thread_connect(AgsConnectable *connectable);
 void ags_audio_thread_disconnect(AgsConnectable *connectable);
+void ags_audio_thread_dispose(GObject *gobject);
 void ags_audio_thread_finalize(GObject *gobject);
 
 void ags_audio_thread_start(AgsThread *thread);
@@ -127,6 +128,7 @@ ags_audio_thread_class_init(AgsAudioThreadClass *audio_thread)
   gobject->set_property = ags_audio_thread_set_property;
   gobject->get_property = ags_audio_thread_get_property;
 
+  gobject->dispose = ags_audio_thread_dispose;
   gobject->finalize = ags_audio_thread_finalize;
 
   /* properties */
@@ -367,11 +369,63 @@ ags_audio_thread_disconnect(AgsConnectable *connectable)
 }
 
 void
+ags_audio_thread_dispose(GObject *gobject)
+{
+  AgsAudioThread *audio_thread;
+
+  audio_thread = AGS_AUDIO_THREAD(gobject);
+
+  /* soundcard */
+  if(audio_thread->soundcard != NULL){
+    g_object_unref(audio_thread->soundcard);
+
+    audio_thread->soundcard = NULL;
+  }
+
+  /* audio */
+  if(audio_thread->audio != NULL){
+    g_object_unref(audio_thread->audio);
+
+    audio_thread->audio = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_audio_thread_parent_class)->dispose(gobject);
+}
+
+void
 ags_audio_thread_finalize(GObject *gobject)
 {
-  G_OBJECT_CLASS(ags_audio_thread_parent_class)->finalize(gobject);
+  AgsAudioThread *audio_thread;
 
-  /* empty */
+  audio_thread = AGS_AUDIO_THREAD(gobject);
+
+  /* soundcard */
+  if(audio_thread->soundcard != NULL){
+    g_object_unref(audio_thread->soundcard);
+  }
+
+  /* wakeup mutex and cond */
+  pthread_mutex_destroy(audio_thread->wakeup_mutex);
+  free(audio_thread->wakeup_mutex);
+  
+  pthread_mutex_destroy(audio_thread->wakeup_cond);
+  free(audio_thread->wakeup_cond);
+
+  /* sync mutex and cond */
+  pthread_mutex_destroy(audio_thread->done_mutex);
+  free(audio_thread->done_mutex);
+  
+  pthread_mutex_destroy(audio_thread->done_cond);
+  free(audio_thread->done_cond);
+
+  /* audio */
+  if(audio_thread->audio != NULL){
+    g_object_unref(audio_thread->audio);
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_audio_thread_parent_class)->finalize(gobject);
 }
 
 void
diff --git a/ags/audio/thread/ags_channel_thread.c b/ags/audio/thread/ags_channel_thread.c
index be745db..09d2caa 100644
--- a/ags/audio/thread/ags_channel_thread.c
+++ b/ags/audio/thread/ags_channel_thread.c
@@ -43,6 +43,7 @@ void ags_channel_thread_get_property(GObject *gobject,
 				     GParamSpec *param_spec);
 void ags_channel_thread_connect(AgsConnectable *connectable);
 void ags_channel_thread_disconnect(AgsConnectable *connectable);
+void ags_channel_thread_dispose(GObject *gobject);
 void ags_channel_thread_finalize(GObject *gobject);
 
 void ags_channel_thread_start(AgsThread *thread);
@@ -120,6 +121,7 @@ ags_channel_thread_class_init(AgsChannelThreadClass *channel_thread)
   gobject->set_property = ags_channel_thread_set_property;
   gobject->get_property = ags_channel_thread_get_property;
 
+  gobject->dispose = ags_channel_thread_dispose;
   gobject->finalize = ags_channel_thread_finalize;
 
   /* properties */
@@ -360,11 +362,63 @@ ags_channel_thread_disconnect(AgsConnectable *connectable)
 }
 
 void
+ags_channel_thread_dispose(GObject *gobject)
+{
+  AgsChannelThread *channel_thread;
+
+  channel_thread = AGS_CHANNEL_THREAD(gobject);
+
+  /* soundcard */
+  if(channel_thread->soundcard != NULL){
+    g_object_unref(channel_thread->soundcard);
+
+    channel_thread->soundcard = NULL;
+  }
+
+  /* channel */
+  if(channel_thread->channel != NULL){
+    g_object_unref(channel_thread->channel);
+
+    channel_thread->channel = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_channel_thread_parent_class)->dispose(gobject);
+}
+
+void
 ags_channel_thread_finalize(GObject *gobject)
 {
-  G_OBJECT_CLASS(ags_channel_thread_parent_class)->finalize(gobject);
+  AgsChannelThread *channel_thread;
 
-  /* empty */
+  channel_thread = AGS_CHANNEL_THREAD(gobject);
+
+  /* soundcard */
+  if(channel_thread->soundcard != NULL){
+    g_object_unref(channel_thread->soundcard);
+  }
+
+  /* wakeup mutex and cond */
+  pthread_mutex_destroy(channel_thread->wakeup_mutex);
+  free(channel_thread->wakeup_mutex);
+  
+  pthread_mutex_destroy(channel_thread->wakeup_cond);
+  free(channel_thread->wakeup_cond);
+
+  /* sync mutex and cond */
+  pthread_mutex_destroy(channel_thread->done_mutex);
+  free(channel_thread->done_mutex);
+  
+  pthread_mutex_destroy(channel_thread->done_cond);
+  free(channel_thread->done_cond);
+
+  /* channel */
+  if(channel_thread->channel != NULL){
+    g_object_unref(channel_thread->channel);
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_channel_thread_parent_class)->finalize(gobject);
 }
 
 void
diff --git a/ags/audio/thread/ags_export_thread.c b/ags/audio/thread/ags_export_thread.c
index f12d7e3..c8e2813 100644
--- a/ags/audio/thread/ags_export_thread.c
+++ b/ags/audio/thread/ags_export_thread.c
@@ -25,6 +25,7 @@
 #include <ags/thread/ags_mutex_manager.h>
 
 #include <ags/audio/ags_devout.h>
+#include <ags/audio/jack/ags_jack_devout.h>
 
 #include <math.h>
 
@@ -41,6 +42,7 @@ void ags_export_thread_get_property(GObject *gobject,
 				    GParamSpec *param_spec);
 void ags_export_thread_connect(AgsConnectable *connectable);
 void ags_export_thread_disconnect(AgsConnectable *connectable);
+void ags_export_thread_dispose(GObject *gobject);
 void ags_export_thread_finalize(GObject *gobject);
 
 void ags_export_thread_start(AgsThread *thread);
@@ -118,6 +120,7 @@ ags_export_thread_class_init(AgsExportThreadClass *export_thread)
   gobject->get_property = ags_export_thread_get_property;
   gobject->set_property = ags_export_thread_set_property;
 
+  gobject->dispose = ags_export_thread_dispose;
   gobject->finalize = ags_export_thread_finalize;
 
   /* properties */
@@ -250,6 +253,9 @@ ags_export_thread_set_property(GObject *gobject,
     {
       GObject *soundcard;
 
+      guint samplerate;
+      guint buffer_size;
+
       soundcard = (GObject *) g_value_get_object(value);
 
       if(export_thread->soundcard != NULL){
@@ -259,9 +265,22 @@ ags_export_thread_set_property(GObject *gobject,
       if(soundcard != NULL){
 	g_object_ref(G_OBJECT(soundcard));
 
+	ags_soundcard_get_presets(AGS_SOUNDCARD(soundcard),
+				  NULL,
+				  &samplerate,
+				  &buffer_size,
+				  NULL);
+	
+	g_object_set(export_thread,
+		     "frequency\0", ceil((gdouble) samplerate / (gdouble) buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK,
+		     NULL);
+
 	if(AGS_IS_DEVOUT(soundcard)){
 	  g_atomic_int_or(&(AGS_THREAD(export_thread)->flags),
 			  (AGS_THREAD_INTERMEDIATE_POST_SYNC));
+	}else if(AGS_IS_JACK_DEVOUT(soundcard)){
+	  g_atomic_int_and(&(AGS_THREAD(export_thread)->flags),
+			   (~AGS_THREAD_INTERMEDIATE_POST_SYNC));
 	}
       }
 
@@ -339,11 +358,49 @@ ags_export_thread_disconnect(AgsConnectable *connectable)
 }
 
 void
+ags_export_thread_dispose(GObject *gobject)
+{
+  AgsExportThread *export_thread;
+
+  export_thread = AGS_EXPORT_THREAD(gobject);
+
+  /* soundcard */
+  if(export_thread->soundcard != NULL){
+    g_object_unref(export_thread->soundcard);
+
+    export_thread->soundcard = NULL;
+  }
+  
+  /* audio file */
+  if(export_thread->audio_file != NULL){
+    g_object_unref(export_thread->audio_file);
+
+    export_thread->audio_file = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_export_thread_parent_class)->dispose(gobject);
+}
+
+void
 ags_export_thread_finalize(GObject *gobject)
 {
-  G_OBJECT_CLASS(ags_export_thread_parent_class)->finalize(gobject);
+  AgsExportThread *export_thread;
 
-  /* empty */
+  export_thread = AGS_EXPORT_THREAD(gobject);
+
+  /* soundcard */
+  if(export_thread->soundcard != NULL){
+    g_object_unref(export_thread->soundcard);
+  }
+  
+  /* audio file */  
+  if(export_thread->audio_file != NULL){
+    g_object_unref(export_thread->audio_file);
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_export_thread_parent_class)->finalize(gobject);
 }
 
 void
diff --git a/ags/audio/thread/ags_sequencer_thread.c b/ags/audio/thread/ags_sequencer_thread.c
index df9d17c..b695e32 100644
--- a/ags/audio/thread/ags_sequencer_thread.c
+++ b/ags/audio/thread/ags_sequencer_thread.c
@@ -47,6 +47,7 @@ void ags_sequencer_thread_get_property(GObject *gobject,
 				       GParamSpec *param_spec);
 void ags_sequencer_thread_connect(AgsConnectable *connectable);
 void ags_sequencer_thread_disconnect(AgsConnectable *connectable);
+void ags_sequencer_thread_dispose(GObject *gobject);
 void ags_sequencer_thread_finalize(GObject *gobject);
 
 void ags_sequencer_thread_start(AgsThread *thread);
@@ -133,6 +134,7 @@ ags_sequencer_thread_class_init(AgsSequencerThreadClass *sequencer_thread)
   gobject->set_property = ags_sequencer_thread_set_property;
   gobject->get_property = ags_sequencer_thread_get_property;
 
+  gobject->dispose = ags_sequencer_thread_dispose;
   gobject->finalize = ags_sequencer_thread_finalize;
 
   /**
@@ -238,6 +240,7 @@ ags_sequencer_thread_init(AgsSequencerThread *sequencer_thread)
 
   sequencer_thread->sequencer = NULL;
 
+  sequencer_thread->timestamp_thread = NULL;
   //  sequencer_thread->timestamp_thread = (AgsThread *) ags_timestamp_thread_new();
   //  ags_thread_add_child(thread, sequencer_thread->timestamp_thread);
 
@@ -271,6 +274,9 @@ ags_sequencer_thread_set_property(GObject *gobject,
 	if(AGS_IS_MIDIIN(sequencer)){
 	  g_atomic_int_or(&(AGS_THREAD(sequencer_thread)->flags),
 			  (AGS_THREAD_INTERMEDIATE_PRE_SYNC));
+	}else if(AGS_IS_JACK_MIDIIN(sequencer)){
+	  g_atomic_int_and(&(AGS_THREAD(sequencer_thread)->flags),
+			   (~AGS_THREAD_INTERMEDIATE_PRE_SYNC));
 	}
       }
 
@@ -329,11 +335,37 @@ ags_sequencer_thread_disconnect(AgsConnectable *connectable)
 }
 
 void
+ags_sequencer_thread_dispose(GObject *gobject)
+{
+  AgsSequencerThread *sequencer_thread;
+
+  sequencer_thread = AGS_SEQUENCER_THREAD(gobject);
+
+  /* sequencer */
+  if(sequencer_thread->sequencer != NULL){
+    g_object_unref(sequencer_thread->sequencer);
+
+    sequencer_thread->sequencer = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_sequencer_thread_parent_class)->dispose(gobject);
+}
+
+void
 ags_sequencer_thread_finalize(GObject *gobject)
 {
-  G_OBJECT_CLASS(ags_sequencer_thread_parent_class)->finalize(gobject);
+  AgsSequencerThread *sequencer_thread;
 
-  /* empty */
+  sequencer_thread = AGS_SEQUENCER_THREAD(gobject);
+
+  /* sequencer */
+  if(sequencer_thread->sequencer != NULL){
+    g_object_unref(sequencer_thread->sequencer);
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_sequencer_thread_parent_class)->finalize(gobject);
 }
 
 void
diff --git a/ags/audio/thread/ags_soundcard_thread.c b/ags/audio/thread/ags_soundcard_thread.c
index 3ed9200..d15941d 100644
--- a/ags/audio/thread/ags_soundcard_thread.c
+++ b/ags/audio/thread/ags_soundcard_thread.c
@@ -48,6 +48,7 @@ void ags_soundcard_thread_get_property(GObject *gobject,
 				       GParamSpec *param_spec);
 void ags_soundcard_thread_connect(AgsConnectable *connectable);
 void ags_soundcard_thread_disconnect(AgsConnectable *connectable);
+void ags_soundcard_thread_dispose(GObject *gobject);
 void ags_soundcard_thread_finalize(GObject *gobject);
 
 void ags_soundcard_thread_start(AgsThread *thread);
@@ -129,6 +130,7 @@ ags_soundcard_thread_class_init(AgsSoundcardThreadClass *soundcard_thread)
   gobject->set_property = ags_soundcard_thread_set_property;
   gobject->get_property = ags_soundcard_thread_get_property;
 
+  gobject->dispose = ags_soundcard_thread_dispose;
   gobject->finalize = ags_soundcard_thread_finalize;
 
   /**
@@ -223,7 +225,8 @@ ags_soundcard_thread_init(AgsSoundcardThread *soundcard_thread)
   /*  */
   soundcard_thread->soundcard = NULL;
 
-  soundcard_thread->timestamp_thread = (AgsThread *) ags_timestamp_thread_new();
+  soundcard_thread->timestamp_thread = NULL;
+  //  soundcard_thread->timestamp_thread = (AgsThread *) ags_timestamp_thread_new();
   //  ags_thread_add_child(thread, soundcard_thread->timestamp_thread);
 
   soundcard_thread->error = NULL;
@@ -242,12 +245,12 @@ ags_soundcard_thread_set_property(GObject *gobject,
   switch(prop_id){
   case PROP_SOUNDCARD:
     {
-      AgsSoundcard *soundcard;
+      GObject *soundcard;
 
       guint samplerate;
       guint buffer_size;
 
-      soundcard = (AgsSoundcard *) g_value_get_object(value);
+      soundcard = (GObject *) g_value_get_object(value);
 
       if(soundcard_thread->soundcard != NULL){
 	g_object_unref(G_OBJECT(soundcard_thread->soundcard));
@@ -269,6 +272,9 @@ ags_soundcard_thread_set_property(GObject *gobject,
 	if(AGS_IS_DEVOUT(soundcard)){
 	  g_atomic_int_or(&(AGS_THREAD(soundcard_thread)->flags),
 			  (AGS_THREAD_INTERMEDIATE_POST_SYNC));
+	}else if(AGS_IS_JACK_DEVOUT(soundcard)){
+	  g_atomic_int_and(&(AGS_THREAD(soundcard_thread)->flags),
+			   (~AGS_THREAD_INTERMEDIATE_POST_SYNC));
 	}
       }
 
@@ -330,11 +336,37 @@ ags_soundcard_thread_disconnect(AgsConnectable *connectable)
 }
 
 void
+ags_soundcard_thread_dispose(GObject *gobject)
+{
+  AgsSoundcardThread *soundcard_thread;
+
+  soundcard_thread = AGS_SOUNDCARD_THREAD(gobject);
+
+  /* soundcard */
+  if(soundcard_thread->soundcard != NULL){
+    g_object_unref(soundcard_thread->soundcard);
+
+    soundcard_thread->soundcard = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_soundcard_thread_parent_class)->dispose(gobject);
+}
+
+void
 ags_soundcard_thread_finalize(GObject *gobject)
 {
-  G_OBJECT_CLASS(ags_soundcard_thread_parent_class)->finalize(gobject);
+  AgsSoundcardThread *soundcard_thread;
 
-  /* empty */
+  soundcard_thread = AGS_SOUNDCARD_THREAD(gobject);
+
+  /* soundcard */
+  if(soundcard_thread->soundcard != NULL){
+    g_object_unref(soundcard_thread->soundcard);
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_soundcard_thread_parent_class)->finalize(gobject);
 }
 
 void
diff --git a/ags/config.h.in b/ags/config.h.in
index 53f16dd..3fe8081 100644
--- a/ags/config.h.in
+++ b/ags/config.h.in
@@ -66,9 +66,6 @@
 /* GLib 2.6 available */
 #undef HAVE_GLIB_2_6
 
-/* Define to 1 if you have the <gmp.h> header file. */
-#undef HAVE_GMP_H
-
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
diff --git a/ags/gsequencer_main.c b/ags/gsequencer_main.c
index d6c7108..1e61f1f 100644
--- a/ags/gsequencer_main.c
+++ b/ags/gsequencer_main.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -21,6 +21,7 @@
 #include <glib-object.h>
 
 #include <gdk/gdk.h>
+#include <pango/pangocairo.h>
 
 #include <X11/Xlib.h>
 
@@ -121,6 +122,7 @@ extern AgsApplicationContext *ags_application_context;
 
 extern volatile gboolean ags_show_start_animation;
 
+#ifndef AGS_USE_TIMER
 void
 ags_signal_handler(int signr)
 {
@@ -132,26 +134,29 @@ ags_signal_handler(int signr)
     sigemptyset(&(ags_sigact.sa_mask));
 
     //    if(signr == AGS_ASYNC_QUEUE_SIGNAL_HIGH){
-      // pthread_yield();
+    // pthread_yield();
     //    }
   }
 }
+#endif
 
+#ifdef AGS_USE_TIMER
 void
 ags_signal_handler_timer(int sig, siginfo_t *si, void *uc)
 {
-    pthread_mutex_lock(AGS_THREAD(ags_application_context->main_loop)->timer_mutex);
+  pthread_mutex_lock(AGS_THREAD(ags_application_context->main_loop)->timer_mutex);
 
-    g_atomic_int_set(&(AGS_THREAD(ags_application_context->main_loop)->timer_expired),
-		     TRUE);
+  g_atomic_int_set(&(AGS_THREAD(ags_application_context->main_loop)->timer_expired),
+		   TRUE);
   
-    if(AGS_THREAD(ags_application_context->main_loop)->timer_wait){
-      pthread_cond_signal(AGS_THREAD(ags_application_context->main_loop)->timer_cond);
-    }
+  if(AGS_THREAD(ags_application_context->main_loop)->timer_wait){
+    pthread_cond_signal(AGS_THREAD(ags_application_context->main_loop)->timer_cond);
+  }
     
-    pthread_mutex_unlock(AGS_THREAD(ags_application_context->main_loop)->timer_mutex);
+  pthread_mutex_unlock(AGS_THREAD(ags_application_context->main_loop)->timer_mutex);
   //  signal(sig, SIG_IGN);
 }
+#endif
 
 static void
 ags_signal_cleanup()
@@ -164,17 +169,19 @@ ags_start_animation_thread(void *ptr)
 {
   GtkWidget *window;
   GdkRectangle rectangle;
-  
-  cairo_t *cr;
+
+  cairo_t *gdk_cr, *cr;
   cairo_surface_t *surface;
-  
+
   AgsLog *log;
 
   gchar *filename;
+  unsigned char *bg_data, *image_data;
   
   /* create a buffer suitable to image size */
   GList *list, *start;
 
+  guint image_size;
   gdouble x0, y0;
   guint i, nth;
   
@@ -186,22 +193,33 @@ ags_start_animation_thread(void *ptr)
   rectangle.y = 0;
   rectangle.width = 800;
   rectangle.height = 450;
+
+  image_size = 4 * 800 * 450;
   
-  cr = gdk_cairo_create(window->window);
+  gdk_cr = gdk_cairo_create(window->window);
   
   filename = g_strdup_printf("%s%s\0", DESTDIR, "/gsequencer/images/ags_supermoon-800x450.png\0");
 
   surface = cairo_image_surface_create_from_png(filename);
+  image_data = cairo_image_surface_get_data(surface);
+  
+  bg_data = (unsigned char *) malloc(image_size * sizeof(unsigned char));
+
+  if(image_data != NULL){
+    memcpy(bg_data, image_data, image_size * sizeof(unsigned char));
+  }
+  
+  cr = cairo_create(surface);
   
   cairo_select_font_face(cr, "Georgia\0",
 			 CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
   cairo_set_font_size(cr, (gdouble) 11.0);
-
+  
   gdk_window_show(window->window);
   
   gdk_threads_leave();
 
-  log = ags_log_get_instance();    
+  log = ags_log_get_instance();  
   nth = 0;
   
   while(g_atomic_int_get(&(ags_show_start_animation))){
@@ -211,6 +229,10 @@ ags_start_animation_thread(void *ptr)
     i = g_list_length(start);
 
     if(i > nth){
+      if(image_data != NULL){
+	memcpy(image_data, bg_data, image_size * sizeof(unsigned char));
+      }
+      
       cairo_set_source_surface(cr, surface, 0, 0);
       cairo_paint(cr);
       cairo_surface_flush(surface);
@@ -226,8 +248,9 @@ ags_start_animation_thread(void *ptr)
 	
 	cairo_move_to(cr,
 		      x0, y0);
+
 	cairo_show_text(cr, list->data);
-	
+
 	list = list->next;
 	y0 -= 12.0;
       }
@@ -235,12 +258,18 @@ ags_start_animation_thread(void *ptr)
       cairo_move_to(cr,
 		    x0, 4.0 + (i + 1) * 12.0);
       cairo_show_text(cr, "...\0");
-
-      gdk_flush();
+      
       nth = g_list_length(start);
-    }    
+    }
+
+    cairo_set_source_surface(gdk_cr, surface, 0, 0);
+    cairo_paint(gdk_cr);
+    cairo_surface_flush(surface);
+    gdk_flush();
   }
 
+  free(bg_data);
+  
   gdk_threads_enter();
 
   gtk_widget_destroy(window);
@@ -267,6 +296,7 @@ ags_start_animation(pthread_t *thread)
 		 ags_start_animation_thread, window);
 }
 
+#ifndef AGS_USE_TIMER
 void
 ags_setup(int argc, char **argv)
 {
@@ -281,7 +311,6 @@ ags_setup(int argc, char **argv)
   struct passwd *pw;
 
   gchar *blacklist_filename;
-  gchar *rc_filename;
   gchar *filename;
   
   uid_t uid;
@@ -424,20 +453,17 @@ ags_setup(int argc, char **argv)
   ags_application_context->argc = argc;
   ags_application_context->argv = argv;
 
+  ags_application_context_register_types(ags_application_context);
+
   /* fix cross-references in managers */
   lv2_worker_manager->thread_pool = ((AgsXorgApplicationContext *) ags_application_context)->thread_pool;
-  
-  /* parse rc file */
-  rc_filename = g_strdup_printf("%s/%s/ags.rc\0",
-				pw->pw_dir,
-				AGS_DEFAULT_DIRECTORY);
-  gtk_rc_parse(rc_filename);
-  g_free(rc_filename);
 
   g_atomic_int_set(&(ags_show_start_animation),
 		   FALSE);
 }
+#endif
 
+#ifndef AGS_USE_TIMER
 void
 ags_launch(gboolean single_thread)
 {
@@ -478,8 +504,8 @@ ags_launch(gboolean single_thread)
 			       polling_thread);
   start_queue = g_list_prepend(start_queue,
 			       task_thread);
-  start_queue = g_list_prepend(start_queue,
-			       gui_thread);
+  //  start_queue = g_list_prepend(start_queue,
+  //			       gui_thread);
   g_atomic_pointer_set(&(audio_loop->start_queue),
 		       start_queue);
   
@@ -507,6 +533,9 @@ ags_launch(gboolean single_thread)
     
     pthread_mutex_unlock(audio_loop->start_mutex);
 
+    /* start gui thread */
+    ags_thread_start(gui_thread);
+    
     /* wait for gui thread */
     pthread_mutex_lock(gui_thread->start_mutex);
 
@@ -526,6 +555,9 @@ ags_launch(gboolean single_thread)
     
     pthread_mutex_unlock(gui_thread->start_mutex);
     
+    g_atomic_int_set(&(AGS_XORG_APPLICATION_CONTEXT(ags_application_context)->gui_ready),
+		     1);
+    
     /* autosave thread */
     if(!g_strcmp0(ags_config_get_value(config,
 				       AGS_CONFIG_GENERIC,
@@ -578,7 +610,9 @@ ags_launch(gboolean single_thread)
     ags_thread_start((AgsThread *) single_thread);
   }
 }
+#endif
 
+#ifndef AGS_USE_TIMER
 void
 ags_launch_filename(gchar *filename,
 		    gboolean single_thread)
@@ -616,7 +650,7 @@ ags_launch_filename(gchar *filename,
   if(g_strcmp0(ags_config_get_value(config,
 				    AGS_CONFIG_GENERIC,
 				    "simple-file\0"),
-		 "false\0")){
+	       "false\0")){
     AgsSimpleFile *simple_file;
 
     AgsSimpleFileRead *simple_file_read;
@@ -645,8 +679,8 @@ ags_launch_filename(gchar *filename,
 				 polling_thread);
     start_queue = g_list_prepend(start_queue,
 				 task_thread);
-    start_queue = g_list_prepend(start_queue,
-				 gui_thread);
+    //    start_queue = g_list_prepend(start_queue,
+    //				 gui_thread);
     g_atomic_pointer_set(&(audio_loop->start_queue),
 			 start_queue);
   
@@ -674,6 +708,9 @@ ags_launch_filename(gchar *filename,
     
       pthread_mutex_unlock(audio_loop->start_mutex);
 
+      /* start gui thread */
+      ags_thread_start(gui_thread);
+      
       /* wait for gui thread */
       pthread_mutex_lock(gui_thread->start_mutex);
 
@@ -692,7 +729,6 @@ ags_launch_filename(gchar *filename,
       }
     
       pthread_mutex_unlock(gui_thread->start_mutex);
-     
       
       /* autosave thread */
       if(!g_strcmp0(ags_config_get_value(config,
@@ -747,7 +783,9 @@ ags_launch_filename(gchar *filename,
     		 NULL);
   }
 }
+#endif
 
+#ifdef AGS_USE_TIMER
 timer_t*
 ags_timer_setup()
 {
@@ -782,11 +820,13 @@ ags_timer_setup()
   if(timer_create(CLOCK_MONOTONIC, &ags_sev_timer, timer_id) == -1){
     perror("timer_create\0");
     exit(EXIT_FAILURE);
-  }
+  }  
 
   return(timer_id);
 }
+#endif
 
+#ifdef AGS_USE_TIMER
 void
 ags_timer_start(timer_t *timer_id)
 {
@@ -807,9 +847,11 @@ ags_timer_start(timer_t *timer_id)
   if(sigprocmask(SIG_UNBLOCK, &ags_timer_mask, NULL) == -1){
     perror("sigprocmask\0");
     exit(EXIT_FAILURE);
-  }
+  }  
 }
+#endif
 
+#ifdef AGS_USE_TIMER
 void
 ags_timer_launch(timer_t *timer_id,
 		 gboolean single_thread)
@@ -851,8 +893,8 @@ ags_timer_launch(timer_t *timer_id,
 			       polling_thread);
   start_queue = g_list_prepend(start_queue,
 			       task_thread);
-  start_queue = g_list_prepend(start_queue,
-			       gui_thread);
+  //  start_queue = g_list_prepend(start_queue,
+  //			       gui_thread);
   g_atomic_pointer_set(&(audio_loop->start_queue),
 		       start_queue);
 
@@ -883,6 +925,9 @@ ags_timer_launch(timer_t *timer_id,
     }
   
     pthread_mutex_unlock(audio_loop->start_mutex);
+
+    /* start gui thread */
+    ags_thread_start(gui_thread);
     
     /* wait for gui thread */
     pthread_mutex_lock(gui_thread->start_mutex);
@@ -890,11 +935,11 @@ ags_timer_launch(timer_t *timer_id,
     if(g_atomic_int_get(&(gui_thread->start_done)) == FALSE){
       
       g_atomic_int_set(&(gui_thread->start_wait),
-		       TRUE);
+    		       TRUE);
 
       while(g_atomic_int_get(&(gui_thread->start_done)) == FALSE){
 	g_atomic_int_set(&(gui_thread->start_wait),
-			 TRUE);
+    			 TRUE);
 	
 	pthread_cond_wait(gui_thread->start_cond,
 			  gui_thread->start_mutex);
@@ -903,6 +948,9 @@ ags_timer_launch(timer_t *timer_id,
     
     pthread_mutex_unlock(gui_thread->start_mutex);
 
+    g_atomic_int_set(&(AGS_XORG_APPLICATION_CONTEXT(ags_application_context)->gui_ready),
+		     1);
+
     /* autosave thread */
     if(!g_strcmp0(ags_config_get_value(config,
 				       AGS_CONFIG_GENERIC,
@@ -954,7 +1002,9 @@ ags_timer_launch(timer_t *timer_id,
     ags_thread_start((AgsThread *) single_thread);
   }
 }
+#endif
 
+#ifdef AGS_USE_TIMER
 void
 ags_timer_launch_filename(timer_t *timer_id, gchar *filename,
 			  gboolean single_thread)
@@ -1021,8 +1071,8 @@ ags_timer_launch_filename(timer_t *timer_id, gchar *filename,
 				 polling_thread);
     start_queue = g_list_prepend(start_queue,
 				 task_thread);
-    start_queue = g_list_prepend(start_queue,
-				 gui_thread);
+    //    start_queue = g_list_prepend(start_queue,
+    //				 gui_thread);
     g_atomic_pointer_set(&(audio_loop->start_queue),
 			 start_queue);
 
@@ -1054,17 +1104,20 @@ ags_timer_launch_filename(timer_t *timer_id, gchar *filename,
   
       pthread_mutex_unlock(audio_loop->start_mutex);
     
+      /* start gui thread */
+      ags_thread_start(gui_thread);
+
       /* wait for gui thread */
       pthread_mutex_lock(gui_thread->start_mutex);
 
       if(g_atomic_int_get(&(gui_thread->start_done)) == FALSE){
       
-	g_atomic_int_set(&(gui_thread->start_wait),
+      	g_atomic_int_set(&(gui_thread->start_wait),
 			 TRUE);
 
-	while(g_atomic_int_get(&(gui_thread->start_done)) == FALSE){
-	  g_atomic_int_set(&(gui_thread->start_wait),
-			   TRUE);
+      	while(g_atomic_int_get(&(gui_thread->start_done)) == FALSE){
+      	  g_atomic_int_set(&(gui_thread->start_wait),
+      			   TRUE);
 	
 	  pthread_cond_wait(gui_thread->start_cond,
 			    gui_thread->start_mutex);
@@ -1128,6 +1181,7 @@ ags_timer_launch_filename(timer_t *timer_id, gchar *filename,
 		 NULL);
   }
 }
+#endif
 
 void
 ags_show_file_error(gchar *filename,
@@ -1160,6 +1214,7 @@ main(int argc, char **argv)
   gchar *str;
 
   gboolean single_thread_enabled;
+  gboolean builtin_theme_disabled;
   guint i;
 
   struct sched_param param;
@@ -1168,7 +1223,8 @@ main(int argc, char **argv)
   struct passwd *pw;
 
   gchar *wdir, *config_file;
-
+  gchar *rc_filename;
+  
   uid_t uid;
   int result;
 
@@ -1182,6 +1238,7 @@ main(int argc, char **argv)
   putenv("LANG=C\0");
 
   single_thread_enabled = FALSE;
+  builtin_theme_disabled = FALSE;
   
   //  mtrace();
   atexit(ags_signal_cleanup);
@@ -1233,10 +1290,11 @@ main(int argc, char **argv)
     if(!strncmp(argv[i], "--help\0", 7)){
       printf("GSequencer is an audio sequencer and notation editor\n\n\0");
 
-      printf("Usage:\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\n",
+      printf("Usage:\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n\n",
 	     "Report bugs to <jkraehemann at gmail.com>\n\0",
 	     "--filename file     open file\0",
-	     "--single-thread     run in single thread mode\0",     
+	     "--single-thread     run in single thread mode\0",
+	     "--no-builtin-theme  disable built-in theme\0",
 	     "--help              display this help and exit\0",
 	     "--version           output version information and exit\0");
       
@@ -1245,7 +1303,7 @@ main(int argc, char **argv)
       printf("GSequencer %s\n\n\0", AGS_VERSION);
       
       printf("%s\n%s\n%s\n\n\0",
-	     "Copyright (C) 2005-2015 Joël Krähemann\0",
+	     "Copyright (C) 2005-2017 Joël Krähemann\0",
 	     "This is free software; see the source for copying conditions.  There is NO\0",
 	     "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\0");
       
@@ -1254,6 +1312,8 @@ main(int argc, char **argv)
       exit(0);
     }else if(!strncmp(argv[i], "--single-thread\0", 16)){
       single_thread_enabled = TRUE;
+    }else if(!strncmp(argv[i], "--no-builtin-theme\0", 19)){
+      builtin_theme_disabled = TRUE;
     }else if(!strncmp(argv[i], "--filename\0", 11)){
       filename = argv[i + 1];
       i++;
@@ -1261,18 +1321,54 @@ main(int argc, char **argv)
   }
 
   XInitThreads();
-
+  
+  uid = getuid();
+  pw = getpwuid(uid);
+    
+  /* parse rc file */
+  if(!builtin_theme_disabled){
+    rc_filename = g_strdup_printf("%s/%s/ags.rc\0",
+				  pw->pw_dir,
+				  AGS_DEFAULT_DIRECTORY);
+
+    if(!g_file_test(rc_filename,
+		    G_FILE_TEST_IS_REGULAR)){
+      g_free(rc_filename);
+      rc_filename = g_strdup_printf("%s%s\0",
+				    DESTDIR,
+				    "/gsequencer/styles/ags.rc\0");
+    }
+  
+    gtk_rc_parse(rc_filename);
+    g_free(rc_filename);
+  }
+  
   /**/
   LIBXML_TEST_VERSION;
 
   //ao_initialize();
-  
+
   gdk_threads_enter();
   //  g_thread_init(NULL);
   gtk_init(&argc, &argv);
+
+  if(!builtin_theme_disabled){
+    g_object_set(gtk_settings_get_default(),
+		 "gtk-theme-name\0", "Raleigh\0",
+		 NULL);
+    g_signal_handlers_block_matched(gtk_settings_get_default(),
+				    G_SIGNAL_MATCH_DETAIL,
+				    g_signal_lookup("set-property\0",
+						    GTK_TYPE_SETTINGS),
+				    g_quark_from_string("gtk-theme-name\0"),
+				    NULL,
+				    NULL,
+				    NULL);
+  }
+  
   ipatch_init();
-  //  g_log_set_fatal_mask("GLib-GObject\0", //G_LOG_DOMAIN,
-  //		       G_LOG_LEVEL_CRITICAL);
+  //  g_log_set_fatal_mask("GLib-GObject\0", // "Gtk\0" G_LOG_DOMAIN, // 
+		       //		       G_LOG_LEVEL_CRITICAL); // G_LOG_LEVEL_WARNING
 
   /* animate */
   animation_thread = (pthread_t *) malloc(sizeof(pthread_t));
@@ -1282,9 +1378,6 @@ main(int argc, char **argv)
   ags_start_animation(animation_thread);
   
   /* setup */
-  uid = getuid();
-  pw = getpwuid(uid);
-
   wdir = g_strdup_printf("%s/%s\0",
 			 pw->pw_dir,
 			 AGS_DEFAULT_DIRECTORY);
diff --git a/ags/lib/ags_conversion.c b/ags/lib/ags_conversion.c
index a7430cb..4ffda3b 100644
--- a/ags/lib/ags_conversion.c
+++ b/ags/lib/ags_conversion.c
@@ -261,6 +261,9 @@ ags_conversion_finalize(GObject *gobject)
   if(conversion->description != NULL){
     g_free(conversion->description);
   }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_conversion_parent_class)->finalize(gobject);
 }
 
 gdouble
diff --git a/ags/lib/ags_function.c b/ags/lib/ags_function.c
index c67fc97..7850cea 100644
--- a/ags/lib/ags_function.c
+++ b/ags/lib/ags_function.c
@@ -342,6 +342,9 @@ ags_function_finalize(GObject *gobject)
 
     free(function->pivot_table);
   }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_function_parent_class)->finalize(gobject);
 }
 
 /**
diff --git a/ags/lib/ags_log.c b/ags/lib/ags_log.c
index 96a3622..bf117e7 100644
--- a/ags/lib/ags_log.c
+++ b/ags/lib/ags_log.c
@@ -97,6 +97,7 @@ ags_log_finalize(GObject *gobject)
   g_list_free_full(g_atomic_pointer_get(&(log->messages)),
 		   g_free);
 
+  /* call parent */
   G_OBJECT_CLASS(ags_log_parent_class)->finalize(gobject);
 }
 
diff --git a/ags/lib/ags_turtle.c b/ags/lib/ags_turtle.c
index 3adf58e..9d6cbaf 100644
--- a/ags/lib/ags_turtle.c
+++ b/ags/lib/ags_turtle.c
@@ -207,10 +207,14 @@ ags_turtle_get_property(GObject *gobject,
 
   switch(prop_id){
   case PROP_FILENAME:
-    g_value_set_string(value, turtle->filename);
+    {
+      g_value_set_string(value, turtle->filename);
+    }
     break;
   case PROP_XML_DOC:
-    g_value_set_pointer(value, turtle->doc);
+    {
+      g_value_set_pointer(value, turtle->doc);
+    }
     break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
@@ -225,6 +229,17 @@ ags_turtle_finalize(GObject *gobject)
   gchar **str;
   
   turtle = AGS_TURTLE(gobject);
+
+  if(turtle->filename != NULL){
+    g_free(turtle->filename);
+  }
+
+  if(turtle->doc != NULL){
+    xmlFreeDoc(turtle->doc);
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_turtle_parent_class)->finalize(gobject);
 }
 
 /**
diff --git a/ags/lib/ags_turtle_manager.c b/ags/lib/ags_turtle_manager.c
index 8066ada..9d1902a 100644
--- a/ags/lib/ags_turtle_manager.c
+++ b/ags/lib/ags_turtle_manager.c
@@ -22,6 +22,7 @@
 
 void ags_turtle_manager_class_init(AgsTurtleManagerClass *turtle_manager);
 void ags_turtle_manager_init (AgsTurtleManager *turtle_manager);
+void ags_turtle_manager_dispose(GObject *gobject);
 void ags_turtle_manager_finalize(GObject *gobject);
 
 /**
@@ -76,6 +77,7 @@ ags_turtle_manager_class_init(AgsTurtleManagerClass *turtle_manager)
   /* GObjectClass */
   gobject = (GObjectClass *) turtle_manager;
 
+  gobject->dispose = ags_turtle_manager_dispose;
   gobject->finalize = ags_turtle_manager_finalize;
 }
 
@@ -86,17 +88,42 @@ ags_turtle_manager_init(AgsTurtleManager *turtle_manager)
 }
 
 void
-ags_turtle_manager_finalize(GObject *gobject)
+ags_turtle_manager_dispose(GObject *gobject)
 {
   AgsTurtleManager *turtle_manager;
+
   GList *turtle;
 
   turtle_manager = AGS_TURTLE_MANAGER(gobject);
 
   turtle = turtle_manager->turtle;
-
+  turtle_manager->turtle = NULL;
+  
   g_list_free_full(turtle,
 		   g_object_unref);
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_turtle_manager_parent_class)->dispose(gobject);
+}
+
+void
+ags_turtle_manager_finalize(GObject *gobject)
+{
+  AgsTurtleManager *turtle_manager;
+
+  GList *turtle;
+
+  turtle_manager = AGS_TURTLE_MANAGER(gobject);
+
+  turtle = turtle_manager->turtle;
+
+  if(turtle != NULL){
+    g_list_free_full(turtle,
+		     g_object_unref);
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_turtle_manager_parent_class)->finalize(gobject);
 }
 
 /**
diff --git a/ags/libags-audio.h b/ags/libags-audio.h
index d38d56e..e4130ac 100644
--- a/ags/libags-audio.h
+++ b/ags/libags-audio.h
@@ -31,6 +31,7 @@
 #include <ags/plugin/ags_lv2_conversion.h>
 #include <ags/plugin/ags_lv2_manager.h>
 #include <ags/plugin/ags_lv2_plugin.h>
+#include <ags/plugin/ags_lv2_preset.h>
 #include <ags/plugin/ags_lv2_event_manager.h>
 #include <ags/plugin/ags_lv2_log_manager.h>
 #include <ags/plugin/ags_lv2_uri_map_manager.h>
@@ -174,6 +175,10 @@
 #include <ags/audio/recall/ags_play_notation_audio_run.h>
 #include <ags/audio/recall/ags_play_note.h>
 #include <ags/audio/recall/ags_play_recycling.h>
+#include <ags/audio/recall/ags_prepare_audio_signal.h>
+#include <ags/audio/recall/ags_prepare_channel.h>
+#include <ags/audio/recall/ags_prepare_channel_run.h>
+#include <ags/audio/recall/ags_prepare_recycling.h>
 #include <ags/audio/recall/ags_record_midi_audio.h>
 #include <ags/audio/recall/ags_record_midi_audio_run.h>
 #include <ags/audio/recall/ags_route_dssi_audio.h>
diff --git a/ags/libags.h b/ags/libags.h
index 591595f..9e48bb0 100644
--- a/ags/libags.h
+++ b/ags/libags.h
@@ -69,9 +69,11 @@
 /* thread */
 #include <ags/thread/ags_autosave_thread.h>
 #include <ags/thread/ags_concurrency_provider.h>
+#include <ags/thread/ags_destroy_worker.h>
 #include <ags/thread/ags_generic_main_loop.h>
 #include <ags/thread/ags_history.h>
 #include <ags/thread/ags_mutex_manager.h>
+#include <ags/thread/ags_condition_manager.h>
 #include <ags/thread/ags_poll_fd.h>
 #include <ags/thread/ags_polling_thread.h>
 #include <ags/thread/ags_returnable_thread.h>
@@ -85,6 +87,7 @@
 #include <ags/thread/ags_timestamp_factory.h>
 #include <ags/thread/ags_timestamp_thread.h>
 #include <ags/thread/ags_timestamp.h>
+#include <ags/thread/ags_worker_thread.h>
 
 /* thread file */
 #include <ags/thread/file/ags_thread_file_xml.h>
diff --git a/ags/object/ags_application_context.c b/ags/object/ags_application_context.c
index 1a6ba24..6ff56e8 100644
--- a/ags/object/ags_application_context.c
+++ b/ags/object/ags_application_context.c
@@ -43,6 +43,7 @@ void ags_application_context_get_property(GObject *gobject,
 					  GParamSpec *param_spec);
 void ags_application_context_connect(AgsConnectable *connectable);
 void ags_application_context_disconnect(AgsConnectable *connectable);
+void ags_application_context_dispose(GObject *gobject);
 void ags_application_context_finalize(GObject *gobject);
 
 void ags_application_context_real_load_config(AgsApplicationContext *application_context);
@@ -133,6 +134,7 @@ ags_application_context_class_init(AgsApplicationContextClass *application_conte
   gobject->set_property = ags_application_context_set_property;
   gobject->get_property = ags_application_context_get_property;
 
+  gobject->dispose = ags_application_context_dispose;
   gobject->finalize = ags_application_context_finalize;
 
   /* properties */
@@ -436,6 +438,75 @@ ags_application_context_disconnect(AgsConnectable *connectable)
 }
 
 void
+ags_application_context_dispose(GObject *gobject)
+{
+  AgsApplicationContext *application_context;
+
+  application_context = AGS_APPLICATION_CONTEXT(gobject);
+  
+  /* log */
+  if(application_context->log != NULL){
+    g_object_unref(application_context->log);
+
+    application_context->log = NULL;
+  }
+
+  /* config */
+  if(application_context->config != NULL){
+    g_object_set(application_context->config,
+		 "application-context\0", NULL,
+		 NULL);
+    
+    g_object_unref(application_context->config);
+
+    application_context->config = NULL;
+  }
+  
+  /* main loop */
+  if(application_context->main_loop != NULL){
+    g_object_set(application_context->main_loop,
+		 "application-context\0", NULL,
+		 NULL);
+
+    g_object_unref(application_context->main_loop);
+
+    application_context->main_loop = NULL;
+  }
+
+  /* autosave thread */
+  if(application_context->autosave_thread != NULL){
+    g_object_set(application_context->autosave_thread,
+		 "application-context\0", NULL,
+		 NULL);
+
+    g_object_unref(application_context->autosave_thread);
+
+    application_context->autosave_thread = NULL;
+  }
+
+  /* task thread */
+  if(application_context->task_thread != NULL){
+    g_object_unref(application_context->task_thread);
+
+    application_context->task_thread = NULL;
+  }
+
+  /* file */
+  if(application_context->file != NULL){
+    g_object_set(application_context->file,
+		 "application-context\0", NULL,
+		 NULL);
+
+    g_object_unref(application_context->file);
+
+    application_context->file = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_application_context_parent_class)->dispose(gobject);
+}
+
+void
 ags_application_context_finalize(GObject *gobject)
 {
   AgsApplicationContext *application_context;
@@ -449,16 +520,43 @@ ags_application_context_finalize(GObject *gobject)
   pthread_mutex_destroy(application_context->mutex);
   free(application_context->mutex);
 
+  /* log */
+  if(application_context->log != NULL){
+    g_object_unref(application_context->log);
+  }
+
   /* config */
   if(application_context->config != NULL){
+    g_object_set(application_context->config,
+		 "application-context\0", NULL,
+		 NULL);
+
     g_object_unref(application_context->config);
   }
   
   /* main loop */
   if(application_context->main_loop != NULL){
+    g_object_set(application_context->main_loop,
+		 "application-context\0", NULL,
+		 NULL);
+
     g_object_unref(application_context->main_loop);
   }
-  
+
+  /* autosave thread */
+  if(application_context->autosave_thread != NULL){
+    g_object_set(application_context->autosave_thread,
+		 "application-context\0", NULL,
+		 NULL);
+
+    g_object_unref(application_context->autosave_thread);
+  }
+
+  /* task thread */
+  if(application_context->task_thread != NULL){
+    g_object_unref(application_context->task_thread);
+  }
+
   /* file */
   if(application_context->file != NULL){
     g_object_unref(application_context->file);
diff --git a/ags/object/ags_config.c b/ags/object/ags_config.c
index 8202595..9e91720 100644
--- a/ags/object/ags_config.c
+++ b/ags/object/ags_config.c
@@ -52,6 +52,7 @@ void ags_config_remove_from_registry(AgsConnectable *connectable);
 gboolean ags_config_is_connected(AgsConnectable *connectable);
 void ags_config_connect(AgsConnectable *connectable);
 void ags_config_disconnect(AgsConnectable *connectable);
+void ags_config_dispose(GObject *gobject);
 void ags_config_finalize(GObject *gobject);
 gchar* ags_config_get_version(AgsConfig *config);
 void ags_config_set_version(AgsConfig *config, gchar *version);
@@ -141,6 +142,7 @@ ags_config_class_init(AgsConfigClass *config)
   gobject->set_property = ags_config_set_property;
   gobject->get_property = ags_config_get_property;
 
+  gobject->dispose = ags_config_dispose;
   gobject->finalize = ags_config_finalize;
 
   /* properties */
@@ -267,15 +269,18 @@ ags_config_set_property(GObject *gobject,
       
       application_context = (AgsApplicationContext *) g_value_get_object(value);
 
-      if(application_context == ((AgsApplicationContext *) config->application_context))
+      if(application_context == ((AgsApplicationContext *) config->application_context)){
 	return;
+      }
 
-      if(config->application_context != NULL)
+      if(config->application_context != NULL){
 	g_object_unref(config->application_context);
-
-      if(application_context != NULL)
+      }
+      
+      if(application_context != NULL){
 	g_object_ref(G_OBJECT(application_context));
-
+      }
+      
       config->application_context = (GObject *) application_context;
     }
     break;
@@ -338,11 +343,38 @@ ags_config_disconnect(AgsConnectable *connectable)
 }
 
 void
+ags_config_dispose(GObject *gobject)
+{
+  AgsConfig *config;
+
+  config = (AgsConfig *) gobject;
+
+  if(config->application_context != NULL){
+    g_object_unref(config->application_context);
+
+    config->application_context = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_config_parent_class)->dispose(gobject);
+}
+
+void
 ags_config_finalize(GObject *gobject)
 {
+  AgsConfig *config;
 
-  //TODO:JK: implement me
+  config = (AgsConfig *) gobject;
+
+  if(config->application_context != NULL){
+    g_object_unref(config->application_context);
+  }
+
+  if(config->key_file != NULL){
+    g_key_file_unref(config->key_file);
+  }
 
+  /* call parent */
   G_OBJECT_CLASS(ags_config_parent_class)->finalize(gobject);
 }
 
@@ -376,6 +408,7 @@ ags_config_real_load_defaults(AgsConfig *config)
   ags_config_set_value(config, AGS_CONFIG_GENERIC, "autosave-thread\0", "false\0");
   ags_config_set_value(config, AGS_CONFIG_GENERIC, "simple-file\0", "true\0");
   ags_config_set_value(config, AGS_CONFIG_GENERIC, "disable-feature\0", "experimental\0");
+  ags_config_set_value(config, AGS_CONFIG_GENERIC, "engine-mode\0", "performance\0");
 
   ags_config_set_value(config, AGS_CONFIG_THREAD, "model\0", "super-threaded\0");
   ags_config_set_value(config, AGS_CONFIG_THREAD, "super-threaded-scope\0", "channel\0");
diff --git a/ags/object/ags_connection.c b/ags/object/ags_connection.c
index 2c8fe95..bf3f1b8 100644
--- a/ags/object/ags_connection.c
+++ b/ags/object/ags_connection.c
@@ -29,6 +29,7 @@ void ags_connection_get_property(GObject *gobject,
 				 guint prop_id,
 				 GValue *value,
 				 GParamSpec *param_spec);
+void ags_connection_dispose(GObject *gobject);
 void ags_connection_finalize(GObject *gobject);
 
 /**
@@ -91,6 +92,7 @@ ags_connection_class_init(AgsConnectionClass *connection)
   gobject->set_property = ags_connection_set_property;
   gobject->get_property = ags_connection_get_property;
 
+  gobject->dispose = ags_connection_dispose;
   gobject->finalize = ags_connection_finalize;
 
   /* properties */
@@ -177,6 +179,23 @@ ags_connection_get_property(GObject *gobject,
 }
 
 void
+ags_connection_dispose(GObject *gobject)
+{
+  AgsConnection *connection;
+
+  connection = AGS_CONNECTION(gobject);
+
+  if(connection->data_object != NULL){
+    g_object_unref(connection->data_object);
+
+    connection->data_object = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_connection_parent_class)->dispose(gobject);
+}
+
+void
 ags_connection_finalize(GObject *gobject)
 {
   AgsConnection *connection;
@@ -186,6 +205,9 @@ ags_connection_finalize(GObject *gobject)
   if(connection->data_object != NULL){
     g_object_unref(connection->data_object);
   }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_connection_parent_class)->finalize(gobject);
 }
 
 /**
diff --git a/ags/object/ags_connection_manager.c b/ags/object/ags_connection_manager.c
index a2ab942..bccdc15 100644
--- a/ags/object/ags_connection_manager.c
+++ b/ags/object/ags_connection_manager.c
@@ -21,6 +21,7 @@
 
 void ags_connection_manager_class_init(AgsConnectionManagerClass *connection_manager);
 void ags_connection_manager_init (AgsConnectionManager *connection_manager);
+void ags_connection_manager_dispose(GObject *gobject);
 void ags_connection_manager_finalize(GObject *gobject);
 
 /**
@@ -75,6 +76,7 @@ ags_connection_manager_class_init(AgsConnectionManagerClass *connection_manager)
   /* GObjectClass */
   gobject = (GObjectClass *) connection_manager;
 
+  gobject->dispose = ags_connection_manager_dispose;
   gobject->finalize = ags_connection_manager_finalize;
 }
 
@@ -85,6 +87,24 @@ ags_connection_manager_init(AgsConnectionManager *connection_manager)
 }
 
 void
+ags_connection_manager_dispose(GObject *gobject)
+{
+  AgsConnectionManager *connection_manager;
+
+  connection_manager = AGS_CONNECTION_MANAGER(gobject);
+
+  if(connection_manager->connection != NULL){
+    g_list_free_full(connection_manager->connection,
+		     g_object_unref);
+
+    connection_manager->connection = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_connection_manager_parent_class)->dispose(gobject);
+}
+
+void
 ags_connection_manager_finalize(GObject *gobject)
 {
   AgsConnectionManager *connection_manager;
@@ -96,6 +116,7 @@ ags_connection_manager_finalize(GObject *gobject)
 		     g_object_unref);
   }
 
+  /* call parent */
   G_OBJECT_CLASS(ags_connection_manager_parent_class)->finalize(gobject);
 }
 
diff --git a/ags/object/ags_main_loop.c b/ags/object/ags_main_loop.c
index c32df0e..c88e826 100644
--- a/ags/object/ags_main_loop.c
+++ b/ags/object/ags_main_loop.c
@@ -39,6 +39,7 @@ void ags_main_loop_class_init(AgsMainLoopInterface *interface);
 enum {
   INTERRUPT,
   MONITOR,
+  CHANGE_FREQUENCY,
   LAST_SIGNAL,
 };
 
@@ -105,6 +106,25 @@ ags_main_loop_class_init(AgsMainLoopInterface *interface)
 		 g_cclosure_user_marshal_BOOLEAN__UINT_POINTER,
 		 G_TYPE_BOOLEAN, 2,
 		 G_TYPE_UINT, G_TYPE_POINTER);
+
+  /**
+   * AgsMainLoop::change-frequency:
+   * @main_loop: the #AgsMainLoop
+   * @frequency: the new frequency
+   *
+   * Change frequency.
+   * 
+   * Since: 0.7.122.2
+   */
+  main_loop_signals[CHANGE_FREQUENCY] =
+    g_signal_new("change-frequency\0",
+		 G_TYPE_FROM_INTERFACE(interface),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMainLoopInterface, change_frequency),
+		 NULL, NULL,
+		 g_cclosure_marshal_VOID__DOUBLE,
+		 G_TYPE_NONE, 1,
+		 G_TYPE_DOUBLE);
 }
 
 /**
@@ -348,3 +368,21 @@ ags_main_loop_monitor(AgsMainLoop *main_loop,
   return(has_monitor);
 }
 
+/**
+ * ags_main_loop_change_frequency:
+ * @main_loop: the #AgsMainLoop
+ * @frequency: the new frequency
+ *
+ * Change frequency.
+ *
+ * Since: 0.7.122.2
+ */
+void
+ags_main_loop_change_frequency(AgsMainLoop *main_loop,
+			       gdouble frequency)
+{
+  g_signal_emit(main_loop,
+		main_loop_signals[CHANGE_FREQUENCY],
+		0,
+		frequency);
+}
diff --git a/ags/object/ags_main_loop.h b/ags/object/ags_main_loop.h
index d2b23e7..971e7af 100644
--- a/ags/object/ags_main_loop.h
+++ b/ags/object/ags_main_loop.h
@@ -60,6 +60,9 @@ struct _AgsMainLoopInterface
 		    guint time_cycle, guint *time_spent);
   gboolean (*monitor)(AgsMainLoop *main_loop,
 		      guint time_cycle, guint *time_spent);
+
+  void (*change_frequency)(AgsMainLoop *main_loop,
+			   gdouble frequency);
 };
 
 GType ags_main_loop_get_type();
@@ -84,4 +87,7 @@ void ags_main_loop_interrupt(AgsMainLoop *main_loop,
 gboolean ags_main_loop_monitor(AgsMainLoop *main_loop,
 			       guint time_cycle, guint *time_spent);
 
+void ags_main_loop_change_frequency(AgsMainLoop *main_loop,
+				    gdouble frequency);
+
 #endif /*__AGS_MAIN_LOOP_H__*/
diff --git a/ags/object/ags_soundcard.h b/ags/object/ags_soundcard.h
index d8ded40..c718d20 100644
--- a/ags/object/ags_soundcard.h
+++ b/ags/object/ags_soundcard.h
@@ -48,7 +48,7 @@
 #define AGS_SOUNDCARD_DEFAULT_TACTRATE (1.0 / AGS_SOUNDCARD_DEFAULT_TACT_JIFFIE)
 
 #define AGS_SOUNDCARD_DEFAULT_SCALE (1.0)
-#define AGS_SOUNDCARD_DEFAULT_DELAY (60.0 * ((AGS_SOUNDCARD_DEFAULT_SAMPLERATE / AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE) / AGS_SOUNDCARD_DEFAULT_BPM)) * ((1.0 / 16.0) * (1.0 / AGS_SOUNDCARD_DEFAULT_DELAY_FACTOR)))
+#define AGS_SOUNDCARD_DEFAULT_DELAY ((60.0 * ((AGS_SOUNDCARD_DEFAULT_SAMPLERATE / AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE) / AGS_SOUNDCARD_DEFAULT_BPM)) * ((1.0 / 16.0) * (1.0 / AGS_SOUNDCARD_DEFAULT_DELAY_FACTOR)))
 
 #define AGS_SOUNDCARD_DEFAULT_PERIOD (64.0)
 
diff --git a/ags/plugin/ags_base_plugin.c b/ags/plugin/ags_base_plugin.c
index 4017800..9277d27 100644
--- a/ags/plugin/ags_base_plugin.c
+++ b/ags/plugin/ags_base_plugin.c
@@ -33,6 +33,7 @@ void ags_base_plugin_get_property(GObject *gobject,
 				  guint prop_id,
 				  GValue *value,
 				  GParamSpec *param_spec);
+void ags_base_plugin_dispose(GObject *gobject);
 void ags_base_plugin_finalize(GObject *gobject);
 
 /**
@@ -60,6 +61,9 @@ enum{
   PROP_FILENAME,
   PROP_EFFECT,
   PROP_EFFECT_INDEX,
+  PROP_UI_FILENAME,
+  PROP_UI_EFFECT,
+  PROP_UI_EFFECT_INDEX,  
   PROP_UI_PLUGIN,
 };
 
@@ -107,6 +111,7 @@ ags_base_plugin_class_init(AgsBasePluginClass *base_plugin)
   gobject->set_property = ags_base_plugin_set_property;
   gobject->get_property = ags_base_plugin_get_property;
 
+  gobject->dispose = ags_base_plugin_dispose;
   gobject->finalize = ags_base_plugin_finalize;
 
   /* properties */
@@ -161,6 +166,56 @@ ags_base_plugin_class_init(AgsBasePluginClass *base_plugin)
 				  param_spec);
 
   /**
+   * AgsBasePlugin:ui-filename:
+   *
+   * The assigned UI filename.
+   * 
+   * Since: 0.7.127
+   */
+  param_spec = g_param_spec_string("ui-filename\0",
+				   "UI filename of the plugin\0",
+				   "The UI filename this plugin is located in\0",
+				   NULL,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_UI_FILENAME,
+				  param_spec);
+
+  /**
+   * AgsBasePlugin:ui-effect:
+   *
+   * The assigned ui-effect.
+   * 
+   * Since: 0.7.127
+   */
+  param_spec = g_param_spec_string("ui-effect\0",
+				   "UI effect of the plugin\0",
+				   "The UI effect this plugin is assigned with\0",
+				   NULL,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_UI_EFFECT,
+				  param_spec);
+
+  /**
+   * AgsBasePlugin:ui-effect-index:
+   *
+   * The assigned ui-effect-index.
+   * 
+   * Since: 0.7.127
+   */
+  param_spec = g_param_spec_uint("ui-effect-index\0",
+				 "UI effect-index of the plugin\0",
+				 "The UI effect-index this plugin is assigned with\0",
+				 0,
+				 G_MAXUINT,
+				 0,
+				 G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_UI_EFFECT_INDEX,
+				  param_spec);
+
+  /**
    * AgsBasePlugin:ui-plugin:
    *
    * The assigned ui-plugin.
@@ -195,6 +250,8 @@ ags_base_plugin_class_init(AgsBasePluginClass *base_plugin)
    *
    * The ::instantiate signal creates a new instance of plugin.
    * 
+   * Returns: the new plugin instance
+   * 
    * Since: 0.7.6
    */
   base_plugin_signals[INSTANTIATE] =
@@ -375,6 +432,49 @@ ags_base_plugin_set_property(GObject *gobject,
       base_plugin->effect_index = effect_index;
     }
     break;
+  case PROP_UI_FILENAME:
+    {
+      gchar *ui_filename;
+
+      ui_filename = (gchar *) g_value_get_string(value);
+
+      if(base_plugin->ui_filename == ui_filename){
+	return;
+      }
+      
+      if(base_plugin->ui_filename != NULL){
+	g_free(base_plugin->ui_filename);
+      }
+
+      base_plugin->ui_filename = g_strdup(ui_filename);
+    }
+    break;
+  case PROP_UI_EFFECT:
+    {
+      gchar *ui_effect;
+
+      ui_effect = (gchar *) g_value_get_string(value);
+
+      if(base_plugin->ui_effect == ui_effect){
+	return;
+      }
+      
+      if(base_plugin->ui_effect != NULL){
+	g_free(base_plugin->ui_effect);
+      }
+
+      base_plugin->ui_effect = g_strdup(ui_effect);
+    }
+    break;
+  case PROP_UI_EFFECT_INDEX:
+    {
+      guint ui_effect_index;
+
+      ui_effect_index = g_value_get_uint(value);
+
+      base_plugin->ui_effect_index = ui_effect_index;
+    }
+    break;
   case PROP_UI_PLUGIN:
     {
       GObject *ui_plugin;
@@ -414,16 +514,39 @@ ags_base_plugin_get_property(GObject *gobject,
 
   switch(prop_id){
   case PROP_FILENAME:
-    g_value_set_string(value, base_plugin->filename);
+    {
+      g_value_set_string(value, base_plugin->filename);
+    }
     break;
   case PROP_EFFECT:
-    g_value_set_string(value, base_plugin->effect);
+    {
+      g_value_set_string(value, base_plugin->effect);
+    }
     break;
   case PROP_EFFECT_INDEX:
-    g_value_set_uint(value, base_plugin->effect_index);
+    {
+      g_value_set_uint(value, base_plugin->effect_index);
+    }
+    break;
+  case PROP_UI_FILENAME:
+    {
+      g_value_set_string(value, base_plugin->ui_filename);
+    }
+    break;
+  case PROP_UI_EFFECT:
+    {
+      g_value_set_string(value, base_plugin->ui_effect);
+    }
+    break;
+  case PROP_UI_EFFECT_INDEX:
+    {
+      g_value_set_uint(value, base_plugin->ui_effect_index);
+    }
     break;
   case PROP_UI_PLUGIN:
-    g_value_set_object(value, base_plugin->ui_plugin);
+    {
+      g_value_set_object(value, base_plugin->ui_plugin);
+    }
     break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
@@ -432,6 +555,23 @@ ags_base_plugin_get_property(GObject *gobject,
 }
 
 void
+ags_base_plugin_dispose(GObject *gobject)
+{
+  AgsBasePlugin *base_plugin;
+
+  base_plugin = AGS_BASE_PLUGIN(gobject);
+
+  if(base_plugin->ui_plugin != NULL){
+    g_object_unref(base_plugin->ui_plugin);
+
+    base_plugin->ui_plugin = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_base_plugin_parent_class)->dispose(gobject);
+}
+
+void
 ags_base_plugin_finalize(GObject *gobject)
 {
   AgsBasePlugin *base_plugin;
@@ -472,7 +612,7 @@ ags_port_descriptor_alloc()
   port_descriptor->port_name = NULL;
   port_descriptor->port_symbol = NULL;
 
-  port_descriptor->scale_steps = 8;
+  port_descriptor->scale_steps = -1;
   port_descriptor->scale_points = NULL;
   port_descriptor->scale_value = NULL;
   
@@ -521,6 +661,37 @@ ags_port_descriptor_free(AgsPortDescriptor *port_descriptor)
 }
 
 /**
+ * ags_port_descriptor_find_symbol:
+ * @port_descriptor: the #GList-struct containing #AgsPortDescriptor
+ * @port_symbol: the port symbol
+ * 
+ * Find @port_symbol within @port_descriptor.
+ * 
+ * Returns: the matching #GList-struct containing #AgsPortDescriptor
+ * 
+ * Since: 0.7.122.8 
+ */
+GList*
+ags_port_descriptor_find_symbol(GList *port_descriptor,
+				gchar *port_symbol)
+{
+  if(port_symbol == NULL){
+    return(NULL);
+  }
+
+  while(port_descriptor != NULL){
+    if(!g_strcmp0(port_symbol,
+		  AGS_PORT_DESCRIPTOR(port_descriptor->data)->port_symbol)){
+      return(port_descriptor);
+    }
+    
+    port_descriptor = port_descriptor->next;
+  }
+  
+  return(NULL);
+}
+
+/**
  * ags_base_plugin_find_filename:
  * @base_plugin: the #GList-struct containing #AgsBasePlugin
  * @filename: the filename as string
@@ -552,7 +723,7 @@ ags_base_plugin_find_filename(GList *base_plugin, gchar *filename)
  * @filename: the filename as string
  * @effect: the effect as string
  * 
- * Find filename and effect in @base_plugin #GList-struct of #AgsBasePlugin.
+ * Find @filename and @effect in @base_plugin #GList-struct of #AgsBasePlugin.
  *
  * Returns: the next matching #GList-struct
  * 
@@ -576,6 +747,34 @@ ags_base_plugin_find_effect(GList *base_plugin, gchar *filename, gchar *effect)
 }
 
 /**
+ * ags_base_plugin_find_ui_effect_index:
+ * @base_plugin: the #GList-struct containing #AgsBasePlugin
+ * @ui_filename: the UI filename as string
+ * @ui_effect_index: the UI effect index
+ * 
+ * Find @ui_filename and @ui_effect_index in @base_plugin #GList-struct of #AgsBasePlugin.
+ *
+ * Returns: the next matching #GList-struct
+ * 
+ * Since: 0.7.127
+ */
+GList*
+ags_base_plugin_find_ui_effect_index(GList *base_plugin, gchar *ui_filename, guint ui_effect_index)
+{
+  while(base_plugin != NULL){
+    if(!g_ascii_strcasecmp(AGS_BASE_PLUGIN(base_plugin->data)->ui_filename,
+			   ui_filename) &&
+       AGS_BASE_PLUGIN(base_plugin->data)->ui_effect_index == ui_effect_index){
+      return(base_plugin);
+    }
+
+    base_plugin = base_plugin->next;
+  }
+
+  return(NULL);
+}
+
+/**
  * ags_base_plugin_sort:
  * @base_plugin: the #GList-struct containing #AgsBasePlugin
  *
diff --git a/ags/plugin/ags_base_plugin.h b/ags/plugin/ags_base_plugin.h
index 0c6cfdf..4635cef 100644
--- a/ags/plugin/ags_base_plugin.h
+++ b/ags/plugin/ags_base_plugin.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -57,6 +57,7 @@ typedef enum{
   AGS_PORT_DESCRIPTOR_SAMPLERATE      = 1 << 11,
   AGS_PORT_DESCRIPTOR_BOUNDED_BELOW   = 1 << 12,
   AGS_PORT_DESCRIPTOR_BOUNDED_ABOVE   = 1 << 13,
+  AGS_PORT_DESCRIPTOR_UI_NOTIFICATION = 1 << 14,
 }AgsPortDescriptorFlags;
 
 struct _AgsBasePlugin
@@ -77,6 +78,14 @@ struct _AgsBasePlugin
   void *plugin_descriptor;
   void *plugin_handle;
 
+  gchar *ui_filename;
+  gchar *ui_effect;
+  
+  guint ui_effect_index;
+  void *ui_plugin_so;
+  void *ui_plugin_descriptor;
+  void *ui_plugin_handle;
+  
   GObject *ui_plugin;
 };
 
@@ -109,7 +118,7 @@ struct _AgsPortDescriptor
   gchar *port_name;
   gchar *port_symbol;
 
-  guint scale_steps;
+  gint scale_steps;
   gchar **scale_points;
   float *scale_value;
   
@@ -126,9 +135,14 @@ GType ags_base_plugin_get_type(void);
 AgsPortDescriptor* ags_port_descriptor_alloc();
 void ags_port_descriptor_free(AgsPortDescriptor *port_descriptor);
 
+GList* ags_port_descriptor_find_symbol(GList *port_descriptor,
+				       gchar *port_symbol);
+
 GList* ags_base_plugin_find_filename(GList *base_plugin, gchar *filename);
 GList* ags_base_plugin_find_effect(GList *base_plugin, gchar *filename, gchar *effect);
 
+GList* ags_base_plugin_find_ui_effect_index(GList *base_plugin, gchar *ui_filename, guint ui_effect_index);
+
 GList* ags_base_plugin_sort(GList *base_plugin);
 
 void ags_base_plugin_apply_port_group_by_prefix(AgsBasePlugin *base_plugin);
diff --git a/ags/plugin/ags_dssi_manager.c b/ags/plugin/ags_dssi_manager.c
index 2ddcd30..41b9745 100644
--- a/ags/plugin/ags_dssi_manager.c
+++ b/ags/plugin/ags_dssi_manager.c
@@ -39,6 +39,7 @@
 
 void ags_dssi_manager_class_init(AgsDssiManagerClass *dssi_manager);
 void ags_dssi_manager_init (AgsDssiManager *dssi_manager);
+void ags_dssi_manager_dispose(GObject *gobject);
 void ags_dssi_manager_finalize(GObject *gobject);
 
 /**
@@ -99,6 +100,7 @@ ags_dssi_manager_class_init(AgsDssiManagerClass *dssi_manager)
   /* GObjectClass */
   gobject = (GObjectClass *) dssi_manager;
 
+  gobject->dispose = ags_dssi_manager_dispose;
   gobject->finalize = ags_dssi_manager_finalize;
 }
 
@@ -117,6 +119,24 @@ ags_dssi_manager_init(AgsDssiManager *dssi_manager)
 }
 
 void
+ags_dssi_manager_dispose(GObject *gobject)
+{
+  AgsDssiManager *dssi_manager;
+
+  dssi_manager = AGS_DSSI_MANAGER(gobject);
+
+  if(dssi_manager->dssi_plugin != NULL){
+    g_list_free_full(dssi_manager->dssi_plugin,
+		     (GDestroyNotify) g_object_unref);
+
+    dssi_manager->dssi_plugin = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_dssi_manager_parent_class)->dispose(gobject);
+}
+
+void
 ags_dssi_manager_finalize(GObject *gobject)
 {
   AgsDssiManager *dssi_manager;
@@ -129,6 +149,9 @@ ags_dssi_manager_finalize(GObject *gobject)
 
   g_list_free_full(dssi_plugin,
 		   (GDestroyNotify) g_object_unref);
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_dssi_manager_parent_class)->finalize(gobject);
 }
 
 /**
diff --git a/ags/plugin/ags_ladspa_manager.c b/ags/plugin/ags_ladspa_manager.c
index b264fda..74f462c 100644
--- a/ags/plugin/ags_ladspa_manager.c
+++ b/ags/plugin/ags_ladspa_manager.c
@@ -39,6 +39,7 @@
 
 void ags_ladspa_manager_class_init(AgsLadspaManagerClass *ladspa_manager);
 void ags_ladspa_manager_init (AgsLadspaManager *ladspa_manager);
+void ags_ladspa_manager_dispose(GObject *gobject);
 void ags_ladspa_manager_finalize(GObject *gobject);
 
 /**
@@ -99,6 +100,7 @@ ags_ladspa_manager_class_init(AgsLadspaManagerClass *ladspa_manager)
   /* GObjectClass */
   gobject = (GObjectClass *) ladspa_manager;
 
+  gobject->dispose = ags_ladspa_manager_dispose;
   gobject->finalize = ags_ladspa_manager_finalize;
 }
 
@@ -117,9 +119,28 @@ ags_ladspa_manager_init(AgsLadspaManager *ladspa_manager)
 }
 
 void
+ags_ladspa_manager_dispose(GObject *gobject)
+{
+  AgsLadspaManager *ladspa_manager;
+
+  ladspa_manager = AGS_LADSPA_MANAGER(gobject);
+
+  if(ladspa_manager->ladspa_plugin != NULL){
+    g_list_free_full(ladspa_manager->ladspa_plugin,
+		     (GDestroyNotify) g_object_unref);
+
+    ladspa_manager->ladspa_plugin = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_ladspa_manager_parent_class)->dispose(gobject);
+}
+
+void
 ags_ladspa_manager_finalize(GObject *gobject)
 {
   AgsLadspaManager *ladspa_manager;
+  
   GList *ladspa_plugin;
 
   ladspa_manager = AGS_LADSPA_MANAGER(gobject);
@@ -128,6 +149,9 @@ ags_ladspa_manager_finalize(GObject *gobject)
 
   g_list_free_full(ladspa_plugin,
 		   (GDestroyNotify) g_object_unref);
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_ladspa_manager_parent_class)->finalize(gobject);
 }
 
 /**
diff --git a/ags/plugin/ags_lv2_event_manager.c b/ags/plugin/ags_lv2_event_manager.c
index 34b4bf9..e6a07cd 100644
--- a/ags/plugin/ags_lv2_event_manager.c
+++ b/ags/plugin/ags_lv2_event_manager.c
@@ -124,6 +124,9 @@ void
 ags_lv2_event_manager_finalize(GObject *gobject)
 {
   /* empty */
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_lv2_event_manager_parent_class)->finalize(gobject);
 }
 
 uint32_t
diff --git a/ags/plugin/ags_lv2_log_manager.c b/ags/plugin/ags_lv2_log_manager.c
index 763d48e..13287e5 100644
--- a/ags/plugin/ags_lv2_log_manager.c
+++ b/ags/plugin/ags_lv2_log_manager.c
@@ -122,6 +122,9 @@ void
 ags_lv2_log_manager_finalize(GObject *gobject)
 {
   /* empty */
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_lv2_log_manager_parent_class)->finalize(gobject);
 }
 
 /**
diff --git a/ags/plugin/ags_lv2_manager.c b/ags/plugin/ags_lv2_manager.c
index 2a418e7..f012021 100644
--- a/ags/plugin/ags_lv2_manager.c
+++ b/ags/plugin/ags_lv2_manager.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -26,6 +26,7 @@
 #include <ags/object/ags_marshal.h>
 
 #include <ags/plugin/ags_base_plugin.h>
+#include <ags/plugin/ags_lv2_preset.h>
 
 #include <dlfcn.h>
 #include <stdio.h>
@@ -48,6 +49,7 @@ void ags_lv2_manager_get_property(GObject *gobject,
 				  guint prop_id,
 				  GValue *value,
 				  GParamSpec *param_spec);
+void ags_lv2_manager_dispose(GObject *gobject);
 void ags_lv2_manager_finalize(GObject *gobject);
 
 /**
@@ -111,6 +113,7 @@ ags_lv2_manager_class_init(AgsLv2ManagerClass *lv2_manager)
   gobject->set_property = ags_lv2_manager_set_property;
   gobject->get_property = ags_lv2_manager_get_property;
 
+  gobject->dispose = ags_lv2_manager_dispose;
   gobject->finalize = ags_lv2_manager_finalize;
 
   /* properties */
@@ -207,9 +210,28 @@ ags_lv2_manager_get_property(GObject *gobject,
 }
 
 void
+ags_lv2_manager_dispose(GObject *gobject)
+{
+  AgsLv2Manager *lv2_manager;
+
+  lv2_manager = AGS_LV2_MANAGER(gobject);
+
+  if(lv2_manager->lv2_plugin != NULL){
+    g_list_free_full(lv2_manager->lv2_plugin,
+		     g_object_unref);
+
+    lv2_manager->lv2_plugin = NULL;
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_lv2_manager_parent_class)->dispose(gobject);
+}
+
+void
 ags_lv2_manager_finalize(GObject *gobject)
 {
   AgsLv2Manager *lv2_manager;
+
   GList *lv2_plugin;
 
   lv2_manager = AGS_LV2_MANAGER(gobject);
@@ -218,6 +240,9 @@ ags_lv2_manager_finalize(GObject *gobject)
 
   g_list_free_full(lv2_plugin,
 		   g_object_unref);
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_lv2_manager_parent_class)->finalize(gobject);
 }
 
 /**
@@ -371,12 +396,14 @@ ags_lv2_manager_load_file(AgsLv2Manager *lv2_manager,
 
   xmlNode *node;
 
+  GList *pname_list;
   GList *effect_list;
   GList *uri_list;
-  
+
   gchar *str;
   gchar *path;
   gchar *xpath;
+  gchar *turtle_pname;
   gchar *effect;
   gchar *escaped_effect;
   gchar *uri;
@@ -406,6 +433,8 @@ ags_lv2_manager_load_file(AgsLv2Manager *lv2_manager,
 			 filename);
 
   g_message("lv2 check - %s\0", path);
+
+  //  xmlSaveFormatFileEnc("-\0", turtle->doc, "UTF-8\0", 1);
   
   /* parse lv2 plugin */
   xpath = "//rdf-triple//rdf-verb//rdf-pname-ln[substring(text(), string-length(text()) - string-length('doap:name') + 1) = 'doap:name']/ancestor::*[self::rdf-verb][1]/following-sibling::rdf-object-list[1]//rdf-string[text()]\0";
@@ -540,6 +569,21 @@ ags_lv2_manager_load_file(AgsLv2Manager *lv2_manager,
       }
     }
 
+    /* turtle pname */
+    xpath = g_strdup_printf("//rdf-triple//rdf-string[text()='\"%s\"']/ancestor::*[self::rdf-triple]//rdf-pname-ln[1]\0",
+			    escaped_effect);
+
+    pname_list = ags_turtle_find_xpath(turtle,
+				       xpath);
+
+    if(pname_list != NULL){
+      turtle_pname = xmlNodeGetContent(pname_list->data);
+    
+      g_list_free(pname_list);
+    }else{
+      turtle_pname = NULL;
+    }
+    
     /* get uri index and append plugin */
     plugin_so = dlopen(path,
 		       RTLD_NOW);
@@ -586,6 +630,7 @@ ags_lv2_manager_load_file(AgsLv2Manager *lv2_manager,
 				      "turtle\0", turtle,
 				      "filename\0", path,
 				      "effect\0", effect,
+				      "pname\0", turtle_pname,
 				      "uri\0", uri,
 				      "effect-index\0", i,
 				      NULL);
@@ -606,6 +651,159 @@ ags_lv2_manager_load_file(AgsLv2Manager *lv2_manager,
 }
 
 /**
+ * ags_lv2_manager_load_preset:
+ * @lv2_manager: the #AgsLv2Manager
+ * @lv2_plugin: the #AgsLv2Plugin
+ * @preset: the #AgsTurtle
+ * 
+ * Load preset.
+ * 
+ * Since: 0.7.122.8
+ */
+void
+ags_lv2_manager_load_preset(AgsLv2Manager *lv2_manager,
+			    AgsLv2Plugin *lv2_plugin,
+			    AgsTurtle *preset)
+{
+  AgsLv2Preset *lv2_preset;
+
+  GList *preset_list;
+
+  gchar *str;
+  gchar *xpath;
+  gchar *uri;
+
+  if(lv2_plugin == NULL ||
+     lv2_plugin->preset != NULL){
+    return;
+  }
+  
+  xpath = "//rdf-triple//rdf-verb[@verb='a']/following-sibling::*[self::rdf-object-list]//rdf-pname-ln[substring(text(), string-length(text()) - string-length(':preset') + 1) = ':preset']/ancestor::*[self::rdf-triple][1]/rdf-subject/rdf-iri\0";
+
+  preset_list = ags_turtle_find_xpath(preset,
+				      xpath);
+
+  while(preset_list != NULL){
+    xmlNode *child;
+    
+    child = ((xmlNode *) preset_list->data)->children;
+    uri = NULL;
+    
+    while(child != NULL){
+      if(child->type == XML_ELEMENT_NODE){
+	if(!g_ascii_strncasecmp(child->name,
+				"rdf-iriref\0",
+				11)){
+	  uri = xmlNodeGetContent(child);
+
+	  if(strlen(uri) > 2){
+	    uri = g_strndup(uri + 1,
+			    strlen(uri) - 2);
+	  }
+	  break;
+	}else if(!g_ascii_strncasecmp(child->name,
+				      "rdf-prefixed-name\0",
+				      18)){
+	  xmlNode *pname_node;
+
+	  gchar *pname;
+	  
+	  pname_node = child->children;
+	  pname = NULL;
+	  
+	  while(pname_node != NULL){
+	    if(pname_node->type == XML_ELEMENT_NODE){
+	      if(!g_ascii_strncasecmp(pname_node->name,
+				      "rdf-pname-ln\0",
+				      11)){
+		pname = xmlNodeGetContent(pname_node);
+		
+		break;
+	      }
+	    }
+
+	    pname_node = pname_node->next;
+	  }
+
+	  uri = pname;
+	    
+	  if(pname != NULL){
+	    gchar *suffix, *prefix;
+	    gchar *offset;
+
+	    offset = index(pname, ':');
+
+	    if(offset != NULL){
+	      GList *prefix_node;
+	      
+	      offset++;
+	      suffix = g_strndup(offset,
+				 strlen(pname) - (offset - pname));
+	      prefix = g_strndup(pname,
+				 offset - pname);
+
+	      str = g_strdup_printf("//rdf-pname-ns[text()='%s']/following-sibling::*[self::rdf-iriref][1]\0",
+				    prefix);
+	      prefix_node = ags_turtle_find_xpath(preset,
+						  str);
+	      free(str);
+
+	      if(prefix_node != NULL){
+		gchar *iriref;
+
+		iriref = xmlNodeGetContent(prefix_node->data);
+
+		if(iriref != NULL){
+		  if(strlen(iriref) > 2){
+		    gchar *tmp;
+		    
+		    tmp = g_strndup(iriref + 1,
+				    strlen(iriref) - 2);
+		    uri = g_strdup_printf("%s%s\0",
+					  tmp,
+					  suffix);
+		    free(tmp);
+		  }
+		  
+		  free(iriref);
+		}
+	      }
+	    }
+	  }
+	  
+	  break;
+	}
+      }
+
+      child = child->next;
+    }
+
+    if(uri == NULL){
+      g_message("uri not found %s\0", AGS_BASE_PLUGIN(lv2_plugin)->filename);
+      
+      /* iterate */
+      preset_list = preset_list->next;
+
+      continue;
+    }
+
+    g_message("parse presets for %s\0", uri);
+    
+    lv2_preset = g_object_new(AGS_TYPE_LV2_PRESET,
+			      "lv2-plugin\0", lv2_plugin,
+			      "turtle\0", preset,
+			      "uri\0", uri,
+			      NULL);
+    ags_lv2_preset_parse_turtle(lv2_preset);
+    lv2_plugin->preset = g_list_append(lv2_plugin->preset,
+				       lv2_preset);
+    
+    /* iterate */
+    preset_list = preset_list->next;
+  }
+}
+
+/**
  * ags_lv2_manager_load_default_directory:
  * @lv2_manager: the #AgsLv2Manager
  * 
@@ -620,6 +818,7 @@ ags_lv2_manager_load_default_directory(AgsLv2Manager *lv2_manager)
 
   gchar **lv2_path;
   gchar *path, *plugin_path;
+  gchar *xpath;
   gchar *str;
 
   GError *error;
@@ -663,20 +862,30 @@ ags_lv2_manager_load_default_directory(AgsLv2Manager *lv2_manager)
 
       if(g_file_test(plugin_path,
 		     G_FILE_TEST_IS_DIR)){
+	AgsLv2Plugin *lv2_plugin;
+	
 	AgsTurtle *manifest, *turtle;
-
+	AgsTurtle *preset;
+	
 	xmlDoc *doc;
 
-	FILE *out;
+	//	FILE *out;
 
-	xmlChar *buffer;
-	int size;
+	//	xmlChar *buffer;
+	//	int size;
       
 	GList *ttl_list, *binary_list;
-
+	GList *preset_list;
+	GList *pname_list;
+	GList *list;
+	
 	gchar *manifest_filename;
-	gchar *turtle_path, *filename;
 
+	gchar *turtle_path, *filename;
+	gchar *turtle_pname;
+	
+	gchar *preset_path;
+	
 	gboolean turtle_loaded;
 
 	manifest_filename = g_strdup_printf("%s/manifest.ttl\0",
@@ -787,7 +996,84 @@ ags_lv2_manager_load_default_directory(AgsLv2Manager *lv2_manager)
 	  binary_list = binary_list->next;
 	}
 
-	g_object_unref(manifest);
+    	/* read presets from turtle */
+	xpath = "//rdf-triple//rdf-verb[@verb='a']/following-sibling::*[self::rdf-object-list]//rdf-pname-ln[substring(text(), string-length(text()) - string-length(':preset') + 1) = ':preset']/ancestor::*[self::rdf-triple]\0";
+	preset_list = ags_turtle_find_xpath(manifest,
+					    xpath);
+
+	while(preset_list != NULL){
+	  xpath = ".//rdf-iriref[substring(text(), string-length(text()) - string-length('.ttl>') + 1) = '.ttl>']";
+	  list = ags_turtle_find_xpath_with_context_node(manifest,
+							 xpath,
+							 preset_list->data);
+	  
+	  /* read filename of turtle */
+	  preset_path = xmlNodeGetContent((xmlNode *) list->data);
+
+	  if(preset_path == NULL){
+	    preset_list = preset_list->next;
+
+	    continue;
+	  }
+
+	  /* read filename */
+	  preset_path = g_strndup(&(preset_path[1]),
+				  strlen(preset_path) - 2);
+	
+	  if(!g_ascii_strncasecmp(preset_path,
+				  "http://\0",
+				  7)){
+	    preset_list = preset_list->next;
+	  
+	    continue;
+	  }
+
+	  /* turtle pname */
+	  xpath = ".//rdf-pname-ln[substring(text(), string-length(text()) - string-length(':appliesto') + 1) = ':appliesto']/ancestor::*[self::rdf-verb][1]/following-sibling::*[self::rdf-object-list][1]//rdf-pname-ln\0";
+	  pname_list = ags_turtle_find_xpath_with_context_node(manifest,
+							       xpath,
+							       preset_list->data);
+
+	  if(pname_list != NULL){
+	    turtle_pname = xmlNodeGetContent(pname_list->data);
+    
+	    g_list_free(pname_list);
+	  }else{
+	    preset_list = preset_list->next;
+
+	    continue;
+	  }
+
+	  /* find lv2 plugin by pname */
+	  list = ags_lv2_plugin_find_pname(lv2_manager->lv2_plugin,
+					   turtle_pname);	  
+	  
+	  if(list == NULL){
+	    preset_list = preset_list->next;
+
+	    continue;
+	  }
+
+	  lv2_plugin = list->data;
+	  
+	  /* load turtle doc */
+	  if((preset = (AgsTurtle *) ags_turtle_manager_find(ags_turtle_manager_get_instance(),
+							     preset_path)) == NULL){
+	    preset = ags_turtle_new(g_strdup_printf("%s/%s\0",
+						    plugin_path,
+						    preset_path));
+	    ags_turtle_load(preset,
+			    NULL);
+	    ags_turtle_manager_add(ags_turtle_manager_get_instance(),
+				   (GObject *) preset);
+	  }
+
+	  ags_lv2_manager_load_preset(lv2_manager,
+				      lv2_plugin,
+				      preset);
+
+	  preset_list = preset_list->next;
+	}
       }
     }
 
diff --git a/ags/plugin/ags_lv2_manager.h b/ags/plugin/ags_lv2_manager.h
index b4f7f66..e7a427b 100644
--- a/ags/plugin/ags_lv2_manager.h
+++ b/ags/plugin/ags_lv2_manager.h
@@ -72,6 +72,9 @@ void ags_lv2_manager_load_file(AgsLv2Manager *lv2_manager,
 			       AgsTurtle *turtle,
 			       gchar *lv2_path,
 			       gchar *filename);
+void ags_lv2_manager_load_preset(AgsLv2Manager *lv2_manager,
+				 AgsLv2Plugin *lv2_plugin,
+				 AgsTurtle *preset);
 void ags_lv2_manager_load_default_directory(AgsLv2Manager *lv2_manager);
 
 /*  */
diff --git a/ags/plugin/ags_lv2_plugin.c b/ags/plugin/ags_lv2_plugin.c
index 4dac0ea..0d04727 100644
--- a/ags/plugin/ags_lv2_plugin.c
+++ b/ags/plugin/ags_lv2_plugin.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -45,6 +45,7 @@ void ags_lv2_plugin_get_property(GObject *gobject,
 				 guint prop_id,
 				 GValue *value,
 				 GParamSpec *param_spec);
+void ags_lv2_plugin_dispose(GObject *gobject);
 void ags_lv2_plugin_finalize(GObject *gobject);
 
 gpointer ags_lv2_plugin_instantiate(AgsBasePlugin *base_plugin,
@@ -75,7 +76,9 @@ void ags_lv2_plugin_load_plugin(AgsBasePlugin *base_plugin);
 
 enum{
   PROP_0,
+  PROP_PNAME,
   PROP_URI,
+  PROP_UI_URI,
   PROP_MANIFEST,
   PROP_TURTLE,
 };
@@ -125,10 +128,27 @@ ags_lv2_plugin_class_init(AgsLv2PluginClass *lv2_plugin)
   gobject->set_property = ags_lv2_plugin_set_property;
   gobject->get_property = ags_lv2_plugin_get_property;
 
+  gobject->dispose = ags_lv2_plugin_dispose;
   gobject->finalize = ags_lv2_plugin_finalize;
 
   /* properties */
   /**
+   * AgsLv2Plugin:pname:
+   *
+   * The assigned pname.
+   * 
+   * Since: 0.122.8
+   */
+  param_spec = g_param_spec_string("pname\0",
+				   "pname of the plugin\0",
+				   "The pname this plugin is associated with\0",
+				   NULL,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_PNAME,
+				  param_spec);
+
+  /**
    * AgsLv2Plugin:uri:
    *
    * The assigned uri.
@@ -145,11 +165,27 @@ ags_lv2_plugin_class_init(AgsLv2PluginClass *lv2_plugin)
 				  param_spec);
 
   /**
+   * AgsLv2Plugin:ui-uri:
+   *
+   * The assigned ui-uri.
+   * 
+   * Since: 0.7.127
+   */
+  param_spec = g_param_spec_string("ui-uri\0",
+				   "ui-uri of the plugin\0",
+				   "The ui-uri this plugin has\0",
+				   NULL,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_UI_URI,
+				  param_spec);
+
+  /**
    * AgsLv2Plugin:manifest:
    *
    * The assigned manifest.
    * 
-   * Since: 1.0.0
+   * Since: 0.7.127
    */
   param_spec = g_param_spec_object("manifest\0",
 				   "manifest of the plugin\0",
@@ -196,10 +232,19 @@ ags_lv2_plugin_init(AgsLv2Plugin *lv2_plugin)
 {
   lv2_plugin->flags = 0;
 
+  lv2_plugin->pname = NULL;
   lv2_plugin->uri = NULL;
+  lv2_plugin->ui_uri = NULL;
 
   lv2_plugin->manifest = NULL;
   lv2_plugin->turtle = NULL;
+  
+  lv2_plugin->doap_name = NULL;
+  lv2_plugin->foaf_name = NULL;
+  lv2_plugin->foaf_homepage = NULL;
+  lv2_plugin->foaf_mbox = NULL;
+
+  lv2_plugin->preset = NULL;
 }
 
 void
@@ -213,6 +258,23 @@ ags_lv2_plugin_set_property(GObject *gobject,
   lv2_plugin = AGS_LV2_PLUGIN(gobject);
 
   switch(prop_id){
+  case PROP_PNAME:
+    {
+      gchar *pname;
+
+      pname = (gchar *) g_value_get_string(value);
+
+      if(lv2_plugin->pname == pname){
+	return;
+      }
+      
+      if(lv2_plugin->pname != NULL){
+	g_free(lv2_plugin->pname);
+      }
+
+      lv2_plugin->pname = g_strdup(pname);
+    }
+    break;
   case PROP_URI:
     {
       gchar *uri;
@@ -230,6 +292,23 @@ ags_lv2_plugin_set_property(GObject *gobject,
       lv2_plugin->uri = g_strdup(uri);
     }
     break;
+  case PROP_UI_URI:
+    {
+      gchar *ui_uri;
+
+      ui_uri = (gchar *) g_value_get_string(value);
+
+      if(lv2_plugin->ui_uri == ui_uri){
+	return;
+      }
+      
+      if(lv2_plugin->ui_uri != NULL){
+	g_free(lv2_plugin->ui_uri);
+      }
+
+      lv2_plugin->ui_uri = g_strdup(ui_uri);
+    }
+    break;
   case PROP_MANIFEST:
     {
       AgsTurtle *manifest;
@@ -289,11 +368,21 @@ ags_lv2_plugin_get_property(GObject *gobject,
   lv2_plugin = AGS_LV2_PLUGIN(gobject);
 
   switch(prop_id){
+  case PROP_PNAME:
+    {
+      g_value_set_string(value, lv2_plugin->pname);
+    }
+    break;
   case PROP_URI:
     {
       g_value_set_string(value, lv2_plugin->uri);
     }
     break;
+  case PROP_UI_URI:
+    {
+      g_value_set_string(value, lv2_plugin->ui_uri);
+    }
+    break;
   case PROP_MANIFEST:
     {
       g_value_set_object(value, lv2_plugin->manifest);
@@ -311,6 +400,29 @@ ags_lv2_plugin_get_property(GObject *gobject,
 }
 
 void
+ags_lv2_plugin_dispose(GObject *gobject)
+{
+  AgsLv2Plugin *lv2_plugin;
+
+  lv2_plugin = AGS_LV2_PLUGIN(gobject);
+
+  if(lv2_plugin->manifest != NULL){
+    g_object_unref(lv2_plugin->manifest);
+
+    lv2_plugin->manifest = NULL;
+  }
+  
+  if(lv2_plugin->turtle != NULL){
+    g_object_unref(lv2_plugin->turtle);
+
+    lv2_plugin->turtle = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_lv2_plugin_parent_class)->dispose(gobject);
+}
+
+void
 ags_lv2_plugin_finalize(GObject *gobject)
 {
   AgsLv2Plugin *lv2_plugin;
@@ -318,6 +430,7 @@ ags_lv2_plugin_finalize(GObject *gobject)
   lv2_plugin = AGS_LV2_PLUGIN(gobject);
 
   g_free(lv2_plugin->uri);
+  g_free(lv2_plugin->ui_uri);
 
   if(lv2_plugin->manifest != NULL){
     g_object_unref(lv2_plugin->manifest);
@@ -326,6 +439,9 @@ ags_lv2_plugin_finalize(GObject *gobject)
   if(lv2_plugin->turtle != NULL){
     g_object_unref(lv2_plugin->turtle);
   }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_lv2_plugin_parent_class)->finalize(gobject);
 }
 
 gpointer
@@ -399,6 +515,8 @@ ags_lv2_plugin_load_plugin(AgsBasePlugin *base_plugin)
 
   GList *metadata_list;
   GList *instrument_list;
+  GList *feature_list;
+  GList *ui_list;
   GList *port_list;
   GList *port_descriptor_list;
   
@@ -506,6 +624,19 @@ ags_lv2_plugin_load_plugin(AgsBasePlugin *base_plugin)
       g_list_free(metadata_list);
     }
 
+    /* check needs worker */
+    xpath = ".//rdf-pname-ln[text()='lv2:requiredFeature']/ancestor::*[self::rdf-verb][1]/following-sibling::*[self::rdf-object-list][1]//rdf-pname-ln[text()=lv2worker:schedule]";
+
+    feature_list = ags_turtle_find_xpath_with_context_node(lv2_plugin->turtle,
+							   xpath,
+							   triple_node);
+
+    if(feature_list != NULL){
+      lv2_plugin->flags |= AGS_LV2_PLUGIN_NEEDS_WORKER;
+    
+      g_list_free(feature_list);
+    }
+
     /* check if is synthesizer */
     xpath = ".//rdf-verb[@verb='a']/following-sibling::*[self::rdf-object-list]//rdf-pname-ln[substring(text(), string-length(text()) - string-length(':instrumentplugin') + 1) = ':instrumentplugin']\0";
     instrument_list = ags_turtle_find_xpath_with_context_node(lv2_plugin->turtle,
@@ -517,7 +648,33 @@ ags_lv2_plugin_load_plugin(AgsBasePlugin *base_plugin)
 
       g_list_free(instrument_list);
     }
-    
+
+    /* check UI */
+    xpath = ".//rdf-pname-ln[text()='uiext:ui']/ancestor::*[self::rdf-verb][1]/following-sibling::*[self::rdf-object-list][1]//rdf-iriref";
+
+    ui_list = ags_turtle_find_xpath_with_context_node(lv2_plugin->turtle,
+						      xpath,
+						      triple_node);
+
+    if(ui_list != NULL){
+      gchar *ui_uri;
+
+      ui_uri = xmlNodeGetContent(ui_list->data);
+
+      if(strlen(ui_uri) > 2){
+	ui_uri = g_strndup(ui_uri + 1,
+			   strlen(ui_uri) - 2);
+      }
+
+      g_object_set(lv2_plugin,
+		   "ui-uri\0", ui_uri,
+		   NULL);
+      
+      g_message("*** found UI <%s> ***\0", ui_uri);
+
+      g_list_free(ui_list);
+    }
+
     /* load ports */
     xpath = ".//rdf-verb//rdf-pname-ln[substring(text(), string-length(text()) - string-length(':port') + 1) = ':port']/ancestor::*[self::rdf-verb][1]/following-sibling::*[self::rdf-object-list]/rdf-object[.//rdf-pname-ln[substring(text(), string-length(text()) - string-length(':index') + 1) = ':index']]\0";
     port_list = ags_turtle_find_xpath_with_context_node(lv2_plugin->turtle,
@@ -871,7 +1028,8 @@ ags_lv2_plugin_load_plugin(AgsBasePlugin *base_plugin)
 
 	g_list_free(list);
       }
-      
+
+      /* iterate */
       port_list = port_list->next;
     }
 
@@ -1205,6 +1363,37 @@ ags_lv2_plugin_clear_atom_sequence(void *atom_sequence,
 }
 
 /**
+ * ags_lv2_plugin_find_pname:
+ * @lv2_plugin: a #GList-struct containig #AgsLv2Plugin
+ * @pname: the pname to find
+ * 
+ * Find pname in @lv2_plugin #GList-struct
+ * 
+ * Returns: the matching #GList-struct containing #AgsLv2Plugin
+ * 
+ * Since: 0.7.122.8
+ */
+GList*
+ags_lv2_plugin_find_pname(GList *lv2_plugin,
+			  gchar *pname)
+{
+  if(pname == NULL){
+    return(NULL);
+  }
+
+  while(lv2_plugin != NULL){
+    if(!g_ascii_strcasecmp(pname,
+			   AGS_LV2_PLUGIN(lv2_plugin->data)->pname)){
+      return(lv2_plugin);
+    }
+    
+    lv2_plugin = lv2_plugin->next;
+  }
+
+  return(NULL);
+}
+
+/**
  * ags_lv2_plugin_new:
  * @turtle: the turtle
  * @filename: the plugin .so
diff --git a/ags/plugin/ags_lv2_plugin.h b/ags/plugin/ags_lv2_plugin.h
index bd34f56..d041563 100644
--- a/ags/plugin/ags_lv2_plugin.h
+++ b/ags/plugin/ags_lv2_plugin.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -26,6 +26,7 @@
 #include <stdarg.h>
 
 #include <ags/plugin/ags_base_plugin.h>
+
 #include <ags/lib/ags_turtle.h>
 
 #include <alsa/seq_midi_event.h>
@@ -55,6 +56,7 @@ typedef struct _AgsLv2PluginClass AgsLv2PluginClass;
 
 typedef enum{
   AGS_LV2_PLUGIN_IS_SYNTHESIZER  = 1,
+  AGS_LV2_PLUGIN_NEEDS_WORKER    = 1 <<  1,
 }AgsLv2PluginFlags;
 
 struct _AgsLv2Plugin
@@ -62,9 +64,11 @@ struct _AgsLv2Plugin
   AgsBasePlugin base_plugin;
 
   guint flags;
-  
-  gchar *uri;
 
+  gchar *pname;
+  gchar *uri;
+  gchar *ui_uri;
+  
   AgsTurtle *manifest;
   AgsTurtle *turtle;
 
@@ -72,6 +76,8 @@ struct _AgsLv2Plugin
   gchar *foaf_name;
   gchar *foaf_homepage;
   gchar *foaf_mbox;
+
+  GList *preset;
 };
 
 struct _AgsLv2PluginClass
@@ -101,6 +107,9 @@ gboolean ags_lv2_plugin_atom_sequence_append_midi(void *atom_sequence,
 void ags_lv2_plugin_clear_atom_sequence(void *atom_sequence,
 					guint sequence_size);
 
+GList* ags_lv2_plugin_find_pname(GList *lv2_plugin,
+				 gchar *pname);
+
 AgsLv2Plugin* ags_lv2_plugin_new(AgsTurtle *turtle, gchar *filename, gchar *effect, gchar *uri, guint effect_index);
 
 #endif /*__AGS_LV2_PLUGIN_H__*/
diff --git a/ags/plugin/ags_lv2_preset.c b/ags/plugin/ags_lv2_preset.c
new file mode 100644
index 0000000..ff93492
--- /dev/null
+++ b/ags/plugin/ags_lv2_preset.c
@@ -0,0 +1,668 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/plugin/ags_lv2_preset.h>
+
+#include <ags/object/ags_connectable.h>
+
+#include <ags/plugin/ags_lv2_plugin.h>
+
+#include <stdlib.h>
+
+void ags_lv2_preset_class_init(AgsLv2PresetClass *lv2_preset);
+void ags_lv2_preset_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_lv2_preset_init(AgsLv2Preset *lv2_preset);
+void ags_lv2_preset_set_property(GObject *gobject,
+				 guint prop_id,
+				 const GValue *value,
+				 GParamSpec *param_spec);
+void ags_lv2_preset_get_property(GObject *gobject,
+				 guint prop_id,
+				 GValue *value,
+				 GParamSpec *param_spec);
+void ags_lv2_preset_connect(AgsConnectable *connectable);
+void ags_lv2_preset_disconnect(AgsConnectable *connectable);
+void ags_lv2_preset_finalize(GObject *gobject);
+
+/**
+ * SECTION:ags_lv2_preset
+ * @short_description: task thread
+ * @title: AgsLv2Preset
+ * @section_id:
+ * @include: ags/plugin/ags_lv2_preset.h
+ *
+ * The #AgsLv2Preset handles LV2 presets mapped to a bank.
+ */
+
+enum{
+  PROP_0,
+  PROP_LV2_PLUGIN,
+  PROP_URI,
+  PROP_BANK,
+  PROP_PRESET_LABEL,
+  PROP_TURTLE,
+};
+
+static gpointer ags_lv2_preset_parent_class = NULL;
+static AgsConnectableInterface *ags_lv2_preset_parent_connectable_interface;
+
+GType
+ags_lv2_preset_get_type()
+{
+  static GType ags_type_lv2_preset = 0;
+
+  if(!ags_type_lv2_preset){
+    static const GTypeInfo ags_lv2_preset_info = {
+      sizeof (AgsLv2PresetClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_lv2_preset_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof (AgsLv2Preset),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_lv2_preset_init,
+    };
+
+    static const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_lv2_preset_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+    
+    ags_type_lv2_preset = g_type_register_static(G_TYPE_OBJECT,
+						 "AgsLv2Preset\0",
+						 &ags_lv2_preset_info,
+						 0);
+    
+    g_type_add_interface_static(ags_type_lv2_preset,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+  }
+  
+  return (ags_type_lv2_preset);
+}
+
+void
+ags_lv2_preset_class_init(AgsLv2PresetClass *lv2_preset)
+{
+  GObjectClass *gobject;
+  GParamSpec *param_spec;
+  
+  ags_lv2_preset_parent_class = g_type_class_peek_parent(lv2_preset);
+
+  /* GObject */
+  gobject = (GObjectClass *) lv2_preset;
+
+  gobject->set_property = ags_lv2_preset_set_property;
+  gobject->get_property = ags_lv2_preset_get_property;
+
+  gobject->finalize = ags_lv2_preset_finalize;
+
+  /* properties */
+  /**
+   * AgsLv2Preset:lv2-plugin:
+   *
+   * The assigned lv2 plugin.
+   * 
+   * Since: 0.7.122.8
+   */
+  param_spec = g_param_spec_object("lv2-plugin\0",
+				   "lv2 plugin of the preset\0",
+				   "The lv2 plugin this preset is located in\0",
+				   AGS_TYPE_LV2_PLUGIN,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_LV2_PLUGIN,
+				  param_spec);
+
+  /**
+   * AgsLv2Preset:uri:
+   *
+   * The assigned uri.
+   * 
+   * Since: 0.7.122.8
+   */
+  param_spec = g_param_spec_string("uri\0",
+				   "uri of the preset\0",
+				   "The uri this preset is located in\0",
+				   NULL,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_URI,
+				  param_spec);
+
+  /**
+   * AgsLv2Preset:bank:
+   *
+   * The assigned bank.
+   * 
+   * Since: 0.7.122.8
+   */
+  param_spec = g_param_spec_string("bank\0",
+				   "bank of the preset\0",
+				   "The bank this preset is assigned with\0",
+				   NULL,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_BANK,
+				  param_spec);
+
+  /**
+   * AgsLv2Preset:preset-label:
+   *
+   * The preset label.
+   * 
+   * Since: 0.7.122.8
+   */
+  param_spec = g_param_spec_string("preset-label\0",
+				   "preset label\0",
+				   "The preset label\0",
+				   NULL,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_PRESET_LABEL,
+				  param_spec);
+
+  /**
+   * AgsLv2Preset:turtle:
+   *
+   * The assigned turtle.
+   * 
+   * Since: 0.7.122.8
+   */
+  param_spec = g_param_spec_object("turtle\0",
+				   "turtle of the preset\0",
+				   "The turtle this preset is located in\0",
+				   AGS_TYPE_TURTLE,
+				   G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_TURTLE,
+				  param_spec);
+}
+
+void
+ags_lv2_preset_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  ags_lv2_preset_parent_connectable_interface = g_type_interface_peek_parent(connectable);
+
+  connectable->connect = ags_lv2_preset_connect;
+  connectable->disconnect = ags_lv2_preset_disconnect;
+}
+
+void
+ags_lv2_preset_init(AgsLv2Preset *lv2_preset)
+{
+  lv2_preset->flags = 0;
+
+  lv2_preset->lv2_plugin = NULL;
+
+  lv2_preset->uri = NULL;
+
+  lv2_preset->bank = NULL;
+  lv2_preset->preset_label = NULL;
+
+  lv2_preset->turtle = NULL;
+}
+
+
+void
+ags_lv2_preset_set_property(GObject *gobject,
+			    guint prop_id,
+			    const GValue *value,
+			    GParamSpec *param_spec)
+{
+  AgsLv2Preset *lv2_preset;
+
+  lv2_preset = AGS_LV2_PRESET(gobject);
+
+  switch(prop_id){
+  case PROP_LV2_PLUGIN:
+    {
+      AgsLv2Plugin *lv2_plugin;
+
+      lv2_plugin = (AgsLv2Plugin *) g_value_get_object(value);
+
+      if(lv2_preset->lv2_plugin == lv2_plugin){
+	return;
+      }
+
+      if(lv2_preset->lv2_plugin != NULL){
+	g_object_unref(lv2_preset->lv2_plugin);
+      }
+
+      if(lv2_plugin != NULL){
+	g_object_ref(lv2_plugin);
+      }
+      
+      lv2_preset->lv2_plugin = lv2_plugin;
+    }
+    break;
+  case PROP_URI:
+    {
+      gchar *uri;
+
+      uri = (gchar *) g_value_get_string(value);
+
+      if(lv2_preset->uri == uri){
+	return;
+      }
+      
+      if(lv2_preset->uri != NULL){
+	g_free(lv2_preset->uri);
+      }
+
+      lv2_preset->uri = g_strdup(uri);
+    }
+    break;
+  case PROP_BANK:
+    {
+      gchar *bank;
+
+      bank = (gchar *) g_value_get_string(value);
+
+      if(lv2_preset->bank == bank){
+	return;
+      }
+      
+      if(lv2_preset->bank != NULL){
+	g_free(lv2_preset->bank);
+      }
+
+      lv2_preset->bank = g_strdup(bank);
+    }
+    break;
+  case PROP_PRESET_LABEL:
+    {
+      gchar *preset_label;
+
+      preset_label = (gchar *) g_value_get_string(value);
+
+      if(lv2_preset->preset_label == preset_label){
+	return;
+      }
+      
+      if(lv2_preset->preset_label != NULL){
+	g_free(lv2_preset->preset_label);
+      }
+
+      lv2_preset->preset_label = g_strdup(preset_label);
+    }
+    break;
+  case PROP_TURTLE:
+    {
+      AgsTurtle *turtle;
+
+      turtle = (AgsTurtle *) g_value_get_object(value);
+
+      if(lv2_preset->turtle == turtle){
+	return;
+      }
+
+      if(lv2_preset->turtle != NULL){
+	g_object_unref(lv2_preset->turtle);
+      }
+
+      if(turtle != NULL){
+	g_object_ref(turtle);
+      }
+      
+      lv2_preset->turtle = turtle;
+    }
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  }
+}
+
+void
+ags_lv2_preset_get_property(GObject *gobject,
+			    guint prop_id,
+			    GValue *value,
+			    GParamSpec *param_spec)
+{
+  AgsLv2Preset *lv2_preset;
+
+  lv2_preset = AGS_LV2_PRESET(gobject);
+
+  switch(prop_id){
+  case PROP_LV2_PLUGIN:
+    {
+      g_value_set_object(value, lv2_preset->lv2_plugin);
+    }
+    break;
+  case PROP_URI:
+    {
+      g_value_set_string(value, lv2_preset->uri);
+    }
+    break;
+  case PROP_BANK:
+    {
+      g_value_set_string(value, lv2_preset->bank);
+    }
+    break;
+  case PROP_PRESET_LABEL:
+    {
+      g_value_set_string(value, lv2_preset->preset_label);
+    }
+    break;
+  case PROP_TURTLE:
+    {
+      g_value_set_object(value, lv2_preset->turtle);
+    }
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  }
+}
+
+void
+ags_lv2_preset_connect(AgsConnectable *connectable)
+{
+  /* empty */
+}
+
+void
+ags_lv2_preset_disconnect(AgsConnectable *connectable)
+{
+  /* empty */
+}
+
+void
+ags_lv2_preset_finalize(GObject *gobject)
+{
+  AgsLv2Preset *lv2_preset;
+
+  lv2_preset = AGS_LV2_PRESET(gobject);
+
+  /* lv2 plugin */
+  if(lv2_preset->lv2_plugin != NULL){
+    g_object_unref(lv2_preset->lv2_plugin);
+  }
+
+  /* uri */
+  if(lv2_preset->uri != NULL){
+    free(lv2_preset->uri);
+  }
+
+  /* bank and preset label */
+  if(lv2_preset->bank != NULL){
+    free(lv2_preset->bank);
+  }
+  
+  if(lv2_preset->preset_label != NULL){
+    free(lv2_preset->preset_label);
+  }
+
+  /* turtle */
+  if(lv2_preset->turtle != NULL){
+    g_object_unref(lv2_preset->turtle);
+  }
+
+  /* port preset */
+  if(lv2_preset->port_preset != NULL){
+    g_list_free_full(lv2_preset->port_preset,
+		     ags_lv2_port_preset_free);
+  }
+  
+  /* call parent */
+  G_OBJECT_CLASS(ags_lv2_preset_parent_class)->finalize(gobject);
+}
+
+AgsLv2PortPreset*
+ags_lv2_port_preset_alloc(gchar *port_symbol,
+			  GType port_type)
+{
+  AgsLv2PortPreset *lv2_port_preset;
+
+  lv2_port_preset = (AgsLv2PortPreset *) malloc(sizeof(AgsLv2PortPreset));
+
+  lv2_port_preset->port_symbol = port_symbol;
+
+  lv2_port_preset->port_value = g_new0(GValue,
+				       1);
+  
+  if(port_type != G_TYPE_NONE){
+    g_value_init(lv2_port_preset->port_value,
+		 port_type);
+  }
+
+  return(lv2_port_preset);
+}
+
+void
+ags_lv2_port_preset_free(AgsLv2PortPreset *lv2_port_preset)
+{
+  if(lv2_port_preset->port_symbol != NULL){
+    free(lv2_port_preset->port_symbol);
+  }
+  
+  if(lv2_port_preset->port_value != NULL){
+    g_value_unset(lv2_port_preset->port_value);
+
+    free(lv2_port_preset->port_value);
+  }
+  
+  free(lv2_port_preset);
+}
+
+void
+ags_lv2_preset_parse_turtle(AgsLv2Preset *lv2_preset)
+{
+  AgsLv2PortPreset *lv2_port_preset;
+  
+  xmlNode *triple_node;
+  xmlNode *port_node;
+  xmlNode *current;
+  
+  GList *label_list;
+  GList *bank_list;
+  GList *port_list, *list;
+
+  gchar *str;
+  gchar *xpath;
+  
+  if(lv2_preset == NULL ||
+     lv2_preset->turtle == NULL ||
+     lv2_preset->uri == NULL){
+    return;
+  }
+
+  /* retrieve triple by uri */
+  xpath = g_strdup_printf("(//rdf-triple/rdf-subject/rdf-iri/rdf-iriref[text() = '%s'])/ancestor::*[self::rdf-triple][1]\0",
+			  lv2_preset->uri);
+    
+  list = ags_turtle_find_xpath(lv2_preset->turtle,
+			       xpath);
+
+  free(xpath);
+
+  if(list != NULL){
+    triple_node = (xmlNode *) list->data;
+
+    g_list_free(list);
+  }else{
+    xpath = g_strdup_printf("//rdf-triple//rdf-iriref[text() = '<%s>']/ancestor::*[self::rdf-triple][1]\0",
+			    lv2_preset->uri);
+    
+    list = ags_turtle_find_xpath(lv2_preset->turtle,
+				 xpath);
+
+    free(xpath);
+    
+    if(list != NULL){
+      triple_node = (xmlNode *) list->data;
+
+      g_list_free(list);
+    }else{
+      g_warning("rdf-triple not found\0");
+      
+      return;
+    }
+  }
+
+  /* preset label */
+  xpath = ".//rdf-pname-ln[text()='rdfs:label']/ancestor::*[self::rdf-verb][1]/following-sibling::*[self::rdf-object-list][1]//rdf-string\0";
+  label_list = ags_turtle_find_xpath_with_context_node(lv2_preset->turtle,
+						       xpath,
+						       triple_node);
+
+  if(label_list != NULL){
+    lv2_preset->preset_label = xmlNodeGetContent((xmlNode *) label_list->data);
+
+    g_list_free(label_list);
+  }
+
+  /* bank */
+  xpath = ".//rdf-pname-ln[substring(text(), string-length(text()) - string-length(':bank') + 1) = ':bank']/ancestor::*[self::rdf-verb][1]/following-sibling::*[self::rdf-object-list][1]//rdf-iriref\0";
+  bank_list = ags_turtle_find_xpath_with_context_node(lv2_preset->turtle,
+						      xpath,
+						      triple_node);
+
+  if(bank_list != NULL){
+    str = xmlNodeGetContent((xmlNode *) bank_list->data);
+
+    lv2_preset->bank = g_strndup(&(str[1]),
+				 strlen(str) - 2);
+
+    g_list_free(bank_list);
+  }
+
+  /* load ports */
+  xpath = ".//rdf-pname-ln[substring(text(), string-length(text()) - string-length(':port') + 1) = ':port']/ancestor::*[self::rdf-verb][1]/following-sibling::*[self::rdf-object-list]/rdf-object\0";
+  port_list = ags_turtle_find_xpath_with_context_node(lv2_preset->turtle,
+						      xpath,
+						      triple_node);
+
+  while(port_list != NULL){
+    lv2_port_preset = ags_lv2_port_preset_alloc(NULL,
+						G_TYPE_FLOAT);
+    lv2_preset->port_preset = g_list_prepend(lv2_preset->port_preset,
+					     lv2_port_preset);
+    port_node = port_list->data;
+    
+    /* load symbol */
+    xpath = g_ascii_strdown(".//rdf-object-list//rdf-string[ancestor::*[self::rdf-object-list][1]/preceding-sibling::*[self::rdf-verb][1]//rdf-pname-ln[substring(text(), string-length(text()) - string-length(':symbol') + 1) = ':symbol']]\0",
+			    -1);
+    list = ags_turtle_find_xpath_with_context_node(lv2_preset->turtle,
+						   xpath,
+						   port_node);
+
+    if(list != NULL){
+      gchar *str;
+	
+      current = (xmlNode *) list->data;
+      str = xmlNodeGetContent(current);
+
+      if(strlen(str) > 2){
+	lv2_port_preset->port_symbol = g_strndup(str + 1,
+						 strlen(str) - 2);
+      }
+
+      g_list_free(list);
+    }
+
+    /* port value */
+    xpath = g_ascii_strdown(".//rdf-verb//rdf-pname-ln[substring(text(), string-length(text()) - string-length(':value') + 1) = ':value']/ancestor::*[self::rdf-verb][1]/following-sibling::*[self::rdf-object-list][1]//rdf-numeric\0",
+			    -1);
+    list = ags_turtle_find_xpath_with_context_node(lv2_preset->turtle,
+						   xpath,
+						   port_node);
+
+    if(list != NULL){
+      current = (xmlNode *) list->data;
+
+      g_value_set_float(lv2_port_preset->port_value,
+			g_ascii_strtod(xmlNodeGetContent(current),
+				       NULL));
+
+      g_list_free(list);
+    }
+
+    /* iterate */
+    port_list = port_list->next;
+  }
+
+  lv2_preset->port_preset = g_list_reverse(lv2_preset->port_preset);
+  
+  if(port_list != NULL){
+    g_list_free(port_list);
+  }
+}
+
+/**
+ * ags_lv2_preset_find_preset_label:
+ * @lv2_preset: the #GList-struct containing #AgsLv2Preset
+ * @preset_label: the preset label
+ * 
+ * Find @preset_label within @lv2_preset.
+ * 
+ * Returns: the matching #GList-struct containing #AgsLv2Preset
+ * 
+ * Since: 0.7.122.8
+ */
+GList*
+ags_lv2_preset_find_preset_label(GList *lv2_preset,
+				 gchar *preset_label)
+{
+  if(preset_label == NULL){
+    return(NULL);
+  }
+
+  while(lv2_preset != NULL){
+    if(!g_strcmp0(preset_label,
+		  AGS_LV2_PRESET(lv2_preset->data)->preset_label)){
+      return(lv2_preset);
+    }
+
+    lv2_preset = lv2_preset->next;
+  }
+  
+  return(NULL);
+}
+
+/**
+ * ags_lv2_preset_new:
+ * @lv2_plugin: an #AgsLv2Plugin
+ * @turtle: the #AgsTurtle
+ * @uri: the URI as string
+ * 
+ * Create a new instance of #AgsLv2Preset.
+ *
+ * Returns: the new #AgsLv2Preset
+ *
+ * Since: 0.7.122.8
+ */ 
+AgsLv2Preset*
+ags_lv2_preset_new(GObject *lv2_plugin,
+		   AgsTurtle *turtle,
+		   gchar *uri)
+{
+  AgsLv2Preset *lv2_preset;
+
+  lv2_preset = (AgsLv2Preset *) g_object_new(AGS_TYPE_LV2_PRESET,
+					     "lv2-plugin\0", lv2_plugin,
+					     "turtle\0", turtle,
+					     "uri\0", uri,
+					     NULL);
+
+  return(lv2_preset);
+}
diff --git a/ags/plugin/ags_lv2_preset.h b/ags/plugin/ags_lv2_preset.h
new file mode 100644
index 0000000..6c58174
--- /dev/null
+++ b/ags/plugin/ags_lv2_preset.h
@@ -0,0 +1,93 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_LV2_PRESET_H__
+#define __AGS_LV2_PRESET_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <ags/lib/ags_turtle.h>
+
+#include <lv2.h>
+#include <lv2/lv2plug.in/ns/ext/presets/presets.h>
+
+#define AGS_TYPE_LV2_PRESET                (ags_lv2_preset_get_type())
+#define AGS_LV2_PRESET(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_LV2_PRESET, AgsLv2Preset))
+#define AGS_LV2_PRESET_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_LV2_PRESET, AgsLv2PresetClass))
+#define AGS_IS_LV2_PRESET(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_LV2_PRESET))
+#define AGS_IS_LV2_PRESET_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_LV2_PRESET))
+#define AGS_LV2_PRESET_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), AGS_TYPE_LV2_PRESET, AgsLv2PresetClass))
+
+#define AGS_LV2_PORT_PRESET(ptr) ((AgsLv2PortPreset*)(ptr))
+
+typedef struct _AgsLv2Preset AgsLv2Preset;
+typedef struct _AgsLv2PresetClass AgsLv2PresetClass;
+typedef struct _AgsLv2PortPreset AgsLv2PortPreset;
+
+typedef enum{
+  AGS_LV2_PRESET_CONNECTED    = 1,
+}AgsLv2PresetFlags;
+
+struct _AgsLv2Preset
+{
+  GObject gobject;
+
+  guint flags;
+  
+  GObject *lv2_plugin;
+
+  gchar *uri;
+
+  gchar *bank;
+  gchar *preset_label;
+  
+  AgsTurtle *turtle;
+
+  GList *port_preset;
+};
+
+struct _AgsLv2PresetClass
+{
+  GObjectClass gobject;
+};
+
+struct _AgsLv2PortPreset
+{
+  gchar *port_symbol;
+
+  GValue *port_value;
+};
+
+GType ags_lv2_preset_get_type(void);
+
+AgsLv2PortPreset* ags_lv2_port_preset_alloc(gchar *port_symobl,
+					    GType port_type);
+void ags_lv2_port_preset_free(AgsLv2PortPreset *lv2_port_preset);
+
+void ags_lv2_preset_parse_turtle(AgsLv2Preset *lv2_preset);
+
+GList* ags_lv2_preset_find_preset_label(GList *lv2_preset,
+					gchar *preset_label);
+
+AgsLv2Preset* ags_lv2_preset_new(GObject *lv2_plugin,
+				 AgsTurtle *turtle,
+				 gchar *uri);
+
+#endif /*__AGS_LV2_PRESET_H__*/
diff --git a/ags/plugin/ags_lv2_uri_map_manager.c b/ags/plugin/ags_lv2_uri_map_manager.c
index af893b6..c097147 100644
--- a/ags/plugin/ags_lv2_uri_map_manager.c
+++ b/ags/plugin/ags_lv2_uri_map_manager.c
@@ -133,6 +133,9 @@ ags_lv2_uri_map_manager_finalize(GObject *gobject)
   lv2_uri_map_manager = AGS_LV2_URI_MAP_MANAGER(gobject);
 
   g_hash_table_destroy(lv2_uri_map_manager->uri_map);
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_lv2_uri_map_manager_parent_class)->finalize(gobject);
 }
 
 void
diff --git a/ags/plugin/ags_lv2_urid_manager.c b/ags/plugin/ags_lv2_urid_manager.c
index 472964e..354f4d7 100644
--- a/ags/plugin/ags_lv2_urid_manager.c
+++ b/ags/plugin/ags_lv2_urid_manager.c
@@ -134,6 +134,9 @@ ags_lv2_urid_manager_finalize(GObject *gobject)
   lv2_urid_manager = AGS_LV2_URID_MANAGER(gobject);
 
   g_hash_table_destroy(lv2_urid_manager->urid);
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_lv2_urid_manager_parent_class)->finalize(gobject);
 }
 
 void
diff --git a/ags/plugin/ags_lv2_worker.c b/ags/plugin/ags_lv2_worker.c
index fdddc0f..284d77d 100644
--- a/ags/plugin/ags_lv2_worker.c
+++ b/ags/plugin/ags_lv2_worker.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -121,21 +121,20 @@ void
 ags_lv2_worker_connect(AgsConnectable *connectable)
 {
   /* empty */
-
-  ags_lv2_worker_parent_connectable_interface->connect(connectable);
 }
 
 void
 ags_lv2_worker_disconnect(AgsConnectable *connectable)
 {
   /* empty */
-
-  ags_lv2_worker_parent_connectable_interface->disconnect(connectable);
 }
 
 void
 ags_lv2_worker_finalize(GObject *gobject)
 {
+  /* empty */
+
+  /* call parent */
   G_OBJECT_CLASS(ags_lv2_worker_parent_class)->finalize(gobject);
 }
 
@@ -193,9 +192,9 @@ ags_lv2_worker_interrupted_callback(AgsThread *thread,
     
     if((AGS_LV2_WORKER_RUN & (g_atomic_int_get(&(lv2_worker->flags)))) != 0){
 #ifdef AGS_PTHREAD_SUSPEND
-    pthread_suspend(thread->thread);
+      pthread_suspend(thread->thread);
 #else
-    pthread_kill(*(thread->thread), AGS_THREAD_SUSPEND_SIG);
+      pthread_kill(*(thread->thread), AGS_THREAD_SUSPEND_SIG);
 #endif
     }
   }
diff --git a/ags/plugin/ags_lv2_worker.h b/ags/plugin/ags_lv2_worker.h
index c6a8f42..e92dc1b 100644
--- a/ags/plugin/ags_lv2_worker.h
+++ b/ags/plugin/ags_lv2_worker.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/plugin/ags_lv2_worker_manager.c b/ags/plugin/ags_lv2_worker_manager.c
index 52d56bc..885f14b 100644
--- a/ags/plugin/ags_lv2_worker_manager.c
+++ b/ags/plugin/ags_lv2_worker_manager.c
@@ -130,6 +130,9 @@ void
 ags_lv2_worker_manager_finalize(GObject *gobject)
 {
   /* empty */
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_lv2_worker_manager_parent_class)->finalize(gobject);
 }
 
 GObject*
diff --git a/ags/plugin/ags_lv2ui_manager.c b/ags/plugin/ags_lv2ui_manager.c
index 6c703de..7f11264 100644
--- a/ags/plugin/ags_lv2ui_manager.c
+++ b/ags/plugin/ags_lv2ui_manager.c
@@ -34,10 +34,13 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <stdio.h>
+
 #include <ags/config.h>
 
 void ags_lv2ui_manager_class_init(AgsLv2uiManagerClass *lv2ui_manager);
 void ags_lv2ui_manager_init (AgsLv2uiManager *lv2ui_manager);
+void ags_lv2ui_manager_dispose(GObject *gobject);
 void ags_lv2ui_manager_finalize(GObject *gobject);
 
 /**
@@ -92,6 +95,7 @@ ags_lv2ui_manager_class_init(AgsLv2uiManagerClass *lv2ui_manager)
   /* GObjectClass */
   gobject = (GObjectClass *) lv2ui_manager;
 
+  gobject->dispose = ags_lv2ui_manager_dispose;
   gobject->finalize = ags_lv2ui_manager_finalize;
 }
 
@@ -110,9 +114,28 @@ ags_lv2ui_manager_init(AgsLv2uiManager *lv2ui_manager)
 }
 
 void
+ags_lv2ui_manager_dispose(GObject *gobject)
+{
+  AgsLv2uiManager *lv2ui_manager;
+
+  lv2ui_manager = AGS_LV2UI_MANAGER(gobject);
+
+  if(lv2ui_manager->lv2ui_plugin != NULL){
+    g_list_free_full(lv2ui_manager->lv2ui_plugin,
+		     g_object_unref);
+
+    lv2ui_manager->lv2ui_plugin = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_lv2ui_manager_parent_class)->dispose(gobject);
+}
+
+void
 ags_lv2ui_manager_finalize(GObject *gobject)
 {
   AgsLv2uiManager *lv2ui_manager;
+
   GList *lv2ui_plugin;
 
   lv2ui_manager = AGS_LV2UI_MANAGER(gobject);
@@ -121,6 +144,9 @@ ags_lv2ui_manager_finalize(GObject *gobject)
 
   g_list_free_full(lv2ui_plugin,
 		   g_object_unref);
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_lv2ui_manager_parent_class)->finalize(gobject);
 }
 
 /**
@@ -149,23 +175,23 @@ ags_lv2ui_manager_get_filenames(AgsLv2uiManager *lv2ui_manager)
   for(i = 0; lv2ui_plugin != NULL;){
     if(filenames == NULL){
       filenames = (gchar **) malloc(2 * sizeof(gchar *));
-      filenames[i] = AGS_BASE_PLUGIN(lv2ui_plugin->data)->filename;
+      filenames[i] = AGS_BASE_PLUGIN(lv2ui_plugin->data)->ui_filename;
       filenames[i + 1] = NULL;
 
       i++;
     }else{
 #ifdef HAVE_GLIB_2_44
       contains_filename = g_strv_contains(filenames,
-					  AGS_BASE_PLUGIN(lv2ui_plugin->data)->filename);
+					  AGS_BASE_PLUGIN(lv2ui_plugin->data)->ui_filename);
 #else
       contains_filename = ags_strv_contains(filenames,
-					    AGS_BASE_PLUGIN(lv2ui_plugin->data)->filename);
+					    AGS_BASE_PLUGIN(lv2ui_plugin->data)->ui_filename);
 #endif
       
       if(!contains_filename){
 	filenames = (gchar **) realloc(filenames,
 				       (i + 2) * sizeof(gchar *));
-	filenames[i] = AGS_BASE_PLUGIN(lv2ui_plugin->data)->filename;
+	filenames[i] = AGS_BASE_PLUGIN(lv2ui_plugin->data)->ui_filename;
 	filenames[i + 1] = NULL;
 	
 	i++;
@@ -181,10 +207,10 @@ ags_lv2ui_manager_get_filenames(AgsLv2uiManager *lv2ui_manager)
 /**
  * ags_lv2ui_manager_find_lv2ui_plugin:
  * @lv2ui_manager: the #AgsLv2uiManager
- * @filename: the filename of the plugin
- * @effect: the effect's name
+ * @ui_filename: the UI filename of the plugin
+ * @ui_effect: the UI effect's name
  *
- * Lookup filename in loaded plugins.
+ * Lookup UI filename in loaded plugins.
  *
  * Returns: the #AgsLv2uiPlugin-struct
  *
@@ -192,14 +218,57 @@ ags_lv2ui_manager_get_filenames(AgsLv2uiManager *lv2ui_manager)
  */
 AgsLv2uiPlugin*
 ags_lv2ui_manager_find_lv2ui_plugin(AgsLv2uiManager *lv2ui_manager,
-				    gchar *filename, gchar *effect)
+				    gchar *ui_filename, gchar *ui_effect)
+{
+  AgsLv2uiPlugin *lv2ui_plugin;
+  
+  GList *list;
+
+  if(ui_filename == NULL ||
+     ui_effect == NULL){
+    return(NULL);
+  }
+  
+  list = lv2ui_manager->lv2ui_plugin;
+  
+  while(list != NULL){
+    lv2ui_plugin = AGS_LV2UI_PLUGIN(list->data);
+    
+    if(!g_ascii_strcasecmp(AGS_BASE_PLUGIN(lv2ui_plugin)->ui_filename,
+			   ui_filename) &&
+       !g_ascii_strcasecmp(AGS_BASE_PLUGIN(lv2ui_plugin)->ui_effect,
+			   ui_effect)){
+      return(lv2ui_plugin);
+    }
+
+    list = list->next;
+  }
+
+  return(NULL);
+}
+
+/**
+ * ags_lv2ui_manager_find_lv2ui_plugin_with_index:
+ * @lv2ui_manager: the #AgsLv2uiManager
+ * @ui_filename: the UI filename of the plugin
+ * @ui_effect_index: the UI index
+ *
+ * Lookup @ui_filename with @ui_effect_index in loaded plugins.
+ *
+ * Returns: the #AgsLv2uiPlugin-struct
+ *
+ * Since: 0.7.127
+ */
+AgsLv2uiPlugin*
+ags_lv2ui_manager_find_lv2ui_plugin_with_index(AgsLv2uiManager *lv2ui_manager,
+					       gchar *ui_filename,
+					       guint ui_effect_index)
 {
   AgsLv2uiPlugin *lv2ui_plugin;
   
   GList *list;
 
-  if(filename == NULL ||
-     effect == NULL){
+  if(ui_filename == NULL){
     return(NULL);
   }
   
@@ -208,10 +277,9 @@ ags_lv2ui_manager_find_lv2ui_plugin(AgsLv2uiManager *lv2ui_manager,
   while(list != NULL){
     lv2ui_plugin = AGS_LV2UI_PLUGIN(list->data);
     
-    if(!g_ascii_strcasecmp(AGS_BASE_PLUGIN(lv2ui_plugin)->filename,
-			   filename) &&
-       !g_ascii_strcasecmp(AGS_BASE_PLUGIN(lv2ui_plugin)->effect,
-			   effect)){
+    if(!g_ascii_strcasecmp(AGS_BASE_PLUGIN(lv2ui_plugin)->ui_filename,
+			   ui_filename) &&
+       AGS_BASE_PLUGIN(lv2ui_plugin)->ui_effect_index == ui_effect_index){
       return(lv2ui_plugin);
     }
 
@@ -282,12 +350,6 @@ ags_lv2ui_manager_load_file(AgsLv2uiManager *lv2ui_manager,
   
   GError *error;
 
-  void *plugin_so;
-  LV2_Descriptor_Function lv2_descriptor;
-  LV2_Descriptor *plugin_descriptor;
-
-  uint32_t i;
-
   static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 
   auto void ags_lv2ui_manager_load_file_ui_plugin(GList *list);
@@ -296,13 +358,21 @@ ags_lv2ui_manager_load_file(AgsLv2uiManager *lv2ui_manager,
     GList *uri_list;
     GList *binary_list;
 
-    gchar *gui_filename;
+    gchar *ui_filename;
     gchar *str;
     gchar *path;
-    gchar *gui_path;
+    gchar *ui_path;
     gchar *xpath;
-    gchar *uri;
+    gchar *gui_uri;
+
+    guint ui_effect_index;
     
+    void *ui_plugin_so;
+    LV2UI_DescriptorFunction lv2ui_descriptor;
+    LV2UI_Descriptor *ui_plugin_descriptor;
+    
+    uint32_t i;
+
     if(list == NULL){
       return;
     }
@@ -314,7 +384,7 @@ ags_lv2ui_manager_load_file(AgsLv2uiManager *lv2ui_manager,
 							 xpath,
 							 list->data);
       
-      uri = NULL;
+      gui_uri = NULL;
   
       if(uri_list != NULL){
 	xmlNode *child;
@@ -326,11 +396,11 @@ ags_lv2ui_manager_load_file(AgsLv2uiManager *lv2ui_manager,
 	    if(!g_ascii_strncasecmp(child->name,
 				    "rdf-iriref\0",
 				    11)){
-	      uri = xmlNodeGetContent(child);
+	      gui_uri = xmlNodeGetContent(child);
 
-	      if(strlen(uri) > 2){
-		uri = g_strndup(uri + 1,
-				strlen(uri) - 2);
+	      if(strlen(gui_uri) > 2){
+		gui_uri = g_strndup(gui_uri + 1,
+				    strlen(gui_uri) - 2);
 	      }
 	      break;
 	    }else if(!g_ascii_strncasecmp(child->name,
@@ -357,7 +427,7 @@ ags_lv2ui_manager_load_file(AgsLv2uiManager *lv2ui_manager,
 		pname_node = pname_node->next;
 	      }
 
-	      uri = pname;
+	      gui_uri = pname;
 	    
 	      if(pname != NULL){
 		gchar *suffix, *prefix;
@@ -391,9 +461,9 @@ ags_lv2ui_manager_load_file(AgsLv2uiManager *lv2ui_manager,
 		    
 			tmp = g_strndup(iriref + 1,
 					strlen(iriref) - 2);
-			uri = g_strdup_printf("%s%s\0",
-					      tmp,
-					      suffix);
+			gui_uri = g_strdup_printf("%s%s\0",
+						  tmp,
+						  suffix);
 			free(tmp);
 		      }
 		  
@@ -412,7 +482,7 @@ ags_lv2ui_manager_load_file(AgsLv2uiManager *lv2ui_manager,
       }
 
       /* load plugin */
-      if(uri == NULL){
+      if(gui_uri == NULL){
 	list = list->next;
 
 	continue;
@@ -446,9 +516,9 @@ ags_lv2ui_manager_load_file(AgsLv2uiManager *lv2ui_manager,
 	  continue;
 	}
 	
-	gui_filename = g_strdup_printf("%s/%s\0",
-				       tmp,
-				       str);
+	ui_filename = g_strdup_printf("%s/%s\0",
+				      tmp,
+				      str);
 	free(str);
 
 	break;
@@ -458,11 +528,70 @@ ags_lv2ui_manager_load_file(AgsLv2uiManager *lv2ui_manager,
 			     lv2ui_path,
 			     filename);
       
-      gui_path = g_strdup_printf("%s/%s\0",
-				 lv2ui_path,
-				 gui_filename);
+      ui_path = g_strdup_printf("%s/%s\0",
+				lv2ui_path,
+				ui_filename);
       
-      g_message("lv2ui check - %s\0", gui_path);
+      g_message("lv2ui check - %s\0", ui_path);
+
+      /* get gui_uri index and append plugin */
+      ui_plugin_so = dlopen(ui_path,
+			    RTLD_NOW);
+  
+      if(ui_plugin_so == NULL){
+	g_warning("ags_lv2ui_manager.c - failed to load static object file\0");
+    
+	dlerror();
+
+	list = list->next;
+      
+	continue;
+      }
+
+      lv2ui_descriptor = (LV2UI_DescriptorFunction) dlsym(ui_plugin_so,
+							  "lv2ui_descriptor\0");
+  
+      if(dlerror() == NULL && lv2ui_descriptor){
+	for(i = 0; (ui_plugin_descriptor = lv2ui_descriptor(i)) != NULL; i++){
+	  if(ui_path != NULL &&
+	     gui_uri != NULL &&
+	     !g_ascii_strcasecmp(ui_plugin_descriptor->URI,
+				 gui_uri)){
+	    ui_effect_index = i;
+	    
+	    /* check if already added */
+	    lv2ui_plugin = ags_lv2ui_manager_find_lv2ui_plugin_with_index(lv2ui_manager,
+									  ui_path,
+									  ui_effect_index);
+
+	    if(lv2ui_plugin != NULL){
+	      break;
+	    }
+
+	    if(ags_base_plugin_find_ui_effect_index(lv2ui_manager->lv2ui_plugin,
+						    ui_path,
+						    ui_effect_index) == NULL){
+	      g_message("ags_lv2ui_manager.c loading - %s %s with ui-effect-index %u\0",
+			ui_path,
+			turtle->filename,
+			ui_effect_index);
+
+	      lv2ui_plugin = g_object_new(AGS_TYPE_LV2UI_PLUGIN,
+					  "gui-uri\0", gui_uri,
+					  "manifest\0", manifest,
+					  "gui-turtle\0", turtle,
+					  "ui-filename\0", ui_path,
+					  "ui-effect-index\0", ui_effect_index,
+					  NULL);
+	      ags_base_plugin_load_plugin((AgsBasePlugin *) lv2ui_plugin);
+	      lv2ui_manager->lv2ui_plugin = g_list_prepend(lv2ui_manager->lv2ui_plugin,
+							   lv2ui_plugin);
+	    }
+	  
+	    break;
+	  }
+	}  
+      }
       
       list = list->next;
     }    
diff --git a/ags/plugin/ags_lv2ui_manager.h b/ags/plugin/ags_lv2ui_manager.h
index 9478bbf..ca34f22 100644
--- a/ags/plugin/ags_lv2ui_manager.h
+++ b/ags/plugin/ags_lv2ui_manager.h
@@ -62,6 +62,9 @@ gchar** ags_lv2ui_manager_get_filenames(AgsLv2uiManager *lv2ui_manager);
 AgsLv2uiPlugin* ags_lv2ui_manager_find_lv2ui_plugin(AgsLv2uiManager *lv2ui_manager,
 						    gchar *filename,
 						    gchar *effect);
+AgsLv2uiPlugin* ags_lv2ui_manager_find_lv2ui_plugin_with_index(AgsLv2uiManager *lv2ui_manager,
+							       gchar *filename,
+							       guint index);
 
 void ags_lv2ui_manager_load_blacklist(AgsLv2uiManager *lv2ui_manager,
 				      gchar *blacklist_filename);
diff --git a/ags/plugin/ags_lv2ui_plugin.c b/ags/plugin/ags_lv2ui_plugin.c
index 6c8b4ba..cedf0bb 100644
--- a/ags/plugin/ags_lv2ui_plugin.c
+++ b/ags/plugin/ags_lv2ui_plugin.c
@@ -42,6 +42,7 @@ void ags_lv2ui_plugin_get_property(GObject *gobject,
 				   guint prop_id,
 				   GValue *value,
 				   GParamSpec *param_spec);
+void ags_lv2ui_plugin_dispose(GObject *gobject);
 void ags_lv2ui_plugin_finalize(GObject *gobject);
 
 gpointer ags_lv2ui_plugin_instantiate(AgsBasePlugin *base_plugin,
@@ -124,31 +125,16 @@ ags_lv2ui_plugin_class_init(AgsLv2uiPluginClass *lv2ui_plugin)
   gobject->set_property = ags_lv2ui_plugin_set_property;
   gobject->get_property = ags_lv2ui_plugin_get_property;
 
+  gobject->dispose = ags_lv2ui_plugin_dispose;
   gobject->finalize = ags_lv2ui_plugin_finalize;
 
   /* properties */
   /**
-   * AgsLv2uiPlugin:gui-filename:
-   *
-   * The assigned GUI filename.
-   * 
-   * Since: 1.0.0
-   */
-  param_spec = g_param_spec_string("gui-filename\0",
-				   "GUI filename of the plugin\0",
-				   "The GUI filename this plugin is located in\0",
-				   NULL,
-				   G_PARAM_READABLE | G_PARAM_WRITABLE);
-  g_object_class_install_property(gobject,
-				  PROP_GUI_FILENAME,
-				  param_spec);
-
-  /**
    * AgsLv2uiPlugin:gui-uri:
    *
    * The assigned GUI URI.
    * 
-   * Since: 1.0.0
+   * Since: 0.7.127
    */
   param_spec = g_param_spec_string("gui-uri\0",
 				   "GUI URI of the plugin\0",
@@ -180,7 +166,7 @@ ags_lv2ui_plugin_class_init(AgsLv2uiPluginClass *lv2ui_plugin)
    *
    * The assigned GUI turtle.
    * 
-   * Since: 1.0.0
+   * Since: 0.7.127
    */
   param_spec = g_param_spec_object("gui-turtle\0",
 				   "GUI turtle of the plugin\0",
@@ -196,7 +182,7 @@ ags_lv2ui_plugin_class_init(AgsLv2uiPluginClass *lv2ui_plugin)
    *
    * The assigned LV2 plugin.
    * 
-   * Since: 1.0.0
+   * Since: 0.7.127
    */
   param_spec = g_param_spec_object("lv2-plugin\0",
 				   "LV2 plugin of the plugin\0",
@@ -218,8 +204,6 @@ ags_lv2ui_plugin_init(AgsLv2uiPlugin *lv2ui_plugin)
 {
   lv2ui_plugin->flags = 0;
 
-  lv2ui_plugin->gui_filename = NULL;
-
   lv2ui_plugin->gui_uri = NULL;
 
   lv2ui_plugin->manifest = NULL;
@@ -239,23 +223,6 @@ ags_lv2ui_plugin_set_property(GObject *gobject,
   lv2ui_plugin = AGS_LV2UI_PLUGIN(gobject);
 
   switch(prop_id){
-  case PROP_GUI_FILENAME:
-    {
-      gchar *gui_filename;
-
-      gui_filename = (gchar *) g_value_get_string(value);
-
-      if(lv2ui_plugin->gui_filename == gui_filename){
-	return;
-      }
-      
-      if(lv2ui_plugin->gui_filename != NULL){
-	g_free(lv2ui_plugin->gui_filename);
-      }
-
-      lv2ui_plugin->gui_filename = g_strdup(gui_filename);
-    }
-    break;
   case PROP_GUI_URI:
     {
       gchar *gui_uri;
@@ -353,11 +320,6 @@ ags_lv2ui_plugin_get_property(GObject *gobject,
   lv2ui_plugin = AGS_LV2UI_PLUGIN(gobject);
 
   switch(prop_id){
-  case PROP_GUI_FILENAME:
-    {
-      g_value_set_string(value, lv2ui_plugin->gui_filename);
-    }
-    break;
   case PROP_GUI_URI:
     {
       g_value_set_string(value, lv2ui_plugin->gui_uri);
@@ -385,6 +347,35 @@ ags_lv2ui_plugin_get_property(GObject *gobject,
 }
 
 void
+ags_lv2ui_plugin_dispose(GObject *gobject)
+{
+  AgsLv2uiPlugin *lv2ui_plugin;
+
+  lv2ui_plugin = AGS_LV2UI_PLUGIN(gobject);
+
+  if(lv2ui_plugin->manifest != NULL){
+    g_object_unref(lv2ui_plugin->manifest);
+
+    lv2ui_plugin->manifest = NULL;
+  }
+
+  if(lv2ui_plugin->gui_turtle != NULL){
+    g_object_unref(lv2ui_plugin->gui_turtle);
+
+    lv2ui_plugin->gui_turtle = NULL;
+  }
+
+  if(lv2ui_plugin->lv2_plugin != NULL){
+    g_object_unref(lv2ui_plugin->lv2_plugin);
+
+    lv2ui_plugin->lv2_plugin = NULL;
+  }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_lv2ui_plugin_parent_class)->dispose(gobject);
+}
+
+void
 ags_lv2ui_plugin_finalize(GObject *gobject)
 {
   AgsLv2uiPlugin *lv2ui_plugin;
@@ -404,11 +395,47 @@ ags_lv2ui_plugin_finalize(GObject *gobject)
   if(lv2ui_plugin->lv2_plugin != NULL){
     g_object_unref(lv2ui_plugin->lv2_plugin);
   }
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_lv2ui_plugin_parent_class)->finalize(gobject);
 }
 
 void
 ags_lv2ui_plugin_load_plugin(AgsBasePlugin *base_plugin)
 {
+  //TODO:JK: implement me  
+}
+
+/**
+ * ags_lv2ui_plugin_find_gui_uri:
+ * @lv2ui_plugin: the #GList-struct containing #AgsLv2uiPlugin
+ * @gui_uri: the gui-uri as string
+ * 
+ * Find next matching gui-uri in @lv2ui_plugin.
+ * 
+ * Returns: the next matching #GList-struct
+ * 
+ * Since: 0.7.127
+ */
+GList*
+ags_lv2ui_plugin_find_gui_uri(GList *lv2ui_plugin,
+			      gchar *gui_uri)
+{
+  if(gui_uri == NULL){
+    return(NULL);
+  }
+  
+  while(lv2ui_plugin != NULL){
+    if(AGS_LV2UI_PLUGIN(lv2ui_plugin->data)->gui_uri != NULL &&
+       !g_ascii_strcasecmp(AGS_LV2UI_PLUGIN(lv2ui_plugin->data)->gui_uri,
+			   gui_uri)){
+      return(lv2ui_plugin);
+    }
+
+    lv2ui_plugin = lv2ui_plugin->next;
+  }
+
+  return(NULL);
 }
 
 /**
diff --git a/ags/plugin/ags_lv2ui_plugin.h b/ags/plugin/ags_lv2ui_plugin.h
index 840389a..b2ab5ec 100644
--- a/ags/plugin/ags_lv2ui_plugin.h
+++ b/ags/plugin/ags_lv2ui_plugin.h
@@ -53,8 +53,6 @@ struct _AgsLv2uiPlugin
 
   guint flags;
 
-  gchar *gui_filename;
-  
   gchar *gui_uri;
 
   AgsTurtle *manifest;
@@ -70,6 +68,9 @@ struct _AgsLv2uiPluginClass
 
 GType ags_lv2ui_plugin_get_type(void);
 
+GList* ags_lv2ui_plugin_find_gui_uri(GList *lv2ui_plugin,
+				     gchar *gui_uri);
+
 AgsLv2uiPlugin* ags_lv2ui_plugin_new(AgsTurtle *gui_turtle, gchar *filename, gchar *effect, gchar *gui_uri, guint effect_index);
 
 #endif /*__AGS_LV2UI_PLUGIN_H__*/
diff --git a/ags/test/X/ags_functional_machine_add_and_destroy_test.c b/ags/test/X/ags_functional_machine_add_and_destroy_test.c
new file mode 100644
index 0000000..1cfefcb
--- /dev/null
+++ b/ags/test/X/ags_functional_machine_add_and_destroy_test.c
@@ -0,0 +1,365 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
+
+#include <ags/gsequencer_main.h>
+
+#include <ags/test/X/libgsequencer.h>
+
+#include "gsequencer_setup_util.h"
+#include "ags_functional_test_util.h"
+
+int ags_functional_machine_add_and_destroy_test_init_suite();
+int ags_functional_machine_add_and_destroy_test_clean_suite();
+
+void ags_functional_machine_add_and_destroy_test_panel();
+void ags_functional_machine_add_and_destroy_test_mixer();
+void ags_functional_machine_add_and_destroy_test_drum();
+void ags_functional_machine_add_and_destroy_test_matrix();
+void ags_functional_machine_add_and_destroy_test_synth();
+void ags_functional_machine_add_and_destroy_test_ffplayer();
+
+#define AGS_FUNCTIONAL_MACHINE_ADD_AND_DESTROY_TEST_CONFIG "[generic]\n" \
+  "autosave-thread=false\n"			       \
+  "simple-file=true\n"				       \
+  "disable-feature=experimental\n"		       \
+  "segmentation=4/4\n"				       \
+  "\n"						       \
+  "[thread]\n"					       \
+  "model=super-threaded\n"			       \
+  "super-threaded-scope=channel\n"		       \
+  "lock-global=ags-thread\n"			       \
+  "lock-parent=ags-recycling-thread\n"		       \
+  "\n"						       \
+  "[soundcard-0]\n"				       \
+  "backend=alsa\n"                                     \
+  "device=hw:0,0\n"                                    \
+  "samplerate=44100\n"				       \
+  "buffer-size=1024\n"				       \
+  "pcm-channels=2\n"				       \
+  "dsp-channels=2\n"				       \
+  "format=16\n"					       \
+  "\n"						       \
+  "[recall]\n"					       \
+  "auto-sense=true\n"				       \
+  "\n"
+
+extern AgsApplicationContext *ags_application_context;
+
+extern struct sigaction ags_test_sigact;
+
+extern volatile gboolean ags_show_start_animation;
+
+AgsGuiThread *gui_thread;
+
+
+/* The suite initialization function.
+ * Opens the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_machine_add_and_destroy_test_init_suite()
+{
+  AgsConfig *config;
+
+  config = ags_config_get_instance();
+  ags_config_load_from_data(config,
+			    AGS_FUNCTIONAL_MACHINE_ADD_AND_DESTROY_TEST_CONFIG,
+			    strlen(AGS_FUNCTIONAL_MACHINE_ADD_AND_DESTROY_TEST_CONFIG));
+
+  ags_functional_test_util_setup_and_launch();
+
+  /* get gui thread */
+  gui_thread = ags_thread_find_type(ags_application_context->main_loop,
+				    AGS_TYPE_GUI_THREAD);
+    
+  return(0);
+}
+
+/* The suite cleanup function.
+ * Closes the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_machine_add_and_destroy_test_clean_suite()
+{  
+  ags_thread_stop(gui_thread);  
+
+  return(0);
+}
+
+void
+ags_functional_machine_add_and_destroy_test_panel()
+{  
+  gboolean success;
+  
+  /* add panel */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Panel");
+
+  CU_ASSERT(success == TRUE);
+
+  ags_functional_test_util_idle();
+
+  /* destroy panel */
+  success = ags_functional_test_util_machine_destroy(0);
+  
+  CU_ASSERT(success == TRUE);
+}
+
+void
+ags_functional_machine_add_and_destroy_test_mixer()
+{
+  gboolean success;
+
+  /* add mixer */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Mixer");
+
+  CU_ASSERT(success == TRUE);
+
+  /* destroy mixer */
+  success = ags_functional_test_util_machine_destroy(0);
+  
+  CU_ASSERT(success == TRUE);
+}
+
+void
+ags_functional_machine_add_and_destroy_test_drum()
+{
+  gboolean success;
+
+  /* add drum */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Drum");
+
+  CU_ASSERT(success == TRUE);
+
+  /* destroy drum */
+  success = ags_functional_test_util_machine_destroy(0);
+  
+  CU_ASSERT(success == TRUE);
+}
+
+void
+ags_functional_machine_add_and_destroy_test_matrix()
+{
+  gboolean success;
+
+  /* add matrix */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Matrix");
+
+  CU_ASSERT(success == TRUE);
+
+  /* destroy matrix */
+  success = ags_functional_test_util_machine_destroy(0);
+  
+  CU_ASSERT(success == TRUE);
+}
+
+void
+ags_functional_machine_add_and_destroy_test_synth()
+{
+  gboolean success;
+
+  /* add synth */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Synth");
+
+  CU_ASSERT(success == TRUE);
+
+  /* destroy synth */
+  success = ags_functional_test_util_machine_destroy(0);
+  
+  CU_ASSERT(success == TRUE);
+}
+
+void
+ags_functional_machine_add_and_destroy_test_ffplayer()
+{
+  gboolean success;
+
+  /* add fplayer */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "FPlayer");
+
+  CU_ASSERT(success == TRUE);
+
+  /* destroy fplayer */
+  success = ags_functional_test_util_machine_destroy(0);
+  
+  CU_ASSERT(success == TRUE);
+}
+
+int
+main(int argc, char **argv)
+{
+  CU_pSuite pSuite = NULL;
+
+  AgsConfig *config;
+
+  pthread_t *animation_thread;
+
+  struct sched_param param;
+  struct rlimit rl;
+  struct sigaction sa;
+
+  gchar *rc_filename;
+  
+  int result;
+
+  const rlim_t kStackSize = 64L * 1024L * 1024L;   // min stack size = 64 Mb
+
+#ifdef AGS_USE_TIMER
+  timer_t *timer_id
+#endif
+  
+  putenv("LC_ALL=C\0");
+  putenv("LANG=C\0");
+
+  //  mtrace();
+  atexit(ags_test_signal_cleanup);
+
+  result = getrlimit(RLIMIT_STACK, &rl);
+
+  /* set stack size 64M */
+  if(result == 0){
+    if(rl.rlim_cur < kStackSize){
+      rl.rlim_cur = kStackSize;
+      result = setrlimit(RLIMIT_STACK, &rl);
+
+      if(result != 0){
+	//TODO:JK
+      }
+    }
+  }
+
+  param.sched_priority = GSEQUENCER_RT_PRIORITY;
+      
+  if(sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
+    perror("sched_setscheduler failed\0");
+  }
+
+  /* Ignore interactive and job-control signals.  */
+  signal(SIGINT, SIG_IGN);
+  signal(SIGQUIT, SIG_IGN);
+  signal(SIGTSTP, SIG_IGN);
+  signal(SIGTTIN, SIG_IGN);
+  signal(SIGTTOU, SIG_IGN);
+  signal(SIGCHLD, SIG_IGN);
+  signal(AGS_THREAD_RESUME_SIG, SIG_IGN);
+  signal(AGS_THREAD_SUSPEND_SIG, SIG_IGN);
+
+  ags_test_sigact.sa_handler = ags_test_signal_handler;
+  sigemptyset(&ags_test_sigact.sa_mask);
+  ags_test_sigact.sa_flags = 0;
+  sigaction(SIGINT, &ags_test_sigact, (struct sigaction *) NULL);
+  sigaction(SA_RESTART, &ags_test_sigact, (struct sigaction *) NULL);
+
+  XInitThreads();
+      
+  /* parse rc file */
+  rc_filename = g_strdup_printf("%s/%s\0",
+				SRCDIR,
+				"gsequencer.share/styles/ags.rc\0");
+  
+  gtk_rc_parse(rc_filename);
+  g_free(rc_filename);
+  
+  /**/
+  LIBXML_TEST_VERSION;
+
+  //ao_initialize();
+
+  gdk_threads_enter();
+  //  g_thread_init(NULL);
+  gtk_init(&argc, &argv);
+
+  g_object_set(gtk_settings_get_default(),
+	       "gtk-theme-name\0", "Raleigh\0",
+	       NULL);
+  g_signal_handlers_block_matched(gtk_settings_get_default(),
+				  G_SIGNAL_MATCH_DETAIL,
+				  g_signal_lookup("set-property\0",
+						  GTK_TYPE_SETTINGS),
+				  g_quark_from_string("gtk-theme-name\0"),
+				  NULL,
+				  NULL,
+				  NULL);
+  
+  ipatch_init();
+  //  g_log_set_fatal_mask("GLib-GObject\0", // "Gtk\0" G_LOG_DOMAIN, // 
+		       //		       G_LOG_LEVEL_CRITICAL); // G_LOG_LEVEL_WARNING
+
+  /* animate */
+  animation_thread = (pthread_t *) malloc(sizeof(pthread_t));
+  g_atomic_int_set(&(ags_show_start_animation),
+		   TRUE);
+  
+  ags_test_start_animation(animation_thread);
+  
+  /* initialize the CUnit test registry */
+  if(CUE_SUCCESS != CU_initialize_registry()){
+    return CU_get_error();
+  }
+
+  /* add a suite to the registry */
+  pSuite = CU_add_suite("AgsFuncitonalMachineAddAndDestroyTest\0", ags_functional_machine_add_and_destroy_test_init_suite, ags_functional_machine_add_and_destroy_test_clean_suite);
+  
+  if(pSuite == NULL){
+    CU_cleanup_registry();
+    
+    return CU_get_error();
+  }
+
+  gtk_init(NULL,
+	   NULL);
+  //  g_log_set_fatal_mask(G_LOG_DOMAIN, // , // "Gtk\0" G_LOG_DOMAIN,"GLib-GObject\0",
+  //		       G_LOG_LEVEL_CRITICAL);
+
+  /* add the tests to the suite */
+  if((CU_add_test(pSuite, "functional test of GSequencer machine add and destroy AgsPanel\0", ags_functional_machine_add_and_destroy_test_panel) == NULL) ||
+     (CU_add_test(pSuite, "functional test of GSequencer machine add and destroy AgsMixer\0", ags_functional_machine_add_and_destroy_test_mixer) == NULL) ||
+     (CU_add_test(pSuite, "functional test of GSequencer machine add and destroy AgsDrum\0", ags_functional_machine_add_and_destroy_test_drum) == NULL) ||
+     (CU_add_test(pSuite, "functional test of GSequencer machine add and destroy AgsMatrix\0", ags_functional_machine_add_and_destroy_test_matrix) == NULL) ||
+     (CU_add_test(pSuite, "functional test of GSequencer machine add and destroy AgsSynth\0", ags_functional_machine_add_and_destroy_test_synth) == NULL) ||
+     (CU_add_test(pSuite, "functional test of GSequencer machine add and destroy AgsFFPlayer\0", ags_functional_machine_add_and_destroy_test_ffplayer) == NULL)){
+    CU_cleanup_registry();
+      
+    return CU_get_error();
+  }
+  
+  /* Run all tests using the CUnit Basic interface */
+  CU_basic_set_mode(CU_BRM_VERBOSE);
+  CU_basic_run_tests();
+  
+  CU_cleanup_registry();
+  
+  return(CU_get_error());
+}
+
diff --git a/ags/test/X/ags_functional_note_edit_test.c b/ags/test/X/ags_functional_note_edit_test.c
new file mode 100644
index 0000000..dca1940
--- /dev/null
+++ b/ags/test/X/ags_functional_note_edit_test.c
@@ -0,0 +1,335 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
+
+#include <ags/gsequencer_main.h>
+
+#include <ags/X/ags_xorg_application_context.h>
+
+#include <ags/X/thread/ags_gui_thread.h>
+
+#include "gsequencer_setup_util.h"
+
+int ags_functional_note_edit_test_init_suite();
+int ags_functional_note_edit_test_clean_suite();
+
+void ags_functional_note_edit_test_quit_stub(AgsApplicationContext *application_context);
+
+void ags_functional_note_edit_test_note_file_setup();
+
+#define AGS_FUNCTIONAL_NOTE_EDIT_TEST_FILE_SETUP_FILENAME SRCDIR "/" "ags_functional_note_edit_test.xml\0"
+#define AGS_FUNCTIONAL_NOTE_EDIT_TEST_FILE_SETUP_PLAYBACK_COUNT (3)
+#define AGS_FUNCTIONAL_NOTE_EDIT_TEST_FILE_SETUP_PLAYBACK_DURATION (30)
+
+#define AGS_FUNCTIONAL_NOTE_EDIT_TEST_CONFIG "[generic]\n" \
+  "autosave-thread=false\n"			       \
+  "simple-file=true\n"				       \
+  "disable-feature=experimental\n"		       \
+  "segmentation=4/4\n"				       \
+  "\n"						       \
+  "[thread]\n"					       \
+  "model=super-threaded\n"			       \
+  "super-threaded-scope=channel\n"		       \
+  "lock-global=ags-thread\n"			       \
+  "lock-parent=ags-recycling-thread\n"		       \
+  "\n"						       \
+  "[soundcard-0]\n"				       \
+  "backend=alsa\n"                                     \
+  "device=hw:0,0\n"                                    \
+  "samplerate=44100\n"				       \
+  "buffer-size=1024\n"				       \
+  "pcm-channels=2\n"				       \
+  "dsp-channels=2\n"				       \
+  "format=16\n"					       \
+  "\n"						       \
+  "[recall]\n"					       \
+  "auto-sense=true\n"				       \
+  "\n"
+
+extern struct sigaction ags_test_sigact;
+
+extern AgsApplicationContext *ags_application_context;
+extern volatile gboolean ags_show_start_animation;
+
+/* The suite initialization function.
+ * Opens the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_note_edit_test_init_suite()
+{
+  AgsConfig *config;
+
+  config = ags_config_get_instance();
+  ags_config_load_from_data(config,
+			    AGS_FUNCTIONAL_NOTE_EDIT_TEST_CONFIG,
+			    strlen(AGS_FUNCTIONAL_NOTE_EDIT_TEST_CONFIG));
+    
+  return(0);
+}
+
+/* The suite cleanup function.
+ * Closes the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_note_edit_test_clean_suite()
+{  
+  return(0);
+}
+
+void
+ags_functional_note_edit_test_quit_stub(AgsApplicationContext *application_context)
+{
+  g_critical("quit stub\0");
+}
+
+void
+ags_functional_note_edit_test_file_setup()
+{
+  GtkButton *play_button;
+  GtkButton *stop_button;
+  
+  AgsGuiThread *gui_thread;
+  
+  struct timespec start_time, current_time;
+
+  gchar *start_arg[] = {
+    "./gsequencer\0"
+  };
+  
+  guint i;
+  gboolean expired;
+  gboolean success;
+  
+  ags_application_context = NULL;
+
+  ags_test_setup(1, start_arg);
+
+  AGS_APPLICATION_CONTEXT_GET_CLASS(ags_application_context)->quit = ags_functional_note_edit_test_quit_stub;
+
+  /* get gui thread */
+  gui_thread = ags_thread_find_type(ags_application_context->main_loop,
+				    AGS_TYPE_GUI_THREAD);
+
+  /* get buttons */
+  play_button = AGS_XORG_APPLICATION_CONTEXT(ags_application_context)->window->navigation->play;
+  stop_button = AGS_XORG_APPLICATION_CONTEXT(ags_application_context)->window->navigation->stop;
+
+  /* launch application */
+  ags_test_launch_filename(AGS_FUNCTIONAL_NOTE_EDIT_TEST_FILE_SETUP_FILENAME,
+			   FALSE);
+
+  /* get initial time */
+  clock_gettime(CLOCK_MONOTONIC, &start_time);
+  success = TRUE;
+  
+  /* do the work */
+  while(g_atomic_int_get(&(AGS_XORG_APPLICATION_CONTEXT(ags_application_context)->gui_ready)) == 0){
+    usleep(500000);
+  }
+
+  usleep(10000000);
+  
+  for(i = 0; success && i < AGS_FUNCTIONAL_NOTE_EDIT_TEST_FILE_SETUP_PLAYBACK_COUNT; i++){
+    expired = FALSE;
+    
+    g_message("start playback");
+    gtk_button_clicked(play_button);
+
+    while(!expired){  
+      /* check expired */
+      clock_gettime(CLOCK_MONOTONIC, &current_time);
+      
+      if(start_time.tv_sec + AGS_FUNCTIONAL_NOTE_EDIT_TEST_FILE_SETUP_PLAYBACK_DURATION < current_time.tv_sec){
+	expired = TRUE;
+      }
+    }
+
+    g_message("stop playback");
+    gtk_button_clicked(stop_button);
+
+    /* wait some time before next playback */
+    usleep(5000000);
+
+    if(!expired){
+      success = FALSE;
+    }
+  }
+
+  ags_thread_stop(gui_thread);
+  
+  CU_ASSERT(success == TRUE);
+}
+
+int
+main(int argc, char **argv)
+{
+  CU_pSuite pSuite = NULL;
+
+  AgsConfig *config;
+
+  pthread_t *animation_thread;
+
+  struct sched_param param;
+  struct rlimit rl;
+  struct sigaction sa;
+  struct passwd *pw;
+
+  gchar *rc_filename;
+  
+  uid_t uid;
+  int result;
+
+  const rlim_t kStackSize = 64L * 1024L * 1024L;   // min stack size = 64 Mb
+
+#ifdef AGS_USE_TIMER
+  timer_t *timer_id
+#endif
+  
+  putenv("LC_ALL=C\0");
+  putenv("LANG=C\0");
+
+  //  mtrace();
+  atexit(ags_test_signal_cleanup);
+
+  result = getrlimit(RLIMIT_STACK, &rl);
+
+  /* set stack size 64M */
+  if(result == 0){
+    if(rl.rlim_cur < kStackSize){
+      rl.rlim_cur = kStackSize;
+      result = setrlimit(RLIMIT_STACK, &rl);
+
+      if(result != 0){
+	//TODO:JK
+      }
+    }
+  }
+
+  param.sched_priority = GSEQUENCER_RT_PRIORITY;
+      
+  if(sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
+    perror("sched_setscheduler failed\0");
+  }
+
+  /* Ignore interactive and job-control signals.  */
+  signal(SIGINT, SIG_IGN);
+  signal(SIGQUIT, SIG_IGN);
+  signal(SIGTSTP, SIG_IGN);
+  signal(SIGTTIN, SIG_IGN);
+  signal(SIGTTOU, SIG_IGN);
+  signal(SIGCHLD, SIG_IGN);
+  signal(AGS_THREAD_RESUME_SIG, SIG_IGN);
+  signal(AGS_THREAD_SUSPEND_SIG, SIG_IGN);
+
+  ags_test_sigact.sa_handler = ags_test_signal_handler;
+  sigemptyset(&ags_test_sigact.sa_mask);
+  ags_test_sigact.sa_flags = 0;
+  sigaction(SIGINT, &ags_test_sigact, (struct sigaction *) NULL);
+  sigaction(SA_RESTART, &ags_test_sigact, (struct sigaction *) NULL);
+
+  XInitThreads();
+  
+  uid = getuid();
+  pw = getpwuid(uid);
+    
+  /* parse rc file */
+  rc_filename = g_strdup_printf("gsequencer.share/styles/ags.rc\0",
+				pw->pw_dir,
+				AGS_DEFAULT_DIRECTORY);
+  
+  gtk_rc_parse(rc_filename);
+  g_free(rc_filename);
+  
+  /**/
+  LIBXML_TEST_VERSION;
+
+  //ao_initialize();
+
+  gdk_threads_enter();
+  //  g_thread_init(NULL);
+  gtk_init(&argc, &argv);
+
+  g_object_set(gtk_settings_get_default(),
+	       "gtk-theme-name\0", "Raleigh\0",
+	       NULL);
+  g_signal_handlers_block_matched(gtk_settings_get_default(),
+				  G_SIGNAL_MATCH_DETAIL,
+				  g_signal_lookup("set-property\0",
+						  GTK_TYPE_SETTINGS),
+				  g_quark_from_string("gtk-theme-name\0"),
+				  NULL,
+				  NULL,
+				  NULL);
+  
+  ipatch_init();
+  //  g_log_set_fatal_mask("GLib-GObject\0", // "Gtk\0" G_LOG_DOMAIN, // 
+		       //		       G_LOG_LEVEL_CRITICAL); // G_LOG_LEVEL_WARNING
+
+  /* animate */
+  animation_thread = (pthread_t *) malloc(sizeof(pthread_t));
+  g_atomic_int_set(&(ags_show_start_animation),
+		   TRUE);
+  
+  ags_test_start_animation(animation_thread);
+  
+  /* initialize the CUnit test registry */
+  if(CUE_SUCCESS != CU_initialize_registry()){
+    return CU_get_error();
+  }
+
+  /* add a suite to the registry */
+  pSuite = CU_add_suite("AgsFuncitonalNoteEditTest\0", ags_functional_note_edit_test_init_suite, ags_functional_note_edit_test_clean_suite);
+  
+  if(pSuite == NULL){
+    CU_cleanup_registry();
+    
+    return CU_get_error();
+  }
+
+  gtk_init(NULL,
+	   NULL);
+  //  g_log_set_fatal_mask(G_LOG_DOMAIN, // "GLib-GObject\0", // "Gtk\0" G_LOG_DOMAIN,
+  //		       G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
+
+  /* add the tests to the suite */
+  if((CU_add_test(pSuite, "functional test of GSequencer setup by file and editing notes\0", ags_functional_note_edit_test_file_setup) == NULL)){
+    CU_cleanup_registry();
+      
+    return CU_get_error();
+  }
+  
+  /* Run all tests using the CUnit Basic interface */
+  CU_basic_set_mode(CU_BRM_VERBOSE);
+  CU_basic_run_tests();
+  
+  CU_cleanup_registry();
+  
+  return(CU_get_error());
+}
+
diff --git a/ags/test/X/ags_functional_test_util.c b/ags/test/X/ags_functional_test_util.c
new file mode 100644
index 0000000..7cdd3e0
--- /dev/null
+++ b/ags/test/X/ags_functional_test_util.c
@@ -0,0 +1,2559 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/test/X/ags_functional_test_util.h>
+
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
+
+#include <ags/thread/ags_mutex_manager.h>
+
+#include <ags/plugin/ags_ladspa_manager.h>
+
+#include <ags/gsequencer_main.h>
+
+#include <ags/test/X/libgsequencer.h>
+
+#include <gdk/gdk.h>
+#include <gdk/gdkevents.h>
+
+#define AGS_FUNCTIONAL_TEST_UTIL_REACTION_TIME (4000)
+
+extern AgsApplicationContext *ags_application_context;
+
+extern AgsMutexManager *ags_mutex_manager;
+
+extern AgsLadspaManager *ags_ladspa_manager;
+extern AgsDssiManager *ags_dssi_manager;
+extern AgsLv2Manager *ags_lv2_manager;
+extern AgsLv2uiManager *ags_lv2ui_manager;
+
+AgsTaskThread *task_thread;
+AgsGuiThread *gui_thread;
+
+void
+ags_functional_test_util_clear_application_context()
+{  
+  ags_application_context = NULL;
+
+  //  ags_mutex_manager = NULL;
+
+  //  ags_ladspa_manager = NULL;
+  //  ags_dssi_manager = NULL;
+  //  ags_lv2_manager = NULL;
+  //  ags_lv2ui_manager = NULL;
+}
+
+void
+ags_functional_test_util_setup_and_launch()
+{
+  gchar *start_arg[] = {
+    "./gsequencer\0"
+  };
+
+  gboolean success;
+
+  ags_functional_test_util_clear_application_context();
+  
+  ags_test_setup(1, start_arg);
+
+  /* get gui thread */
+  gui_thread = ags_thread_find_type(ags_application_context->main_loop,
+				    AGS_TYPE_GUI_THREAD);
+
+  task_thread = ags_thread_find_type(ags_application_context->main_loop,
+				     AGS_TYPE_TASK_THREAD);
+
+  /* launch application */
+  ags_test_launch(FALSE);
+
+  /* do the work */
+  while(g_atomic_int_get(&(AGS_XORG_APPLICATION_CONTEXT(ags_application_context)->gui_ready)) == 0){
+    usleep(500000);
+  }
+
+  usleep(10000000);
+}
+
+void
+ags_functional_test_util_idle()
+{
+  usleep(5000000);
+}
+
+GtkMenu*
+ags_functional_test_util_submenu_find(GtkMenu *menu,
+				      gchar *item_label)
+{
+  GtkMenu *submenu;
+
+  GList *list_start, *list;
+  
+  gchar *str;
+  
+  if(!GTK_IS_MENU(menu) ||
+     item_label == NULL){
+    return(NULL);
+  }
+
+  gdk_threads_enter();
+
+  list =
+    list_start = gtk_container_get_children(menu);
+  submenu = NULL;
+  
+  while(list != NULL){
+    if(GTK_IS_MENU_ITEM(list->data)){
+      str = NULL;
+      g_object_get(list->data,
+		   "label\0", &str,
+		   NULL);
+
+      if(!g_ascii_strcasecmp(str,
+			     item_label)){
+	g_object_get(list->data,
+		     "submenu\0", &submenu,
+		     NULL);
+
+	break;
+      }
+    }
+
+    list = list->next;
+  }
+
+  g_list_free(list_start);
+
+  gdk_threads_leave();
+  
+  return(submenu);
+}
+
+gboolean
+ags_functional_test_util_menu_bar_click(gchar *item_label)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+  GtkMenuBar *menu_bar;
+  
+  GList *list_start, *list;
+  
+  gchar *str;
+
+  gboolean success;
+  
+  if(item_label == NULL){
+    return(FALSE);
+  }
+
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+  menu_bar = xorg_application_context->window->menu_bar;
+
+  list =
+    list_start = gtk_container_get_children(menu_bar);
+  success = FALSE;
+
+  gdk_threads_leave();
+  
+  while(list != NULL){
+    if(GTK_IS_MENU_ITEM(list->data)){
+      str = NULL;
+      g_object_get(list->data,
+		   "label\0", &str,
+		   NULL);
+
+      if(!g_ascii_strcasecmp(str,
+			     item_label)){
+	GtkWidget *widget;
+
+	GdkWindow *window;
+	GdkEvent *event_motion;
+
+	struct timespec spec;
+	
+	gint x, y;
+	gint origin_x, origin_y;
+	
+	widget = GTK_WIDGET(list->data);
+
+	/*  */
+	pthread_mutex_lock(task_thread->launch_mutex);
+
+	x = widget->allocation.x;
+	y = widget->allocation.y;
+
+	window = gtk_widget_get_window(widget);
+
+	x = widget->allocation.x;
+	y = widget->allocation.y;
+
+	gdk_window_get_origin(window, &origin_x, &origin_y);
+
+	gdk_display_warp_pointer(gtk_widget_get_display(widget),
+				 gtk_widget_get_screen(widget),
+				 origin_x + x + 15, origin_y + y + 5);
+	
+	pthread_mutex_unlock(task_thread->launch_mutex);
+
+	/*  */
+	usleep(AGS_FUNCTIONAL_TEST_UTIL_REACTION_TIME);
+
+	gdk_test_simulate_button(window,
+				 x + 5,
+				 y + 5,
+				 1,
+				 GDK_BUTTON1_MASK,
+				 GDK_BUTTON_PRESS);
+
+	usleep(AGS_FUNCTIONAL_TEST_UTIL_REACTION_TIME);
+
+	gdk_test_simulate_button(window,
+				 x + 5,
+				 y + 5,
+				 1,
+				 GDK_BUTTON1_MASK,
+				 GDK_BUTTON_RELEASE);
+
+	usleep(AGS_FUNCTIONAL_TEST_UTIL_REACTION_TIME);
+
+	/*  */
+	pthread_mutex_lock(task_thread->launch_mutex);
+
+	g_signal_emit_by_name(widget,
+			      "activate-item\0");
+	
+	pthread_mutex_unlock(task_thread->launch_mutex);
+
+	success = TRUE;
+
+	break;
+      }
+    }
+
+    list = list->next;
+  }
+
+  g_list_free(list_start);
+
+  ags_functional_test_util_idle();
+  
+  return(success);
+}
+
+gboolean
+ags_functional_test_util_menu_click(GtkMenu *menu,
+				    gchar *item_label)
+{
+  GList *list_start, *list;
+  
+  gchar *str;
+
+  gboolean success;
+  
+  if(menu == NULL ||
+     item_label == NULL ||
+     !GTK_IS_MENU(menu)){
+    return(FALSE);
+  }
+
+  gdk_threads_enter();
+
+  list =
+    list_start = gtk_container_get_children(menu);
+  success = FALSE;
+
+  gdk_threads_leave();
+  
+  while(list != NULL){
+    if(GTK_IS_MENU_ITEM(list->data)){
+      str = NULL;
+      g_object_get(list->data,
+		   "label\0", &str,
+		   NULL);
+
+      if(!g_ascii_strcasecmp(str,
+			     item_label)){
+	GtkWidget *widget;
+
+	GdkWindow *window;
+	
+	gint x, y;
+	gint origin_x, origin_y;
+	
+	widget = GTK_WIDGET(list->data);
+
+	/*  */
+	pthread_mutex_lock(task_thread->launch_mutex);
+
+	window = gtk_widget_get_window(widget);
+
+	x = widget->allocation.x;
+	y = widget->allocation.y;
+
+	gdk_window_get_origin(window, &origin_x, &origin_y);
+
+	gdk_display_warp_pointer(gtk_widget_get_display(widget),
+				 gtk_widget_get_screen(widget),
+				 origin_x + x + 15, origin_y + y + 5);
+
+	pthread_mutex_unlock(task_thread->launch_mutex);
+
+	usleep(AGS_FUNCTIONAL_TEST_UTIL_REACTION_TIME);
+	
+	gdk_test_simulate_button(window,
+				 x + 5,
+				 y + 5,
+				 1,
+				 GDK_BUTTON1_MASK,
+				 GDK_BUTTON_PRESS);
+
+
+	usleep(AGS_FUNCTIONAL_TEST_UTIL_REACTION_TIME);
+
+	gdk_test_simulate_button(window,
+				 x + 5,
+				 y + 5,
+				 1,
+				 GDK_BUTTON1_MASK,
+				 GDK_BUTTON_RELEASE);
+  	
+	usleep(AGS_FUNCTIONAL_TEST_UTIL_REACTION_TIME);
+
+	success = TRUE;
+
+	/*  */
+	pthread_mutex_lock(task_thread->launch_mutex);
+
+	g_signal_emit_by_name(widget,
+			      "activate-item\0");
+	
+	pthread_mutex_unlock(task_thread->launch_mutex);
+
+	break;
+      }
+    }
+
+    list = list->next;
+  }
+
+  g_list_free(list_start);
+
+  ags_functional_test_util_idle();
+  
+  return(success);
+}
+
+gboolean
+ags_functional_test_util_button_click(GtkButton *button)
+{
+  GtkWidget *widget;
+
+  GdkWindow *window;
+
+  gint x, y;
+  gint origin_x, origin_y;
+	
+  if(button == NULL ||
+     !GTK_IS_BUTTON(button)){
+    return(FALSE);
+  }
+  
+  widget = button;
+
+  /*  */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  window = gtk_widget_get_window(widget);
+
+  x = widget->allocation.x;
+  y = widget->allocation.y;
+
+  gdk_window_get_origin(window, &origin_x, &origin_y);
+
+  gdk_display_warp_pointer(gtk_widget_get_display(widget),
+			   gtk_widget_get_screen(widget),
+			   origin_x + x + 15, origin_y + y + 5);
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  /*  */
+  usleep(AGS_FUNCTIONAL_TEST_UTIL_REACTION_TIME);
+	
+  gdk_test_simulate_button(window,
+			   x + 5,
+			   y + 5,
+			   1,
+			   GDK_BUTTON1_MASK,
+			   GDK_BUTTON_PRESS);
+
+
+  usleep(AGS_FUNCTIONAL_TEST_UTIL_REACTION_TIME);
+
+  gdk_test_simulate_button(window,
+			   x + 5,
+			   y + 5,
+			   1,
+			   GDK_BUTTON1_MASK,
+			   GDK_BUTTON_RELEASE);
+  	
+  usleep(AGS_FUNCTIONAL_TEST_UTIL_REACTION_TIME);
+
+  ags_functional_test_util_idle();
+  
+  return(TRUE);
+}
+
+gboolean
+ags_functional_test_util_menu_tool_button_click(GtkButton *button)
+{
+  GtkWidget *widget;
+
+  GdkWindow *window;
+
+  gint x, y;
+  gint origin_x, origin_y;
+	
+  if(button == NULL ||
+     !GTK_IS_MENU_TOOL_BUTTON(button)){
+    return(FALSE);
+  }
+  
+  widget = button;
+  
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  window = gtk_widget_get_window(widget);
+
+  x = widget->allocation.x;
+  y = widget->allocation.y;
+
+  gdk_window_get_origin(window, &origin_x, &origin_y);
+
+  gdk_display_warp_pointer(gtk_widget_get_display(widget),
+			   gtk_widget_get_screen(widget),
+			   origin_x + x + 15, origin_y + y + 5);
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  usleep(AGS_FUNCTIONAL_TEST_UTIL_REACTION_TIME);
+	
+  gdk_test_simulate_button(window,
+			   x + 5,
+			   y + 5,
+			   1,
+			   GDK_BUTTON1_MASK,
+			   GDK_BUTTON_PRESS);
+
+
+  usleep(AGS_FUNCTIONAL_TEST_UTIL_REACTION_TIME);
+
+  gdk_test_simulate_button(window,
+			   x + 5,
+			   y + 5,
+			   1,
+			   GDK_BUTTON1_MASK,
+			   GDK_BUTTON_RELEASE);
+  	
+  usleep(AGS_FUNCTIONAL_TEST_UTIL_REACTION_TIME);
+
+  /*  */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  g_signal_emit_by_name(widget,
+			"clicked\0");
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+
+  /*  */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  gtk_menu_popup(gtk_menu_tool_button_get_menu(widget),
+		 NULL,
+		 NULL,
+		 NULL,
+		 widget,
+		 1,
+		 gtk_get_current_event_time());
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+  
+  return(TRUE);
+}
+
+gboolean
+ags_functional_test_util_dialog_apply(GtkDialog *dialog)
+{
+  if(!GTK_IS_DIALOG(dialog)){
+    return(FALSE);
+  }
+
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  gtk_dialog_response(dialog,
+		      GTK_RESPONSE_APPLY);
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+  
+  return(TRUE);
+}
+
+gboolean
+ags_functional_test_util_dialog_ok(GtkDialog *dialog)
+{
+  GtkButton *ok_button;
+
+  GList *list_start, *list;
+
+  gboolean success;
+  
+  if(!GTK_IS_DIALOG(dialog)){
+    return(FALSE);
+  }
+
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  ok_button = NULL;
+  
+  list_start = 
+    list = gtk_container_get_children(gtk_dialog_get_action_area(dialog));
+
+  while(list != NULL){
+    if(!g_strcmp0(GTK_STOCK_OK, gtk_button_get_label(list->data))){
+      ok_button = list->data;
+      
+      break;
+    }
+
+    list = list->next;
+  }
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  g_list_free(list_start);
+
+  if(ok_button == NULL){
+    return(FALSE);
+  }
+  
+  success = ags_functional_test_util_button_click(ok_button);
+  
+  return(success);
+}
+
+gboolean
+ags_functional_test_util_dialog_cancel(GtkDialog *dialog)
+{
+  GtkButton *cancel_button;
+
+  GList *list_start, *list;
+
+  gboolean success;
+  
+  if(!GTK_IS_DIALOG(dialog)){
+    return(FALSE);
+  }
+
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  cancel_button = NULL;
+  
+  list_start = 
+    list = gtk_container_get_children(gtk_dialog_get_action_area(dialog));
+
+  while(list != NULL){
+    if(!g_strcmp0(GTK_STOCK_CANCEL, gtk_button_get_label(list->data))){
+      cancel_button = list->data;
+      
+      break;
+    }
+
+    list = list->next;
+  }
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  g_list_free(list_start);
+
+  if(cancel_button == NULL){
+    return(FALSE);
+  }
+  
+  success = ags_functional_test_util_button_click(cancel_button);
+  
+  return(success);
+}
+
+gboolean
+ags_functional_test_util_file_chooser_open_path(GtkFileChooser *file_chooser,
+						gchar *path)
+{
+  if(file_chooser == NULL ||
+     path == NULL ||
+     !GTK_IS_FILE_CHOOSER(file_chooser)){
+    return(FALSE);
+  }
+  
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  gtk_file_chooser_set_current_folder(file_chooser,
+				      path);
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+  
+  return(TRUE);
+}
+
+gboolean
+ags_functional_test_util_file_chooser_select_filename(GtkFileChooser *file_chooser,
+						      gchar *filename)
+{
+  if(file_chooser == NULL ||
+     filename == NULL ||
+     !GTK_IS_FILE_CHOOSER(file_chooser)){
+    return(FALSE);
+  }
+  
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  gtk_file_chooser_select_filename(file_chooser,
+				   filename);
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+  
+  return(TRUE);
+}
+
+gboolean
+ags_functional_test_util_file_chooser_select_filenames(GtkFileChooser *file_chooser,
+						       GSList *filename)
+{
+  if(file_chooser == NULL ||
+     filename == NULL ||
+     !GTK_IS_FILE_CHOOSER(file_chooser)){
+    return(FALSE);
+  }
+  
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  while(filename != NULL){
+    gtk_file_chooser_select_filename(file_chooser,
+				     filename->data);
+
+    filename = filename->next;
+  }
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+  
+  return(TRUE); 
+}
+
+gboolean
+ags_functional_test_util_file_chooser_select_all(GtkFileChooser *file_chooser)
+{
+  if(file_chooser == NULL ||
+     !GTK_IS_FILE_CHOOSER(file_chooser)){
+    return(FALSE);
+  }
+  
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  gtk_file_chooser_select_all(file_chooser);
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+  
+  return(TRUE); 
+}
+
+gboolean
+ags_functional_test_util_open()
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  GtkMenu *menu;
+  
+  gboolean success;
+
+  if(!ags_functional_test_util_menu_bar_click(GTK_STOCK_FILE)){
+    return(FALSE);
+  }
+
+  pthread_mutex_lock(task_thread->launch_mutex);
+    
+  xorg_application_context = ags_application_context_get_instance();
+  menu = xorg_application_context->window->menu_bar->file;
+  
+  success = ags_functional_test_util_menu_click(menu,
+						"open\0");
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+  
+  return(success); 
+}
+
+gboolean
+ags_functional_test_util_save()
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  GtkMenu *menu;
+  
+  gboolean success;
+
+  if(!ags_functional_test_util_menu_bar_click(GTK_STOCK_FILE)){
+    return(FALSE);
+  }
+    
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  xorg_application_context = ags_application_context_get_instance();
+  menu = xorg_application_context->window->menu_bar->file;
+  
+  success = ags_functional_test_util_menu_click(menu,
+						"save\0");
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+  
+  return(success); 
+}
+
+gboolean
+ags_functional_test_util_save_as()
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  GtkMenu *menu;
+  
+  gboolean success;
+
+  if(!ags_functional_test_util_menu_bar_click(GTK_STOCK_FILE)){
+    return(FALSE);
+  }
+    
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  xorg_application_context = ags_application_context_get_instance();
+  menu = xorg_application_context->window->menu_bar->file;
+  
+  success = ags_functional_test_util_menu_click(menu,
+						"save as\0");
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+  
+  ags_functional_test_util_idle();
+  
+  return(success); 
+}
+
+gboolean
+ags_functional_test_util_export_open()
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  GtkMenu *menu;
+  
+  gboolean success;
+
+  if(!ags_functional_test_util_menu_bar_click(GTK_STOCK_FILE)){
+    return(FALSE);
+  }
+
+  pthread_mutex_lock(task_thread->launch_mutex);
+    
+  xorg_application_context = ags_application_context_get_instance();
+  menu = xorg_application_context->window->menu_bar->file;
+  
+  success = ags_functional_test_util_menu_click(menu,
+						"export\0");
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+  
+  ags_functional_test_util_idle();
+  
+  return(success); 
+}
+
+gboolean
+ags_functional_test_util_export_close()
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  GtkDialog *dialog;
+  
+  gboolean success;
+
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  xorg_application_context = ags_application_context_get_instance();
+  dialog = xorg_application_context->window->export_window;
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  success = ags_functional_test_util_dialog_close(dialog);
+  
+  ags_functional_test_util_idle();
+  
+  return(success); 
+}
+
+gboolean
+ags_funcitonal_test_util_export_add()
+{
+  AgsXorgApplicationContext *xorg_application_context;
+  AgsExportWindow *export_window;
+  GtkButton *add_button;
+
+  gboolean success;
+  
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  xorg_application_context = ags_application_context_get_instance();
+  export_window = xorg_application_context->window->export_window;
+
+  add_button = export_window->add;
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  success = ags_functional_test_util_button_click(add_button);
+  
+  return(success);
+}
+
+gboolean
+ags_funcitonal_test_util_export_tact(gdouble tact)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  AgsExportWindow *export_window;
+  
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  xorg_application_context = ags_application_context_get_instance();
+  export_window = xorg_application_context->window->export_window;
+
+  gtk_spin_button_set_value(export_window->tact,
+			    tact);
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+  
+  return(TRUE);
+}
+
+gboolean
+ags_funcitonal_test_util_export_remove(guint nth)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  AgsExportWindow *export_window;
+
+  GList *list_start, *list;
+  GtkButton *remove_button;
+  
+  guint i;
+  gboolean success;
+  
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  xorg_application_context = ags_application_context_get_instance();
+  export_window = xorg_application_context->window->export_window;
+
+  remove_button = NULL;
+  
+  list_start =
+    list = gtk_container_get_children(export_window->export_soundcard);
+
+  success = FALSE;
+
+  for(i = 0; list != NULL; i++){
+    if(i == nth){
+      GtkHBox *hbox;
+      
+      GList *tmp_start;
+      
+      hbox = GTK_HBOX(list->data);
+      tmp_start = gtk_container_get_children(hbox);
+
+      remove_button = gtk_bin_get_child(tmp_start->next->data);
+      g_list_free(tmp_start);
+
+      success = TRUE;
+      
+      break;
+    }
+
+    list = list->next;
+  }
+
+  g_list_free(list_start);
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  if(!success){
+    return(FALSE);
+  }
+  
+  success = ags_functional_test_util_button_click(remove_button);
+  
+  return(success);
+}
+
+gboolean
+ags_funcitonal_test_util_export_set_backend(guint nth,
+					    gchar *backend)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  AgsExportWindow *export_window;
+
+  GList *list_start, *list;
+
+  guint i;
+  gboolean success;
+
+  pthread_mutex_lock(task_thread->launch_mutex);
+  
+  xorg_application_context = ags_application_context_get_instance();
+  export_window = xorg_application_context->window->export_window;
+
+  list_start =
+    list = gtk_container_get_children(export_window->export_soundcard);
+  success = FALSE;
+
+  for(i = 0; list != NULL; i++){
+    if(i == nth){
+      AgsExportSoundcard *export_soundcard;
+      GtkHBox *hbox;
+      GtkTreeModel *model;
+
+      GtkTreeIter iter;
+      GList *tmp_start;
+
+      gchar *value;
+
+      guint active;
+      
+      hbox = GTK_HBOX(list->data);
+      tmp_start = gtk_container_get_children(hbox);
+
+      export_soundcard = AGS_EXPORT_SOUNDCARD(tmp_start->data);
+      g_list_free(tmp_start);
+
+      model = gtk_combo_box_get_model(GTK_COMBO_BOX(export_soundcard->backend));
+      active = 0;
+
+      if(gtk_tree_model_get_iter_first(model, &iter)){
+	do{
+	  gtk_tree_model_get(model, &iter,
+			     0, &value,
+			     -1);
+
+	  if(!g_strcmp0(backend,
+			value)){
+	    gtk_combo_box_set_active_iter((GtkComboBox *) export_soundcard->backend,
+					  &iter);
+	    success = TRUE;
+	    
+	    break;
+	  }
+	}while(gtk_tree_model_iter_next(model,
+					&iter));
+      }      
+      
+      break;
+    }
+
+    list = list->next;
+  }
+
+  g_list_free(list_start);
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+  
+  return(success);
+}
+
+gboolean
+ags_funcitonal_test_util_export_set_device(guint nth,
+					   gchar *device)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  AgsExportWindow *export_window;
+
+  GList *list_start, *list;
+
+  guint i;
+  gboolean success;
+  
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  xorg_application_context = ags_application_context_get_instance();
+  export_window = xorg_application_context->window->export_window;
+
+  list_start =
+    list = gtk_container_get_children(export_window->export_soundcard);
+  success = FALSE;
+
+  for(i = 0; list != NULL; i++){
+    if(i == nth){
+      AgsExportSoundcard *export_soundcard;
+      GtkHBox *hbox;
+      GtkTreeModel *model;
+
+      GtkTreeIter iter;
+      GList *tmp_start;
+
+      gchar *value;
+
+      guint active;
+      
+      hbox = GTK_HBOX(list->data);
+      tmp_start = gtk_container_get_children(hbox);
+
+      export_soundcard = AGS_EXPORT_SOUNDCARD(tmp_start->data);
+      g_list_free(tmp_start);
+
+      model = gtk_combo_box_get_model(GTK_COMBO_BOX(export_soundcard->card));
+      active = 0;
+
+      if(gtk_tree_model_get_iter_first(model, &iter)){
+	do{
+	  gtk_tree_model_get(model, &iter,
+			     0, &value,
+			     -1);
+
+	  if(!g_strcmp0(device,
+			value)){
+	    gtk_combo_box_set_active_iter((GtkComboBox *) export_soundcard->card,
+					  &iter);
+	    success = TRUE;
+	    
+	    break;
+	  }
+	}while(gtk_tree_model_iter_next(model,
+					&iter));
+      }      
+      
+      break;
+    }
+
+    list = list->next;
+  }
+
+  g_list_free(list_start);
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+  
+  ags_functional_test_util_idle();
+  
+  return(success);
+}
+
+gboolean
+ags_funcitonal_test_util_export_set_filename(guint nth,
+					     gchar *filename)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  AgsExportWindow *export_window;
+
+  GList *list_start, *list;
+
+  guint i;
+  gboolean success;
+
+  pthread_mutex_lock(task_thread->launch_mutex);
+  
+  xorg_application_context = ags_application_context_get_instance();
+  export_window = xorg_application_context->window->export_window;
+
+  list_start =
+    list = gtk_container_get_children(export_window->export_soundcard);
+  success = FALSE;
+
+  for(i = 0; list != NULL; i++){
+    if(i == nth){
+      AgsExportSoundcard *export_soundcard;
+      GtkHBox *hbox;
+
+      GList *tmp_start;
+      
+      hbox = GTK_HBOX(list->data);
+      tmp_start = gtk_container_get_children(hbox);
+
+      export_soundcard = AGS_EXPORT_SOUNDCARD(tmp_start->data);
+      g_list_free(tmp_start);
+
+      gtk_entry_set_text(export_soundcard->filename,
+			 filename);
+      
+      success = TRUE;
+      
+      break;
+    }
+    
+    list = list->next;
+  }
+
+  g_list_free(list_start);
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+  
+  ags_functional_test_util_idle();
+  
+  return(success);
+}
+
+gboolean
+ags_funcitonal_test_util_export_open(guint nth)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_funcitonal_test_util_export_set_format(guint nth,
+					   gchar *format)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_funcitonal_test_util_export_do_export(guint nth,
+					  gchar *format)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_quit()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_add_machine(gchar *submenu,
+				     gchar *machine_name)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+  AgsMenuBar *menu_bar;
+  
+  GtkMenu *add_menu;
+
+  gboolean success;
+  
+  if(machine_name == NULL){
+    return(FALSE);
+  }
+
+  if(!ags_functional_test_util_menu_bar_click(GTK_STOCK_EDIT)){    
+    return(FALSE);
+  }
+
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+  menu_bar = xorg_application_context->window->menu_bar;
+
+  gdk_threads_leave();
+
+  success = FALSE;
+  
+  success = ags_functional_test_util_menu_click(menu_bar->edit,
+						GTK_STOCK_ADD);
+
+  if(!success){
+    return(FALSE);
+  }
+  
+  add_menu = ags_functional_test_util_submenu_find(menu_bar->edit,
+						   GTK_STOCK_ADD);
+
+  if(submenu == NULL){
+    success = ags_functional_test_util_menu_click(add_menu,
+						  machine_name);
+  }else{
+    GtkMenu *bridge_menu;
+    
+    bridge_menu = ags_functional_test_util_submenu_find(add_menu,
+							submenu);
+
+    success = ags_functional_test_util_menu_click(bridge_menu,
+						  machine_name);    
+  }
+
+  ags_functional_test_util_idle();
+  
+  return(success);
+}
+
+gboolean
+ags_functional_test_util_automation_open()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_close()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_preferences_open()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_preferences_close()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_about_open()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_about_close()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_navigation_expand()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_navigation_bpm(gdouble bpm)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_navigation_rewind()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_navigation_prev()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_navigation_play()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_navigation_stop()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_navigation_next()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_navigation_forward()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_navigation_loop()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_navigation_position(gdouble position)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_navigation_loop_left(gdouble loop_left)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_navigation_loop_right(gdouble loop_right)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_navigation_exclude_sequencers()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_toolbar_cursor_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_toolbar_edit_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_toolbar_delete_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_toolbar_select_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_toolbar_invert_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_toolbar_paste_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_toolbar_copy_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_toolbar_cut_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_toolbar_zoom(guint nth_zoom)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_selector_select(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_selection_select(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_selection_remove_index()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_selection_add_index()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_selection_link_index()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_selection_reverse_mapping()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_selection_shift_piano(guint nth_shift)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_pattern_edit_delete_point(guint nth_index,
+						   guint x,
+						   guint y)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_pattern_edit_add_point(guint nth_index,
+						guint x,
+						guint y)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_pattern_edit_select_region(guint nth_index,
+						    guint x0, guint x1,
+						    guint y0, guint y1)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_note_edit_delete_point(guint nth_index,
+						guint x,
+						guint y)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_note_edit_add_point(guint nth_index,
+					     guint x0, guint x1,
+					     guint y)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_note_edit_select_region(guint nth_index,
+						 guint x0, guint x1,
+						 guint y0, guint y1)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_toolbar_cursor_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_toolbar_edit_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_toolbar_delete_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_toolbar_select_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_toolbar_paste_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_toolbar_copy_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_toolbar_cut_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_toolbar_zoom(guint nth_zoom)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_edit_audio_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_edit_output_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_edit_input_click()
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_edit_delete_point(guint nth_index,
+						      guint x,
+						      guint y)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_edit_add_point(guint nth_index,
+						   guint x,
+						   guint y)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_automation_edit_select_region(guint nth_index,
+						       guint x0, guint x1,
+						       guint y0, guint y1)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_move_up(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_move_down(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_hide(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_show(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_destroy(guint nth_machine)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+  AgsMachine *machine;
+
+  GList *list_start, *list;
+  
+  gboolean success;
+
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve machine */
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+  
+  if(list != NULL &&
+     AGS_IS_MACHINE(list->data)){
+    machine = list->data;
+  }else{
+    return(FALSE);
+  }
+  
+  g_list_free(list_start);
+
+  /* activate destroy */
+  success = ags_functional_test_util_menu_tool_button_click(machine->menu_tool_button);
+
+  success = ags_functional_test_util_menu_click(machine->popup,
+						"destroy\0");
+
+  return(success);
+}
+
+gboolean
+ags_functional_test_util_machine_rename_open(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_rename_close(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_rename_set_name(guint nth_machine,
+						 gchar *name)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_open(guint nth_machine)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+  AgsMachine *machine;
+
+  GList *list_start, *list;
+  
+  gboolean success;
+
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve machine */
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+  
+  if(list != NULL &&
+     AGS_IS_MACHINE(list->data)){
+    machine = list->data;
+  }else{
+    return(FALSE);
+  }
+  
+  g_list_free(list_start);
+
+  /* activate destroy */
+  success = ags_functional_test_util_menu_tool_button_click(machine->menu_tool_button);
+
+  success = ags_functional_test_util_menu_click(machine->popup,
+						"properties\0");
+
+  return(success);
+}
+
+gboolean
+ags_functional_test_util_machine_properties_close(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_click_tab(guint nth_machine,
+						      guint nth_tab)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+  AgsMachine *machine;
+  AgsMachineEditor *machine_editor;
+  
+  GList *list_start, *list;
+  
+  gboolean success;
+
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve machine */
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+  
+  if(list != NULL &&
+     AGS_IS_MACHINE(list->data)){
+    machine = list->data;
+  }else{
+    return(FALSE);
+  }
+
+  g_list_free(list_start);
+
+  /* click tab */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  machine_editor = machine->properties;
+
+  gtk_notebook_set_current_page(machine_editor->notebook,
+				nth_tab);
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+
+  return(TRUE);
+}
+
+gboolean
+ags_functional_test_util_machine_properties_click_enable(guint nth_machine)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+  AgsMachine *machine;
+  AgsMachineEditor *machine_editor;
+  GtkButton *enable_button;
+  
+  GList *list_start, *list;
+
+  guint nth_tab;
+  gboolean success;
+
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve machine */
+  enable_button = NULL;
+  
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+  
+  if(list != NULL &&
+     AGS_IS_MACHINE(list->data)){
+    machine = list->data;
+  }else{
+    return(FALSE);
+  }
+
+  g_list_free(list_start);
+
+  /* click tab */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  machine_editor = machine->properties;
+
+  nth_tab = gtk_notebook_get_current_page(machine_editor->notebook);
+
+  switch(nth_tab){
+  case 0:
+    {
+      enable_button = AGS_PROPERTY_EDITOR(machine_editor->output_editor)->enabled;
+    }
+    break;
+  case 1:
+    {
+      enable_button = AGS_PROPERTY_EDITOR(machine_editor->input_editor)->enabled;
+    }
+    break;
+  case 2:
+    {
+      enable_button = AGS_PROPERTY_EDITOR(machine_editor->output_link_editor)->enabled;
+    }
+    break;
+  case 3:
+    {
+      enable_button = AGS_PROPERTY_EDITOR(machine_editor->input_link_editor)->enabled;
+    }
+    break;
+  case 4:
+    {
+      enable_button = AGS_PROPERTY_EDITOR(machine_editor->resize_editor)->enabled;
+    }
+    break;
+  }
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  success = ags_functional_test_util_button_click(enable_button);
+
+  return(success);
+}
+
+gboolean
+ags_functional_test_util_machine_properties_link_set(guint nth_machine,
+						     guint pad, guint audio_channel,
+						     gchar *link_name, guint link_nth_line)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_link_open(guint nth_machine,
+						      guint pad, guint audio_channel)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_effect_add(guint nth_machine,
+						       guint pad, guint audio_channel)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_effect_remove(guint nth_machine,
+							  guint pad, guint audio_channel,
+							  guint nth)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_effect_plugin_type(guint nth_machine,
+							       guint pad, guint audio_channel,
+							       gchar *plugin_type)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_ladspa_filename(guint nth_machine,
+							    guint pad, guint audio_channel,
+							    gchar *filename)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_ladspa_effect(guint nth_machine,
+							  guint pad, guint audio_channel,
+							  gchar *effect)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_lv2_filename(guint nth_machine,
+							 guint pad, guint audio_channel,
+							 gchar *filename)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_lv2_effect(guint nth_machine,
+						       guint pad, guint audio_channel,
+						       gchar *effect)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_bulk_add(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_bulk_remove(guint nth_machine,
+							guint nth_bulk)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_bulk_link(guint nth_machine,
+						      guint nth_bulk,
+						      gchar *link)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_bulk_first_line(guint nth_machine,
+							    guint nth_bulk,
+							    guint first_line)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_bulk_link_line(guint nth_machine,
+							   guint nth_bulk,
+							   guint first_link_line)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_bulk_count(guint nth_machine,
+						       guint nth_bulk,
+						       guint count)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_properties_resize_audio_channels(guint nth_machine,
+								  guint audio_channels)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+  AgsMachine *machine;
+  AgsMachineEditor *machine_editor;
+  
+  GList *list_start, *list;
+
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve machine */  
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+  
+  if(list != NULL &&
+     AGS_IS_MACHINE(list->data)){
+    machine = list->data;
+  }else{
+    return(FALSE);
+  }
+
+  g_list_free(list_start);
+
+  /* resize audio channels */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  machine_editor = machine->properties;
+  gtk_spin_button_set_value(machine_editor->resize_editor->audio_channels,
+			    audio_channels);
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+
+  return(TRUE);
+}
+
+gboolean
+ags_functional_test_util_machine_properties_resize_inputs(guint nth_machine,
+							  guint inputs)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+  AgsMachine *machine;
+  AgsMachineEditor *machine_editor;
+  
+  GList *list_start, *list;
+
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve machine */
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+  
+  if(list != NULL &&
+     AGS_IS_MACHINE(list->data)){
+    machine = list->data;
+  }else{
+    return(FALSE);
+  }
+
+  g_list_free(list_start);
+
+  /* resize input pads */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  machine_editor = machine->properties;
+  gtk_spin_button_set_value(machine_editor->resize_editor->input_pads,
+			    inputs);
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+
+  return(TRUE);
+}
+
+gboolean
+ags_functional_test_util_machine_properties_resize_outputs(guint nth_machine,
+							   guint outputs)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+  AgsMachine *machine;
+  AgsMachineEditor *machine_editor;
+  
+  GList *list_start, *list;
+
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve machine */
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+  
+  if(list != NULL &&
+     AGS_IS_MACHINE(list->data)){
+    machine = list->data;
+  }else{
+    return(FALSE);
+  }
+
+  g_list_free(list_start);
+
+  /* resize output pads */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  machine_editor = machine->properties;
+  gtk_spin_button_set_value(machine_editor->resize_editor->output_pads,
+			    outputs);
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_idle();
+
+  return(TRUE);
+}
+
+gboolean
+ags_functional_test_util_machine_edit_copy(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_line_member_set_toggled(gchar *specifier,
+						 gboolean is_toggled)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_line_member_set_value(gchar *specifier,
+					       gdouble value)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_audio_connection_click_tab(guint nth_machine,
+							    guint nth_tab)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_audio_connection_click_enable(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_audio_connection_set_device(guint nth_machine,
+							     guint pad, guint audio_channel,
+							     gchar *device)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_audio_connection_set_line(guint nth_machine,
+							   uint pad, guint audio_channel,
+							   guint line)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_audio_connection_bulk_add(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_audio_connection_bulk_remove(guint nth_machine,
+							      guint nth_bulk)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_audio_connection_bulk_first_line(guint nth_machine,
+								  guint nth_bulk,
+								  guint first_line)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_audio_connection_bulk_count(guint nth_machine,
+							     guint nth_bulk,
+							     guint count)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_audio_connection_bulk_device(guint nth_machine,
+							      guint nth_bulk,
+							      gchar *device)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_midi_connection_midi_channel(guint nth_machine,
+							      guint midi_channel)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_midi_connection_audio_start_mapping(guint nth_machine,
+								     guint audio_start_mapping)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_midi_connection_audio_end_mapping(guint nth_machine,
+								   guint audio_end_mapping)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_midi_connection_midi_start_mapping(guint nth_machine,
+								    guint midi_start_mapping)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_midi_connection_midi_end_mapping(guint nth_machine,
+								  guint midi_end_mapping)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_machine_midi_connection_midi_device(guint nth_machine,
+							     gchar *device)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_pad_group(guint nth_machine,
+				   guint nth_pad)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_pad_mute(guint nth_machine,
+				  guint nth_pad)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_pad_solo(guint nth_machine,
+				  guint nth_pad)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_pad_play(guint nth_machine,
+				  guint nth_pad)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_expander(guint nth_machine,
+				  guint nth_pad, guint nth_audio_channel)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_effect_bulk_add(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_effect_bulk_remove(guint nth_machine,
+					    guint nth_bulk_effect)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_effect_bulk_ladspa_filename(guint nth_machine,
+						     gchar *filename)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_effect_bulk_ladspa_effect(guint nth_machine,
+						   gchar *effect)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_effect_bulk_lv2_filename(guint nth_machine,
+						  gchar *filename)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_effect_bulk_lv2_effect(guint nth_machine,
+						gchar *effect)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_panel_mute_line(guint nth_machine,
+					 guint nth_pad, guint nth_audio_channel)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_mixer_input_line_volume(guint nth_machine,
+						 guint nth_pad, guint nth_audio_channel,
+						 gdouble volume)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_drum_open(guint nth_machine)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+  AgsDrum *drum;
+  GtkButton *open_button;
+
+  GList *list_start, *list;
+  
+  gboolean success;
+
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve drum */
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+  
+  if(list != NULL &&
+     AGS_IS_DRUM(list->data)){
+    drum = list->data;
+  }else{
+    return(FALSE);
+  }
+  
+  g_list_free(list_start);
+
+  /* open dialog */
+  pthread_mutex_lock(task_thread->launch_mutex);
+  
+  open_button = drum->open;
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  /* click open */
+  success = ags_functional_test_util_button_click(open_button);
+  
+  return(success);
+}
+
+gboolean
+ags_functional_test_util_drum_run(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_drum_loop(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_drum_bank_0(guint nth_machine,
+				     guint bank_0)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_drum_bank_1(guint nth_machine,
+				     guint bank_1)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_drum_length(guint nth_machine,
+				     guint length)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_drum_index(guint nth_machine,
+				    guint nth_radio)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_drum_pad(guint nth_machine,
+				  guint nth_pad)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_drum_pad_open(guint nth_machine,
+				       guint nth_pad)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_drum_pad_edit(guint nth_machine,
+				       guint nth_pad)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_drum_input_line_volume(guint nth_machine,
+						guint nth_pad, guint nth_audio_channel,
+						gdouble volume)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_matrix_run(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_matrix_loop(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_matrix_bank_1(guint nth_machine,
+				       guint bank_1)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_matrix_length(guint nth_machine,
+				       guint length)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_matrix_gutter(guint nth_machine,
+				       guint nth_gutter)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_drum_cell(guint nth_machine,
+				   guint x, guint y)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_synth_auto_update(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_synth_update(guint nth_machine)
+{
+  //TODO:JK: 
+}
+
+gboolean ags_functional_test_util_oscillator_wave(guint nth_machine,
+						  guint nth_oscillator,
+						  gchar *wave)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_oscillator_phase(guint nth_machine,
+					  guint nth_oscillator,
+					  gdouble phase)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_oscillator_attack(guint nth_machine,
+					   guint nth_oscillator,
+					   gdouble attack)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_oscillator_frequency(guint nth_machine,
+					      guint nth_oscillator,
+					      gdouble frequency)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_oscillator_length(guint nth_machine,
+					   guint nth_oscillator,
+					   gdouble length)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_oscillator_volume(guint nth_machine,
+					   guint nth_oscillator,
+					   gdouble volume)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_ffplayer_open(guint nth_machine)
+{
+  AgsXorgApplicationContext *xorg_application_context;
+  AgsFFPlayer *ffplayer;
+  GtkButton *open_button;
+
+  GList *list_start, *list;
+  
+  gboolean success;
+
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve ffplayer */
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+  
+  if(list != NULL &&
+     AGS_IS_FFPLAYER(list->data)){
+    ffplayer = list->data;
+  }else{
+    return(FALSE);
+  }
+  
+  g_list_free(list_start);
+
+  /* open dialog */
+  pthread_mutex_lock(task_thread->launch_mutex);
+  
+  open_button = ffplayer->open;
+
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  /* click open */
+  success = ags_functional_test_util_button_click(open_button);
+  
+  return(success);
+}
+
+gboolean ags_functional_test_util_ffplayer_preset(guint nth_machine,
+						  gchar *preset)
+{
+  //TODO:JK: 
+}
+
+gboolean
+ags_functional_test_util_ffplayer_instrument(guint nth_machine,
+					     gchar *instrument)
+{
+  //TODO:JK: 
+}
diff --git a/ags/test/X/ags_functional_test_util.h b/ags/test/X/ags_functional_test_util.h
new file mode 100644
index 0000000..2da381b
--- /dev/null
+++ b/ags/test/X/ags_functional_test_util.h
@@ -0,0 +1,433 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_FUNCTIONAL_TEST_UTIL_H__
+#define __AGS_FUNCTIONAL_TEST_UTIL_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+void ags_functional_test_util_setup_and_launch();
+void ags_functional_test_util_idle();
+
+GtkMenu* ags_functional_test_util_submenu_find(GtkMenu *menu,
+					       gchar *item_label);
+gboolean ags_functional_test_util_menu_bar_click(gchar *item_label);
+gboolean ags_functional_test_util_menu_click(GtkMenu *menu,
+					     gchar *item_label);
+
+gboolean ags_functional_test_util_button_click(GtkButton *button);
+
+/* generic dialog */
+gboolean ags_functional_test_util_dialog_apply(GtkDialog *dialog);
+gboolean ags_functional_test_util_dialog_ok(GtkDialog *dialog);
+gboolean ags_functional_test_util_dialog_cancel(GtkDialog *dialog);
+
+#define ags_functional_test_util_dialog_close ags_functional_test_util_dialog_cancel
+
+/* file chooser */
+gboolean ags_functional_test_util_file_chooser_open_path(GtkFileChooser *file_chooser,
+							 gchar *path);
+gboolean ags_functional_test_util_file_chooser_select_filename(GtkFileChooser *file_chooser,
+							       gchar *filename);
+gboolean ags_functional_test_util_file_chooser_select_filenames(GtkFileChooser *file_chooser,
+								GSList *filename);
+gboolean ags_functional_test_util_file_chooser_select_all(GtkFileChooser *file_chooser);
+
+/* file */
+gboolean ags_functional_test_util_open();
+
+gboolean ags_functional_test_util_save();
+gboolean ags_functional_test_util_save_as();
+
+gboolean ags_functional_test_util_export_open();
+gboolean ags_functional_test_util_export_close();
+gboolean ags_funcitonal_test_util_export_add();
+gboolean ags_funcitonal_test_util_export_tact(gdouble tact);
+
+gboolean ags_funcitonal_test_util_export_remove(guint nth);
+gboolean ags_funcitonal_test_util_export_set_backend(guint nth,
+						     gchar *backend);
+gboolean ags_funcitonal_test_util_export_set_device(guint nth,
+						    gchar *device);
+gboolean ags_funcitonal_test_util_export_set_filename(guint nth,
+						      gchar *filename);
+gboolean ags_funcitonal_test_util_export_open(guint nth);
+gboolean ags_funcitonal_test_util_export_set_format(guint nth,
+						    gchar *format);
+
+gboolean ags_funcitonal_test_util_export_do_export();
+
+gboolean ags_functional_test_util_quit();
+
+/* edit */
+gboolean ags_functional_test_util_add_machine(gchar *submenu,
+					      gchar *machine_name);
+
+gboolean ags_functional_test_util_automation_open();
+gboolean ags_functional_test_util_automation_close();
+
+gboolean ags_functional_test_util_preferences_open();
+gboolean ags_functional_test_util_preferences_close();
+
+/* help */
+gboolean ags_functional_test_util_about_open();
+gboolean ags_functional_test_util_about_close();
+
+/* navigation */
+gboolean ags_functional_test_util_navigation_expand();
+
+gboolean ags_functional_test_util_navigation_bpm(gdouble bpm);
+
+gboolean ags_functional_test_util_navigation_rewind();
+gboolean ags_functional_test_util_navigation_prev();
+gboolean ags_functional_test_util_navigation_play();
+gboolean ags_functional_test_util_navigation_stop();
+gboolean ags_functional_test_util_navigation_next();
+gboolean ags_functional_test_util_navigation_forward();
+
+gboolean ags_functional_test_util_navigation_loop();
+
+gboolean ags_functional_test_util_navigation_position(gdouble position);
+
+gboolean ags_functional_test_util_navigation_loop_left(gdouble loop_left);
+gboolean ags_functional_test_util_navigation_loop_right(gdouble loop_right);
+
+gboolean ags_functional_test_util_navigation_exclude_sequencers();
+
+/* toolbar */
+gboolean ags_functional_test_util_toolbar_cursor_click();
+gboolean ags_functional_test_util_toolbar_edit_click();
+gboolean ags_functional_test_util_toolbar_delete_click();
+gboolean ags_functional_test_util_toolbar_select_click();
+gboolean ags_functional_test_util_toolbar_invert_click();
+
+gboolean ags_functional_test_util_toolbar_paste_click();
+gboolean ags_functional_test_util_toolbar_copy_click();
+gboolean ags_functional_test_util_toolbar_cut_click();
+
+gboolean ags_functional_test_util_toolbar_zoom(guint nth_zoom);
+
+/* machine selector */
+gboolean ags_functional_test_util_machine_selector_select(guint nth_machine);
+
+/* machine selection */
+gboolean ags_functional_test_util_machine_selection_select(guint nth_machine);
+
+gboolean ags_functional_test_util_machine_selection_remove_index();
+gboolean ags_functional_test_util_machine_selection_add_index();
+gboolean ags_functional_test_util_machine_selection_link_index();
+gboolean ags_functional_test_util_machine_selection_reverse_mapping();
+gboolean ags_functional_test_util_machine_selection_shift_piano(guint nth_shift);
+
+/* pattern edit */
+gboolean ags_functional_test_util_pattern_edit_delete_point(guint nth_index,
+							    guint x,
+							    guint y);
+gboolean ags_functional_test_util_pattern_edit_add_point(guint nth_index,
+							 guint x,
+							 guint y);
+gboolean ags_functional_test_util_pattern_edit_select_region(guint nth_index,
+							     guint x0, guint x1,
+							     guint y0, guint y1);
+
+/* note edit */
+gboolean ags_functional_test_util_note_edit_delete_point(guint nth_index,
+							 guint x,
+							 guint y);
+gboolean ags_functional_test_util_note_edit_add_point(guint nth_index,
+						      guint x0, guint x1,
+						      guint y);
+gboolean ags_functional_test_util_note_edit_select_region(guint nth_index,
+							  guint x0, guint x1,
+							  guint y0, guint y1);
+
+/* automation toolbar */
+gboolean ags_functional_test_util_automation_toolbar_cursor_click();
+gboolean ags_functional_test_util_automation_toolbar_edit_click();
+gboolean ags_functional_test_util_automation_toolbar_delete_click();
+gboolean ags_functional_test_util_automation_toolbar_select_click();
+
+gboolean ags_functional_test_util_automation_toolbar_paste_click();
+gboolean ags_functional_test_util_automation_toolbar_copy_click();
+gboolean ags_functional_test_util_automation_toolbar_cut_click();
+
+gboolean ags_functional_test_util_automation_toolbar_zoom(guint nth_zoom);
+
+/* automation edit */
+gboolean ags_functional_test_util_automation_edit_audio_click();
+gboolean ags_functional_test_util_automation_edit_output_click();
+gboolean ags_functional_test_util_automation_edit_input_click();
+
+/* automation area */
+gboolean ags_functional_test_util_automation_edit_delete_point(guint nth_index,
+							       guint x,
+							       guint y);
+gboolean ags_functional_test_util_automation_edit_add_point(guint nth_index,
+							    guint x,
+							    guint y);
+gboolean ags_functional_test_util_automation_edit_select_region(guint nth_index,
+								guint x0, guint x1,
+								guint y0, guint y1);
+
+/* generic machine */
+gboolean ags_functional_test_util_machine_move_up(guint nth_machine);
+gboolean ags_functional_test_util_machine_move_down(guint nth_machine);
+
+gboolean ags_functional_test_util_machine_hide(guint nth_machine);
+gboolean ags_functional_test_util_machine_show(guint nth_machine);
+
+gboolean ags_functional_test_util_machine_destroy(guint nth_machine);
+
+gboolean ags_functional_test_util_machine_rename_open(guint nth_machine);
+gboolean ags_functional_test_util_machine_rename_close(guint nth_machine);
+gboolean ags_functional_test_util_machine_rename_set_name(guint nth_machine,
+							  gchar *name);
+
+gboolean ags_functional_test_util_machine_properties_open(guint nth_machine);
+gboolean ags_functional_test_util_machine_properties_close(guint nth_machine);
+
+gboolean ags_functional_test_util_machine_properties_click_tab(guint nth_machine,
+							       guint nth_tab);
+gboolean ags_functional_test_util_machine_properties_click_enable(guint nth_machine);
+
+gboolean ags_functional_test_util_machine_properties_link_set(guint nth_machine,
+							      guint pad, guint audio_channel,
+							      gchar *link_name, guint link_nth_line);
+gboolean ags_functional_test_util_machine_properties_link_open(guint nth_machine,
+							       guint pad, guint audio_channel);
+
+gboolean ags_functional_test_util_machine_properties_effect_add(guint nth_machine,
+								guint pad, guint audio_channel);
+gboolean ags_functional_test_util_machine_properties_effect_remove(guint nth_machine,
+								   guint pad, guint audio_channel,
+								   guint nth);
+
+gboolean ags_functional_test_util_machine_properties_effect_plugin_type(guint nth_machine,
+									guint pad, guint audio_channel,
+									gchar *plugin_type);
+
+gboolean ags_functional_test_util_machine_properties_ladspa_filename(guint nth_machine,
+								     guint pad, guint audio_channel,
+								     gchar *filename);
+gboolean ags_functional_test_util_machine_properties_ladspa_effect(guint nth_machine,
+								   guint pad, guint audio_channel,
+								   gchar *effect);
+
+gboolean ags_functional_test_util_machine_properties_lv2_filename(guint nth_machine,
+								  guint pad, guint audio_channel,
+								  gchar *filename);
+gboolean ags_functional_test_util_machine_properties_lv2_effect(guint nth_machine,
+								guint pad, guint audio_channel,
+								gchar *effect);
+
+gboolean ags_functional_test_util_machine_properties_bulk_add(guint nth_machine);
+gboolean ags_functional_test_util_machine_properties_bulk_remove(guint nth_machine,
+								 guint nth_bulk);
+
+gboolean ags_functional_test_util_machine_properties_bulk_link(guint nth_machine,
+							       guint nth_bulk,
+							       gchar *link);
+gboolean ags_functional_test_util_machine_properties_bulk_first_line(guint nth_machine,
+								     guint nth_bulk,
+								     guint first_line);
+gboolean ags_functional_test_util_machine_properties_bulk_link_line(guint nth_machine,
+								    guint nth_bulk,
+								    guint first_link_line);
+gboolean ags_functional_test_util_machine_properties_bulk_count(guint nth_machine,
+								guint nth_bulk,
+								guint count);
+
+gboolean ags_functional_test_util_machine_properties_resize_audio_channels(guint nth_machine,
+									   guint audio_channels);
+gboolean ags_functional_test_util_machine_properties_resize_inputs(guint nth_machine,
+								   guint inputs);
+gboolean ags_functional_test_util_machine_properties_resize_outputs(guint nth_machine,
+								    guint outputs);
+
+gboolean ags_functional_test_util_machine_edit_copy(guint nth_machine);
+
+/* line member */
+gboolean ags_functional_test_util_line_member_set_toggled(gchar *specifier,
+							  gboolean is_toggled);
+gboolean ags_functional_test_util_line_member_set_value(gchar *specifier,
+							gdouble value);
+
+/* audio connection */
+gboolean ags_functional_test_util_machine_audio_connection_click_tab(guint nth_machine,
+								     guint nth_tab);
+gboolean ags_functional_test_util_machine_audio_connection_click_enable(guint nth_machine);
+
+gboolean ags_functional_test_util_machine_audio_connection_set_device(guint nth_machine,
+								      guint pad, guint audio_channel,
+								      gchar *device);
+gboolean ags_functional_test_util_machine_audio_connection_set_line(guint nth_machine,
+								    uint pad, guint audio_channel,
+								    guint line);
+
+gboolean ags_functional_test_util_machine_audio_connection_bulk_add(guint nth_machine);
+gboolean ags_functional_test_util_machine_audio_connection_bulk_remove(guint nth_machine,
+								       guint nth_bulk);
+
+gboolean ags_functional_test_util_machine_audio_connection_bulk_first_line(guint nth_machine,
+									   guint nth_bulk,
+									   guint first_line);
+gboolean ags_functional_test_util_machine_audio_connection_bulk_count(guint nth_machine,
+								      guint nth_bulk,
+								      guint count);
+gboolean ags_functional_test_util_machine_audio_connection_bulk_device(guint nth_machine,
+								       guint nth_bulk,
+								       gchar *device);
+
+/* midi connection */
+gboolean ags_functional_test_util_machine_midi_connection_midi_channel(guint nth_machine,
+								       guint midi_channel);
+
+gboolean ags_functional_test_util_machine_midi_connection_audio_start_mapping(guint nth_machine,
+									      guint audio_start_mapping);
+gboolean ags_functional_test_util_machine_midi_connection_audio_end_mapping(guint nth_machine,
+									    guint audio_end_mapping);
+
+gboolean ags_functional_test_util_machine_midi_connection_midi_start_mapping(guint nth_machine,
+									     guint midi_start_mapping);
+gboolean ags_functional_test_util_machine_midi_connection_midi_end_mapping(guint nth_machine,
+									   guint midi_end_mapping);
+gboolean ags_functional_test_util_machine_midi_connection_midi_device(guint nth_machine,
+								      gchar *device);
+
+/* generic pad */
+gboolean ags_functional_test_util_pad_group(guint nth_machine,
+					    guint nth_pad);
+gboolean ags_functional_test_util_pad_mute(guint nth_machine,
+					   guint nth_pad);
+gboolean ags_functional_test_util_pad_solo(guint nth_machine,
+					   guint nth_pad);
+
+gboolean ags_functional_test_util_pad_play(guint nth_machine,
+					   guint nth_pad);
+
+/* generic line */
+gboolean ags_functional_test_util_expander(guint nth_machine,
+					   guint nth_pad, guint nth_audio_channel);
+
+/* generic effect bulk */
+gboolean ags_functional_test_util_effect_bulk_add(guint nth_machine);
+
+gboolean ags_functional_test_util_effect_bulk_remove(guint nth_machine,
+						     guint nth_bulk_effect);
+
+gboolean ags_functional_test_util_effect_bulk_ladspa_filename(guint nth_machine,
+							      gchar *filename);
+gboolean ags_functional_test_util_effect_bulk_ladspa_effect(guint nth_machine,
+							    gchar *effect);
+
+gboolean ags_functional_test_util_effect_bulk_lv2_filename(guint nth_machine,
+							   gchar *filename);
+gboolean ags_functional_test_util_effect_bulk_lv2_effect(guint nth_machine,
+							 gchar *effect);
+
+/* panel */
+gboolean ags_functional_test_util_panel_mute_line(guint nth_machine,
+						  guint nth_pad, guint nth_audio_channel);
+
+/* mixer input line */
+gboolean ags_functional_test_util_mixer_input_line_volume(guint nth_machine,
+							  guint nth_pad, guint nth_audio_channel,
+							  gdouble volume);
+
+/* drum */
+gboolean ags_functional_test_util_drum_open(guint nth_machine);
+
+gboolean ags_functional_test_util_drum_run(guint nth_machine);
+gboolean ags_functional_test_util_drum_loop(guint nth_machine);
+
+gboolean ags_functional_test_util_drum_bank_0(guint nth_machine,
+					      guint bank_0);
+gboolean ags_functional_test_util_drum_bank_1(guint nth_machine,
+					      guint bank_1);
+
+gboolean ags_functional_test_util_drum_length(guint nth_machine,
+					      guint length);
+gboolean ags_functional_test_util_drum_index(guint nth_machine,
+					     guint nth_radio);
+
+gboolean ags_functional_test_util_drum_pad(guint nth_machine,
+					   guint nth_pad);
+
+/* drum input pad */
+gboolean ags_functional_test_util_drum_pad_open(guint nth_machine,
+						guint nth_pad);
+gboolean ags_functional_test_util_drum_pad_edit(guint nth_machine,
+						guint nth_pad);
+
+/* drum input line */
+gboolean ags_functional_test_util_drum_input_line_volume(guint nth_machine,
+							 guint nth_pad, guint nth_audio_channel,
+							 gdouble volume);
+
+/* matrix */
+gboolean ags_functional_test_util_matrix_run(guint nth_machine);
+gboolean ags_functional_test_util_matrix_loop(guint nth_machine);
+
+gboolean ags_functional_test_util_matrix_bank_1(guint nth_machine,
+						guint bank_1);
+
+gboolean ags_functional_test_util_matrix_length(guint nth_machine,
+						guint length);
+
+gboolean ags_functional_test_util_matrix_gutter(guint nth_machine,
+						guint nth_gutter);
+
+gboolean ags_functional_test_util_drum_cell(guint nth_machine,
+					    guint x, guint y);
+
+/* synth */
+gboolean ags_functional_test_util_synth_auto_update(guint nth_machine);
+gboolean ags_functional_test_util_synth_update(guint nth_machine);
+
+gboolean ags_functional_test_util_oscillator_wave(guint nth_machine,
+						  guint nth_oscillator,
+						  gchar *wave);
+gboolean ags_functional_test_util_oscillator_phase(guint nth_machine,
+						   guint nth_oscillator,
+						   gdouble phase);
+gboolean ags_functional_test_util_oscillator_attack(guint nth_machine,
+						    guint nth_oscillator,
+						    gdouble attack);
+gboolean ags_functional_test_util_oscillator_frequency(guint nth_machine,
+						       guint nth_oscillator,
+						       gdouble frequency);
+gboolean ags_functional_test_util_oscillator_length(guint nth_machine,
+						    guint nth_oscillator,
+						    gdouble length);
+gboolean ags_functional_test_util_oscillator_volume(guint nth_machine,
+						    guint nth_oscillator,
+						    gdouble volume);
+
+/* ffplayer */
+gboolean ags_functional_test_util_ffplayer_open(guint nth_machine);
+
+gboolean ags_functional_test_util_ffplayer_preset(guint nth_machine,
+						  gchar *preset);
+gboolean ags_functional_test_util_ffplayer_instrument(guint nth_machine,
+						      gchar *instrument);
+
+#endif /*__AGS_FUNCTIONAL_TEST_UTIL_H__*/
diff --git a/ags/test/X/ags_xorg_application_context_test.c b/ags/test/X/ags_xorg_application_context_test.c
new file mode 100644
index 0000000..2c89bfc
--- /dev/null
+++ b/ags/test/X/ags_xorg_application_context_test.c
@@ -0,0 +1,198 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
+
+#include <ags/X/ags_xorg_application_context.h>
+
+#define AGS_XORG_APPLICATION_CONTEXT_TEST_DISPOSE_DEVOUT_COUNT (8)
+
+int ags_xorg_application_context_test_init_suite();
+int ags_xorg_application_context_test_clean_suite();
+
+void ags_xorg_application_context_test_dispose();
+void ags_xorg_application_context_test_finalize();
+
+void ags_xorg_application_context_test_finalize_stub(GObject *gobject);
+
+#define AGS_XORG_APPLICATION_CONTEXT_TEST_CONFIG "[generic]\n" \
+  "autosave-thread=false\n"			       \
+  "simple-file=true\n"				       \
+  "disable-feature=experimental\n"		       \
+  "segmentation=4/4\n"				       \
+  "\n"						       \
+  "[thread]\n"					       \
+  "model=super-threaded\n"			       \
+  "super-threaded-scope=channel\n"		       \
+  "lock-global=ags-thread\n"			       \
+  "lock-parent=ags-recycling-thread\n"		       \
+  "\n"						       \
+  "[soundcard-0]\n"				       \
+  "backend=alsa\n"                                     \
+  "device=hw:0,0\n"                                    \
+  "samplerate=44100\n"				       \
+  "buffer-size=1024\n"				       \
+  "pcm-channels=2\n"				       \
+  "dsp-channels=2\n"				       \
+  "format=16\n"					       \
+  "\n"						       \
+  "[soundcard-1]\n"				       \
+  "backend=alsa\n"                                     \
+  "device=hw:0,0\n"                                    \
+  "samplerate=44100\n"				       \
+  "buffer-size=1024\n"				       \
+  "pcm-channels=2\n"				       \
+  "dsp-channels=2\n"				       \
+  "format=16\n"					       \
+  "\n"						       \
+  "[recall]\n"					       \
+  "auto-sense=true\n"				       \
+  "\n"
+
+gboolean xorg_application_context_test_finalized;
+
+/* The suite initialization function.
+ * Opens the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_xorg_application_context_test_init_suite()
+{
+  AgsConfig *config;
+
+  config = ags_config_get_instance();
+  ags_config_load_from_data(config,
+			    AGS_XORG_APPLICATION_CONTEXT_TEST_CONFIG,
+			    strlen(AGS_XORG_APPLICATION_CONTEXT_TEST_CONFIG));
+    
+  return(0);
+}
+
+/* The suite cleanup function.
+ * Closes the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_xorg_application_context_test_clean_suite()
+{
+  
+  return(0);
+}
+
+void
+ags_xorg_application_context_test_dispose()
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  xorg_application_context = g_object_new(AGS_TYPE_XORG_APPLICATION_CONTEXT,
+					   NULL);
+
+  /* run dispose */
+  g_object_run_dispose(xorg_application_context);
+
+  /* assert */
+  CU_ASSERT(xorg_application_context->thread_pool == NULL);
+  CU_ASSERT(xorg_application_context->polling_thread == NULL);
+  CU_ASSERT(xorg_application_context->soundcard_thread == NULL);
+  CU_ASSERT(xorg_application_context->export_thread == NULL);
+  CU_ASSERT(xorg_application_context->autosave_thread == NULL);
+  CU_ASSERT(xorg_application_context->server == NULL);
+  CU_ASSERT(xorg_application_context->soundcard == NULL);
+  CU_ASSERT(xorg_application_context->sequencer == NULL);
+  CU_ASSERT(xorg_application_context->distributed_manager == NULL);
+  CU_ASSERT(xorg_application_context->window == NULL);
+}
+
+void
+ags_xorg_application_context_test_finalize()
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  xorg_application_context = g_object_new(AGS_TYPE_XORG_APPLICATION_CONTEXT,
+					   NULL);
+
+  /* run dispose */
+  g_object_run_dispose(xorg_application_context);
+
+  /* stub finalize */
+  xorg_application_context_test_finalized = FALSE;
+  G_OBJECT_GET_CLASS(xorg_application_context)->finalize = ags_xorg_application_context_test_finalize_stub;
+
+  /* unref and assert */
+  g_object_unref(xorg_application_context);
+  
+  CU_ASSERT(xorg_application_context_test_finalized == TRUE);
+}
+
+void
+ags_xorg_application_context_test_finalize_stub(GObject *gobject)
+{
+  xorg_application_context_test_finalized = TRUE;
+}
+
+int
+main(int argc, char **argv)
+{
+  CU_pSuite pSuite = NULL;
+
+  putenv("LC_ALL=C\0");
+  putenv("LANG=C\0");
+
+  /* initialize the CUnit test registry */
+  if(CUE_SUCCESS != CU_initialize_registry()){
+    return CU_get_error();
+  }
+
+  /* add a suite to the registry */
+  pSuite = CU_add_suite("AgsXorgApplicationContextTest\0", ags_xorg_application_context_test_init_suite, ags_xorg_application_context_test_clean_suite);
+  
+  if(pSuite == NULL){
+    CU_cleanup_registry();
+    
+    return CU_get_error();
+  }
+
+  gtk_init(NULL,
+	   NULL);
+  //  g_log_set_fatal_mask(G_LOG_DOMAIN, // "GLib-GObject\0", // "Gtk\0" G_LOG_DOMAIN,
+  //		       G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
+
+  /* add the tests to the suite */
+  if((CU_add_test(pSuite, "test of AgsXorgApplicationContext doing dispose\0", ags_xorg_application_context_test_dispose) == NULL) ||
+     (CU_add_test(pSuite, "test of AgsXorgApplicationContext doing finalize\0", ags_xorg_application_context_test_finalize) == NULL)){
+    CU_cleanup_registry();
+      
+    return CU_get_error();
+  }
+  
+  /* Run all tests using the CUnit Basic interface */
+  CU_basic_set_mode(CU_BRM_VERBOSE);
+  CU_basic_run_tests();
+  
+  CU_cleanup_registry();
+  
+  return(CU_get_error());
+}
diff --git a/ags/test/X/gsequencer_setup_util.c b/ags/test/X/gsequencer_setup_util.c
new file mode 100644
index 0000000..683db73
--- /dev/null
+++ b/ags/test/X/gsequencer_setup_util.c
@@ -0,0 +1,701 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gdk/gdk.h>
+#include <pango/pangocairo.h>
+
+#include <X11/Xlib.h>
+
+#include <libinstpatch/libinstpatch.h>
+
+#include "gsequencer_setup_util.h"
+
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
+#include <ags/libags-gui.h>
+
+#include <ags/X/ags_xorg_application_context.h>
+#include <ags/X/ags_window.h>
+
+#include <ags/X/file/ags_simple_file.h>
+
+#include <ags/X/thread/ags_gui_thread.h>
+#include <ags/X/thread/ags_simple_autosave_thread.h>
+
+#include <ags/X/task/ags_simple_file_read.h>
+
+#include <libxml/parser.h>
+#include <libxml/xlink.h>
+#include <libxml/xpath.h>
+#include <libxml/valid.h>
+#include <libxml/xmlIO.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/xmlsave.h>
+
+#include <string.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "config.h"
+
+struct sigaction ags_test_sigact;
+
+extern AgsApplicationContext *ags_application_context;
+
+extern volatile gboolean ags_show_start_animation;
+
+void
+ags_test_show_file_error(gchar *filename,
+			 GError *error)
+{
+  GtkDialog *dialog;
+      
+  g_warning("could not parse file %s\0", filename);
+      
+  dialog = gtk_message_dialog_new(NULL,
+				  0,
+				  GTK_MESSAGE_WARNING,
+				  GTK_BUTTONS_OK,
+				  "Failed to open '%s'\0",
+				  filename);
+  gtk_widget_show_all((GtkWidget *) dialog);
+  g_signal_connect(dialog, "response\0",
+		   G_CALLBACK(gtk_main_quit), NULL);
+  gtk_main();
+}
+
+void
+ags_test_signal_handler(int signr)
+{
+  if(signr == SIGINT){
+    //TODO:JK: do backup
+    
+    exit(-1);
+  }else{
+    sigemptyset(&(ags_test_sigact.sa_mask));
+
+    //    if(signr == AGS_ASYNC_QUEUE_SIGNAL_HIGH){
+      // pthread_yield();
+    //    }
+  }
+}
+
+void
+ags_test_signal_cleanup()
+{
+  sigemptyset(&(ags_test_sigact.sa_mask));
+}
+
+void
+ags_test_setup(int argc, char **argv)
+{
+  AgsLadspaManager *ladspa_manager;
+  AgsDssiManager *dssi_manager;
+  AgsLv2Manager *lv2_manager;
+  AgsLv2uiManager *lv2ui_manager;
+  AgsLv2WorkerManager *lv2_worker_manager;
+
+  AgsLog *log;
+
+  gchar *blacklist_filename;
+  gchar *filename;
+  
+  uid_t uid;
+
+  guint i;
+  
+  /* check filename */
+  log = ags_log_get_instance();
+  filename = NULL;
+
+  ags_log_add_message(log,
+		      "Welcome to Advanced Gtk+ Sequencer\0");
+  
+  for(i = 0; i < argc; i++){
+    if(!strncmp(argv[i], "--filename\0", 11)){
+      AgsSimpleFile *simple_file;
+
+      xmlXPathContext *xpath_context; 
+      xmlXPathObject *xpath_object;
+      xmlNode **node;
+
+      xmlChar *xpath;
+      
+      gchar *buffer;
+      guint buffer_length;
+      
+      filename = argv[i + 1];
+      simple_file = ags_simple_file_new();
+      g_object_set(simple_file,
+		   "filename\0", filename,
+		   NULL);
+      ags_simple_file_open(simple_file,
+			   NULL);
+
+      xpath = "/ags-simple-file/ags-sf-config";
+
+      /* Create xpath evaluation context */
+      xpath_context = xmlXPathNewContext(simple_file->doc);
+
+      if(xpath_context == NULL) {
+	g_warning("Error: unable to create new XPath context\0");
+
+	break;
+      }
+
+      /* Evaluate xpath expression */
+      xpath_object = xmlXPathEval(xpath, xpath_context);
+
+      if(xpath_object == NULL) {
+	g_warning("Error: unable to evaluate xpath expression \"%s\"\0", xpath);
+	xmlXPathFreeContext(xpath_context); 
+
+	break;
+      }
+
+      node = xpath_object->nodesetval->nodeTab;
+  
+      for(i = 0; i < xpath_object->nodesetval->nodeNr; i++){
+	if(node[i]->type == XML_ELEMENT_NODE){
+	  buffer = xmlNodeGetContent(node[i]);
+	  buffer_length = strlen(buffer);
+	  
+	  break;
+	}
+      }
+      
+      if(buffer != NULL){
+	//	ags_config_clear(ags_config_get_instance());
+	ags_config_load_from_data(ags_config_get_instance(),
+				  buffer, buffer_length);
+      }
+      
+      break;
+    }
+  }
+
+  /* load ladspa manager */
+  ladspa_manager = ags_ladspa_manager_get_instance();
+
+  blacklist_filename = "ladspa.blacklist\0";
+  ags_ladspa_manager_load_blacklist(ladspa_manager,
+				    blacklist_filename);
+
+  ags_log_add_message(ags_log_get_instance(),
+		      "* Loading LADSPA plugins\0");
+  
+  ags_ladspa_manager_load_default_directory(ladspa_manager);
+
+  /* load dssi manager */
+  dssi_manager = ags_dssi_manager_get_instance();
+
+  blacklist_filename = "dssi_plugin.blacklist\0";
+  ags_dssi_manager_load_blacklist(dssi_manager,
+				  blacklist_filename);
+
+  ags_log_add_message(ags_log_get_instance(),
+		      "* Loading DSSI plugins\0");
+
+  ags_dssi_manager_load_default_directory(dssi_manager);
+
+  /* load lv2 manager */
+  lv2_manager = ags_lv2_manager_get_instance();
+  lv2_worker_manager = ags_lv2_worker_manager_get_instance();    
+
+  blacklist_filename = "lv2_plugin.blacklist\0";
+  ags_lv2_manager_load_blacklist(lv2_manager,
+				 blacklist_filename);
+
+  ags_log_add_message(ags_log_get_instance(),
+		      "* Loading Lv2 plugins\0");
+
+  ags_lv2_manager_load_default_directory(lv2_manager);
+
+  /* load lv2ui manager */
+  lv2ui_manager = ags_lv2ui_manager_get_instance();  
+
+  blacklist_filename = "lv2ui_plugin.blacklist\0";
+  ags_lv2ui_manager_load_blacklist(lv2ui_manager,
+				   blacklist_filename);
+  
+  ags_log_add_message(ags_log_get_instance(),
+		      "* Loading Lv2ui plugins\0");
+
+  ags_lv2ui_manager_load_default_directory(lv2ui_manager);
+  
+  /* application contex */
+  ags_application_context = (AgsApplicationContext *) ags_xorg_application_context_new();
+  ags_application_context->argc = argc;
+  ags_application_context->argv = argv;
+
+  ags_application_context_register_types(ags_application_context);
+
+  /* fix cross-references in managers */
+  lv2_worker_manager->thread_pool = ((AgsXorgApplicationContext *) ags_application_context)->thread_pool;
+
+  g_atomic_int_set(&(ags_show_start_animation),
+		   FALSE);
+}
+
+void
+ags_test_start_animation(pthread_t *thread)
+{
+  GtkWindow *window;
+
+  GdkWindowAttr *attr;
+
+  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+  g_object_set(window,
+	       "decorated\0", FALSE,
+	       0);
+  gtk_widget_set_size_request(window,
+			      800, 450);
+  gtk_widget_show_all(window);
+
+  pthread_create(thread, NULL,
+		 ags_test_start_animation_thread, window);
+}
+void*
+ags_test_start_animation_thread(void *ptr)
+{
+  GtkWidget *window;
+  GdkRectangle rectangle;
+
+  cairo_t *gdk_cr, *cr;
+  cairo_surface_t *surface;
+
+  AgsLog *log;
+
+  gchar *filename;
+  unsigned char *bg_data, *image_data;
+  
+  /* create a buffer suitable to image size */
+  GList *list, *start;
+
+  guint image_size;
+  gdouble x0, y0;
+  guint i, nth;
+  
+  gdk_threads_enter();
+  
+  window = (GtkWidget *) ptr;
+
+  rectangle.x = 0;
+  rectangle.y = 0;
+  rectangle.width = 800;
+  rectangle.height = 450;
+
+  image_size = 4 * 800 * 450;
+  
+  gdk_cr = gdk_cairo_create(window->window);
+  
+  filename = g_strdup_printf("%s/%s\0",
+			     SRCDIR,
+			     "gsequencer.share/images/ags_supermoon-800x450.png\0");
+
+  surface = cairo_image_surface_create_from_png(filename);
+  image_data = cairo_image_surface_get_data(surface);
+  
+  bg_data = (unsigned char *) malloc(image_size * sizeof(unsigned char));
+
+  if(image_data != NULL){
+    memcpy(bg_data, image_data, image_size * sizeof(unsigned char));
+  }
+  
+  cr = cairo_create(surface);
+  
+  cairo_select_font_face(cr, "Georgia\0",
+			 CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+  cairo_set_font_size(cr, (gdouble) 11.0);
+  
+  gdk_window_show(window->window);
+  
+  gdk_threads_leave();
+
+  log = ags_log_get_instance();  
+  nth = 0;
+  
+  while(g_atomic_int_get(&(ags_show_start_animation))){
+    start = 
+      list = ags_log_get_messages(log);
+
+    i = g_list_length(start);
+
+    if(i > nth){
+      if(image_data != NULL){
+	memcpy(image_data, bg_data, image_size * sizeof(unsigned char));
+      }
+      
+      cairo_set_source_surface(cr, surface, 0, 0);
+      cairo_paint(cr);
+      cairo_surface_flush(surface);
+    
+      x0 = 4.0;
+      y0 = 4.0 + (i * 12.0);
+
+      while(y0 > 4.0 && list != NULL){
+	cairo_set_source_rgb(cr,
+			     1.0,
+			     0.0,
+			     1.0);
+	
+	cairo_move_to(cr,
+		      x0, y0);
+
+	cairo_show_text(cr, list->data);
+
+	list = list->next;
+	y0 -= 12.0;
+      }
+
+      cairo_move_to(cr,
+		    x0, 4.0 + (i + 1) * 12.0);
+      cairo_show_text(cr, "...\0");
+      
+      nth = g_list_length(start);
+    }
+
+    cairo_set_source_surface(gdk_cr, surface, 0, 0);
+    cairo_paint(gdk_cr);
+    cairo_surface_flush(surface);
+    gdk_flush();
+  }
+
+  free(bg_data);
+  
+  gdk_threads_enter();
+
+  gtk_widget_destroy(window);
+  
+  gdk_threads_leave();
+}
+
+void
+ags_test_launch(gboolean single_thread)
+{
+  AgsMutexManager *mutex_manager;
+  AgsThread *audio_loop, *polling_thread, *gui_thread, *task_thread;
+  AgsThreadPool *thread_pool;
+
+  AgsConfig *config;
+
+  GList *start_queue;  
+
+  pthread_mutex_t *application_mutex;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+    
+  /* get threads, thread pool and config */
+  pthread_mutex_lock(application_mutex);
+  
+  audio_loop = (AgsThread *) ags_application_context->main_loop;
+  task_thread = (AgsThread *) ags_application_context->task_thread;
+  thread_pool = AGS_TASK_THREAD(task_thread)->thread_pool;
+
+  config = ags_application_context->config;
+  
+  pthread_mutex_unlock(application_mutex);
+  
+  polling_thread = ags_thread_find_type(audio_loop,
+					AGS_TYPE_POLLING_THREAD);
+  gui_thread = ags_thread_find_type(audio_loop,
+				    AGS_TYPE_GUI_THREAD);
+
+  /* start engine */
+  pthread_mutex_lock(audio_loop->start_mutex);
+  
+  start_queue = NULL;
+  start_queue = g_list_prepend(start_queue,
+			       polling_thread);
+  start_queue = g_list_prepend(start_queue,
+			       task_thread);
+  //  start_queue = g_list_prepend(start_queue,
+  //			       gui_thread);
+  g_atomic_pointer_set(&(audio_loop->start_queue),
+		       start_queue);
+  
+  pthread_mutex_unlock(audio_loop->start_mutex);
+
+  /* start audio loop and thread pool*/
+  ags_thread_start(audio_loop);
+  
+  ags_thread_pool_start(thread_pool);
+
+  if(!single_thread){
+    /* wait for audio loop */
+    pthread_mutex_lock(audio_loop->start_mutex);
+
+    if(g_atomic_int_get(&(audio_loop->start_wait)) == TRUE){	
+      g_atomic_int_set(&(audio_loop->start_done),
+		       FALSE);
+      
+      while(g_atomic_int_get(&(audio_loop->start_wait)) == TRUE &&
+	    g_atomic_int_get(&(audio_loop->start_done)) == FALSE){
+	pthread_cond_wait(audio_loop->start_cond,
+			  audio_loop->start_mutex);
+      }
+    }
+    
+    pthread_mutex_unlock(audio_loop->start_mutex);
+
+    /* start gui thread */
+    ags_thread_start(gui_thread);
+
+    /* wait for gui thread */
+    pthread_mutex_lock(gui_thread->start_mutex);
+
+    if(g_atomic_int_get(&(gui_thread->start_done)) == FALSE){
+      
+      g_atomic_int_set(&(gui_thread->start_wait),
+    		       TRUE);
+
+      while(g_atomic_int_get(&(gui_thread->start_done)) == FALSE){
+    	g_atomic_int_set(&(gui_thread->start_wait),
+    			 TRUE);
+	
+    	pthread_cond_wait(gui_thread->start_cond,
+			  gui_thread->start_mutex);
+      }
+    }
+    
+    pthread_mutex_unlock(gui_thread->start_mutex);
+
+    g_atomic_int_set(&(AGS_XORG_APPLICATION_CONTEXT(ags_application_context)->gui_ready),
+		     1);
+    
+    /* autosave thread */
+    if(!g_strcmp0(ags_config_get_value(config,
+				       AGS_CONFIG_GENERIC,
+				       "autosave-thread\0"),
+		  "true\0")){
+      pthread_mutex_lock(audio_loop->start_mutex);
+
+      start_queue = g_atomic_pointer_get(&(audio_loop->start_queue));
+      start_queue = g_list_prepend(start_queue,
+				   task_thread);
+
+      g_atomic_pointer_set(&(audio_loop->start_queue),
+			   start_queue);
+	
+      pthread_mutex_unlock(audio_loop->start_mutex);
+    }
+  }else{
+    AgsSingleThread *single_thread;
+
+    /* single thread */
+    single_thread = ags_single_thread_new((GObject *) ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(ags_application_context))->data);
+
+    /* add known threads to single_thread */
+    ags_thread_add_child(AGS_THREAD(single_thread),
+			 audio_loop);
+    
+    /* autosave thread */
+    if(!g_strcmp0(ags_config_get_value(config,
+				       AGS_CONFIG_GENERIC,
+				       "autosave-thread\0"),
+		  "true\0")){
+      pthread_mutex_lock(audio_loop->start_mutex);
+
+      start_queue = g_atomic_pointer_get(&(audio_loop->start_queue));
+      start_queue = g_list_prepend(start_queue,
+				   task_thread);
+
+      g_atomic_pointer_set(&(audio_loop->start_queue),
+			   start_queue);
+	
+      pthread_mutex_unlock(audio_loop->start_mutex);
+    }
+
+    /* start thread tree */
+    ags_thread_start((AgsThread *) single_thread);
+  }
+}
+
+void
+ags_test_launch_filename(gchar *filename,
+			 gboolean single_thread)
+{
+  AgsMutexManager *mutex_manager;
+  AgsThread *audio_loop, *polling_thread, *gui_thread, *task_thread;
+  AgsThreadPool *thread_pool;
+
+  AgsConfig *config;
+
+  GList *start_queue;  
+
+  pthread_mutex_t *application_mutex;
+
+  mutex_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+    
+  /* get threads, thread pool and config */
+  pthread_mutex_lock(application_mutex);
+
+  audio_loop = (AgsThread *) ags_application_context->main_loop;
+  task_thread =(AgsThread *)  ags_application_context->task_thread;
+  thread_pool = AGS_TASK_THREAD(task_thread)->thread_pool;
+
+  config = ags_application_context->config;
+  
+  pthread_mutex_unlock(application_mutex);
+
+  polling_thread = ags_thread_find_type(audio_loop,
+					AGS_TYPE_POLLING_THREAD);
+  gui_thread = ags_thread_find_type(audio_loop,
+				    AGS_TYPE_GUI_THREAD);
+
+  /* open file */
+  if(g_strcmp0(ags_config_get_value(config,
+				    AGS_CONFIG_GENERIC,
+				    "simple-file\0"),
+		 "false\0")){
+    AgsSimpleFile *simple_file;
+
+    AgsSimpleFileRead *simple_file_read;
+      
+    GError *error;
+
+    simple_file = (AgsSimpleFile *) g_object_new(AGS_TYPE_SIMPLE_FILE,
+						 "application-context\0", ags_application_context,
+						 "filename\0", filename,
+						 NULL);
+    error = NULL;
+    ags_simple_file_open(simple_file,
+			 &error);
+
+    if(error != NULL){
+      ags_test_show_file_error(filename,
+			       error);
+      ags_application_context_quit(ags_application_context);
+    }
+    
+    /* start engine */  
+    pthread_mutex_lock(audio_loop->start_mutex);
+    
+    start_queue = NULL;
+    start_queue = g_list_prepend(start_queue,
+				 polling_thread);
+    start_queue = g_list_prepend(start_queue,
+				 task_thread);
+    //    start_queue = g_list_prepend(start_queue,
+    //				 gui_thread);
+    g_atomic_pointer_set(&(audio_loop->start_queue),
+			 start_queue);
+  
+    pthread_mutex_unlock(audio_loop->start_mutex);
+
+    /* start audio loop and thread pool */
+    ags_thread_start(audio_loop);
+
+    ags_thread_pool_start(thread_pool);
+
+    if(!single_thread){
+      /* wait for audio loop */
+      pthread_mutex_lock(audio_loop->start_mutex);
+
+      if(g_atomic_int_get(&(audio_loop->start_wait)) == TRUE){	
+	g_atomic_int_set(&(audio_loop->start_done),
+			 FALSE);
+      
+	while(g_atomic_int_get(&(audio_loop->start_wait)) == TRUE &&
+	      g_atomic_int_get(&(audio_loop->start_done)) == FALSE){
+	  pthread_cond_wait(audio_loop->start_cond,
+			    audio_loop->start_mutex);
+	}
+      }
+    
+      pthread_mutex_unlock(audio_loop->start_mutex);
+      
+      /* start gui thread */
+      ags_thread_start(gui_thread);
+
+      /* wait for gui thread */
+      pthread_mutex_lock(gui_thread->start_mutex);
+
+      if(g_atomic_int_get(&(gui_thread->start_done)) == FALSE){
+      
+      	g_atomic_int_set(&(gui_thread->start_wait),
+      			 TRUE);
+
+    	while(g_atomic_int_get(&(gui_thread->start_done)) == FALSE){
+    	  g_atomic_int_set(&(gui_thread->start_wait),
+    			   TRUE);
+	
+    	  pthread_cond_wait(gui_thread->start_cond,
+    			    gui_thread->start_mutex);
+    	}
+      }
+    
+      pthread_mutex_unlock(gui_thread->start_mutex);     
+      
+      /* autosave thread */
+      if(!g_strcmp0(ags_config_get_value(config,
+					 AGS_CONFIG_GENERIC,
+					 "autosave-thread\0"),
+		    "true\0")){
+	pthread_mutex_lock(audio_loop->start_mutex);
+
+	start_queue = g_atomic_pointer_get(&(audio_loop->start_queue));
+	start_queue = g_list_prepend(start_queue,
+				     task_thread);
+
+	g_atomic_pointer_set(&(audio_loop->start_queue),
+			     start_queue);
+	
+	pthread_mutex_unlock(audio_loop->start_mutex);
+      }
+    
+      /* now start read task */
+      simple_file_read = ags_simple_file_read_new(simple_file);
+      ags_task_thread_append_task((AgsTaskThread *) task_thread,
+				  (AgsTask *) simple_file_read);
+    }else{
+      AgsFile *file;
+
+      GError *error;
+    
+      file = g_object_new(AGS_TYPE_FILE,
+			  "application-context\0", ags_application_context,
+			  "filename\0", filename,
+			  NULL);
+      error = NULL;
+      ags_file_open(file,
+		    &error);
+
+      if(error != NULL){
+	ags_test_show_file_error(filename,
+				 error);
+	
+	ags_application_context_quit(ags_application_context);
+      }
+    
+      ags_file_read(file);
+      ags_file_close(file);
+    }
+  }
+
+  if(!single_thread){
+    ags_thread_start(gui_thread);    
+  }
+}
diff --git a/ags/lib/ags_complex.h b/ags/test/X/gsequencer_setup_util.h
similarity index 56%
copy from ags/lib/ags_complex.h
copy to ags/test/X/gsequencer_setup_util.h
index 48fb78e..9a37518 100644
--- a/ags/lib/ags_complex.h
+++ b/ags/test/X/gsequencer_setup_util.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -17,26 +17,25 @@
  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __AGS_COMPLEX__
-#define __AGS_COMPLEX__
+#ifndef __GSEQUENCER_TEST_SETUP_UTIL_H__
+#define __GSEQUENCER_TEST_SETUP_UTIL_H__
 
 #include <glib.h>
 #include <glib-object.h>
 
-#include <complex.h>
+void ags_test_show_file_error(gchar *filename,
+			      GError *error);
 
-#define AGS_TYPE_COMPLEX                (ags_complex_get_type())
+void ags_test_signal_handler(int signr);
+void ags_test_signal_cleanup();
 
-typedef long double AgsComplex[2];
+void ags_test_setup(int argc, char **argv);
 
-GType ags_complex_get_type(void);
+void ags_test_start_animation(pthread_t *thread);
+void* ags_test_start_animation_thread(void *ptr);
 
-AgsComplex* ags_complex_alloc();
+void ags_test_launch(gboolean single_thread);
+void ags_test_launch_filename(gchar *filename,
+			      gboolean single_thread);
 
-gpointer ags_complex_copy(AgsComplex *ptr);
-void ags_complex_free(AgsComplex *ptr);
-
-complex ags_complex_get(AgsComplex *ptr);
-void ags_complex_set(AgsComplex *ptr, complex z);
-
-#endif /*__AGS_COMPLEX__*/
+#endif /*__GSEQUENCER_TEST_SETUP_UTIL_H__*/
diff --git a/ags/test/X/libgsequencer.h b/ags/test/X/libgsequencer.h
new file mode 100644
index 0000000..0acfa69
--- /dev/null
+++ b/ags/test/X/libgsequencer.h
@@ -0,0 +1,229 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LIBGSEQUENCER_H__
+#define __LIBGSEQUENCER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+#include <ags/X/ags_midi_preferences_callbacks.h>
+#include <ags/X/ags_automation_editor_callbacks.h>
+#include <ags/X/ags_performance_preferences_callbacks.h>
+#include <ags/X/ags_soundcard_editor_callbacks.h>
+#include <ags/X/ags_line_editor_callbacks.h>
+#include <ags/X/ags_output_listing_editor_callbacks.h>
+#include <ags/X/ags_menu_bar.h>
+#include <ags/X/ags_editor_callbacks.h>
+#include <ags/X/ags_machine.h>
+#include <ags/X/ags_pad_callbacks.h>
+#include <ags/X/ags_effect_bulk_callbacks.h>
+#include <ags/X/ags_export_soundcard.h>
+#include <ags/X/ags_lv2_browser_callbacks.h>
+#include <ags/X/ags_dssi_browser.h>
+#include <ags/X/ags_line.h>
+#include <ags/X/ags_ladspa_browser_callbacks.h>
+#include <ags/X/ags_pad_editor_callbacks.h>
+#include <ags/X/file/ags_simple_file.h>
+#include <ags/X/file/ags_gui_file_xml.h>
+#include <ags/X/ags_line_member_editor_callbacks.h>
+#include <ags/X/ags_editor.h>
+#include <ags/X/ags_plugin_preferences_callbacks.h>
+#include <ags/X/editor/ags_sf2_chooser.h>
+#include <ags/X/editor/ags_machine_selector_callbacks.h>
+#include <ags/X/editor/ags_automation_edit_callbacks.h>
+#include <ags/X/editor/ags_meter.h>
+#include <ags/X/editor/ags_automation_area.h>
+#include <ags/X/editor/ags_scale_area_callbacks.h>
+#include <ags/X/editor/ags_machine_radio_button.h>
+#include <ags/X/editor/ags_pattern_edit_callbacks.h>
+#include <ags/X/editor/ags_automation_edit.h>
+#include <ags/X/editor/ags_toolbar_callbacks.h>
+#include <ags/X/editor/ags_inline_player.h>
+#include <ags/X/editor/ags_sf2_chooser_callbacks.h>
+#include <ags/X/editor/ags_note_edit.h>
+#include <ags/X/editor/ags_pattern_edit.h>
+#include <ags/X/editor/ags_file_selection.h>
+#include <ags/X/editor/ags_scale_area.h>
+#include <ags/X/editor/ags_automation_area_callbacks.h>
+#include <ags/X/editor/ags_file_selection_callbacks.h>
+#include <ags/X/editor/ags_automation_toolbar_callbacks.h>
+#include <ags/X/editor/ags_toolbar.h>
+#include <ags/X/editor/ags_note_edit_callbacks.h>
+#include <ags/X/editor/ags_inline_player_callbacks.h>
+#include <ags/X/editor/ags_toolbar_mode_stock.h>
+#include <ags/X/editor/ags_notebook_callbacks.h>
+#include <ags/X/editor/ags_scale_callbacks.h>
+#include <ags/X/editor/ags_machine_selector.h>
+#include <ags/X/editor/ags_machine_selection.h>
+#include <ags/X/editor/ags_scale.h>
+#include <ags/X/editor/ags_notebook.h>
+#include <ags/X/editor/ags_meter_callbacks.h>
+#include <ags/X/editor/ags_automation_toolbar.h>
+#include <ags/X/ags_link_editor.h>
+#include <ags/X/import/ags_track_collection.h>
+#include <ags/X/import/ags_track_collection_mapper.h>
+#include <ags/X/import/ags_midi_import_wizard.h>
+#include <ags/X/import/ags_midi_import_wizard_callbacks.h>
+#include <ags/X/import/ags_track_collection_mapper_callbacks.h>
+#include <ags/X/import/ags_track_collection_callbacks.h>
+#include <ags/X/ags_midi_dialog_callbacks.h>
+#include <ags/X/ags_export_soundcard_callbacks.h>
+#include <ags/X/ags_navigation_callbacks.h>
+#include <ags/X/ags_plugin_preferences.h>
+#include <ags/X/machine/ags_synth.h>
+#include <ags/X/machine/ags_matrix_bridge.h>
+#include <ags/X/machine/ags_drum_output_line.h>
+#include <ags/X/machine/ags_pattern_box_callbacks.h>
+#include <ags/X/machine/ags_ffplayer_callbacks.h>
+#include <ags/X/machine/ags_synth_input_line.h>
+#include <ags/X/machine/ags_ffplayer_bridge.h>
+#include <ags/X/machine/ags_ffplayer_input_line.h>
+#include <ags/X/machine/ags_mixer_callbacks.h>
+#include <ags/X/machine/ags_lv2_bridge_callbacks.h>
+#include <ags/X/machine/ags_matrix_bridge_callbacks.h>
+#include <ags/X/machine/ags_mixer_input_line.h>
+#include <ags/X/machine/ags_ffplayer_bulk_input_callbacks.h>
+#include <ags/X/machine/ags_ffplayer_input_line_callbacks.h>
+#include <ags/X/machine/ags_oscillator.h>
+#include <ags/X/machine/ags_pattern_box.h>
+#include <ags/X/machine/ags_dssi_bridge.h>
+#include <ags/X/machine/ags_matrix_bulk_input_callbacks.h>
+#include <ags/X/machine/ags_mixer.h>
+#include <ags/X/machine/ags_panel_input_line_callbacks.h>
+#include <ags/X/machine/ags_ffplayer.h>
+#include <ags/X/machine/ags_cell_pattern.h>
+#include <ags/X/machine/ags_mixer_input_pad.h>
+#include <ags/X/machine/ags_dssi_bridge_callbacks.h>
+#include <ags/X/machine/ags_drum_input_pad.h>
+#include <ags/X/machine/ags_oscillator_callbacks.h>
+#include <ags/X/machine/ags_matrix_bulk_input.h>
+#include <ags/X/machine/ags_synth_input_pad.h>
+#include <ags/X/machine/ags_matrix_callbacks.h>
+#include <ags/X/machine/ags_ffplayer_bridge_callbacks.h>
+#include <ags/X/machine/ags_ladspa_bridge_callbacks.h>
+#include <ags/X/machine/ags_drum_output_pad_callbacks.h>
+#include <ags/X/machine/ags_ffplayer_bulk_input.h>
+#include <ags/X/machine/ags_cell_pattern_callbacks.h>
+#include <ags/X/machine/ags_drum_input_line_callbacks.h>
+#include <ags/X/machine/ags_panel.h>
+#include <ags/X/machine/ags_lv2_bridge.h>
+#include <ags/X/machine/ags_panel_input_line.h>
+#include <ags/X/machine/ags_ladspa_bridge.h>
+#include <ags/X/machine/ags_panel_input_pad.h>
+#include <ags/X/machine/ags_synth_callbacks.h>
+#include <ags/X/machine/ags_matrix.h>
+#include <ags/X/machine/ags_drum.h>
+#include <ags/X/machine/ags_drum_callbacks.h>
+#include <ags/X/machine/ags_drum_output_line_callbacks.h>
+#include <ags/X/machine/ags_panel_callbacks.h>
+#include <ags/X/machine/ags_drum_input_line.h>
+#include <ags/X/machine/ags_ffplayer_input_pad.h>
+#include <ags/X/machine/ags_drum_output_pad.h>
+#include <ags/X/machine/ags_ffplayer_input_pad_callbacks.h>
+#include <ags/X/machine/ags_drum_input_pad_callbacks.h>
+#include <ags/X/ags_lv2_browser.h>
+#include <ags/X/ags_machine_editor.h>
+#include <ags/X/ags_line_editor.h>
+#include <ags/X/ags_sequencer_editor.h>
+#include <ags/X/ags_effect_line_callbacks.h>
+#include <ags/X/ags_listing_editor_callbacks.h>
+#include <ags/X/ags_soundcard_editor.h>
+#include <ags/X/ags_machine_callbacks.h>
+#include <ags/X/ags_dssi_browser_callbacks.h>
+#include <ags/X/ags_pad.h>
+#include <ags/X/ags_line_member.h>
+#include <ags/X/ags_sequencer_editor_callbacks.h>
+#include <ags/X/ags_window.h>
+#include <ags/X/ags_machine_editor_callbacks.h>
+#include <ags/X/ags_effect_bridge_callbacks.h>
+#include <ags/X/ags_automation_editor.h>
+#include <ags/X/ags_output_collection_editor_callbacks.h>
+#include <ags/X/ags_plugin_browser.h>
+#include <ags/X/ags_property_editor.h>
+#include <ags/X/ags_effect_bridge.h>
+#include <ags/X/ags_server_preferences.h>
+#include <ags/X/ags_connection_editor.h>
+#include <ags/X/ags_export_window.h>
+#include <ags/X/ags_export_window_callbacks.h>
+#include <ags/X/ags_link_collection_editor_callbacks.h>
+#include <ags/X/ags_xorg_application_context.h>
+#include <ags/X/ags_output_editor.h>
+#include <ags/X/ags_listing_editor.h>
+#include <ags/X/ags_preferences.h>
+#include <ags/X/ags_automation_window_callbacks.h>
+#include <ags/X/ags_menu_bar_callbacks.h>
+#include <ags/X/ags_plugin_browser_callbacks.h>
+#include <ags/X/ags_generic_preferences_callbacks.h>
+#include <ags/X/ags_property_collection_editor.h>
+#include <ags/X/ags_automation_window.h>
+#include <ags/X/ags_connection_editor_callbacks.h>
+#include <ags/X/ags_property_collection_editor_callbacks.h>
+#include <ags/X/ags_server_preferences_callbacks.h>
+#include <ags/X/ags_link_collection_editor.h>
+#include <ags/X/ags_output_editor_callbacks.h>
+#include <ags/X/ags_effect_pad.h>
+#include <ags/X/ags_output_collection_editor.h>
+#include <ags/X/task/ags_blink_cell_pattern_cursor.h>
+#include <ags/X/task/ags_toggle_led.h>
+#include <ags/X/task/ags_add_soundcard_editor_jack.h>
+#include <ags/X/task/ags_remove_soundcard_editor_jack.h>
+#include <ags/X/task/ags_display_tact.h>
+#include <ags/X/task/ags_scroll_on_play.h>
+#include <ags/X/task/ags_change_tact.h>
+#include <ags/X/task/ags_remove_sequencer_editor_jack.h>
+#include <ags/X/task/ags_add_line_member.h>
+#include <ags/X/task/ags_simple_file_write.h>
+#include <ags/X/task/ags_add_sequencer_editor_jack.h>
+#include <ags/X/task/ags_update_bulk_member.h>
+#include <ags/X/task/ags_change_indicator.h>
+#include <ags/X/task/ags_simple_file_read.h>
+#include <ags/X/task/ags_add_bulk_member.h>
+#include <ags/X/ags_link_editor_callbacks.h>
+#include <ags/X/ags_effect_pad_callbacks.h>
+#include <ags/X/ags_window_callbacks.h>
+#include <ags/X/ags_bulk_member.h>
+#include <ags/X/thread/ags_gui_thread.h>
+#include <ags/X/thread/ags_simple_autosave_thread.h>
+#include <ags/X/ags_effect_line.h>
+#include <ags/X/ags_line_member_callbacks.h>
+#include <ags/X/ags_resize_editor.h>
+#include <ags/X/ags_midi_preferences.h>
+#include <ags/X/ags_history_browser_callbacks.h>
+#include <ags/X/ags_ladspa_browser.h>
+#include <ags/X/ags_history_browser.h>
+#include <ags/X/ags_property_listing_editor.h>
+#include <ags/X/ags_performance_preferences.h>
+#include <ags/X/ags_audio_preferences.h>
+#include <ags/X/ags_generic_preferences.h>
+#include <ags/X/ags_bulk_member_callbacks.h>
+#include <ags/X/ags_property_editor_callbacks.h>
+#include <ags/X/ags_line_member_editor.h>
+#include <ags/X/ags_preferences_callbacks.h>
+#include <ags/X/ags_output_listing_editor.h>
+#include <ags/X/ags_audio_preferences_callbacks.h>
+#include <ags/X/ags_navigation.h>
+#include <ags/X/ags_line_callbacks.h>
+#include <ags/X/ags_pad_editor.h>
+#include <ags/X/ags_midi_dialog.h>
+#include <ags/X/ags_effect_bulk.h>
+
+#endif /*__LIBGSEQUENCER_H__*/
diff --git a/ags/test/X/machine/ags_functional_drum_test.c b/ags/test/X/machine/ags_functional_drum_test.c
new file mode 100644
index 0000000..b952c15
--- /dev/null
+++ b/ags/test/X/machine/ags_functional_drum_test.c
@@ -0,0 +1,489 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
+
+#include <ags/gsequencer_main.h>
+
+#include <ags/test/X/libgsequencer.h>
+
+#include "../gsequencer_setup_util.h"
+#include "../ags_functional_test_util.h"
+
+int ags_functional_drum_test_init_suite();
+int ags_functional_drum_test_clean_suite();
+
+void ags_functional_drum_test_open_drum_kit();
+void ags_functional_drum_test_resize_pads();
+void ags_functional_drum_test_resize_audio_channels();
+
+#define AGS_FUNCTIONAL_DRUM_TEST_OPEN_DRUM_KIT_PATH "/usr/share/hydrogen/data/drumkits/Synthie-1/"
+
+#define AGS_FUNCTIONAL_DRUM_TEST_RESIZE_OUTPUT_PADS (5)
+#define AGS_FUNCTIONAL_DRUM_TEST_RESIZE_INPUT_PADS (15)
+
+#define AGS_FUNCTIONAL_DRUM_TEST_RESIZE_AUDIO_CHANNELS (7)
+
+#define AGS_FUNCTIONAL_DRUM_TEST_CONFIG "[generic]\n" \
+  "autosave-thread=false\n"			       \
+  "simple-file=true\n"				       \
+  "disable-feature=experimental\n"		       \
+  "segmentation=4/4\n"				       \
+  "\n"						       \
+  "[thread]\n"					       \
+  "model=super-threaded\n"			       \
+  "super-threaded-scope=channel\n"		       \
+  "lock-global=ags-thread\n"			       \
+  "lock-parent=ags-recycling-thread\n"		       \
+  "\n"						       \
+  "[soundcard-0]\n"				       \
+  "backend=alsa\n"                                     \
+  "device=hw:0,0\n"                                    \
+  "samplerate=44100\n"				       \
+  "buffer-size=1024\n"				       \
+  "pcm-channels=2\n"				       \
+  "dsp-channels=2\n"				       \
+  "format=16\n"					       \
+  "\n"						       \
+  "[recall]\n"					       \
+  "auto-sense=true\n"				       \
+  "\n"
+
+extern AgsApplicationContext *ags_application_context;
+
+extern struct sigaction ags_test_sigact;
+
+extern volatile gboolean ags_show_start_animation;
+
+AgsGuiThread *gui_thread;
+AgsTaskThread *task_thread;
+
+/* The suite initialization function.
+ * Opens the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_drum_test_init_suite()
+{
+  AgsConfig *config;
+
+  config = ags_config_get_instance();
+  ags_config_load_from_data(config,
+			    AGS_FUNCTIONAL_DRUM_TEST_CONFIG,
+			    strlen(AGS_FUNCTIONAL_DRUM_TEST_CONFIG));
+
+  ags_functional_test_util_setup_and_launch();
+
+  /* get gui thread */
+  gui_thread = ags_thread_find_type(ags_application_context->main_loop,
+				    AGS_TYPE_GUI_THREAD);
+
+  task_thread = ags_thread_find_type(ags_application_context->main_loop,
+				     AGS_TYPE_TASK_THREAD);
+    
+  return(0);
+}
+
+/* The suite cleanup function.
+ * Closes the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_drum_test_clean_suite()
+{  
+  ags_thread_stop(gui_thread);  
+
+  return(0);
+}
+
+void
+ags_functional_drum_test_open_drum_kit()
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  AgsDrum *drum;
+
+  GList *list_start, *list;
+
+  guint nth_machine;
+  gboolean success;
+
+  /* add drum */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Drum");
+
+  CU_ASSERT(success == TRUE);
+
+  /*  */
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve drum */
+  nth_machine = 0;
+
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+
+  if(list != NULL &&
+     AGS_IS_DRUM(list->data)){
+    drum = list->data;
+  }else{
+    drum = NULL;
+  }
+  
+  CU_ASSERT(drum != NULL);
+
+  /* open dialog */
+  success = ags_functional_test_util_drum_open(0);
+
+  CU_ASSERT(success == TRUE);
+
+  /* open path */
+  success = ags_functional_test_util_file_chooser_open_path(GTK_FILE_CHOOSER(drum->open_dialog),
+							    AGS_FUNCTIONAL_DRUM_TEST_OPEN_DRUM_KIT_PATH);
+  CU_ASSERT(success == TRUE);
+
+  /* select all */
+  success = ags_functional_test_util_file_chooser_select_all(GTK_FILE_CHOOSER(drum->open_dialog));
+
+  CU_ASSERT(success == TRUE);
+
+  /* response ok */
+  success = ags_functional_test_util_dialog_ok(GTK_DIALOG(drum->open_dialog));
+
+  CU_ASSERT(success == TRUE);
+
+  /* destroy drum */
+  success = ags_functional_test_util_machine_destroy(0);
+  
+  CU_ASSERT(success == TRUE);
+}
+
+void
+ags_functional_drum_test_resize_pads()
+{
+  GtkDialog *properties;
+
+  AgsXorgApplicationContext *xorg_application_context;
+  
+  AgsDrum *drum;
+
+  GList *list_start, *list;
+
+  guint nth_machine;
+  guint resize_tab;
+  gboolean success;
+
+  /* add drum */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Drum");
+
+  CU_ASSERT(success == TRUE);
+
+  /*  */
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve drum */
+  nth_machine = 0;
+
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+
+  if(list != NULL &&
+     AGS_IS_DRUM(list->data)){
+    drum = list->data;
+  }else{
+    drum = NULL;
+  }
+  
+  CU_ASSERT(drum != NULL);
+
+  /*
+   * resize output and input pads
+   */
+  
+  /* open properties */
+  ags_functional_test_util_machine_properties_open(nth_machine);
+
+  /* click tab */
+  resize_tab = 4;
+  
+  ags_functional_test_util_machine_properties_click_tab(nth_machine,
+							resize_tab);
+  
+  /* click enable */
+  ags_functional_test_util_machine_properties_click_enable(nth_machine);
+
+  /* set output pads */
+  ags_functional_test_util_machine_properties_resize_outputs(nth_machine,
+							     AGS_FUNCTIONAL_DRUM_TEST_RESIZE_OUTPUT_PADS);
+
+  /* set input pads */
+  ags_functional_test_util_machine_properties_resize_inputs(nth_machine,
+							    AGS_FUNCTIONAL_DRUM_TEST_RESIZE_INPUT_PADS);
+
+  /* response ok */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  properties = AGS_MACHINE(drum)->properties;
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_dialog_ok(properties);
+
+  /* destroy drum */
+  success = ags_functional_test_util_machine_destroy(0);
+}
+
+void
+ags_functional_drum_test_resize_audio_channels()
+{
+  GtkDialog *properties;
+
+  AgsXorgApplicationContext *xorg_application_context;
+  
+  AgsDrum *drum;
+
+  GList *list_start, *list;
+
+  guint nth_machine;
+  guint resize_tab;
+  gboolean success;
+
+  /* add drum */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Drum");
+
+  CU_ASSERT(success == TRUE);
+
+  /*  */
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve drum */
+  nth_machine = 0;
+
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+
+  if(list != NULL &&
+     AGS_IS_DRUM(list->data)){
+    drum = list->data;
+  }else{
+    drum = NULL;
+  }
+  
+  CU_ASSERT(drum != NULL);
+
+  /*
+   * resize audio channels
+   */
+  
+  /* open properties */
+  ags_functional_test_util_machine_properties_open(nth_machine);
+
+  /* click tab */
+  resize_tab = 4;
+  
+  ags_functional_test_util_machine_properties_click_tab(nth_machine,
+							resize_tab);
+  
+  /* click enable */
+  ags_functional_test_util_machine_properties_click_enable(nth_machine);
+
+  /* set output audio_channels */
+  ags_functional_test_util_machine_properties_resize_audio_channels(nth_machine,
+								    AGS_FUNCTIONAL_DRUM_TEST_RESIZE_AUDIO_CHANNELS);
+
+  /* response ok */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  properties = AGS_MACHINE(drum)->properties;
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_dialog_ok(properties);
+
+  /* destroy drum */
+  success = ags_functional_test_util_machine_destroy(0);
+}
+
+int
+main(int argc, char **argv)
+{
+  CU_pSuite pSuite = NULL;
+
+  AgsConfig *config;
+
+  pthread_t *animation_thread;
+
+  struct sched_param param;
+  struct rlimit rl;
+  struct sigaction sa;
+
+  gchar *rc_filename;
+  
+  int result;
+
+  const rlim_t kStackSize = 64L * 1024L * 1024L;   // min stack size = 64 Mb
+
+#ifdef AGS_USE_TIMER
+  timer_t *timer_id
+#endif
+  
+  putenv("LC_ALL=C\0");
+  putenv("LANG=C\0");
+
+  //  mtrace();
+  atexit(ags_test_signal_cleanup);
+
+  result = getrlimit(RLIMIT_STACK, &rl);
+
+  /* set stack size 64M */
+  if(result == 0){
+    if(rl.rlim_cur < kStackSize){
+      rl.rlim_cur = kStackSize;
+      result = setrlimit(RLIMIT_STACK, &rl);
+
+      if(result != 0){
+	//TODO:JK
+      }
+    }
+  }
+
+  param.sched_priority = GSEQUENCER_RT_PRIORITY;
+      
+  if(sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
+    perror("sched_setscheduler failed\0");
+  }
+
+  /* Ignore interactive and job-control signals.  */
+  signal(SIGINT, SIG_IGN);
+  signal(SIGQUIT, SIG_IGN);
+  signal(SIGTSTP, SIG_IGN);
+  signal(SIGTTIN, SIG_IGN);
+  signal(SIGTTOU, SIG_IGN);
+  signal(SIGCHLD, SIG_IGN);
+  signal(AGS_THREAD_RESUME_SIG, SIG_IGN);
+  signal(AGS_THREAD_SUSPEND_SIG, SIG_IGN);
+
+  ags_test_sigact.sa_handler = ags_test_signal_handler;
+  sigemptyset(&ags_test_sigact.sa_mask);
+  ags_test_sigact.sa_flags = 0;
+  sigaction(SIGINT, &ags_test_sigact, (struct sigaction *) NULL);
+  sigaction(SA_RESTART, &ags_test_sigact, (struct sigaction *) NULL);
+
+  XInitThreads();
+      
+  /* parse rc file */
+  rc_filename = g_strdup_printf("%s/%s\0",
+				SRCDIR,
+				"gsequencer.share/styles/ags.rc\0");
+  
+  gtk_rc_parse(rc_filename);
+  g_free(rc_filename);
+  
+  /**/
+  LIBXML_TEST_VERSION;
+
+  //ao_initialize();
+
+  gdk_threads_enter();
+  //  g_thread_init(NULL);
+  gtk_init(&argc, &argv);
+
+  g_object_set(gtk_settings_get_default(),
+	       "gtk-theme-name\0", "Raleigh\0",
+	       NULL);
+  g_signal_handlers_block_matched(gtk_settings_get_default(),
+				  G_SIGNAL_MATCH_DETAIL,
+				  g_signal_lookup("set-property\0",
+						  GTK_TYPE_SETTINGS),
+				  g_quark_from_string("gtk-theme-name\0"),
+				  NULL,
+				  NULL,
+				  NULL);
+  
+  ipatch_init();
+  g_log_set_fatal_mask("GLib-GObject\0", // "Gtk\0" G_LOG_DOMAIN, // 
+		       G_LOG_LEVEL_CRITICAL); // G_LOG_LEVEL_WARNING
+
+  /* animate */
+  animation_thread = (pthread_t *) malloc(sizeof(pthread_t));
+  g_atomic_int_set(&(ags_show_start_animation),
+		   TRUE);
+  
+  ags_test_start_animation(animation_thread);
+  
+  /* initialize the CUnit test registry */
+  if(CUE_SUCCESS != CU_initialize_registry()){
+    return CU_get_error();
+  }
+
+  /* add a suite to the registry */
+  pSuite = CU_add_suite("AgsFuncitonalDrumTest\0", ags_functional_drum_test_init_suite, ags_functional_drum_test_clean_suite);
+  
+  if(pSuite == NULL){
+    CU_cleanup_registry();
+    
+    return CU_get_error();
+  }
+
+  gtk_init(NULL,
+	   NULL);
+  //  g_log_set_fatal_mask(G_LOG_DOMAIN, // , // "Gtk\0" G_LOG_DOMAIN,"GLib-GObject\0",
+  //		       G_LOG_LEVEL_CRITICAL);
+
+  /* add the tests to the suite */
+  if((CU_add_test(pSuite, "functional test of AgsDrum open drum kit\0", ags_functional_drum_test_open_drum_kit) == NULL) ||
+     (CU_add_test(pSuite, "functional test of AgsDrum resize pads\0", ags_functional_drum_test_resize_pads) == NULL) ||
+     (CU_add_test(pSuite, "functional test of AgsDrum resize audio channels\0", ags_functional_drum_test_resize_audio_channels) == NULL)){
+    CU_cleanup_registry();
+      
+    return CU_get_error();
+  }
+  
+  /* Run all tests using the CUnit Basic interface */
+  CU_basic_set_mode(CU_BRM_VERBOSE);
+  CU_basic_run_tests();
+  
+  CU_cleanup_registry();
+  
+  return(CU_get_error());
+}
diff --git a/ags/test/X/machine/ags_functional_ffplayer_test.c b/ags/test/X/machine/ags_functional_ffplayer_test.c
new file mode 100644
index 0000000..ea1d250
--- /dev/null
+++ b/ags/test/X/machine/ags_functional_ffplayer_test.c
@@ -0,0 +1,491 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
+
+#include <ags/gsequencer_main.h>
+
+#include <ags/test/X/libgsequencer.h>
+
+#include "../gsequencer_setup_util.h"
+#include "../ags_functional_test_util.h"
+
+int ags_functional_ffplayer_test_init_suite();
+int ags_functional_ffplayer_test_clean_suite();
+
+void ags_functional_ffplayer_test_open_sf2();
+void ags_functional_ffplayer_test_resize_pads();
+void ags_functional_ffplayer_test_resize_audio_channels();
+
+#define AGS_FUNCTIONAL_FFPLAYER_TEST_OPEN_SF2_PATH "/usr/share/sounds/sf2"
+#define AGS_FUNCTIONAL_FFPLAYER_TEST_OPEN_SF2_FILENAME "/usr/share/sounds/sf2/FluidR3_GM.sf2"
+
+#define AGS_FUNCTIONAL_FFPLAYER_TEST_RESIZE_OUTPUT_PADS (5)
+#define AGS_FUNCTIONAL_FFPLAYER_TEST_RESIZE_INPUT_PADS (15)
+
+#define AGS_FUNCTIONAL_FFPLAYER_TEST_RESIZE_AUDIO_CHANNELS (7)
+
+#define AGS_FUNCTIONAL_FFPLAYER_TEST_CONFIG "[generic]\n"	\
+  "autosave-thread=false\n"					\
+  "simple-file=true\n"						\
+  "disable-feature=experimental\n"				\
+  "segmentation=4/4\n"						\
+  "\n"								\
+  "[thread]\n"							\
+  "model=super-threaded\n"					\
+  "super-threaded-scope=channel\n"				\
+  "lock-global=ags-thread\n"					\
+  "lock-parent=ags-recycling-thread\n"				\
+  "\n"								\
+  "[soundcard-0]\n"						\
+  "backend=alsa\n"						\
+  "device=hw:0,0\n"						\
+  "samplerate=44100\n"						\
+  "buffer-size=1024\n"						\
+  "pcm-channels=2\n"						\
+  "dsp-channels=2\n"						\
+  "format=16\n"							\
+  "\n"								\
+  "[recall]\n"							\
+  "auto-sense=true\n"						\
+  "\n"
+
+extern AgsApplicationContext *ags_application_context;
+
+extern struct sigaction ags_test_sigact;
+
+extern volatile gboolean ags_show_start_animation;
+
+AgsGuiThread *gui_thread;
+AgsTaskThread *task_thread;
+
+/* The suite initialization function.
+ * Opens the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_ffplayer_test_init_suite()
+{
+  AgsConfig *config;
+
+  config = ags_config_get_instance();
+  ags_config_load_from_data(config,
+			    AGS_FUNCTIONAL_FFPLAYER_TEST_CONFIG,
+			    strlen(AGS_FUNCTIONAL_FFPLAYER_TEST_CONFIG));
+
+  ags_functional_test_util_setup_and_launch();
+
+  /* get gui thread */
+  gui_thread = ags_thread_find_type(ags_application_context->main_loop,
+				    AGS_TYPE_GUI_THREAD);
+
+  task_thread = ags_thread_find_type(ags_application_context->main_loop,
+				     AGS_TYPE_TASK_THREAD);
+    
+  return(0);
+}
+
+/* The suite cleanup function.
+ * Closes the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_ffplayer_test_clean_suite()
+{  
+  ags_thread_stop(gui_thread);  
+
+  return(0);
+}
+
+void
+ags_functional_ffplayer_test_open_sf2()
+{
+  AgsXorgApplicationContext *xorg_application_context;
+
+  AgsFFPlayer *ffplayer;
+
+  GList *list_start, *list;
+
+  guint nth_machine;
+  gboolean success;
+
+  /* add ffplayer */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "FPlayer");
+
+  CU_ASSERT(success == TRUE);
+
+  /*  */
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve ffplayer */
+  nth_machine = 0;
+
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+
+  if(list != NULL &&
+     AGS_IS_FFPLAYER(list->data)){
+    ffplayer = list->data;
+  }else{
+    ffplayer = NULL;
+  }
+  
+  CU_ASSERT(ffplayer != NULL);
+
+  /* open dialog */
+  success = ags_functional_test_util_ffplayer_open(0);
+
+  CU_ASSERT(success == TRUE);
+
+  /* open path */
+  success = ags_functional_test_util_file_chooser_open_path(GTK_FILE_CHOOSER(ffplayer->open_dialog),
+							    AGS_FUNCTIONAL_FFPLAYER_TEST_OPEN_SF2_PATH);
+  CU_ASSERT(success == TRUE);
+
+  /* select sf2 */
+  success = ags_functional_test_util_file_chooser_select_filename(GTK_FILE_CHOOSER(ffplayer->open_dialog),
+								  AGS_FUNCTIONAL_FFPLAYER_TEST_OPEN_SF2_FILENAME);
+
+  CU_ASSERT(success == TRUE);
+
+  /* response ok */
+  success = ags_functional_test_util_dialog_ok(GTK_DIALOG(ffplayer->open_dialog));
+
+  CU_ASSERT(success == TRUE);
+
+  /* destroy ffplayer */
+  success = ags_functional_test_util_machine_destroy(0);
+  
+  CU_ASSERT(success == TRUE);
+}
+
+void
+ags_functional_ffplayer_test_resize_pads()
+{
+  GtkDialog *properties;
+
+  AgsXorgApplicationContext *xorg_application_context;
+  
+  AgsFFPlayer *ffplayer;
+
+  GList *list_start, *list;
+
+  guint nth_machine;
+  guint resize_tab;
+  gboolean success;
+
+  /* add ffplayer */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "FPlayer");
+
+  CU_ASSERT(success == TRUE);
+
+  /*  */
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve ffplayer */
+  nth_machine = 0;
+
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+
+  if(list != NULL &&
+     AGS_IS_FFPLAYER(list->data)){
+    ffplayer = list->data;
+  }else{
+    ffplayer = NULL;
+  }
+  
+  CU_ASSERT(ffplayer != NULL);
+
+  /*
+   * resize output and input pads
+   */
+  
+  /* open properties */
+  ags_functional_test_util_machine_properties_open(nth_machine);
+
+  /* click tab */
+  resize_tab = 4;
+  
+  ags_functional_test_util_machine_properties_click_tab(nth_machine,
+							resize_tab);
+  
+  /* click enable */
+  ags_functional_test_util_machine_properties_click_enable(nth_machine);
+
+  /* set output pads */
+  ags_functional_test_util_machine_properties_resize_outputs(nth_machine,
+							     AGS_FUNCTIONAL_FFPLAYER_TEST_RESIZE_OUTPUT_PADS);
+
+  /* set input pads */
+  ags_functional_test_util_machine_properties_resize_inputs(nth_machine,
+							    AGS_FUNCTIONAL_FFPLAYER_TEST_RESIZE_INPUT_PADS);
+
+  /* response ok */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  properties = AGS_MACHINE(ffplayer)->properties;
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_dialog_ok(properties);
+
+  /* destroy ffplayer */
+  success = ags_functional_test_util_machine_destroy(0);
+}
+
+void
+ags_functional_ffplayer_test_resize_audio_channels()
+{
+  GtkDialog *properties;
+
+  AgsXorgApplicationContext *xorg_application_context;
+  
+  AgsFFPlayer *ffplayer;
+
+  GList *list_start, *list;
+
+  guint nth_machine;
+  guint resize_tab;
+  gboolean success;
+
+  /* add ffplayer */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "FPlayer");
+
+  CU_ASSERT(success == TRUE);
+
+  /*  */
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve ffplayer */
+  nth_machine = 0;
+
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+
+  if(list != NULL &&
+     AGS_IS_FFPLAYER(list->data)){
+    ffplayer = list->data;
+  }else{
+    ffplayer = NULL;
+  }
+  
+  CU_ASSERT(ffplayer != NULL);
+
+  /*
+   * resize audio channels
+   */
+  
+  /* open properties */
+  ags_functional_test_util_machine_properties_open(nth_machine);
+
+  /* click tab */
+  resize_tab = 4;
+  
+  ags_functional_test_util_machine_properties_click_tab(nth_machine,
+							resize_tab);
+  
+  /* click enable */
+  ags_functional_test_util_machine_properties_click_enable(nth_machine);
+
+  /* set output audio_channels */
+  ags_functional_test_util_machine_properties_resize_audio_channels(nth_machine,
+								    AGS_FUNCTIONAL_FFPLAYER_TEST_RESIZE_AUDIO_CHANNELS);
+
+  /* response ok */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  properties = AGS_MACHINE(ffplayer)->properties;
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_dialog_ok(properties);
+
+  /* destroy ffplayer */
+  success = ags_functional_test_util_machine_destroy(0);
+}
+
+int
+main(int argc, char **argv)
+{
+  CU_pSuite pSuite = NULL;
+
+  AgsConfig *config;
+
+  pthread_t *animation_thread;
+
+  struct sched_param param;
+  struct rlimit rl;
+  struct sigaction sa;
+
+  gchar *rc_filename;
+  
+  int result;
+
+  const rlim_t kStackSize = 64L * 1024L * 1024L;   // min stack size = 64 Mb
+
+#ifdef AGS_USE_TIMER
+  timer_t *timer_id
+#endif
+  
+    putenv("LC_ALL=C\0");
+  putenv("LANG=C\0");
+
+  //  mtrace();
+  atexit(ags_test_signal_cleanup);
+
+  result = getrlimit(RLIMIT_STACK, &rl);
+
+  /* set stack size 64M */
+  if(result == 0){
+    if(rl.rlim_cur < kStackSize){
+      rl.rlim_cur = kStackSize;
+      result = setrlimit(RLIMIT_STACK, &rl);
+
+      if(result != 0){
+	//TODO:JK
+      }
+    }
+  }
+
+  param.sched_priority = GSEQUENCER_RT_PRIORITY;
+      
+  if(sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
+    perror("sched_setscheduler failed\0");
+  }
+
+  /* Ignore interactive and job-control signals.  */
+  signal(SIGINT, SIG_IGN);
+  signal(SIGQUIT, SIG_IGN);
+  signal(SIGTSTP, SIG_IGN);
+  signal(SIGTTIN, SIG_IGN);
+  signal(SIGTTOU, SIG_IGN);
+  signal(SIGCHLD, SIG_IGN);
+  signal(AGS_THREAD_RESUME_SIG, SIG_IGN);
+  signal(AGS_THREAD_SUSPEND_SIG, SIG_IGN);
+
+  ags_test_sigact.sa_handler = ags_test_signal_handler;
+  sigemptyset(&ags_test_sigact.sa_mask);
+  ags_test_sigact.sa_flags = 0;
+  sigaction(SIGINT, &ags_test_sigact, (struct sigaction *) NULL);
+  sigaction(SA_RESTART, &ags_test_sigact, (struct sigaction *) NULL);
+
+  XInitThreads();
+      
+  /* parse rc file */
+  rc_filename = g_strdup_printf("%s/%s\0",
+				SRCDIR,
+				"gsequencer.share/styles/ags.rc\0");
+  
+  gtk_rc_parse(rc_filename);
+  g_free(rc_filename);
+  
+  /**/
+  LIBXML_TEST_VERSION;
+
+  //ao_initialize();
+
+  gdk_threads_enter();
+  //  g_thread_init(NULL);
+  gtk_init(&argc, &argv);
+
+  g_object_set(gtk_settings_get_default(),
+	       "gtk-theme-name\0", "Raleigh\0",
+	       NULL);
+  g_signal_handlers_block_matched(gtk_settings_get_default(),
+				  G_SIGNAL_MATCH_DETAIL,
+				  g_signal_lookup("set-property\0",
+						  GTK_TYPE_SETTINGS),
+				  g_quark_from_string("gtk-theme-name\0"),
+				  NULL,
+				  NULL,
+				  NULL);
+  
+  ipatch_init();
+  g_log_set_fatal_mask("GLib-GObject\0", // "Gtk\0" G_LOG_DOMAIN, // 
+		       G_LOG_LEVEL_CRITICAL); // G_LOG_LEVEL_WARNING
+
+  /* animate */
+  animation_thread = (pthread_t *) malloc(sizeof(pthread_t));
+  g_atomic_int_set(&(ags_show_start_animation),
+		   TRUE);
+  
+  ags_test_start_animation(animation_thread);
+  
+  /* initialize the CUnit test registry */
+  if(CUE_SUCCESS != CU_initialize_registry()){
+    return CU_get_error();
+  }
+
+  /* add a suite to the registry */
+  pSuite = CU_add_suite("AgsFuncitonalFFPlayerTest\0", ags_functional_ffplayer_test_init_suite, ags_functional_ffplayer_test_clean_suite);
+  
+  if(pSuite == NULL){
+    CU_cleanup_registry();
+    
+    return CU_get_error();
+  }
+
+  gtk_init(NULL,
+	   NULL);
+  //  g_log_set_fatal_mask(G_LOG_DOMAIN, // , // "Gtk\0" G_LOG_DOMAIN,"GLib-GObject\0",
+  //		       G_LOG_LEVEL_CRITICAL);
+
+  /* add the tests to the suite */
+  if((CU_add_test(pSuite, "functional test of AgsFFPlayer open sf2\0", ags_functional_ffplayer_test_open_sf2) == NULL) ||
+     (CU_add_test(pSuite, "functional test of AgsFFPlayer resize pads\0", ags_functional_ffplayer_test_resize_pads) == NULL) ||
+     (CU_add_test(pSuite, "functional test of AgsFFPlayer resize audio channels\0", ags_functional_ffplayer_test_resize_audio_channels) == NULL)){
+    CU_cleanup_registry();
+      
+    return CU_get_error();
+  }
+  
+  /* Run all tests using the CUnit Basic interface */
+  CU_basic_set_mode(CU_BRM_VERBOSE);
+  CU_basic_run_tests();
+  
+  CU_cleanup_registry();
+  
+  return(CU_get_error());
+}
diff --git a/ags/test/X/machine/ags_functional_matrix_test.c b/ags/test/X/machine/ags_functional_matrix_test.c
new file mode 100644
index 0000000..12fd406
--- /dev/null
+++ b/ags/test/X/machine/ags_functional_matrix_test.c
@@ -0,0 +1,418 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
+
+#include <ags/gsequencer_main.h>
+
+#include <ags/test/X/libgsequencer.h>
+
+#include "../gsequencer_setup_util.h"
+#include "../ags_functional_test_util.h"
+
+int ags_functional_matrix_test_init_suite();
+int ags_functional_matrix_test_clean_suite();
+
+void ags_functional_matrix_test_resize_pads();
+void ags_functional_matrix_test_resize_audio_channels();
+
+#define AGS_FUNCTIONAL_MATRIX_TEST_RESIZE_OUTPUT_PADS (5)
+#define AGS_FUNCTIONAL_MATRIX_TEST_RESIZE_INPUT_PADS (15)
+
+#define AGS_FUNCTIONAL_MATRIX_TEST_RESIZE_AUDIO_CHANNELS (0)
+
+#define AGS_FUNCTIONAL_MATRIX_TEST_CONFIG "[generic]\n" \
+  "autosave-thread=false\n"				\
+  "simple-file=true\n"					\
+  "disable-feature=experimental\n"			\
+  "segmentation=4/4\n"					\
+  "\n"							\
+  "[thread]\n"						\
+  "model=super-threaded\n"				\
+  "super-threaded-scope=channel\n"			\
+  "lock-global=ags-thread\n"				\
+  "lock-parent=ags-recycling-thread\n"			\
+  "\n"							\
+  "[soundcard-0]\n"					\
+  "backend=alsa\n"					\
+  "device=hw:0,0\n"					\
+  "samplerate=44100\n"					\
+  "buffer-size=1024\n"					\
+  "pcm-channels=2\n"					\
+  "dsp-channels=2\n"					\
+  "format=16\n"						\
+  "\n"							\
+  "[recall]\n"						\
+  "auto-sense=true\n"					\
+  "\n"
+
+extern AgsApplicationContext *ags_application_context;
+
+extern struct sigaction ags_test_sigact;
+
+extern volatile gboolean ags_show_start_animation;
+
+AgsGuiThread *gui_thread;
+AgsTaskThread *task_thread;
+
+/* The suite initialization function.
+ * Opens the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_matrix_test_init_suite()
+{
+  AgsConfig *config;
+
+  config = ags_config_get_instance();
+  ags_config_load_from_data(config,
+			    AGS_FUNCTIONAL_MATRIX_TEST_CONFIG,
+			    strlen(AGS_FUNCTIONAL_MATRIX_TEST_CONFIG));
+
+  ags_functional_test_util_setup_and_launch();
+
+  /* get gui thread */
+  gui_thread = ags_thread_find_type(ags_application_context->main_loop,
+				    AGS_TYPE_GUI_THREAD);
+
+  task_thread = ags_thread_find_type(ags_application_context->main_loop,
+				     AGS_TYPE_TASK_THREAD);
+    
+  return(0);
+}
+
+/* The suite cleanup function.
+ * Closes the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_matrix_test_clean_suite()
+{  
+  ags_thread_stop(gui_thread);  
+
+  return(0);
+}
+
+void
+ags_functional_matrix_test_resize_pads()
+{
+  GtkDialog *properties;
+
+  AgsXorgApplicationContext *xorg_application_context;
+  
+  AgsMatrix *matrix;
+
+  GList *list_start, *list;
+
+  guint nth_machine;
+  guint resize_tab;
+  gboolean success;
+
+  /* add matrix */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Matrix");
+
+  CU_ASSERT(success == TRUE);
+
+  /*  */
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve matrix */
+  nth_machine = 0;
+
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+
+  if(list != NULL &&
+     AGS_IS_MATRIX(list->data)){
+    matrix = list->data;
+  }else{
+    matrix = NULL;
+  }
+  
+  CU_ASSERT(matrix != NULL);
+
+  /*
+   * resize output and input pads
+   */
+  
+  /* open properties */
+  ags_functional_test_util_machine_properties_open(nth_machine);
+
+  /* click tab */
+  resize_tab = 4;
+  
+  ags_functional_test_util_machine_properties_click_tab(nth_machine,
+							resize_tab);
+  
+  /* click enable */
+  ags_functional_test_util_machine_properties_click_enable(nth_machine);
+
+  /* set output pads */
+  ags_functional_test_util_machine_properties_resize_outputs(nth_machine,
+							     AGS_FUNCTIONAL_MATRIX_TEST_RESIZE_OUTPUT_PADS);
+
+  /* set input pads */
+  ags_functional_test_util_machine_properties_resize_inputs(nth_machine,
+							    AGS_FUNCTIONAL_MATRIX_TEST_RESIZE_INPUT_PADS);
+
+  /* response ok */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  properties = AGS_MACHINE(matrix)->properties;
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_dialog_ok(properties);
+
+  /* destroy matrix */
+  success = ags_functional_test_util_machine_destroy(0);
+}
+
+void
+ags_functional_matrix_test_resize_audio_channels()
+{
+  GtkDialog *properties;
+
+  AgsXorgApplicationContext *xorg_application_context;
+  
+  AgsMatrix *matrix;
+
+  GList *list_start, *list;
+
+  guint nth_machine;
+  guint resize_tab;
+  gboolean success;
+
+  /* add matrix */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Matrix");
+
+  CU_ASSERT(success == TRUE);
+
+  /*  */
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve matrix */
+  nth_machine = 0;
+
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+
+  if(list != NULL &&
+     AGS_IS_MATRIX(list->data)){
+    matrix = list->data;
+  }else{
+    matrix = NULL;
+  }
+  
+  CU_ASSERT(matrix != NULL);
+
+  /*
+   * resize audio channels
+   */
+  
+  /* open properties */
+  ags_functional_test_util_machine_properties_open(nth_machine);
+
+  /* click tab */
+  resize_tab = 4;
+  
+  ags_functional_test_util_machine_properties_click_tab(nth_machine,
+							resize_tab);
+  
+  /* click enable */
+  ags_functional_test_util_machine_properties_click_enable(nth_machine);
+
+  /* set output audio_channels */
+  ags_functional_test_util_machine_properties_resize_audio_channels(nth_machine,
+								    AGS_FUNCTIONAL_MATRIX_TEST_RESIZE_AUDIO_CHANNELS);
+
+  /* response ok */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  properties = AGS_MACHINE(matrix)->properties;
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_dialog_ok(properties);
+
+  /* destroy matrix */
+  success = ags_functional_test_util_machine_destroy(0);
+}
+
+int
+main(int argc, char **argv)
+{
+  CU_pSuite pSuite = NULL;
+
+  AgsConfig *config;
+
+  pthread_t *animation_thread;
+
+  struct sched_param param;
+  struct rlimit rl;
+  struct sigaction sa;
+
+  gchar *rc_filename;
+  
+  int result;
+
+  const rlim_t kStackSize = 64L * 1024L * 1024L;   // min stack size = 64 Mb
+
+#ifdef AGS_USE_TIMER
+  timer_t *timer_id
+#endif
+  
+    putenv("LC_ALL=C\0");
+  putenv("LANG=C\0");
+
+  //  mtrace();
+  atexit(ags_test_signal_cleanup);
+
+  result = getrlimit(RLIMIT_STACK, &rl);
+
+  /* set stack size 64M */
+  if(result == 0){
+    if(rl.rlim_cur < kStackSize){
+      rl.rlim_cur = kStackSize;
+      result = setrlimit(RLIMIT_STACK, &rl);
+
+      if(result != 0){
+	//TODO:JK
+      }
+    }
+  }
+
+  param.sched_priority = GSEQUENCER_RT_PRIORITY;
+      
+  if(sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
+    perror("sched_setscheduler failed\0");
+  }
+
+  /* Ignore interactive and job-control signals.  */
+  signal(SIGINT, SIG_IGN);
+  signal(SIGQUIT, SIG_IGN);
+  signal(SIGTSTP, SIG_IGN);
+  signal(SIGTTIN, SIG_IGN);
+  signal(SIGTTOU, SIG_IGN);
+  signal(SIGCHLD, SIG_IGN);
+  signal(AGS_THREAD_RESUME_SIG, SIG_IGN);
+  signal(AGS_THREAD_SUSPEND_SIG, SIG_IGN);
+
+  ags_test_sigact.sa_handler = ags_test_signal_handler;
+  sigemptyset(&ags_test_sigact.sa_mask);
+  ags_test_sigact.sa_flags = 0;
+  sigaction(SIGINT, &ags_test_sigact, (struct sigaction *) NULL);
+  sigaction(SA_RESTART, &ags_test_sigact, (struct sigaction *) NULL);
+
+  XInitThreads();
+      
+  /* parse rc file */
+  rc_filename = g_strdup_printf("%s/%s\0",
+				SRCDIR,
+				"gsequencer.share/styles/ags.rc\0");
+  
+  gtk_rc_parse(rc_filename);
+  g_free(rc_filename);
+  
+  /**/
+  LIBXML_TEST_VERSION;
+
+  //ao_initialize();
+
+  gdk_threads_enter();
+  //  g_thread_init(NULL);
+  gtk_init(&argc, &argv);
+
+  g_object_set(gtk_settings_get_default(),
+	       "gtk-theme-name\0", "Raleigh\0",
+	       NULL);
+  g_signal_handlers_block_matched(gtk_settings_get_default(),
+				  G_SIGNAL_MATCH_DETAIL,
+				  g_signal_lookup("set-property\0",
+						  GTK_TYPE_SETTINGS),
+				  g_quark_from_string("gtk-theme-name\0"),
+				  NULL,
+				  NULL,
+				  NULL);
+  
+  ipatch_init();
+  g_log_set_fatal_mask("GLib-GObject\0", // "Gtk\0" G_LOG_DOMAIN, // 
+		       G_LOG_LEVEL_CRITICAL); // G_LOG_LEVEL_WARNING
+
+  /* animate */
+  animation_thread = (pthread_t *) malloc(sizeof(pthread_t));
+  g_atomic_int_set(&(ags_show_start_animation),
+		   TRUE);
+  
+  ags_test_start_animation(animation_thread);
+  
+  /* initialize the CUnit test registry */
+  if(CUE_SUCCESS != CU_initialize_registry()){
+    return CU_get_error();
+  }
+
+  /* add a suite to the registry */
+  pSuite = CU_add_suite("AgsFuncitonalMatrixTest\0", ags_functional_matrix_test_init_suite, ags_functional_matrix_test_clean_suite);
+  
+  if(pSuite == NULL){
+    CU_cleanup_registry();
+    
+    return CU_get_error();
+  }
+
+  gtk_init(NULL,
+	   NULL);
+  //  g_log_set_fatal_mask(G_LOG_DOMAIN, // , // "Gtk\0" G_LOG_DOMAIN,"GLib-GObject\0",
+  //		       G_LOG_LEVEL_CRITICAL);
+
+  /* add the tests to the suite */
+  if((CU_add_test(pSuite, "functional test of AgsMatrix resize pads\0", ags_functional_matrix_test_resize_pads) == NULL) ||
+     (CU_add_test(pSuite, "functional test of AgsMatrix resize audio channels\0", ags_functional_matrix_test_resize_audio_channels) == NULL)){
+    CU_cleanup_registry();
+      
+    return CU_get_error();
+  }
+  
+  /* Run all tests using the CUnit Basic interface */
+  CU_basic_set_mode(CU_BRM_VERBOSE);
+  CU_basic_run_tests();
+  
+  CU_cleanup_registry();
+  
+  return(CU_get_error());
+}
diff --git a/ags/test/X/machine/ags_functional_mixer_test.c b/ags/test/X/machine/ags_functional_mixer_test.c
new file mode 100644
index 0000000..b65d5f2
--- /dev/null
+++ b/ags/test/X/machine/ags_functional_mixer_test.c
@@ -0,0 +1,418 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
+
+#include <ags/gsequencer_main.h>
+
+#include <ags/test/X/libgsequencer.h>
+
+#include "../gsequencer_setup_util.h"
+#include "../ags_functional_test_util.h"
+
+int ags_functional_mixer_test_init_suite();
+int ags_functional_mixer_test_clean_suite();
+
+void ags_functional_mixer_test_resize_pads();
+void ags_functional_mixer_test_resize_audio_channels();
+
+#define AGS_FUNCTIONAL_MIXER_TEST_RESIZE_OUTPUT_PADS (5)
+#define AGS_FUNCTIONAL_MIXER_TEST_RESIZE_INPUT_PADS (15)
+
+#define AGS_FUNCTIONAL_MIXER_TEST_RESIZE_AUDIO_CHANNELS (7)
+
+#define AGS_FUNCTIONAL_MIXER_TEST_CONFIG "[generic]\n"	\
+  "autosave-thread=false\n"				\
+  "simple-file=true\n"					\
+  "disable-feature=experimental\n"			\
+  "segmentation=4/4\n"					\
+  "\n"							\
+  "[thread]\n"						\
+  "model=super-threaded\n"				\
+  "super-threaded-scope=channel\n"			\
+  "lock-global=ags-thread\n"				\
+  "lock-parent=ags-recycling-thread\n"			\
+  "\n"							\
+  "[soundcard-0]\n"					\
+  "backend=alsa\n"					\
+  "device=hw:0,0\n"					\
+  "samplerate=44100\n"					\
+  "buffer-size=1024\n"					\
+  "pcm-channels=2\n"					\
+  "dsp-channels=2\n"					\
+  "format=16\n"						\
+  "\n"							\
+  "[recall]\n"						\
+  "auto-sense=true\n"					\
+  "\n"
+
+extern AgsApplicationContext *ags_application_context;
+
+extern struct sigaction ags_test_sigact;
+
+extern volatile gboolean ags_show_start_animation;
+
+AgsGuiThread *gui_thread;
+AgsTaskThread *task_thread;
+
+/* The suite initialization function.
+ * Opens the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_mixer_test_init_suite()
+{
+  AgsConfig *config;
+
+  config = ags_config_get_instance();
+  ags_config_load_from_data(config,
+			    AGS_FUNCTIONAL_MIXER_TEST_CONFIG,
+			    strlen(AGS_FUNCTIONAL_MIXER_TEST_CONFIG));
+
+  ags_functional_test_util_setup_and_launch();
+
+  /* get gui thread */
+  gui_thread = ags_thread_find_type(ags_application_context->main_loop,
+				    AGS_TYPE_GUI_THREAD);
+
+  task_thread = ags_thread_find_type(ags_application_context->main_loop,
+				     AGS_TYPE_TASK_THREAD);
+    
+  return(0);
+}
+
+/* The suite cleanup function.
+ * Closes the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_mixer_test_clean_suite()
+{  
+  ags_thread_stop(gui_thread);  
+
+  return(0);
+}
+
+void
+ags_functional_mixer_test_resize_pads()
+{
+  GtkDialog *properties;
+
+  AgsXorgApplicationContext *xorg_application_context;
+  
+  AgsMixer *mixer;
+
+  GList *list_start, *list;
+
+  guint nth_machine;
+  guint resize_tab;
+  gboolean success;
+
+  /* add mixer */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Mixer");
+
+  CU_ASSERT(success == TRUE);
+
+  /*  */
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve mixer */
+  nth_machine = 0;
+
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+
+  if(list != NULL &&
+     AGS_IS_MIXER(list->data)){
+    mixer = list->data;
+  }else{
+    mixer = NULL;
+  }
+  
+  CU_ASSERT(mixer != NULL);
+
+  /*
+   * resize output and input pads
+   */
+  
+  /* open properties */
+  ags_functional_test_util_machine_properties_open(nth_machine);
+
+  /* click tab */
+  resize_tab = 4;
+  
+  ags_functional_test_util_machine_properties_click_tab(nth_machine,
+							resize_tab);
+  
+  /* click enable */
+  ags_functional_test_util_machine_properties_click_enable(nth_machine);
+
+  /* set output pads */
+  ags_functional_test_util_machine_properties_resize_outputs(nth_machine,
+							     AGS_FUNCTIONAL_MIXER_TEST_RESIZE_OUTPUT_PADS);
+
+  /* set input pads */
+  ags_functional_test_util_machine_properties_resize_inputs(nth_machine,
+							    AGS_FUNCTIONAL_MIXER_TEST_RESIZE_INPUT_PADS);
+
+  /* response ok */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  properties = AGS_MACHINE(mixer)->properties;
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_dialog_ok(properties);
+
+  /* destroy mixer */
+  success = ags_functional_test_util_machine_destroy(0);
+}
+
+void
+ags_functional_mixer_test_resize_audio_channels()
+{
+  GtkDialog *properties;
+
+  AgsXorgApplicationContext *xorg_application_context;
+  
+  AgsMixer *mixer;
+
+  GList *list_start, *list;
+
+  guint nth_machine;
+  guint resize_tab;
+  gboolean success;
+
+  /* add mixer */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Mixer");
+
+  CU_ASSERT(success == TRUE);
+
+  /*  */
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve mixer */
+  nth_machine = 0;
+
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+
+  if(list != NULL &&
+     AGS_IS_MIXER(list->data)){
+    mixer = list->data;
+  }else{
+    mixer = NULL;
+  }
+  
+  CU_ASSERT(mixer != NULL);
+
+  /*
+   * resize audio channels
+   */
+  
+  /* open properties */
+  ags_functional_test_util_machine_properties_open(nth_machine);
+
+  /* click tab */
+  resize_tab = 4;
+  
+  ags_functional_test_util_machine_properties_click_tab(nth_machine,
+							resize_tab);
+  
+  /* click enable */
+  ags_functional_test_util_machine_properties_click_enable(nth_machine);
+
+  /* set output audio_channels */
+  ags_functional_test_util_machine_properties_resize_audio_channels(nth_machine,
+								    AGS_FUNCTIONAL_MIXER_TEST_RESIZE_AUDIO_CHANNELS);
+
+  /* response ok */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  properties = AGS_MACHINE(mixer)->properties;
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_dialog_ok(properties);
+
+  /* destroy mixer */
+  success = ags_functional_test_util_machine_destroy(0);
+}
+
+int
+main(int argc, char **argv)
+{
+  CU_pSuite pSuite = NULL;
+
+  AgsConfig *config;
+
+  pthread_t *animation_thread;
+
+  struct sched_param param;
+  struct rlimit rl;
+  struct sigaction sa;
+
+  gchar *rc_filename;
+  
+  int result;
+
+  const rlim_t kStackSize = 64L * 1024L * 1024L;   // min stack size = 64 Mb
+
+#ifdef AGS_USE_TIMER
+  timer_t *timer_id
+#endif
+  
+    putenv("LC_ALL=C\0");
+  putenv("LANG=C\0");
+
+  //  mtrace();
+  atexit(ags_test_signal_cleanup);
+
+  result = getrlimit(RLIMIT_STACK, &rl);
+
+  /* set stack size 64M */
+  if(result == 0){
+    if(rl.rlim_cur < kStackSize){
+      rl.rlim_cur = kStackSize;
+      result = setrlimit(RLIMIT_STACK, &rl);
+
+      if(result != 0){
+	//TODO:JK
+      }
+    }
+  }
+
+  param.sched_priority = GSEQUENCER_RT_PRIORITY;
+      
+  if(sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
+    perror("sched_setscheduler failed\0");
+  }
+
+  /* Ignore interactive and job-control signals.  */
+  signal(SIGINT, SIG_IGN);
+  signal(SIGQUIT, SIG_IGN);
+  signal(SIGTSTP, SIG_IGN);
+  signal(SIGTTIN, SIG_IGN);
+  signal(SIGTTOU, SIG_IGN);
+  signal(SIGCHLD, SIG_IGN);
+  signal(AGS_THREAD_RESUME_SIG, SIG_IGN);
+  signal(AGS_THREAD_SUSPEND_SIG, SIG_IGN);
+
+  ags_test_sigact.sa_handler = ags_test_signal_handler;
+  sigemptyset(&ags_test_sigact.sa_mask);
+  ags_test_sigact.sa_flags = 0;
+  sigaction(SIGINT, &ags_test_sigact, (struct sigaction *) NULL);
+  sigaction(SA_RESTART, &ags_test_sigact, (struct sigaction *) NULL);
+
+  XInitThreads();
+      
+  /* parse rc file */
+  rc_filename = g_strdup_printf("%s/%s\0",
+				SRCDIR,
+				"gsequencer.share/styles/ags.rc\0");
+  
+  gtk_rc_parse(rc_filename);
+  g_free(rc_filename);
+  
+  /**/
+  LIBXML_TEST_VERSION;
+
+  //ao_initialize();
+
+  gdk_threads_enter();
+  //  g_thread_init(NULL);
+  gtk_init(&argc, &argv);
+
+  g_object_set(gtk_settings_get_default(),
+	       "gtk-theme-name\0", "Raleigh\0",
+	       NULL);
+  g_signal_handlers_block_matched(gtk_settings_get_default(),
+				  G_SIGNAL_MATCH_DETAIL,
+				  g_signal_lookup("set-property\0",
+						  GTK_TYPE_SETTINGS),
+				  g_quark_from_string("gtk-theme-name\0"),
+				  NULL,
+				  NULL,
+				  NULL);
+  
+  ipatch_init();
+  g_log_set_fatal_mask("GLib-GObject\0", // "Gtk\0" G_LOG_DOMAIN, // 
+		       G_LOG_LEVEL_CRITICAL); // G_LOG_LEVEL_WARNING
+
+  /* animate */
+  animation_thread = (pthread_t *) malloc(sizeof(pthread_t));
+  g_atomic_int_set(&(ags_show_start_animation),
+		   TRUE);
+  
+  ags_test_start_animation(animation_thread);
+  
+  /* initialize the CUnit test registry */
+  if(CUE_SUCCESS != CU_initialize_registry()){
+    return CU_get_error();
+  }
+
+  /* add a suite to the registry */
+  pSuite = CU_add_suite("AgsFuncitonalMixerTest\0", ags_functional_mixer_test_init_suite, ags_functional_mixer_test_clean_suite);
+  
+  if(pSuite == NULL){
+    CU_cleanup_registry();
+    
+    return CU_get_error();
+  }
+
+  gtk_init(NULL,
+	   NULL);
+  //  g_log_set_fatal_mask(G_LOG_DOMAIN, // , // "Gtk\0" G_LOG_DOMAIN,"GLib-GObject\0",
+  //		       G_LOG_LEVEL_CRITICAL);
+
+  /* add the tests to the suite */
+  if((CU_add_test(pSuite, "functional test of AgsMixer resize pads\0", ags_functional_mixer_test_resize_pads) == NULL) ||
+     (CU_add_test(pSuite, "functional test of AgsMixer resize audio channels\0", ags_functional_mixer_test_resize_audio_channels) == NULL)){
+    CU_cleanup_registry();
+      
+    return CU_get_error();
+  }
+  
+  /* Run all tests using the CUnit Basic interface */
+  CU_basic_set_mode(CU_BRM_VERBOSE);
+  CU_basic_run_tests();
+  
+  CU_cleanup_registry();
+  
+  return(CU_get_error());
+}
diff --git a/ags/test/X/machine/ags_functional_panel_test.c b/ags/test/X/machine/ags_functional_panel_test.c
new file mode 100644
index 0000000..48290ed
--- /dev/null
+++ b/ags/test/X/machine/ags_functional_panel_test.c
@@ -0,0 +1,418 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
+
+#include <ags/gsequencer_main.h>
+
+#include <ags/test/X/libgsequencer.h>
+
+#include "../gsequencer_setup_util.h"
+#include "../ags_functional_test_util.h"
+
+int ags_functional_panel_test_init_suite();
+int ags_functional_panel_test_clean_suite();
+
+void ags_functional_panel_test_resize_pads();
+void ags_functional_panel_test_resize_audio_channels();
+
+#define AGS_FUNCTIONAL_PANEL_TEST_RESIZE_OUTPUT_PADS (5)
+#define AGS_FUNCTIONAL_PANEL_TEST_RESIZE_INPUT_PADS (15)
+
+#define AGS_FUNCTIONAL_PANEL_TEST_RESIZE_AUDIO_CHANNELS (7)
+
+#define AGS_FUNCTIONAL_PANEL_TEST_CONFIG "[generic]\n"	\
+  "autosave-thread=false\n"				\
+  "simple-file=true\n"					\
+  "disable-feature=experimental\n"			\
+  "segmentation=4/4\n"					\
+  "\n"							\
+  "[thread]\n"						\
+  "model=super-threaded\n"				\
+  "super-threaded-scope=channel\n"			\
+  "lock-global=ags-thread\n"				\
+  "lock-parent=ags-recycling-thread\n"			\
+  "\n"							\
+  "[soundcard-0]\n"					\
+  "backend=alsa\n"					\
+  "device=hw:0,0\n"					\
+  "samplerate=44100\n"					\
+  "buffer-size=1024\n"					\
+  "pcm-channels=2\n"					\
+  "dsp-channels=2\n"					\
+  "format=16\n"						\
+  "\n"							\
+  "[recall]\n"						\
+  "auto-sense=true\n"					\
+  "\n"
+
+extern AgsApplicationContext *ags_application_context;
+
+extern struct sigaction ags_test_sigact;
+
+extern volatile gboolean ags_show_start_animation;
+
+AgsGuiThread *gui_thread;
+AgsTaskThread *task_thread;
+
+/* The suite initialization function.
+ * Opens the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_panel_test_init_suite()
+{
+  AgsConfig *config;
+
+  config = ags_config_get_instance();
+  ags_config_load_from_data(config,
+			    AGS_FUNCTIONAL_PANEL_TEST_CONFIG,
+			    strlen(AGS_FUNCTIONAL_PANEL_TEST_CONFIG));
+
+  ags_functional_test_util_setup_and_launch();
+
+  /* get gui thread */
+  gui_thread = ags_thread_find_type(ags_application_context->main_loop,
+				    AGS_TYPE_GUI_THREAD);
+
+  task_thread = ags_thread_find_type(ags_application_context->main_loop,
+				     AGS_TYPE_TASK_THREAD);
+    
+  return(0);
+}
+
+/* The suite cleanup function.
+ * Closes the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_panel_test_clean_suite()
+{  
+  ags_thread_stop(gui_thread);  
+
+  return(0);
+}
+
+void
+ags_functional_panel_test_resize_pads()
+{
+  GtkDialog *properties;
+
+  AgsXorgApplicationContext *xorg_application_context;
+  
+  AgsPanel *panel;
+
+  GList *list_start, *list;
+
+  guint nth_machine;
+  guint resize_tab;
+  gboolean success;
+
+  /* add panel */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Panel");
+
+  CU_ASSERT(success == TRUE);
+
+  /*  */
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve panel */
+  nth_machine = 0;
+
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+
+  if(list != NULL &&
+     AGS_IS_PANEL(list->data)){
+    panel = list->data;
+  }else{
+    panel = NULL;
+  }
+  
+  CU_ASSERT(panel != NULL);
+
+  /*
+   * resize output and input pads
+   */
+  
+  /* open properties */
+  ags_functional_test_util_machine_properties_open(nth_machine);
+
+  /* click tab */
+  resize_tab = 4;
+  
+  ags_functional_test_util_machine_properties_click_tab(nth_machine,
+							resize_tab);
+  
+  /* click enable */
+  ags_functional_test_util_machine_properties_click_enable(nth_machine);
+
+  /* set output pads */
+  ags_functional_test_util_machine_properties_resize_outputs(nth_machine,
+							     AGS_FUNCTIONAL_PANEL_TEST_RESIZE_OUTPUT_PADS);
+
+  /* set input pads */
+  ags_functional_test_util_machine_properties_resize_inputs(nth_machine,
+							    AGS_FUNCTIONAL_PANEL_TEST_RESIZE_INPUT_PADS);
+
+  /* response ok */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  properties = AGS_MACHINE(panel)->properties;
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_dialog_ok(properties);
+
+  /* destroy panel */
+  success = ags_functional_test_util_machine_destroy(0);
+}
+
+void
+ags_functional_panel_test_resize_audio_channels()
+{
+  GtkDialog *properties;
+
+  AgsXorgApplicationContext *xorg_application_context;
+  
+  AgsPanel *panel;
+
+  GList *list_start, *list;
+
+  guint nth_machine;
+  guint resize_tab;
+  gboolean success;
+
+  /* add panel */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Panel");
+
+  CU_ASSERT(success == TRUE);
+
+  /*  */
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve panel */
+  nth_machine = 0;
+
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+
+  if(list != NULL &&
+     AGS_IS_PANEL(list->data)){
+    panel = list->data;
+  }else{
+    panel = NULL;
+  }
+  
+  CU_ASSERT(panel != NULL);
+
+  /*
+   * resize audio channels
+   */
+  
+  /* open properties */
+  ags_functional_test_util_machine_properties_open(nth_machine);
+
+  /* click tab */
+  resize_tab = 4;
+  
+  ags_functional_test_util_machine_properties_click_tab(nth_machine,
+							resize_tab);
+  
+  /* click enable */
+  ags_functional_test_util_machine_properties_click_enable(nth_machine);
+
+  /* set output audio_channels */
+  ags_functional_test_util_machine_properties_resize_audio_channels(nth_machine,
+								    AGS_FUNCTIONAL_PANEL_TEST_RESIZE_AUDIO_CHANNELS);
+
+  /* response ok */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  properties = AGS_MACHINE(panel)->properties;
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_dialog_ok(properties);
+
+  /* destroy panel */
+  success = ags_functional_test_util_machine_destroy(0);
+}
+
+int
+main(int argc, char **argv)
+{
+  CU_pSuite pSuite = NULL;
+
+  AgsConfig *config;
+
+  pthread_t *animation_thread;
+
+  struct sched_param param;
+  struct rlimit rl;
+  struct sigaction sa;
+
+  gchar *rc_filename;
+  
+  int result;
+
+  const rlim_t kStackSize = 64L * 1024L * 1024L;   // min stack size = 64 Mb
+
+#ifdef AGS_USE_TIMER
+  timer_t *timer_id
+#endif
+  
+    putenv("LC_ALL=C\0");
+  putenv("LANG=C\0");
+
+  //  mtrace();
+  atexit(ags_test_signal_cleanup);
+
+  result = getrlimit(RLIMIT_STACK, &rl);
+
+  /* set stack size 64M */
+  if(result == 0){
+    if(rl.rlim_cur < kStackSize){
+      rl.rlim_cur = kStackSize;
+      result = setrlimit(RLIMIT_STACK, &rl);
+
+      if(result != 0){
+	//TODO:JK
+      }
+    }
+  }
+
+  param.sched_priority = GSEQUENCER_RT_PRIORITY;
+      
+  if(sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
+    perror("sched_setscheduler failed\0");
+  }
+
+  /* Ignore interactive and job-control signals.  */
+  signal(SIGINT, SIG_IGN);
+  signal(SIGQUIT, SIG_IGN);
+  signal(SIGTSTP, SIG_IGN);
+  signal(SIGTTIN, SIG_IGN);
+  signal(SIGTTOU, SIG_IGN);
+  signal(SIGCHLD, SIG_IGN);
+  signal(AGS_THREAD_RESUME_SIG, SIG_IGN);
+  signal(AGS_THREAD_SUSPEND_SIG, SIG_IGN);
+
+  ags_test_sigact.sa_handler = ags_test_signal_handler;
+  sigemptyset(&ags_test_sigact.sa_mask);
+  ags_test_sigact.sa_flags = 0;
+  sigaction(SIGINT, &ags_test_sigact, (struct sigaction *) NULL);
+  sigaction(SA_RESTART, &ags_test_sigact, (struct sigaction *) NULL);
+
+  XInitThreads();
+      
+  /* parse rc file */
+  rc_filename = g_strdup_printf("%s/%s\0",
+				SRCDIR,
+				"gsequencer.share/styles/ags.rc\0");
+  
+  gtk_rc_parse(rc_filename);
+  g_free(rc_filename);
+  
+  /**/
+  LIBXML_TEST_VERSION;
+
+  //ao_initialize();
+
+  gdk_threads_enter();
+  //  g_thread_init(NULL);
+  gtk_init(&argc, &argv);
+
+  g_object_set(gtk_settings_get_default(),
+	       "gtk-theme-name\0", "Raleigh\0",
+	       NULL);
+  g_signal_handlers_block_matched(gtk_settings_get_default(),
+				  G_SIGNAL_MATCH_DETAIL,
+				  g_signal_lookup("set-property\0",
+						  GTK_TYPE_SETTINGS),
+				  g_quark_from_string("gtk-theme-name\0"),
+				  NULL,
+				  NULL,
+				  NULL);
+  
+  ipatch_init();
+  g_log_set_fatal_mask("GLib-GObject\0", // "Gtk\0" G_LOG_DOMAIN, // 
+		       G_LOG_LEVEL_CRITICAL); // G_LOG_LEVEL_WARNING
+
+  /* animate */
+  animation_thread = (pthread_t *) malloc(sizeof(pthread_t));
+  g_atomic_int_set(&(ags_show_start_animation),
+		   TRUE);
+  
+  ags_test_start_animation(animation_thread);
+  
+  /* initialize the CUnit test registry */
+  if(CUE_SUCCESS != CU_initialize_registry()){
+    return CU_get_error();
+  }
+
+  /* add a suite to the registry */
+  pSuite = CU_add_suite("AgsFuncitonalPanelTest\0", ags_functional_panel_test_init_suite, ags_functional_panel_test_clean_suite);
+  
+  if(pSuite == NULL){
+    CU_cleanup_registry();
+    
+    return CU_get_error();
+  }
+
+  gtk_init(NULL,
+	   NULL);
+  //  g_log_set_fatal_mask(G_LOG_DOMAIN, // , // "Gtk\0" G_LOG_DOMAIN,"GLib-GObject\0",
+  //		       G_LOG_LEVEL_CRITICAL);
+
+  /* add the tests to the suite */
+  if((CU_add_test(pSuite, "functional test of AgsPanel resize pads\0", ags_functional_panel_test_resize_pads) == NULL) ||
+     (CU_add_test(pSuite, "functional test of AgsPanel resize audio channels\0", ags_functional_panel_test_resize_audio_channels) == NULL)){
+    CU_cleanup_registry();
+      
+    return CU_get_error();
+  }
+  
+  /* Run all tests using the CUnit Basic interface */
+  CU_basic_set_mode(CU_BRM_VERBOSE);
+  CU_basic_run_tests();
+  
+  CU_cleanup_registry();
+  
+  return(CU_get_error());
+}
diff --git a/ags/test/X/machine/ags_functional_synth_test.c b/ags/test/X/machine/ags_functional_synth_test.c
new file mode 100644
index 0000000..5516ad3
--- /dev/null
+++ b/ags/test/X/machine/ags_functional_synth_test.c
@@ -0,0 +1,418 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
+
+#include <ags/gsequencer_main.h>
+
+#include <ags/test/X/libgsequencer.h>
+
+#include "../gsequencer_setup_util.h"
+#include "../ags_functional_test_util.h"
+
+int ags_functional_synth_test_init_suite();
+int ags_functional_synth_test_clean_suite();
+
+void ags_functional_synth_test_resize_pads();
+void ags_functional_synth_test_resize_audio_channels();
+
+#define AGS_FUNCTIONAL_SYNTH_TEST_RESIZE_OUTPUT_PADS (5)
+#define AGS_FUNCTIONAL_SYNTH_TEST_RESIZE_INPUT_PADS (15)
+
+#define AGS_FUNCTIONAL_SYNTH_TEST_RESIZE_AUDIO_CHANNELS (0)
+
+#define AGS_FUNCTIONAL_SYNTH_TEST_CONFIG "[generic]\n"	\
+  "autosave-thread=false\n"				\
+  "simple-file=true\n"					\
+  "disable-feature=experimental\n"			\
+  "segmentation=4/4\n"					\
+  "\n"							\
+  "[thread]\n"						\
+  "model=super-threaded\n"				\
+  "super-threaded-scope=channel\n"			\
+  "lock-global=ags-thread\n"				\
+  "lock-parent=ags-recycling-thread\n"			\
+  "\n"							\
+  "[soundcard-0]\n"					\
+  "backend=alsa\n"					\
+  "device=hw:0,0\n"					\
+  "samplerate=44100\n"					\
+  "buffer-size=1024\n"					\
+  "pcm-channels=2\n"					\
+  "dsp-channels=2\n"					\
+  "format=16\n"						\
+  "\n"							\
+  "[recall]\n"						\
+  "auto-sense=true\n"					\
+  "\n"
+
+extern AgsApplicationContext *ags_application_context;
+
+extern struct sigaction ags_test_sigact;
+
+extern volatile gboolean ags_show_start_animation;
+
+AgsGuiThread *gui_thread;
+AgsTaskThread *task_thread;
+
+/* The suite initialization function.
+ * Opens the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_synth_test_init_suite()
+{
+  AgsConfig *config;
+
+  config = ags_config_get_instance();
+  ags_config_load_from_data(config,
+			    AGS_FUNCTIONAL_SYNTH_TEST_CONFIG,
+			    strlen(AGS_FUNCTIONAL_SYNTH_TEST_CONFIG));
+
+  ags_functional_test_util_setup_and_launch();
+
+  /* get gui thread */
+  gui_thread = ags_thread_find_type(ags_application_context->main_loop,
+				    AGS_TYPE_GUI_THREAD);
+
+  task_thread = ags_thread_find_type(ags_application_context->main_loop,
+				     AGS_TYPE_TASK_THREAD);
+    
+  return(0);
+}
+
+/* The suite cleanup function.
+ * Closes the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_functional_synth_test_clean_suite()
+{  
+  ags_thread_stop(gui_thread);  
+
+  return(0);
+}
+
+void
+ags_functional_synth_test_resize_pads()
+{
+  GtkDialog *properties;
+
+  AgsXorgApplicationContext *xorg_application_context;
+  
+  AgsSynth *synth;
+
+  GList *list_start, *list;
+
+  guint nth_machine;
+  guint resize_tab;
+  gboolean success;
+
+  /* add synth */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Synth");
+
+  CU_ASSERT(success == TRUE);
+
+  /*  */
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve synth */
+  nth_machine = 0;
+
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+
+  if(list != NULL &&
+     AGS_IS_SYNTH(list->data)){
+    synth = list->data;
+  }else{
+    synth = NULL;
+  }
+  
+  CU_ASSERT(synth != NULL);
+
+  /*
+   * resize output and input pads
+   */
+  
+  /* open properties */
+  ags_functional_test_util_machine_properties_open(nth_machine);
+
+  /* click tab */
+  resize_tab = 4;
+  
+  ags_functional_test_util_machine_properties_click_tab(nth_machine,
+							resize_tab);
+  
+  /* click enable */
+  ags_functional_test_util_machine_properties_click_enable(nth_machine);
+
+  /* set output pads */
+  ags_functional_test_util_machine_properties_resize_outputs(nth_machine,
+							     AGS_FUNCTIONAL_SYNTH_TEST_RESIZE_OUTPUT_PADS);
+
+  /* set input pads */
+  ags_functional_test_util_machine_properties_resize_inputs(nth_machine,
+							    AGS_FUNCTIONAL_SYNTH_TEST_RESIZE_INPUT_PADS);
+
+  /* response ok */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  properties = AGS_MACHINE(synth)->properties;
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_dialog_ok(properties);
+
+  /* destroy synth */
+  success = ags_functional_test_util_machine_destroy(0);
+}
+
+void
+ags_functional_synth_test_resize_audio_channels()
+{
+  GtkDialog *properties;
+
+  AgsXorgApplicationContext *xorg_application_context;
+  
+  AgsSynth *synth;
+
+  GList *list_start, *list;
+
+  guint nth_machine;
+  guint resize_tab;
+  gboolean success;
+
+  /* add synth */
+  success = ags_functional_test_util_add_machine(NULL,
+						 "Synth");
+
+  CU_ASSERT(success == TRUE);
+
+  /*  */
+  gdk_threads_enter();
+  
+  xorg_application_context = ags_application_context_get_instance();
+
+  /* retrieve synth */
+  nth_machine = 0;
+
+  list_start = gtk_container_get_children(xorg_application_context->window->machines);
+  list = g_list_nth(list_start,
+		    nth_machine);
+
+  gdk_threads_leave();
+
+  if(list != NULL &&
+     AGS_IS_SYNTH(list->data)){
+    synth = list->data;
+  }else{
+    synth = NULL;
+  }
+  
+  CU_ASSERT(synth != NULL);
+
+  /*
+   * resize audio channels
+   */
+  
+  /* open properties */
+  ags_functional_test_util_machine_properties_open(nth_machine);
+
+  /* click tab */
+  resize_tab = 4;
+  
+  ags_functional_test_util_machine_properties_click_tab(nth_machine,
+							resize_tab);
+  
+  /* click enable */
+  ags_functional_test_util_machine_properties_click_enable(nth_machine);
+
+  /* set output audio_channels */
+  ags_functional_test_util_machine_properties_resize_audio_channels(nth_machine,
+								    AGS_FUNCTIONAL_SYNTH_TEST_RESIZE_AUDIO_CHANNELS);
+
+  /* response ok */
+  pthread_mutex_lock(task_thread->launch_mutex);
+
+  properties = AGS_MACHINE(synth)->properties;
+  
+  pthread_mutex_unlock(task_thread->launch_mutex);
+
+  ags_functional_test_util_dialog_ok(properties);
+
+  /* destroy synth */
+  success = ags_functional_test_util_machine_destroy(0);
+}
+
+int
+main(int argc, char **argv)
+{
+  CU_pSuite pSuite = NULL;
+
+  AgsConfig *config;
+
+  pthread_t *animation_thread;
+
+  struct sched_param param;
+  struct rlimit rl;
+  struct sigaction sa;
+
+  gchar *rc_filename;
+  
+  int result;
+
+  const rlim_t kStackSize = 64L * 1024L * 1024L;   // min stack size = 64 Mb
+
+#ifdef AGS_USE_TIMER
+  timer_t *timer_id
+#endif
+  
+    putenv("LC_ALL=C\0");
+  putenv("LANG=C\0");
+
+  //  mtrace();
+  atexit(ags_test_signal_cleanup);
+
+  result = getrlimit(RLIMIT_STACK, &rl);
+
+  /* set stack size 64M */
+  if(result == 0){
+    if(rl.rlim_cur < kStackSize){
+      rl.rlim_cur = kStackSize;
+      result = setrlimit(RLIMIT_STACK, &rl);
+
+      if(result != 0){
+	//TODO:JK
+      }
+    }
+  }
+
+  param.sched_priority = GSEQUENCER_RT_PRIORITY;
+      
+  if(sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
+    perror("sched_setscheduler failed\0");
+  }
+
+  /* Ignore interactive and job-control signals.  */
+  signal(SIGINT, SIG_IGN);
+  signal(SIGQUIT, SIG_IGN);
+  signal(SIGTSTP, SIG_IGN);
+  signal(SIGTTIN, SIG_IGN);
+  signal(SIGTTOU, SIG_IGN);
+  signal(SIGCHLD, SIG_IGN);
+  signal(AGS_THREAD_RESUME_SIG, SIG_IGN);
+  signal(AGS_THREAD_SUSPEND_SIG, SIG_IGN);
+
+  ags_test_sigact.sa_handler = ags_test_signal_handler;
+  sigemptyset(&ags_test_sigact.sa_mask);
+  ags_test_sigact.sa_flags = 0;
+  sigaction(SIGINT, &ags_test_sigact, (struct sigaction *) NULL);
+  sigaction(SA_RESTART, &ags_test_sigact, (struct sigaction *) NULL);
+
+  XInitThreads();
+      
+  /* parse rc file */
+  rc_filename = g_strdup_printf("%s/%s\0",
+				SRCDIR,
+				"gsequencer.share/styles/ags.rc\0");
+  
+  gtk_rc_parse(rc_filename);
+  g_free(rc_filename);
+  
+  /**/
+  LIBXML_TEST_VERSION;
+
+  //ao_initialize();
+
+  gdk_threads_enter();
+  //  g_thread_init(NULL);
+  gtk_init(&argc, &argv);
+
+  g_object_set(gtk_settings_get_default(),
+	       "gtk-theme-name\0", "Raleigh\0",
+	       NULL);
+  g_signal_handlers_block_matched(gtk_settings_get_default(),
+				  G_SIGNAL_MATCH_DETAIL,
+				  g_signal_lookup("set-property\0",
+						  GTK_TYPE_SETTINGS),
+				  g_quark_from_string("gtk-theme-name\0"),
+				  NULL,
+				  NULL,
+				  NULL);
+  
+  ipatch_init();
+  g_log_set_fatal_mask("GLib-GObject\0", // "Gtk\0" G_LOG_DOMAIN, // 
+		       G_LOG_LEVEL_CRITICAL); // G_LOG_LEVEL_WARNING
+
+  /* animate */
+  animation_thread = (pthread_t *) malloc(sizeof(pthread_t));
+  g_atomic_int_set(&(ags_show_start_animation),
+		   TRUE);
+  
+  ags_test_start_animation(animation_thread);
+  
+  /* initialize the CUnit test registry */
+  if(CUE_SUCCESS != CU_initialize_registry()){
+    return CU_get_error();
+  }
+
+  /* add a suite to the registry */
+  pSuite = CU_add_suite("AgsFuncitonalSynthTest\0", ags_functional_synth_test_init_suite, ags_functional_synth_test_clean_suite);
+  
+  if(pSuite == NULL){
+    CU_cleanup_registry();
+    
+    return CU_get_error();
+  }
+
+  gtk_init(NULL,
+	   NULL);
+  //  g_log_set_fatal_mask(G_LOG_DOMAIN, // , // "Gtk\0" G_LOG_DOMAIN,"GLib-GObject\0",
+  //		       G_LOG_LEVEL_CRITICAL);
+
+  /* add the tests to the suite */
+  if((CU_add_test(pSuite, "functional test of AgsSynth resize pads\0", ags_functional_synth_test_resize_pads) == NULL) ||
+     (CU_add_test(pSuite, "functional test of AgsSynth resize audio channels\0", ags_functional_synth_test_resize_audio_channels) == NULL)){
+    CU_cleanup_registry();
+      
+    return CU_get_error();
+  }
+  
+  /* Run all tests using the CUnit Basic interface */
+  CU_basic_set_mode(CU_BRM_VERBOSE);
+  CU_basic_run_tests();
+  
+  CU_cleanup_registry();
+  
+  return(CU_get_error());
+}
diff --git a/ags/test/audio/ags_audio_application_context_test.c b/ags/test/audio/ags_audio_application_context_test.c
new file mode 100644
index 0000000..edd035b
--- /dev/null
+++ b/ags/test/audio/ags_audio_application_context_test.c
@@ -0,0 +1,192 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
+
+#define AGS_AUDIO_APPLICATION_CONTEXT_TEST_DISPOSE_DEVOUT_COUNT (8)
+
+int ags_audio_application_context_test_init_suite();
+int ags_audio_application_context_test_clean_suite();
+
+void ags_audio_application_context_test_dispose();
+void ags_audio_application_context_test_finalize();
+
+void ags_audio_application_context_test_finalize_stub(GObject *gobject);
+
+#define AGS_AUDIO_APPLICATION_CONTEXT_TEST_CONFIG "[generic]\n" \
+  "autosave-thread=false\n"			       \
+  "simple-file=true\n"				       \
+  "disable-feature=experimental\n"		       \
+  "segmentation=4/4\n"				       \
+  "\n"						       \
+  "[thread]\n"					       \
+  "model=super-threaded\n"			       \
+  "super-threaded-scope=channel\n"		       \
+  "lock-global=ags-thread\n"			       \
+  "lock-parent=ags-recycling-thread\n"		       \
+  "\n"						       \
+  "[soundcard-0]\n"				       \
+  "backend=alsa\n"                                     \
+  "device=hw:0,0\n"                                    \
+  "samplerate=44100\n"				       \
+  "buffer-size=1024\n"				       \
+  "pcm-channels=2\n"				       \
+  "dsp-channels=2\n"				       \
+  "format=16\n"					       \
+  "\n"						       \
+  "[soundcard-1]\n"				       \
+  "backend=alsa\n"                                     \
+  "device=hw:0,0\n"                                    \
+  "samplerate=44100\n"				       \
+  "buffer-size=1024\n"				       \
+  "pcm-channels=2\n"				       \
+  "dsp-channels=2\n"				       \
+  "format=16\n"					       \
+  "\n"						       \
+  "[recall]\n"					       \
+  "auto-sense=true\n"				       \
+  "\n"
+
+gboolean audio_application_context_test_finalized;
+
+/* The suite initialization function.
+ * Opens the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_audio_application_context_test_init_suite()
+{
+  AgsConfig *config;
+
+  config = ags_config_get_instance();
+  ags_config_load_from_data(config,
+			    AGS_AUDIO_APPLICATION_CONTEXT_TEST_CONFIG,
+			    strlen(AGS_AUDIO_APPLICATION_CONTEXT_TEST_CONFIG));
+    
+  return(0);
+}
+
+/* The suite cleanup function.
+ * Closes the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_audio_application_context_test_clean_suite()
+{
+  
+  return(0);
+}
+
+void
+ags_audio_application_context_test_dispose()
+{
+  AgsAudioApplicationContext *audio_application_context;
+
+  audio_application_context = g_object_new(AGS_TYPE_AUDIO_APPLICATION_CONTEXT,
+					   NULL);
+
+  /* run dispose */
+  g_object_run_dispose(audio_application_context);
+
+  /* assert */
+  CU_ASSERT(audio_application_context->thread_pool == NULL);
+  CU_ASSERT(audio_application_context->soundcard_thread == NULL);
+  CU_ASSERT(audio_application_context->export_thread == NULL);
+  CU_ASSERT(audio_application_context->autosave_thread == NULL);
+  CU_ASSERT(audio_application_context->server == NULL);
+  CU_ASSERT(audio_application_context->soundcard == NULL);
+  CU_ASSERT(audio_application_context->sequencer == NULL);
+  CU_ASSERT(audio_application_context->distributed_manager == NULL);
+}
+
+void
+ags_audio_application_context_test_finalize()
+{
+  AgsAudioApplicationContext *audio_application_context;
+
+  audio_application_context = g_object_new(AGS_TYPE_AUDIO_APPLICATION_CONTEXT,
+					   NULL);
+
+  /* run dispose */
+  g_object_run_dispose(audio_application_context);
+
+  /* stub finalize */
+  audio_application_context_test_finalized = FALSE;
+  G_OBJECT_GET_CLASS(audio_application_context)->finalize = ags_audio_application_context_test_finalize_stub;
+
+  /* unref and assert */
+  g_object_unref(audio_application_context);
+  
+  CU_ASSERT(audio_application_context_test_finalized == TRUE);
+}
+
+void
+ags_audio_application_context_test_finalize_stub(GObject *gobject)
+{
+  audio_application_context_test_finalized = TRUE;
+}
+
+int
+main(int argc, char **argv)
+{
+  CU_pSuite pSuite = NULL;
+
+  putenv("LC_ALL=C\0");
+  putenv("LANG=C\0");
+
+  /* initialize the CUnit test registry */
+  if(CUE_SUCCESS != CU_initialize_registry()){
+    return CU_get_error();
+  }
+
+  /* add a suite to the registry */
+  pSuite = CU_add_suite("AgsAudioApplicationContextTest\0", ags_audio_application_context_test_init_suite, ags_audio_application_context_test_clean_suite);
+  
+  if(pSuite == NULL){
+    CU_cleanup_registry();
+    
+    return CU_get_error();
+  }
+
+  g_log_set_fatal_mask("GLib-GObject\0", // "Gtk\0" G_LOG_DOMAIN, // 
+  		       G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
+
+  /* add the tests to the suite */
+  if((CU_add_test(pSuite, "test of AgsAudioApplicationContext doing dispose\0", ags_audio_application_context_test_dispose) == NULL) ||
+     (CU_add_test(pSuite, "test of AgsAudioApplicationContext doing finalize\0", ags_audio_application_context_test_finalize) == NULL)){
+    CU_cleanup_registry();
+      
+    return CU_get_error();
+  }
+  
+  /* Run all tests using the CUnit Basic interface */
+  CU_basic_set_mode(CU_BRM_VERBOSE);
+  CU_basic_run_tests();
+  
+  CU_cleanup_registry();
+  
+  return(CU_get_error());
+}
diff --git a/ags/test/audio/ags_audio_test.c b/ags/test/audio/ags_audio_test.c
index 1e52d57..9d72196 100644
--- a/ags/test/audio/ags_audio_test.c
+++ b/ags/test/audio/ags_audio_test.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -23,25 +23,14 @@
 #include <CUnit/CUnit.h>
 #include <CUnit/Basic.h>
 
-#include <ags/object/ags_soundcard.h>
-
-#include <ags/audio/ags_devout.h>
-#include <ags/audio/ags_audio.h>
-#include <ags/audio/ags_channel.h>
-#include <ags/audio/ags_output.h>
-#include <ags/audio/ags_input.h>
-#include <ags/audio/ags_recall.h>
-#include <ags/audio/ags_recall_audio.h>
-#include <ags/audio/ags_recall_audio_run.h>
-#include <ags/audio/ags_recall_channel.h>
-#include <ags/audio/ags_recall_channel_run.h>
-#include <ags/audio/ags_recall_container.h>
-#include <ags/audio/ags_recall_id.h>
-#include <ags/audio/ags_recycling_context.h>
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
 
 int ags_audio_test_init_suite();
 int ags_audio_test_clean_suite();
 
+void ags_audio_test_dispose();
+void ags_audio_test_finalize();
 void ags_audio_test_set_pads();
 void ags_audio_test_set_audio_channels();
 void ags_audio_test_link_channel();
@@ -54,6 +43,7 @@ void ags_audio_test_duplicate_recall();
 void ags_audio_test_init_recall();
 void ags_audio_test_resolve_recall();
 
+void ags_audio_test_finalize_stub(GObject *gobject);
 void ags_audio_test_set_link_callback(AgsChannel *channel, AgsChannel *link,
 				      GError **error,
 				      AgsAudio *audio);
@@ -62,6 +52,14 @@ void ags_audio_test_init_recall_callback(AgsRecall *recall,
 void ags_audio_test_resolve_recall_callback(AgsRecall *recall,
 					    gpointer data);
 
+#define AGS_AUDIO_TEST_DISPOSE_AUDIO_CHANNELS (2)
+#define AGS_AUDIO_TEST_DISPOSE_INPUT_PADS (12)
+#define AGS_AUDIO_TEST_DISPOSE_OUTPUT_PADS (5)
+
+#define AGS_AUDIO_TEST_FINALIZE_AUDIO_CHANNELS (2)
+#define AGS_AUDIO_TEST_FINALIZE_INPUT_PADS (12)
+#define AGS_AUDIO_TEST_FINALIZE_OUTPUT_PADS (5)
+
 #define AGS_AUDIO_TEST_SET_PADS_AUDIO_CHANNELS (2)
 #define AGS_AUDIO_TEST_SET_PADS_INPUT_PADS (12)
 #define AGS_AUDIO_TEST_SET_PADS_OUTPUT_PADS (5)
@@ -103,6 +101,7 @@ void ags_audio_test_resolve_recall_callback(AgsRecall *recall,
 #define AGS_AUDIO_TEST_FINALIZE_LINKED_CHANNEL_SLAVE_2_OUTPUT_PADS (1)
 
 AgsDevout *devout;
+gboolean audio_test_finalized;
 
 struct{
   AgsAudio *master;
@@ -143,7 +142,8 @@ int
 ags_audio_test_init_suite()
 {
   devout = ags_devout_new(NULL);
-
+  g_object_ref(devout);
+  
   return(0);
 }
 
@@ -160,6 +160,86 @@ ags_audio_test_clean_suite()
 }
 
 void
+ags_audio_test_dispose()
+{
+  AgsAudio *audio;
+
+  /* instantiate audio */
+  audio = ags_audio_new(devout);
+
+  /* set audio channels */
+  audio->audio_channels = AGS_AUDIO_TEST_DISPOSE_AUDIO_CHANNELS;
+
+  /* set input pads */
+  ags_audio_set_pads(audio,
+		     AGS_TYPE_INPUT,
+		     AGS_AUDIO_TEST_DISPOSE_INPUT_PADS);
+
+  /* set output pads */
+  ags_audio_set_pads(audio,
+		     AGS_TYPE_OUTPUT,
+		     AGS_AUDIO_TEST_DISPOSE_OUTPUT_PADS);
+
+  /* run dispose and assert */
+  g_object_run_dispose(audio);
+
+  CU_ASSERT(audio->soundcard == NULL);
+  CU_ASSERT(audio->sequencer == NULL);
+
+  CU_ASSERT(audio->midi_file == NULL);
+  CU_ASSERT(audio->audio_connection == NULL);
+
+  CU_ASSERT(audio->output == NULL);
+  CU_ASSERT(audio->input == NULL);
+
+  CU_ASSERT(audio->playback_domain == NULL);
+
+  CU_ASSERT(audio->notation == NULL);
+  CU_ASSERT(audio->automation == NULL);
+
+  CU_ASSERT(audio->recall_id == NULL);
+  CU_ASSERT(audio->recycling_context == NULL);
+
+  CU_ASSERT(audio->container == NULL);
+  CU_ASSERT(audio->recall == NULL);
+  CU_ASSERT(audio->play == NULL);
+}
+
+void
+ags_audio_test_finalize()
+{
+  AgsAudio *audio;
+
+  /* instantiate audio */
+  audio = ags_audio_new(devout);
+
+  /* set audio channels */
+  audio->audio_channels = AGS_AUDIO_TEST_FINALIZE_AUDIO_CHANNELS;
+
+  /* set input pads */
+  ags_audio_set_pads(audio,
+		     AGS_TYPE_INPUT,
+		     AGS_AUDIO_TEST_FINALIZE_INPUT_PADS);
+
+  /* set output pads */
+  ags_audio_set_pads(audio,
+		     AGS_TYPE_OUTPUT,
+		     AGS_AUDIO_TEST_FINALIZE_OUTPUT_PADS);
+
+  /* run dispose */
+  g_object_run_dispose(audio);
+
+  /* stub */
+  audio_test_finalized = FALSE;
+  G_OBJECT_GET_CLASS(audio)->finalize = ags_audio_test_finalize_stub;
+  
+  /* unref and assert */
+  g_object_unref(audio);
+  
+  CU_ASSERT(audio_test_finalized == TRUE);
+}
+
+void
 ags_audio_test_set_pads()
 {
   AgsAudio *audio;
@@ -168,7 +248,7 @@ ags_audio_test_set_pads()
   guint i, j;
   
   /* instantiate */
-  audio = ags_audio_new(AGS_SOUNDCARD(devout));
+  audio = ags_audio_new(devout);
 
   CU_ASSERT(audio != NULL);
 
@@ -410,7 +490,7 @@ ags_audio_test_set_audio_channels()
   guint i, j;
   
   /* instantiate */
-  audio = ags_audio_new(AGS_SOUNDCARD(devout));
+  audio = ags_audio_new(devout);
 
   CU_ASSERT(audio != NULL);
 
@@ -488,7 +568,7 @@ ags_audio_test_link_channel()
   GError *error;
   
   /* audio - master */
-  test_link_channel.master = ags_audio_new(AGS_SOUNDCARD(devout));
+  test_link_channel.master = ags_audio_new(devout);
   test_link_channel.master->flags |= AGS_AUDIO_ASYNC;
   
   ags_audio_set_audio_channels(test_link_channel.master,
@@ -502,7 +582,7 @@ ags_audio_test_link_channel()
 		     AGS_AUDIO_TEST_LINK_CHANNEL_MASTER_OUTPUT_PADS);
 
   /* audio - slave 0 */
-  test_link_channel.slave_0 = ags_audio_new(AGS_SOUNDCARD(devout));
+  test_link_channel.slave_0 = ags_audio_new(devout);
   test_link_channel.slave_0->flags |= (AGS_AUDIO_OUTPUT_HAS_RECYCLING |
 				       AGS_AUDIO_ASYNC);
   
@@ -517,7 +597,7 @@ ags_audio_test_link_channel()
 		     AGS_AUDIO_TEST_LINK_CHANNEL_SLAVE_0_OUTPUT_PADS);
 
   /* audio - slave 1 */
-  test_link_channel.slave_1 = ags_audio_new(AGS_SOUNDCARD(devout));
+  test_link_channel.slave_1 = ags_audio_new(devout);
   test_link_channel.slave_1->flags |= (AGS_AUDIO_OUTPUT_HAS_RECYCLING |
 				       AGS_AUDIO_ASYNC);
   
@@ -532,7 +612,7 @@ ags_audio_test_link_channel()
 		     AGS_AUDIO_TEST_LINK_CHANNEL_SLAVE_1_OUTPUT_PADS);
 
   /* audio - slave 2 */
-  test_link_channel.slave_2 = ags_audio_new(AGS_SOUNDCARD(devout));
+  test_link_channel.slave_2 = ags_audio_new(devout);
   test_link_channel.slave_2->flags |= (AGS_AUDIO_OUTPUT_HAS_RECYCLING |
 				       AGS_AUDIO_ASYNC);
   
@@ -753,7 +833,7 @@ ags_audio_test_finalize_linked_channel()
   GError *error;
   
   /* audio - master */
-  test_finalize_linked_channel.master = ags_audio_new(AGS_SOUNDCARD(devout));
+  test_finalize_linked_channel.master = ags_audio_new(devout);
   test_finalize_linked_channel.master->flags |= AGS_AUDIO_ASYNC;
   
   ags_audio_set_audio_channels(test_finalize_linked_channel.master,
@@ -767,7 +847,7 @@ ags_audio_test_finalize_linked_channel()
 		     AGS_AUDIO_TEST_FINALIZE_LINKED_CHANNEL_MASTER_OUTPUT_PADS);
 
   /* audio - slave 0 */
-  test_finalize_linked_channel.slave_0 = ags_audio_new(AGS_SOUNDCARD(devout));
+  test_finalize_linked_channel.slave_0 = ags_audio_new(devout);
   test_finalize_linked_channel.slave_0->flags |= (AGS_AUDIO_OUTPUT_HAS_RECYCLING |
 						  AGS_AUDIO_ASYNC);
   
@@ -782,7 +862,7 @@ ags_audio_test_finalize_linked_channel()
 		     AGS_AUDIO_TEST_FINALIZE_LINKED_CHANNEL_SLAVE_0_OUTPUT_PADS);
 
   /* audio - slave 1 */
-  test_finalize_linked_channel.slave_1 = ags_audio_new(AGS_SOUNDCARD(devout));
+  test_finalize_linked_channel.slave_1 = ags_audio_new(devout);
   test_finalize_linked_channel.slave_1->flags |= (AGS_AUDIO_OUTPUT_HAS_RECYCLING |
 						  AGS_AUDIO_ASYNC);
   
@@ -797,7 +877,7 @@ ags_audio_test_finalize_linked_channel()
 		     AGS_AUDIO_TEST_FINALIZE_LINKED_CHANNEL_SLAVE_1_OUTPUT_PADS);
 
   /* audio - slave 2 */
-  test_finalize_linked_channel.slave_2 = ags_audio_new(AGS_SOUNDCARD(devout));
+  test_finalize_linked_channel.slave_2 = ags_audio_new(devout);
   test_finalize_linked_channel.slave_2->flags |= (AGS_AUDIO_OUTPUT_HAS_RECYCLING |
 						  AGS_AUDIO_ASYNC);
   
@@ -1007,7 +1087,7 @@ ags_audio_test_add_recall()
   AgsRecall *recall;
 
   /* instantiate audio */
-  audio = ags_audio_new(AGS_SOUNDCARD(devout));
+  audio = ags_audio_new(devout);
 
   /* instantiate recall */
   recall = ags_recall_new();
@@ -1041,7 +1121,7 @@ ags_audio_test_add_recall_container()
   AgsRecallContainer *recall_container;
   
   /* instantiate audio */
-  audio = ags_audio_new(AGS_SOUNDCARD(devout));
+  audio = ags_audio_new(devout);
 
   /* instantiate recall */
   recall_container = ags_recall_container_new();
@@ -1062,7 +1142,7 @@ ags_audio_test_add_recall_id()
   AgsRecallID *recall_id;
   
   /* instantiate audio */
-  audio = ags_audio_new(AGS_SOUNDCARD(devout));
+  audio = ags_audio_new(devout);
 
   /* instantiate recall */
   recall_id = ags_recall_id_new(NULL);
@@ -1083,7 +1163,7 @@ ags_audio_test_add_recycling_context()
   AgsRecyclingContext *recycling_context;
   
   /* instantiate audio */
-  audio = ags_audio_new(AGS_SOUNDCARD(devout));
+  audio = ags_audio_new(devout);
 
   /* instantiate recall */
   recycling_context = ags_recycling_context_new(0);
@@ -1107,15 +1187,19 @@ ags_audio_test_duplicate_recall()
   AgsRecallID *recall_id;
   
   /* instantiate audio */
-  audio = ags_audio_new(AGS_SOUNDCARD(devout));
+  audio = ags_audio_new(devout);
 
   /* case 1: playback recall */
   recall = ags_recall_new();
+  recall->flags |= (AGS_RECALL_TEMPLATE |
+		    AGS_RECALL_PLAYBACK);
   ags_audio_add_recall(audio,
 		       recall,
 		       TRUE);
   
   recall_audio_run = ags_recall_audio_run_new();
+  recall_audio_run->flags |= (AGS_RECALL_TEMPLATE |
+			      AGS_RECALL_PLAYBACK);
   ags_audio_add_recall(audio,
 		       recall_audio_run,
 		       TRUE);
@@ -1128,6 +1212,7 @@ ags_audio_test_duplicate_recall()
   recycling_context = ags_recycling_context_new(0);
 
   recall_id = ags_recall_id_new(NULL);
+  recall_id->flags |= AGS_RECALL_ID_PLAYBACK;
   g_object_set(recall_id,
 	       "recycling-context\0", recycling_context,
 	       NULL);
@@ -1141,11 +1226,15 @@ ags_audio_test_duplicate_recall()
   
   /* case 2: true recall */
   recall = ags_recall_new();
+  recall->flags |= (AGS_RECALL_TEMPLATE |
+		    AGS_RECALL_PLAYBACK);
   ags_audio_add_recall(audio,
 		       recall,
 		       FALSE);
   
   recall_audio_run = ags_recall_audio_run_new();
+  recall_audio_run->flags |= (AGS_RECALL_TEMPLATE |
+			      AGS_RECALL_PLAYBACK);
   ags_audio_add_recall(audio,
 		       recall_audio_run,
 		       FALSE);
@@ -1163,6 +1252,7 @@ ags_audio_test_duplicate_recall()
 	       NULL);
 
   recall_id = ags_recall_id_new(NULL);
+  recall_id->flags |= AGS_RECALL_ID_PLAYBACK;
   g_object_set(recall_id,
 	       "recycling-context\0", recycling_context,
 	       NULL);
@@ -1185,7 +1275,7 @@ ags_audio_test_init_recall()
   AgsRecallID *recall_id;
     
   /* instantiate audio */
-  audio = ags_audio_new(AGS_SOUNDCARD(devout));
+  audio = ags_audio_new(devout);
 
   /* instantiate recalls */
   recall = ags_recall_new();
@@ -1193,7 +1283,7 @@ ags_audio_test_init_recall()
 		       recall,
 		       TRUE);
 
-  g_signal_connect(G_OBJECT(recall), "init-pre\0",
+  g_signal_connect(G_OBJECT(recall), "run-init-pre\0",
 		   G_CALLBACK(ags_audio_test_init_recall_callback), NULL);
   
   recall_audio_run = ags_recall_audio_run_new();
@@ -1201,7 +1291,7 @@ ags_audio_test_init_recall()
 		       recall_audio_run,
 		       TRUE);
 
-  g_signal_connect(G_OBJECT(recall_audio_run), "init-pre\0",
+  g_signal_connect(G_OBJECT(recall_audio_run), "run-init-pre\0",
 		   G_CALLBACK(ags_audio_test_init_recall_callback), NULL);
   
   /* instantiate recycling context and recall id */
@@ -1238,7 +1328,7 @@ ags_audio_test_resolve_recall()
   AgsRecallID *recall_id;
   
   /* instantiate audio */
-  audio = ags_audio_new(AGS_SOUNDCARD(devout));
+  audio = ags_audio_new(devout);
 
   /* instantiate recalls */
   slave_recall_audio_run = ags_recall_audio_run_new();
@@ -1246,7 +1336,7 @@ ags_audio_test_resolve_recall()
 		       slave_recall_audio_run,
 		       TRUE);
 
-  g_signal_connect(G_OBJECT(slave_recall_audio_run), "resolve\0",
+  g_signal_connect(G_OBJECT(slave_recall_audio_run), "resolve-dependencies\0",
 		   G_CALLBACK(ags_audio_test_resolve_recall_callback), NULL);
   
   /* instantiate recycling context and recall id */
@@ -1270,6 +1360,12 @@ ags_audio_test_resolve_recall()
 }
 
 void
+ags_audio_test_finalize_stub(GObject *gobject)
+{
+  audio_test_finalized = TRUE;
+}
+
+void
 ags_audio_test_set_link_callback(AgsChannel *channel, AgsChannel *link,
 				 GError **error,
 				 AgsAudio *audio)
@@ -1298,7 +1394,7 @@ main(int argc, char **argv)
 
   putenv("LC_ALL=C\0");
   putenv("LANG=C\0");
-  
+
   /* initialize the CUnit test registry */
   if(CUE_SUCCESS != CU_initialize_registry()){
     return CU_get_error();
@@ -1313,8 +1409,13 @@ main(int argc, char **argv)
     return CU_get_error();
   }
 
+  g_log_set_fatal_mask("GLib-GObject\0", // "Gtk\0" G_LOG_DOMAIN,
+  		       G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
+
   /* add the tests to the suite */
-  if((CU_add_test(pSuite, "test of AgsAudio set pads\0", ags_audio_test_set_pads) == NULL) ||
+  if((CU_add_test(pSuite, "test of AgsAudio dispose\0", ags_audio_test_dispose) == NULL) ||
+     (CU_add_test(pSuite, "test of AgsAudio finalize\0", ags_audio_test_finalize) == NULL) ||
+     (CU_add_test(pSuite, "test of AgsAudio set pads\0", ags_audio_test_set_pads) == NULL) ||
      (CU_add_test(pSuite, "test of AgsAudio set audio channels\0", ags_audio_test_set_audio_channels) == NULL) ||
      (CU_add_test(pSuite, "test of AgsAudio link channel\0", ags_audio_test_link_channel) == NULL) ||
      (CU_add_test(pSuite, "test of AgsAudio finalize linked channel\0", ags_audio_test_finalize_linked_channel) == NULL) ||
@@ -1325,10 +1426,10 @@ main(int argc, char **argv)
      (CU_add_test(pSuite, "test of AgsAudio duplicate recall\0", ags_audio_test_duplicate_recall) == NULL) ||
      (CU_add_test(pSuite, "test of AgsAudio initialize recall\0", ags_audio_test_init_recall) == NULL) ||
      (CU_add_test(pSuite, "test of AgsAudio resolve recall\0", ags_audio_test_resolve_recall) == NULL)){
-      CU_cleanup_registry();
-      
-      return CU_get_error();
-    }
+    CU_cleanup_registry();
+    
+    return CU_get_error();
+  }
   
   /* Run all tests using the CUnit Basic interface */
   CU_basic_set_mode(CU_BRM_VERBOSE);
diff --git a/ags/test/audio/ags_channel_test.c b/ags/test/audio/ags_channel_test.c
index 384289c..590f132 100644
--- a/ags/test/audio/ags_channel_test.c
+++ b/ags/test/audio/ags_channel_test.c
@@ -24,23 +24,14 @@
 #include <CUnit/Automated.h>
 #include <CUnit/Basic.h>
 
-#include <ags/object/ags_soundcard.h>
-
-#include <ags/audio/ags_channel.h>
-#include <ags/audio/ags_output.h>
-#include <ags/audio/ags_input.h>
-#include <ags/audio/ags_recall.h>
-#include <ags/audio/ags_recall_audio.h>
-#include <ags/audio/ags_recall_audio_run.h>
-#include <ags/audio/ags_recall_channel.h>
-#include <ags/audio/ags_recall_channel_run.h>
-#include <ags/audio/ags_recall_container.h>
-#include <ags/audio/ags_recall_id.h>
-#include <ags/audio/ags_recycling_context.h>
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
 
 int ags_channel_test_init_suite();
 int ags_channel_test_clean_suite();
 
+void ags_channel_test_dispose();
+void ags_channel_test_finalize();
 void ags_channel_test_add_recall();
 void ags_channel_test_add_recall_container();
 void ags_channel_test_add_recall_id();
@@ -48,11 +39,21 @@ void ags_channel_test_duplicate_recall();
 void ags_channel_test_init_recall();
 void ags_channel_test_resolve_recall();
 
+void ags_channel_test_finalize_stub(GObject *gobject);
 void ags_channel_test_run_init_pre_recall_callback(AgsRecall *recall,
 						   gpointer data);
 void ags_channel_test_resolve_recall_callback(AgsRecall *recall,
 					      gpointer data);
 
+#define AGS_CHANNEL_TEST_DISPOSE_PLAY_COUNT (8)
+#define AGS_CHANNEL_TEST_DISPOSE_RECALL_COUNT (8)
+
+#define AGS_CHANNEL_TEST_FINALIZE_PLAY_COUNT (8)
+#define AGS_CHANNEL_TEST_FINALIZE_RECALL_COUNT (8)
+
+AgsAudio *audio;
+gboolean channel_test_finalized;
+
 guint test_init_recall_callback_hits_count = 0;
 guint test_resolve_recall_callback_hits_count = 0;
 
@@ -63,7 +64,12 @@ guint test_resolve_recall_callback_hits_count = 0;
 int
 ags_channel_test_init_suite()
 {
-  /* empty */
+  audio = g_object_new(AGS_TYPE_AUDIO,
+		       NULL);
+  audio->flags |= (AGS_AUDIO_OUTPUT_HAS_RECYCLING |
+		   AGS_AUDIO_INPUT_HAS_RECYCLING);
+  
+  g_object_ref(audio);
   
   return(0);
 }
@@ -75,12 +81,127 @@ ags_channel_test_init_suite()
 int
 ags_channel_test_clean_suite()
 {
-  /* empty */
+  g_object_unref(audio);
   
   return(0);
 }
 
 void
+ags_channel_test_dispose()
+{
+  AgsChannel *channel;
+  AgsRecall *recall;
+
+  guint i;
+  
+  channel = ags_output_new(audio);
+  
+  channel->first_recycling =
+    channel->last_recycling = ags_recycling_new(NULL);
+  g_object_ref(channel->first_recycling);
+  
+  /* add recall to play context */
+  for(i = 0; i < AGS_CHANNEL_TEST_DISPOSE_PLAY_COUNT; i++){
+    /* instantiate play */
+    recall = ags_recall_new();
+
+    /* add play to audio */
+    ags_audio_add_recall(audio,
+			 recall,
+			 TRUE);
+  }
+  
+  /* add recall to recall context */
+  for(i = 0; i < AGS_CHANNEL_TEST_DISPOSE_RECALL_COUNT; i++){
+    /* instantiate recall */
+    recall = ags_recall_new();
+
+    /* add recall to audio */
+    ags_audio_add_recall(audio,
+			 recall,
+			 FALSE);
+  }
+
+  /* run dispose and assert */
+  g_object_run_dispose(channel);
+  g_object_run_dispose(channel->playback);
+
+  channel->playback = NULL;
+  
+  CU_ASSERT(channel->audio == NULL);
+  CU_ASSERT(channel->soundcard == NULL);
+
+  CU_ASSERT(channel->recall_id == NULL);
+  CU_ASSERT(channel->container == NULL);
+
+  CU_ASSERT(channel->recall == NULL);
+  CU_ASSERT(channel->play == NULL);
+
+  CU_ASSERT(channel->first_recycling == NULL);
+  CU_ASSERT(channel->last_recycling == NULL);
+
+  CU_ASSERT(channel->pattern == NULL);
+}
+
+void
+ags_channel_test_finalize()
+{
+  AgsChannel *channel;
+  AgsRecall *recall;
+
+  guint i;
+  
+  channel = ags_output_new(audio);
+  
+  channel->first_recycling =
+    channel->last_recycling = ags_recycling_new(NULL);
+  g_object_ref(channel->first_recycling);
+  
+  /* add recall to play context */
+  for(i = 0; i < AGS_CHANNEL_TEST_FINALIZE_PLAY_COUNT; i++){
+    /* instantiate play */
+    recall = ags_recall_channel_new();
+    g_object_set(recall,
+		 "source\0", channel,
+		 NULL);
+
+    /* add play to channel */
+    ags_channel_add_recall(channel,
+			   recall,
+			   TRUE);
+  }
+  
+  /* add recall to recall context */
+  for(i = 0; i < AGS_CHANNEL_TEST_FINALIZE_RECALL_COUNT; i++){
+    /* instantiate recall */
+    recall = ags_recall_channel_new();
+    g_object_set(recall,
+		 "source\0", channel,
+		 NULL);
+
+    /* add recall to channel */
+    ags_channel_add_recall(channel,
+			   recall,
+			   FALSE);
+  }
+
+  /* run dispose */
+  g_object_run_dispose(channel);
+  g_object_run_dispose(channel->playback);
+
+  channel->playback = NULL;
+  
+  /* stub */
+  channel_test_finalized = FALSE;
+  G_OBJECT_GET_CLASS(channel)->finalize = ags_channel_test_finalize_stub;
+
+  /* unref and assert */
+  g_object_unref(channel);
+  
+  CU_ASSERT(channel_test_finalized == TRUE);
+}
+
+void
 ags_channel_test_add_recall()
 {
   AgsChannel *channel;
@@ -387,6 +508,12 @@ ags_channel_test_resolve_recall()
 }
 
 void
+ags_channel_test_finalize_stub(GObject *gobject)
+{
+  channel_test_finalized = TRUE;
+}
+
+void
 ags_channel_test_run_init_pre_recall_callback(AgsRecall *recall,
 					      gpointer data)
 {
@@ -423,7 +550,9 @@ main(int argc, char **argv)
   }
 
   /* add the tests to the suite */
-  if((CU_add_test(pSuite, "test of AgsChannel add recall\0", ags_channel_test_add_recall) == NULL) ||
+  if((CU_add_test(pSuite, "test of AgsChannel dispose\0", ags_channel_test_dispose) == NULL) ||
+     (CU_add_test(pSuite, "test of AgsChannel finalize\0", ags_channel_test_finalize) == NULL) ||
+     (CU_add_test(pSuite, "test of AgsChannel add recall\0", ags_channel_test_add_recall) == NULL) ||
      (CU_add_test(pSuite, "test of AgsChannel add recall container\0", ags_channel_test_add_recall_container) == NULL) ||
      (CU_add_test(pSuite, "test of AgsChannel add recall id\0", ags_channel_test_add_recall_id) == NULL) ||
      (CU_add_test(pSuite, "test of AgsChannel add duplicate recall\0", ags_channel_test_duplicate_recall) == NULL) ||
diff --git a/ags/test/audio/ags_devout_test.c b/ags/test/audio/ags_devout_test.c
new file mode 100644
index 0000000..8687bd3
--- /dev/null
+++ b/ags/test/audio/ags_devout_test.c
@@ -0,0 +1,260 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+
+#include <ags/libags.h>
+#include <ags/libags-audio.h>
+
+#define AGS_DEVOUT_TEST_DISPOSE_AUDIO_COUNT (8)
+
+#define AGS_DEVOUT_TEST_FINALIZE_AUDIO_COUNT (8)
+
+int ags_devout_test_init_suite();
+int ags_devout_test_clean_suite();
+
+void ags_devout_test_dispose();
+void ags_devout_test_finalize();
+
+void ags_devout_test_finalize_stub(GObject *gobject);
+
+#define AGS_DEVOUT_TEST_CONFIG "[generic]\n" \
+  "autosave-thread=false\n"			       \
+  "simple-file=true\n"				       \
+  "disable-feature=experimental\n"		       \
+  "segmentation=4/4\n"				       \
+  "\n"						       \
+  "[thread]\n"					       \
+  "model=super-threaded\n"			       \
+  "super-threaded-scope=channel\n"		       \
+  "lock-global=ags-thread\n"			       \
+  "lock-parent=ags-recycling-thread\n"		       \
+  "\n"						       \
+  "[recall]\n"					       \
+  "auto-sense=true\n"				       \
+  "\n"
+
+
+AgsAudioApplicationContext *audio_application_context;
+gboolean devout_test_finalized;
+
+/* The suite initialization function.
+ * Opens the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_devout_test_init_suite()
+{
+  AgsConfig *config;
+
+  config = ags_config_get_instance();
+  ags_config_load_from_data(config,
+			    AGS_DEVOUT_TEST_CONFIG,
+			    strlen(AGS_DEVOUT_TEST_CONFIG));
+  
+  audio_application_context = ags_audio_application_context_new();
+  g_object_ref(audio_application_context);
+  
+  return(0);
+}
+
+/* The suite cleanup function.
+ * Closes the temporary file used by the tests.
+ * Returns zero on success, non-zero otherwise.
+ */
+int
+ags_devout_test_clean_suite()
+{
+  g_object_unref(audio_application_context);
+  
+  return(0);
+}
+
+void
+ags_devout_test_dispose()
+{
+  AgsDevout *devout;
+  AgsAudio *audio;
+  
+  GList *list, *list_start;
+  
+  guint i;
+  gboolean success;
+  
+  devout = g_object_new(AGS_TYPE_DEVOUT,
+			"application-context\0", audio_application_context,
+			NULL);
+  g_object_ref(devout);
+  
+  /* instantiate audio list */
+  list_start = NULL;
+  
+  for(i = 0; i < AGS_DEVOUT_TEST_DISPOSE_AUDIO_COUNT; i++){
+    audio = g_object_new(AGS_TYPE_AUDIO,
+			 NULL);
+    g_object_ref(audio);    
+
+    list_start = g_list_prepend(list_start,
+				audio);
+  }
+
+  /* add to soundcard */
+  list = list_start;
+  
+  while(list != NULL){
+    /* audio list of soundcard */
+    ags_soundcard_set_audio(AGS_SOUNDCARD(devout),
+			    g_list_prepend(ags_soundcard_get_audio(AGS_SOUNDCARD(devout)),
+					   list->data));
+    g_object_ref(list->data);
+
+    /* soundcard property of audio */
+    g_object_set(list->data,
+		 "soundcard\0", devout,
+		 NULL);
+
+    /* iterate */
+    list = list->next;
+  }
+
+  /* run dispose */
+  g_object_run_dispose(devout);
+
+  /* assert no application context */
+  CU_ASSERT(ags_soundcard_get_application_context(AGS_SOUNDCARD(devout)) == NULL);
+  
+  /* assert no audio */
+  CU_ASSERT(ags_soundcard_get_audio(AGS_SOUNDCARD(devout)) == NULL);
+
+  /* verify soundcard equals NULL */
+  list = list_start;
+  success = TRUE;
+  
+  while(list != NULL){
+    GObject *soundcard;
+    
+    g_object_get(list->data,
+		 "soundcard\0", &soundcard,
+		 NULL);
+
+    if(soundcard != NULL){
+      success = FALSE;
+
+      break;
+    }
+    
+    list = list->next;
+  }
+
+  /* assert */
+  CU_ASSERT(success == TRUE);
+}
+
+void
+ags_devout_test_finalize()
+{
+  AgsDevout *devout;
+  AgsAudio *audio;
+    
+  guint i;
+  
+  devout = g_object_new(AGS_TYPE_DEVOUT,
+			"application-context\0", audio_application_context,
+			NULL);
+
+  /* audio list */  
+  for(i = 0; i < AGS_DEVOUT_TEST_FINALIZE_AUDIO_COUNT; i++){
+    /* instantiate audio */
+    audio = g_object_new(AGS_TYPE_AUDIO,
+			 NULL);
+    g_object_ref(audio);    
+
+    /* audio list of soundcard */
+    ags_soundcard_set_audio(AGS_SOUNDCARD(devout),
+			    g_list_prepend(ags_soundcard_get_audio(AGS_SOUNDCARD(devout)),
+					   audio));
+    g_object_ref(audio);
+
+    /* soundcard property of audio */
+    g_object_set(audio,
+		 "soundcard\0", devout,
+		 NULL);
+  }
+
+  /* run dispose */
+  g_object_run_dispose(devout);
+
+  /* stub finalize */
+  devout_test_finalized = FALSE;
+  G_OBJECT_GET_CLASS(devout)->finalize = ags_devout_test_finalize_stub;
+
+  /* unref and assert */
+  g_object_unref(devout);
+  
+  CU_ASSERT(devout_test_finalized == TRUE);
+}
+
+void
+ags_devout_test_finalize_stub(GObject *gobject)
+{
+  devout_test_finalized = TRUE;
+}
+
+int
+main(int argc, char **argv)
+{
+  CU_pSuite pSuite = NULL;
+
+  putenv("LC_ALL=C\0");
+  putenv("LANG=C\0");
+
+  /* initialize the CUnit test registry */
+  if(CUE_SUCCESS != CU_initialize_registry()){
+    return CU_get_error();
+  }
+
+  /* add a suite to the registry */
+  pSuite = CU_add_suite("AgsDevoutTest\0", ags_devout_test_init_suite, ags_devout_test_clean_suite);
+  
+  if(pSuite == NULL){
+    CU_cleanup_registry();
+    
+    return CU_get_error();
+  }
+
+  /* add the tests to the suite */
+  if((CU_add_test(pSuite, "test of AgsDevout doing dispose\0", ags_devout_test_dispose) == NULL) ||
+     (CU_add_test(pSuite, "test of AgsDevout doing finalize\0", ags_devout_test_finalize) == NULL)){
+      CU_cleanup_registry();
+      
+      return CU_get_error();
+    }
+  
+  /* Run all tests using the CUnit Basic interface */
+  CU_basic_set_mode(CU_BRM_VERBOSE);
+  CU_basic_run_tests();
+  
+  CU_cleanup_registry();
+  
+  return(CU_get_error());
+}
diff --git a/ags/test/audio/ags_functional_audio_test.c b/ags/test/audio/ags_functional_audio_test.c
index da25a1b..cca76b4 100644
--- a/ags/test/audio/ags_functional_audio_test.c
+++ b/ags/test/audio/ags_functional_audio_test.c
@@ -589,7 +589,11 @@ ags_functional_audio_test_playback()
   /*
    * Setup audio tree sink, mixer and notation player as source
    */
-  soundcard = audio_application_context->soundcard->data;
+  soundcard = NULL;
+  
+  if(audio_application_context->soundcard != NULL){
+    soundcard = audio_application_context->soundcard->data;
+  }
 
   /* the output panel */
   panel = ags_audio_new(soundcard);
diff --git a/ags/test/thread/ags_thread_test.c b/ags/test/thread/ags_thread_test.c
index e740231..1aa2526 100644
--- a/ags/test/thread/ags_thread_test.c
+++ b/ags/test/thread/ags_thread_test.c
@@ -24,18 +24,7 @@
 #include <CUnit/Automated.h>
 #include <CUnit/Basic.h>
 
-#include <ags/object/ags_application_context.h>
-#include <ags/object/ags_main_loop.h>
-#include <ags/object/ags_async_queue.h>
-
-#ifdef AGS_USE_LINUX_THREADS
-#include <ags/thread/ags_thread-kthreads.h>
-#else
-#include <ags/thread/ags_thread-posix.h>
-#endif 
-
-#include <ags/thread/ags_generic_main_loop.h>
-#include <ags/thread/ags_task_thread.h>
+#include <ags/libags.h>
 
 int ags_thread_test_init_suite();
 int ags_thread_test_clean_suite();
@@ -81,7 +70,13 @@ void ags_thread_test_stop();
 
 #define AGS_THREAD_TEST_ADD_CHILD_N_THREADS (16)
 
-AgsApplicationContext *application_context;
+#define AGS_THREAD_TEST_LOCK_PARENT_PARENT_COUNT (8)
+
+#define AGS_THREAD_TEST_LOCK_SIBLING_SIBLING_COUNT (64)
+
+#define AGS_THREAD_TEST_LOCK_CHILDREN_CHILDREN_COUNT (8)
+
+  AgsApplicationContext *application_context;
 
 AgsThread *main_loop;
 
@@ -304,7 +299,7 @@ ags_thread_test_lock()
   pthread_create(&assert_thread, NULL,
 		 ags_thread_test_lock_assert_locked, thread);
   pthread_join(assert_thread,
-	        NULL);
+	       NULL);
 
   /* unlock the threads */
   for(i = 0; i < AGS_THREAD_TEST_LOCK_N_THREADS; i++){
@@ -614,7 +609,7 @@ ags_thread_test_is_current_ready()
   CU_ASSERT(ags_thread_is_current_ready(thread, 0) == TRUE);
 
   g_atomic_int_and(&(parent->flags),
-		  ~AGS_THREAD_WAIT_0);
+		   ~AGS_THREAD_WAIT_0);
   g_atomic_int_and(&(thread->flags),
 		   ~AGS_THREAD_WAIT_0);
 
@@ -628,7 +623,7 @@ ags_thread_test_is_current_ready()
   CU_ASSERT(ags_thread_is_current_ready(thread, 1) == TRUE);
 
   g_atomic_int_and(&(parent->flags),
-		  ~AGS_THREAD_WAIT_1);
+		   ~AGS_THREAD_WAIT_1);
   g_atomic_int_and(&(thread->flags),
 		   ~AGS_THREAD_WAIT_1);
 
@@ -642,7 +637,7 @@ ags_thread_test_is_current_ready()
   CU_ASSERT(ags_thread_is_current_ready(thread, 2) == TRUE);
 
   g_atomic_int_and(&(parent->flags),
-		  ~AGS_THREAD_WAIT_2);
+		   ~AGS_THREAD_WAIT_2);
   g_atomic_int_and(&(thread->flags),
 		   ~AGS_THREAD_WAIT_2);
 }
@@ -676,7 +671,7 @@ ags_thread_test_is_tree_ready()
   CU_ASSERT(ags_thread_is_tree_ready(parent, 0) == TRUE);
 
   g_atomic_int_and(&(parent->flags),
-		  ~AGS_THREAD_WAIT_0);
+		   ~AGS_THREAD_WAIT_0);
   g_atomic_int_and(&(thread->flags),
 		   ~AGS_THREAD_WAIT_0);
 
@@ -689,7 +684,7 @@ ags_thread_test_is_tree_ready()
   CU_ASSERT(ags_thread_is_tree_ready(parent, 1) == TRUE);
 
   g_atomic_int_and(&(parent->flags),
-		  ~AGS_THREAD_WAIT_1);
+		   ~AGS_THREAD_WAIT_1);
   g_atomic_int_and(&(thread->flags),
 		   ~AGS_THREAD_WAIT_1);
 
@@ -702,7 +697,7 @@ ags_thread_test_is_tree_ready()
   CU_ASSERT(ags_thread_is_tree_ready(parent, 2) == TRUE);
 
   g_atomic_int_and(&(parent->flags),
-		  ~AGS_THREAD_WAIT_2);
+		   ~AGS_THREAD_WAIT_2);
   g_atomic_int_and(&(thread->flags),
 		   ~AGS_THREAD_WAIT_2);
 
@@ -711,37 +706,689 @@ ags_thread_test_is_tree_ready()
 void
 ags_thread_test_next_parent_locked()
 {
-  //TODO:JK: implement me
+  AgsThread *toplevel;
+
+  AgsThread *locked_thread_level_1_a;
+  AgsThread *locked_thread_level_2_a;
+  AgsThread *locked_thread_level_3_a;
+
+  AgsThread *locked_thread_level_1_b;
+  AgsThread *locked_thread_level_2_b;
+
+  AgsThread *locked_thread_level_1_c;
+
+  AgsThread *locked_thread_level_1_d;
+  AgsThread *locked_thread_level_3_d;
+
+  AgsThread *thread_level_4_a;
+  AgsThread *thread_level_4_b;
+  AgsThread *thread_level_4_c;
+  AgsThread *thread_level_4_d;
+
+  AgsThread *current, *parent;
+  
+  toplevel = ags_generic_main_loop_new(NULL);
+
+  /* thread group a */
+  locked_thread_level_1_a = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				locked_thread_level_1_a,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_1_a->sync_flags),
+		  AGS_THREAD_WAITING_FOR_CHILDREN);
+
+  locked_thread_level_2_a = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_1_a,
+				locked_thread_level_2_a,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_2_a->sync_flags),
+		  AGS_THREAD_WAITING_FOR_CHILDREN);
+
+  locked_thread_level_3_a = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_2_a,
+				locked_thread_level_3_a,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_3_a->sync_flags),
+		  AGS_THREAD_WAITING_FOR_CHILDREN);
+
+  thread_level_4_a = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_3_a,
+				thread_level_4_a,
+				TRUE, TRUE);
+
+  /* thread group b */
+  locked_thread_level_1_b = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				locked_thread_level_1_b,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_1_b->sync_flags),
+		  AGS_THREAD_WAITING_FOR_CHILDREN);
+
+  locked_thread_level_2_b = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_1_b,
+				locked_thread_level_2_b,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_2_b->sync_flags),
+		  AGS_THREAD_WAITING_FOR_CHILDREN);
+
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_2_b,
+				current,
+				TRUE, TRUE);
+
+  parent = current;
+  
+  thread_level_4_b = ags_thread_new(NULL);
+  ags_thread_add_child_extended(parent,
+				thread_level_4_b,
+				TRUE, TRUE);
+
+  /* thread group c */
+  locked_thread_level_1_c = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				locked_thread_level_1_c,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_1_c->sync_flags),
+		  AGS_THREAD_WAITING_FOR_CHILDREN);
+
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_1_c,
+				current,
+				TRUE, TRUE);
+
+  parent = current;
+  
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(parent,
+				current,
+				TRUE, TRUE);
+
+  parent = current;
+  
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(parent,
+				current,
+				TRUE, TRUE);
+
+  thread_level_4_c = ags_thread_new(NULL);
+  ags_thread_add_child_extended(current,
+				thread_level_4_c,
+				TRUE, TRUE);
+
+  /* thread group d */
+  locked_thread_level_1_d = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				locked_thread_level_1_d,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_1_d->sync_flags),
+		  AGS_THREAD_WAITING_FOR_CHILDREN);
+
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_1_d,
+				current,
+				TRUE, TRUE);
+
+  parent = current;
+
+  locked_thread_level_3_d = ags_thread_new(NULL);
+  ags_thread_add_child_extended(parent,
+				locked_thread_level_3_d,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_3_d->sync_flags),
+		  AGS_THREAD_WAITING_FOR_CHILDREN);
+
+  thread_level_4_d = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_3_d,
+				thread_level_4_d,
+				TRUE, TRUE);
+
+  /* assert thread group a */
+  current = thread_level_4_a;
+  
+  CU_ASSERT((current = ags_thread_next_parent_locked(current, NULL)) == locked_thread_level_3_a);
+  CU_ASSERT((current = ags_thread_next_parent_locked(current, NULL)) == locked_thread_level_2_a);
+  CU_ASSERT((current = ags_thread_next_parent_locked(current, NULL)) == locked_thread_level_1_a);
+  CU_ASSERT((current = ags_thread_next_parent_locked(current, NULL)) == NULL);
+
+  /* assert thread group b */
+  current = thread_level_4_b;
+  
+  CU_ASSERT((current = ags_thread_next_parent_locked(current, NULL)) == locked_thread_level_2_b);
+  CU_ASSERT((current = ags_thread_next_parent_locked(current, NULL)) == locked_thread_level_1_b);
+  CU_ASSERT((current = ags_thread_next_parent_locked(current, NULL)) == NULL);
+
+  /* assert thread group c */
+  current = thread_level_4_c;
+  
+  CU_ASSERT((current = ags_thread_next_parent_locked(current, NULL)) == locked_thread_level_1_c);
+  CU_ASSERT((current = ags_thread_next_parent_locked(current, NULL)) == NULL);
+  
+  /* assert thread group d */
+  current = thread_level_4_d;
+  
+  CU_ASSERT((current = ags_thread_next_parent_locked(current, NULL)) == locked_thread_level_3_d);
+  CU_ASSERT((current = ags_thread_next_parent_locked(current, NULL)) == locked_thread_level_1_d);
+  CU_ASSERT((current = ags_thread_next_parent_locked(current, NULL)) == NULL);
 }
 
 void
 ags_thread_test_next_sibling_locked()
 {
-  //TODO:JK: implement me
+  AgsThread *toplevel;
+
+  AgsThread *sibling0;
+  AgsThread *sibling1;
+  AgsThread *sibling3;
+  AgsThread *sibling7;
+
+  AgsThread *current, *prev;
+
+  toplevel = ags_generic_main_loop_new(NULL);
+
+  /* create sibling */
+  sibling0 =
+    current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				current,
+				TRUE, TRUE);
+
+  sibling1 =
+    current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				current,
+				TRUE, TRUE);
+  g_atomic_int_or(&(current->sync_flags),
+		  AGS_THREAD_WAITING_FOR_SIBLING);
+  
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				current,
+				TRUE, TRUE);
+
+  sibling3 = 
+    current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				current,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(current->sync_flags),
+		  AGS_THREAD_WAITING_FOR_SIBLING);
+
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				current,
+				TRUE, TRUE);
+
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				current,
+				TRUE, TRUE);
+
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				current,
+				TRUE, TRUE);
+
+  sibling7 =
+    current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				current,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(current->sync_flags),
+		  AGS_THREAD_WAITING_FOR_SIBLING);
+
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				current,
+				TRUE, TRUE);
+
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				current,
+				TRUE, TRUE);
+
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				current,
+				TRUE, TRUE);
+
+  /* assert sibling */
+  current = sibling0;
+
+  CU_ASSERT((current = ags_thread_next_sibling_locked(current)) == sibling1);
+  
+  g_atomic_int_and(&(sibling1->sync_flags),
+		   (~AGS_THREAD_WAITING_FOR_SIBLING));
+  
+  CU_ASSERT((current = ags_thread_next_sibling_locked(current)) == sibling3);
+  
+  g_atomic_int_and(&(sibling3->sync_flags),
+		   (~AGS_THREAD_WAITING_FOR_SIBLING));
+  
+  CU_ASSERT((current = ags_thread_next_sibling_locked(current)) == sibling7);
+  
+  g_atomic_int_and(&(sibling7->sync_flags),
+		   (~AGS_THREAD_WAITING_FOR_SIBLING));
+  
+  CU_ASSERT((current = ags_thread_next_sibling_locked(current)) == NULL);
 }
 
 void
 ags_thread_test_next_children_locked()
 {
-  //TODO:JK: implement me
+  AgsThread *toplevel;
+
+  AgsThread *locked_thread_level_1_a;
+  AgsThread *locked_thread_level_2_a;
+  AgsThread *locked_thread_level_3_a;
+
+  AgsThread *locked_thread_level_1_b;
+  AgsThread *locked_thread_level_2_b;
+
+  AgsThread *locked_thread_level_1_c;
+
+  AgsThread *locked_thread_level_1_d;
+  AgsThread *locked_thread_level_3_d;
+
+  AgsThread *thread_level_4_a;
+  AgsThread *thread_level_4_b;
+  AgsThread *thread_level_4_c;
+  AgsThread *thread_level_4_d;
+
+  AgsThread *current, *parent;
+  
+  toplevel = ags_generic_main_loop_new(NULL);
+
+  /* thread group a */
+  locked_thread_level_1_a = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				locked_thread_level_1_a,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_1_a->sync_flags),
+		  AGS_THREAD_WAITING_FOR_PARENT);
+
+  locked_thread_level_2_a = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_1_a,
+				locked_thread_level_2_a,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_2_a->sync_flags),
+		  AGS_THREAD_WAITING_FOR_PARENT);
+
+  locked_thread_level_3_a = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_2_a,
+				locked_thread_level_3_a,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_3_a->sync_flags),
+		  AGS_THREAD_WAITING_FOR_PARENT);
+
+  thread_level_4_a = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_3_a,
+				thread_level_4_a,
+				TRUE, TRUE);
+
+  /* thread group b */
+  locked_thread_level_1_b = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				locked_thread_level_1_b,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_1_b->sync_flags),
+		  AGS_THREAD_WAITING_FOR_PARENT);
+
+  locked_thread_level_2_b = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_1_b,
+				locked_thread_level_2_b,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_2_b->sync_flags),
+		  AGS_THREAD_WAITING_FOR_PARENT);
+
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_2_b,
+				current,
+				TRUE, TRUE);
+
+  parent = current;
+  
+  thread_level_4_b = ags_thread_new(NULL);
+  ags_thread_add_child_extended(parent,
+				thread_level_4_b,
+				TRUE, TRUE);
+
+  /* thread group c */
+  locked_thread_level_1_c = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				locked_thread_level_1_c,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_1_c->sync_flags),
+		  AGS_THREAD_WAITING_FOR_PARENT);
+
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_1_c,
+				current,
+				TRUE, TRUE);
+
+  parent = current;
+  
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(parent,
+				current,
+				TRUE, TRUE);
+
+  parent = current;
+  
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(parent,
+				current,
+				TRUE, TRUE);
+
+  thread_level_4_c = ags_thread_new(NULL);
+  ags_thread_add_child_extended(current,
+				thread_level_4_c,
+				TRUE, TRUE);
+
+  /* thread group d */
+  locked_thread_level_1_d = ags_thread_new(NULL);
+  ags_thread_add_child_extended(toplevel,
+				locked_thread_level_1_d,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_1_d->sync_flags),
+		  AGS_THREAD_WAITING_FOR_PARENT);
+
+  current = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_1_d,
+				current,
+				TRUE, TRUE);
+
+  parent = current;
+
+  locked_thread_level_3_d = ags_thread_new(NULL);
+  ags_thread_add_child_extended(parent,
+				locked_thread_level_3_d,
+				TRUE, TRUE);
+
+  g_atomic_int_or(&(locked_thread_level_3_d->sync_flags),
+		  AGS_THREAD_WAITING_FOR_PARENT);
+
+  thread_level_4_d = ags_thread_new(NULL);
+  ags_thread_add_child_extended(locked_thread_level_3_d,
+				thread_level_4_d,
+				TRUE, TRUE);
+
+  /* assert children */
+  //NOTE:JK: don't touch because you need the order
+  current = toplevel;
+  
+  /* assert group d */
+  CU_ASSERT((current = ags_thread_next_children_locked(current)) == locked_thread_level_3_d);
+  g_atomic_int_and(&(locked_thread_level_3_d->sync_flags),
+		   (~AGS_THREAD_WAITING_FOR_PARENT));
+  
+  current = toplevel;
+  CU_ASSERT((current = ags_thread_next_children_locked(current)) == locked_thread_level_1_d);
+  g_atomic_int_and(&(locked_thread_level_1_d->sync_flags),
+		   (~AGS_THREAD_WAITING_FOR_PARENT));
+
+  /* assert group c */
+  current = toplevel;
+  CU_ASSERT((current = ags_thread_next_children_locked(current)) == locked_thread_level_1_c);
+  g_atomic_int_and(&(locked_thread_level_1_c->sync_flags),
+		   (~AGS_THREAD_WAITING_FOR_PARENT)); 
+  
+  /* assert group b */
+  current = toplevel;
+  CU_ASSERT((current = ags_thread_next_children_locked(current)) == locked_thread_level_2_b);
+  g_atomic_int_and(&(locked_thread_level_2_b->sync_flags),
+		   (~AGS_THREAD_WAITING_FOR_PARENT));
+
+  current = toplevel;
+  CU_ASSERT((current = ags_thread_next_children_locked(current)) == locked_thread_level_1_b);
+  g_atomic_int_and(&(locked_thread_level_1_b->sync_flags),
+		   (~AGS_THREAD_WAITING_FOR_PARENT));
+
+  /* assert group a */
+  current = toplevel;
+  CU_ASSERT((current = ags_thread_next_children_locked(current)) == locked_thread_level_3_a);
+  g_atomic_int_and(&(locked_thread_level_3_a->sync_flags),
+		   (~AGS_THREAD_WAITING_FOR_PARENT));
+
+  current = toplevel;
+  CU_ASSERT((current = ags_thread_next_children_locked(current)) == locked_thread_level_2_a);
+  g_atomic_int_and(&(locked_thread_level_2_a->sync_flags),
+		   (~AGS_THREAD_WAITING_FOR_PARENT));
+
+  current = toplevel;
+  CU_ASSERT((current = ags_thread_next_children_locked(current)) == locked_thread_level_1_a);
+  g_atomic_int_and(&(locked_thread_level_1_a->sync_flags),
+		   (~AGS_THREAD_WAITING_FOR_PARENT));
+
+  /* assert group NULL */
+  current = toplevel;
+  CU_ASSERT((current = ags_thread_next_children_locked(current)) == NULL);
 }
 
 void
 ags_thread_test_lock_parent()
 {
-  //TODO:JK: implement me
+  AgsThread *toplevel;
+  AgsThread *parent, *current;
+  
+  GList *thread;
+
+  guint i;
+  gboolean success;
+
+  //TODO:JK: improve this test
+  toplevel = ags_generic_main_loop_new(NULL);
+
+  /* create tree */
+  parent = toplevel;
+  
+  for(i = 0; i < AGS_THREAD_TEST_LOCK_PARENT_PARENT_COUNT; i++){
+    current = ags_thread_new(NULL);
+    ags_thread_add_child_extended(parent,
+				  current,
+				  TRUE, TRUE);
+
+    parent = current;
+  }
+
+  /* lock parent */
+  ags_thread_lock_parent(current,
+			 NULL);
+
+  /* assert current not locked */
+  CU_ASSERT((AGS_THREAD_LOCKED & (g_atomic_int_get(&(current->flags)))) != 0);
+  CU_ASSERT((AGS_THREAD_WAITING_FOR_CHILDREN & (g_atomic_int_get(&(current->sync_flags)))) == 0);
+  
+  /* assert all parent locked */
+  current = g_atomic_pointer_get(&(current->parent));
+  success = TRUE;
+  
+  while(current != NULL){
+    if((AGS_THREAD_LOCKED & (g_atomic_int_get(&(current->flags)))) == 0 ||
+       (AGS_THREAD_WAITING_FOR_CHILDREN & (g_atomic_int_get(&(current->sync_flags)))) == 0){
+      success = FALSE;
+
+      break;
+    }
+    
+    current = g_atomic_pointer_get(&(current->parent));
+  }
+
+  CU_ASSERT(success == TRUE);
 }
 
 void
 ags_thread_test_lock_sibling()
 {
-  //TODO:JK: implement me
+  AgsThread *toplevel;
+  AgsThread *parent, *current, *iter;
+
+  guint nth;
+  guint i;
+
+  auto gboolean ags_thread_test_lock_sibling_assert(AgsThread *parent, AgsThread *current){
+    AgsThread *iter;
+    
+    gboolean success;
+    
+    /* assert sibling */
+    iter = g_atomic_pointer_get(&(parent->children));
+    success = TRUE;
+
+    while(iter != NULL){
+      if(iter == current){
+	if((AGS_THREAD_LOCKED & (g_atomic_int_get(&(iter->flags)))) == 0 ||
+	   (AGS_THREAD_WAITING_FOR_SIBLING & (g_atomic_int_get(&(iter->sync_flags)))) != 0){
+	  success = FALSE;
+	  
+	  break;
+	}
+	
+	iter = g_atomic_pointer_get(&(iter->next));
+
+	continue;
+      }
+    
+      if((AGS_THREAD_LOCKED & (g_atomic_int_get(&(iter->flags)))) == 0 ||
+	 (AGS_THREAD_WAITING_FOR_SIBLING & (g_atomic_int_get(&(iter->sync_flags)))) == 0){
+	success = FALSE;
+
+	break;
+      }
+    
+      iter = g_atomic_pointer_get(&(iter->next));
+    }
+
+
+    return(success);
+  }
+  
+  toplevel = ags_thread_new(NULL);
+
+  /* create tree */
+  parent = toplevel;
+  
+  for(i = 0; i < AGS_THREAD_TEST_LOCK_SIBLING_SIBLING_COUNT; i++){
+    current = ags_thread_new(NULL);
+    ags_thread_add_child_extended(toplevel,
+				  current,
+				  TRUE, TRUE);
+  }
+
+  /* lock sibling first */
+  current = g_atomic_pointer_get(&(parent->children));
+  ags_thread_lock_sibling(current);
+
+  /* assert sibling */
+  CU_ASSERT(ags_thread_test_lock_sibling_assert(parent, current) == TRUE);  
+  
+  ags_thread_unlock_sibling(current);
+  
+  /* lock sibling last */
+  current = ags_thread_last(g_atomic_pointer_get(&(parent->children)));
+  ags_thread_lock_sibling(current);
+  
+  /* assert sibling */
+  CU_ASSERT(ags_thread_test_lock_sibling_assert(parent, current) == TRUE);
+  
+  ags_thread_unlock_sibling(current);
+
+  /* lock sibling random 0 */
+  current = g_atomic_pointer_get(&(parent->children));
+  nth = rand() % AGS_THREAD_TEST_LOCK_SIBLING_SIBLING_COUNT;
+
+  for(i = 0; i < nth; i++){
+    current = g_atomic_pointer_get(&(current->next));
+  }  
+  
+  ags_thread_lock_sibling(current);
+
+  /* assert sibling */
+  CU_ASSERT(ags_thread_test_lock_sibling_assert(parent, current) == TRUE);
+  
+  ags_thread_unlock_sibling(current);
+
+  /* lock sibling random 1 */
+  current = g_atomic_pointer_get(&(parent->children));
+  nth = rand() % AGS_THREAD_TEST_LOCK_SIBLING_SIBLING_COUNT;
+
+  for(i = 0; i < nth; i++){
+    current = g_atomic_pointer_get(&(current->next));
+  }  
+  
+  ags_thread_lock_sibling(current);
+
+  /* assert sibling */
+  CU_ASSERT(ags_thread_test_lock_sibling_assert(parent, current) == TRUE);
+  
+  ags_thread_unlock_sibling(current);
 }
 
 void
 ags_thread_test_lock_children()
 {
-  //TODO:JK: implement me
+  AgsThread *toplevel;
+  AgsThread *parent, *current;
+  
+  GList *thread;
+
+  guint i;
+  gboolean success;
+
+  //TODO:JK: improve this test
+  toplevel = ags_generic_main_loop_new(NULL);
+
+  /* create tree */
+  parent = toplevel;
+  
+  for(i = 0; i < AGS_THREAD_TEST_LOCK_PARENT_PARENT_COUNT; i++){
+    current = ags_thread_new(NULL);
+    ags_thread_add_child_extended(parent,
+				  current,
+				  TRUE, TRUE);
+
+    parent = current;
+  }
+
+  /* lock children */
+  ags_thread_lock_children(toplevel);
+
+  /* assert toplevel not locked */
+  CU_ASSERT((AGS_THREAD_LOCKED & (g_atomic_int_get(&(toplevel->flags)))) != 0);
+  CU_ASSERT((AGS_THREAD_WAITING_FOR_PARENT & (g_atomic_int_get(&(toplevel->sync_flags)))) == 0);
+
+  /* assert all children locked */
+  current = g_atomic_pointer_get(&(current->children));
+  success = TRUE;
+  
+  while(current != NULL){
+    if((AGS_THREAD_LOCKED & (g_atomic_int_get(&(current->flags)))) == 0 ||
+       (AGS_THREAD_WAITING_FOR_PARENT & (g_atomic_int_get(&(current->sync_flags)))) == 0){
+      success = FALSE;
+
+      break;
+    }
+    
+    current = g_atomic_pointer_get(&(current->children));
+  }
+
+  CU_ASSERT(success == TRUE);
 }
 
 void
@@ -827,7 +1474,7 @@ main(int argc, char **argv)
      (CU_add_test(pSuite, "test of AgsThread next children locked\0", ags_thread_test_next_children_locked) == NULL) ||
      (CU_add_test(pSuite, "test of AgsThread lock parent\0", ags_thread_test_lock_parent) == NULL) ||
      (CU_add_test(pSuite, "test of AgsThread lock sibling\0", ags_thread_test_lock_sibling) == NULL) ||
-     (CU_add_test(pSuite, "test of AgsThread lock childrend\0", ags_thread_test_lock_children) == NULL) ||
+     (CU_add_test(pSuite, "test of AgsThread lock children\0", ags_thread_test_lock_children) == NULL) ||
      (CU_add_test(pSuite, "test of AgsThread lock all\0", ags_thread_test_lock_all) == NULL) ||
      (CU_add_test(pSuite, "test of AgsThread wait parent\0", ags_thread_test_wait_parent) == NULL) ||
      (CU_add_test(pSuite, "test of AgsThread wait sibling\0", ags_thread_test_wait_sibling) == NULL) ||
@@ -835,10 +1482,10 @@ main(int argc, char **argv)
      (CU_add_test(pSuite, "test of AgsThread suspend\0", ags_thread_test_suspend) == NULL) ||
      (CU_add_test(pSuite, "test of AgsThread timelock\0", ags_thread_test_timelock) == NULL) ||
      (CU_add_test(pSuite, "test of AgsThread stop\0", ags_thread_test_stop) == NULL)){
-      CU_cleanup_registry();
+    CU_cleanup_registry();
       
-      return CU_get_error();
-    }
+    return CU_get_error();
+  }
   
   /* Run all tests using the CUnit Basic interface */
   CU_basic_set_mode(CU_BRM_VERBOSE);
diff --git a/ags/thread/ags_concurrency_provider.c b/ags/thread/ags_concurrency_provider.c
index 0686775..1112741 100644
--- a/ags/thread/ags_concurrency_provider.c
+++ b/ags/thread/ags_concurrency_provider.c
@@ -143,3 +143,47 @@ ags_concurrency_provider_get_thread_pool(AgsConcurrencyProvider *concurrency_pro
   return(concurrency_provider_interface->get_thread_pool(concurrency_provider));
 }
 
+/**
+ * ags_concurrency_provider_get_worker:
+ * @concurrency_provider: the #AgsConcurrencyProvider
+ *
+ * Get workers of application context.
+ *
+ * Returns: the #GList-struct containing workers
+ * 
+ * Since: 0.7.122.8
+ */
+GList*
+ags_concurrency_provider_get_worker(AgsConcurrencyProvider *concurrency_provider)
+{
+  AgsConcurrencyProviderInterface *concurrency_provider_interface;
+
+  g_return_val_if_fail(AGS_IS_CONCURRENCY_PROVIDER(concurrency_provider), NULL);
+  concurrency_provider_interface = AGS_CONCURRENCY_PROVIDER_GET_INTERFACE(concurrency_provider);
+  g_return_val_if_fail(concurrency_provider_interface->get_worker, NULL);
+
+  return(concurrency_provider_interface->get_worker(concurrency_provider));
+}
+
+/**
+ * ags_concurrency_provider_set_worker:
+ * @concurrency_provider: the #AgsConcurrencyProvider
+ * @worker: the #GList-struct containing workers
+ * 
+ * Set workers of application context.
+ * 
+ * Since: 0.7.122.8
+ */
+void
+ags_concurrency_provider_set_worker(AgsConcurrencyProvider *concurrency_provider,
+				    GList *worker)
+{
+  AgsConcurrencyProviderInterface *concurrency_provider_interface;
+
+  g_return_if_fail(AGS_IS_CONCURRENCY_PROVIDER(concurrency_provider));
+  concurrency_provider_interface = AGS_CONCURRENCY_PROVIDER_GET_INTERFACE(concurrency_provider);
+  g_return_if_fail(concurrency_provider_interface->set_worker);
+
+  concurrency_provider_interface->set_worker(concurrency_provider,
+					     worker);
+}
diff --git a/ags/thread/ags_concurrency_provider.h b/ags/thread/ags_concurrency_provider.h
index 7a8d78e..205511d 100644
--- a/ags/thread/ags_concurrency_provider.h
+++ b/ags/thread/ags_concurrency_provider.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -46,13 +46,17 @@ typedef struct _AgsConcurrencyProviderInterface AgsConcurrencyProviderInterface;
 struct _AgsConcurrencyProviderInterface
 {
   GTypeInterface interface;
-
+  
   AgsMutexManager* (*get_mutex_manager)(AgsConcurrencyProvider *concurrency_provider);
   
   AgsThread* (*get_main_loop)(AgsConcurrencyProvider *concurrency_provider);
   AgsThread* (*get_task_thread)(AgsConcurrencyProvider *concurrency_provider);
   
   AgsThreadPool* (*get_thread_pool)(AgsConcurrencyProvider *concurrency_provider);
+  
+  GList* (*get_worker)(AgsConcurrencyProvider *concurrency_provider);
+  void (*set_worker)(AgsConcurrencyProvider *concurrency_provider,
+		     GList *worker);
 };
 
 GType ags_concurrency_provider_get_type();
@@ -64,4 +68,8 @@ AgsThread* ags_concurrency_provider_get_task_thread(AgsConcurrencyProvider *conc
 
 AgsThreadPool* ags_concurrency_provider_get_thread_pool(AgsConcurrencyProvider *concurrency_provider);
 
+GList* ags_concurrency_provider_get_worker(AgsConcurrencyProvider *concurrency_provider);
+void ags_concurrency_provider_set_worker(AgsConcurrencyProvider *concurrency_provider,
+					 GList *worker);
+
 #endif /*__AGS_CONCURRENCY_PROVIDER_H__*/
diff --git a/ags/thread/ags_condition_manager.c b/ags/thread/ags_condition_manager.c
new file mode 100644
index 0000000..ba572aa
--- /dev/null
+++ b/ags/thread/ags_condition_manager.c
@@ -0,0 +1,262 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/thread/ags_condition_manager.h>
+
+#include <ags/object/ags_connectable.h>
+
+void ags_condition_manager_class_init(AgsConditionManagerClass *condition_manager);
+void ags_condition_manager_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_condition_manager_init(AgsConditionManager *condition_manager);
+void ags_condition_manager_connect(AgsConnectable *connectable);
+void ags_condition_manager_disconnect(AgsConnectable *connectable);
+void ags_condition_manager_finalize(GObject *gobject);
+
+void ags_condition_manager_destroy_data(gpointer data);
+
+/**
+ * SECTION:ags_condition_manager
+ * @short_description: condition manager
+ * @title: AgsConditionManager
+ * @section_id:
+ * @include: ags/thread/ags_condition_manager.h
+ *
+ * The #AgsConditionManager keeps your condition in a hash table where you can lookup your
+ * conditions.
+ */
+
+static gpointer ags_condition_manager_parent_class = NULL;
+
+AgsConditionManager *ags_condition_manager = NULL;
+
+GType
+ags_condition_manager_get_type()
+{
+  static GType ags_type_condition_manager = 0;
+
+  if(!ags_type_condition_manager){
+    const GTypeInfo ags_condition_manager_info = {
+      sizeof (AgsConditionManagerClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_condition_manager_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof (AgsConditionManager),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_condition_manager_init,
+    };
+
+    const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_condition_manager_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    ags_type_condition_manager = g_type_register_static(G_TYPE_OBJECT,
+							"AgsConditionManager\0",
+							&ags_condition_manager_info,
+							0);
+
+    g_type_add_interface_static(ags_type_condition_manager,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+  }
+  
+  return(ags_type_condition_manager);
+}
+
+void
+ags_condition_manager_class_init(AgsConditionManagerClass *condition_manager)
+{
+  GObjectClass *gobject;
+  GParamSpec *param_spec;
+
+  ags_condition_manager_parent_class = g_type_class_peek_parent(condition_manager);
+
+  /* GObject */
+  gobject = (GObjectClass *) condition_manager;
+
+  gobject->finalize = ags_condition_manager_finalize;
+}
+
+void
+ags_condition_manager_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  connectable->connect = ags_condition_manager_connect;
+  connectable->disconnect = ags_condition_manager_disconnect;
+}
+
+void
+ags_condition_manager_init(AgsConditionManager *condition_manager)
+{
+  condition_manager->lock_object = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+							 NULL,
+							 (GDestroyNotify) ags_condition_manager_destroy_data);
+}
+
+void
+ags_condition_manager_connect(AgsConnectable *connectable)
+{
+  /* empty */
+}
+
+void
+ags_condition_manager_disconnect(AgsConnectable *connectable)
+{
+  /* empty */
+}
+
+void
+ags_condition_manager_finalize(GObject *gobject)
+{
+  AgsConditionManager *condition_manager;
+
+  condition_manager = AGS_CONDITION_MANAGER(gobject);
+
+  g_hash_table_destroy(condition_manager->lock_object);
+}
+
+void
+ags_condition_manager_destroy_data(gpointer data)
+{
+  pthread_cond_destroy((pthread_cond_t *) data);
+}
+
+/**
+ * ags_condition_manager_insert:
+ * @condition_manager: the #AgsConditionManager
+ * @lock_object: the object as key
+ * @condition: the condition to insert
+ *
+ * Inserts a condition into hash map associated with @lock_object.
+ * 
+ * Returns: %TRUE on success, otherwise %FALSE
+ *
+ * Since: 0.7.122.8
+ */
+gboolean
+ags_condition_manager_insert(AgsConditionManager *condition_manager,
+			     GObject *lock_object, pthread_cond_t *cond)
+{
+  if(condition_manager == NULL ||
+     lock_object == NULL ||
+     cond == NULL){
+    return(FALSE);
+  }
+
+  g_hash_table_insert(condition_manager->lock_object,
+		      lock_object, cond);
+
+  return(TRUE);
+}
+
+/**
+ * ags_condition_manager_remove:
+ * @condition_manager: the #AgsConditionManager
+ * @lock_object: the object to remove
+ * 
+ * Removes a lock associated with @lock_object.3
+ *
+ * Returns: %TRUE as successfully removed, otherwise %FALSE
+ *
+ * Since: 0.7.122.8
+ */
+gboolean
+ags_condition_manager_remove(AgsConditionManager *condition_manager,
+			     GObject *lock_object)
+{
+  pthread_cond_t *cond;
+
+  cond = g_hash_table_lookup(condition_manager->lock_object,
+			     lock_object);
+
+  if(cond == NULL){
+    return(FALSE);
+  }
+
+  g_hash_table_remove(condition_manager->lock_object,
+		      lock_object);
+
+  free(cond);
+  
+  return(TRUE);
+}
+
+/**
+ * ags_condition_manager_lookup:
+ * @condition_manager: the #AgsConditionManager
+ * @lock_object: the object to lookup
+ *
+ * Lookup a condition associated with @lock_object in @condition_manager
+ *
+ * Returns: the condition on success, else %NULL
+ *
+ * Since: 0.7.122.8
+ */
+pthread_cond_t*
+ags_condition_manager_lookup(AgsConditionManager *condition_manager,
+			     GObject *lock_object)
+{
+  pthread_cond_t *cond;
+
+  cond = (pthread_cond_t *) g_hash_table_lookup(condition_manager->lock_object,
+						lock_object);
+
+  return(cond);
+}
+
+/**
+ * ags_condition_manager_get_instance:
+ * 
+ * Singleton function to optain the condition manager instance.
+ *
+ * Returns: an instance of #AgsConditionManager
+ *
+ * Since: 0.7.122.8
+ */
+AgsConditionManager*
+ags_condition_manager_get_instance()
+{
+  if(ags_condition_manager == NULL){
+    ags_condition_manager = ags_condition_manager_new();
+  }
+
+  return(ags_condition_manager);
+}
+
+/**
+ * ags_condition_manager_new:
+ *
+ * Instantiate a condition manager. 
+ *
+ * Returns: a new #AgsConditionManager
+ *
+ * Since: 0.7.122.8
+ */
+AgsConditionManager*
+ags_condition_manager_new()
+{
+  AgsConditionManager *condition_manager;
+
+  condition_manager = (AgsConditionManager *) g_object_new(AGS_TYPE_CONDITION_MANAGER,
+							   NULL);
+
+  return(condition_manager);
+}
diff --git a/ags/thread/ags_condition_manager.h b/ags/thread/ags_condition_manager.h
new file mode 100644
index 0000000..8a20208
--- /dev/null
+++ b/ags/thread/ags_condition_manager.h
@@ -0,0 +1,61 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_CONDITION_MANAGER_H__
+#define __AGS_CONDITION_MANAGER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#define AGS_TYPE_CONDITION_MANAGER                (ags_condition_manager_get_type())
+#define AGS_CONDITION_MANAGER(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_CONDITION_MANAGER, AgsConditionManager))
+#define AGS_CONDITION_MANAGER_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST(class, AGS_TYPE_CONDITION_MANAGER, AgsConditionManagerClass))
+#define AGS_IS_CONDITION_MANAGER(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_CONDITION_MANAGER))
+#define AGS_IS_CONDITION_MANAGER_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_CONDITION_MANAGER))
+#define AGS_CONDITION_MANAGER_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS(obj, AGS_TYPE_CONDITION_MANAGER, AgsConditionManagerClass))
+
+typedef struct _AgsConditionManager AgsConditionManager;
+typedef struct _AgsConditionManagerClass AgsConditionManagerClass;
+
+struct _AgsConditionManager
+{
+  GObject object;
+
+  GHashTable *lock_object;
+};
+
+struct _AgsConditionManagerClass
+{
+  GObjectClass object;
+};
+
+GType ags_condition_manager_get_type();
+
+gboolean ags_condition_manager_insert(AgsConditionManager *condition_manager,
+				      GObject *lock_object, pthread_cond_t *cond);
+gboolean ags_condition_manager_remove(AgsConditionManager *condition_manager,
+				      GObject *lock_object);
+
+pthread_cond_t* ags_condition_manager_lookup(AgsConditionManager *condition_manager,
+					     GObject *lock_object);
+
+AgsConditionManager* ags_condition_manager_get_instance();
+AgsConditionManager* ags_condition_manager_new();
+
+#endif /*__AGS_CONDITION_MANAGER_H__*/
diff --git a/ags/thread/ags_destroy_worker.c b/ags/thread/ags_destroy_worker.c
new file mode 100644
index 0000000..fd4b8d5
--- /dev/null
+++ b/ags/thread/ags_destroy_worker.c
@@ -0,0 +1,301 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/thread/ags_destroy_worker.h>
+
+#include <ags/object/ags_connectable.h>
+
+#include <stdlib.h>
+
+void ags_destroy_worker_class_init(AgsDestroyWorkerClass *destroy_worker);
+void ags_destroy_worker_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_destroy_worker_init(AgsDestroyWorker *destroy_worker);
+void ags_destroy_worker_connect(AgsConnectable *connectable);
+void ags_destroy_worker_disconnect(AgsConnectable *connectable);
+void ags_destroy_worker_finalize(GObject *gobject);
+
+void ags_destroy_worker_start(AgsThread *thread);
+void ags_destroy_worker_stop(AgsThread *thread);
+
+void ags_destroy_worker_do_poll(AgsWorkerThread *worker_thread);
+
+/**
+ * SECTION:ags_destroy_worker
+ * @short_description: destroy worker
+ * @title: AgsDestroyWorker
+ * @section_id:
+ * @include: ags/worker/ags_destroy_worker.h
+ *
+ * The #AgsDestroyWorker does non-realtime work. You might want
+ * give it the responsibility to destroy your objects.
+ */
+
+static gpointer ags_destroy_worker_parent_class = NULL;
+
+GType
+ags_destroy_worker_get_type()
+{
+  static GType ags_type_destroy_worker = 0;
+
+  if(!ags_type_destroy_worker){
+    static const GTypeInfo ags_destroy_worker_info = {
+      sizeof (AgsDestroyWorkerClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_destroy_worker_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof (AgsDestroyWorker),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_destroy_worker_init,
+    };
+
+    static const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_destroy_worker_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    ags_type_destroy_worker = g_type_register_static(AGS_TYPE_WORKER_THREAD,
+						     "AgsDestroyWorker\0",
+						     &ags_destroy_worker_info,
+						     0);
+    
+    g_type_add_interface_static(ags_type_destroy_worker,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+  }
+  
+  return (ags_type_destroy_worker);
+}
+
+void
+ags_destroy_worker_class_init(AgsDestroyWorkerClass *destroy_worker)
+{
+  GObjectClass *gobject;
+  AgsThreadClass *thread;
+  AgsWorkerThreadClass *worker_thread;
+
+  ags_destroy_worker_parent_class = g_type_class_peek_parent(destroy_worker);
+
+  /* GObject */
+  gobject = (GObjectClass *) destroy_worker;
+
+  gobject->finalize = ags_destroy_worker_finalize;
+
+  /* AgsThread */
+  thread = (AgsThreadClass *) destroy_worker;
+
+  thread->start = ags_destroy_worker_start;
+  thread->run = NULL;
+  thread->stop = ags_destroy_worker_stop;
+
+  /* AgsDestroyWorker */
+  worker_thread = (AgsWorkerThreadClass *) destroy_worker;
+
+  worker_thread->do_poll = ags_destroy_worker_do_poll;
+}
+
+void
+ags_destroy_worker_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  connectable->connect = ags_destroy_worker_connect;
+  connectable->disconnect = ags_destroy_worker_disconnect;
+}
+
+void
+ags_destroy_worker_init(AgsDestroyWorker *destroy_worker)
+{
+  destroy_worker->destroy_interval = (struct timespec *) malloc(sizeof(struct timespec));
+
+  destroy_worker->destroy_interval->tv_sec = 1;
+  destroy_worker->destroy_interval->tv_nsec = 0;
+  
+  /* lock destroy list */
+  destroy_worker->destroy_mutexattr = (pthread_mutexattr_t *) malloc(sizeof(pthread_mutexattr_t));
+
+  pthread_mutexattr_init(destroy_worker->destroy_mutexattr);
+  pthread_mutexattr_settype(destroy_worker->destroy_mutexattr,
+			    PTHREAD_MUTEX_RECURSIVE);
+
+  destroy_worker->destroy_mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
+  pthread_mutex_init(destroy_worker->destroy_mutex, destroy_worker->destroy_mutexattr);
+
+  /* destroy list */
+  destroy_worker->destroy_list = NULL;
+}
+
+void
+ags_destroy_worker_connect(AgsConnectable *connectable)
+{
+  /* empty */
+}
+
+void
+ags_destroy_worker_disconnect(AgsConnectable *connectable)
+{
+  /* empty */
+}
+
+void
+ags_destroy_worker_finalize(GObject *gobject)
+{
+  AgsDestroyWorker *destroy_worker;
+
+  destroy_worker = AGS_DESTROY_WORKER(gobject);
+
+  if(destroy_worker->destroy_interval != NULL){
+    free(destroy_worker->destroy_interval);
+  }
+  
+  /* destroy mutex */
+  pthread_mutex_destroy(destroy_worker->destroy_mutex);
+  free(destroy_worker->destroy_mutex);
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_destroy_worker_parent_class)->finalize(gobject);
+}
+
+void
+ags_destroy_worker_start(AgsThread *thread)
+{
+  AgsWorkerThread *worker_thread;
+
+  worker_thread = AGS_WORKER_THREAD(thread);
+
+  g_atomic_int_or(&(worker_thread->flags),
+		  AGS_WORKER_THREAD_RUNNING);
+
+  pthread_create(worker_thread->worker_thread, worker_thread->worker_thread_attr,
+		 ags_woker_thread_do_poll_loop, worker_thread);
+}
+
+void
+ags_destroy_worker_stop(AgsThread *thread)
+{
+  AgsWorkerThread *worker_thread;
+
+  worker_thread = AGS_WORKER_THREAD(thread);
+
+  g_atomic_int_and(&(worker_thread->flags),
+		   (~(AGS_WORKER_THREAD_RUNNING)));
+}
+
+void
+ags_destroy_worker_do_poll(AgsWorkerThread *worker_thread)
+{
+  AgsDestroyWorker *destroy_worker;
+
+  GList *list, *list_start;
+  
+  destroy_worker = AGS_DESTROY_WORKER(worker_thread);
+
+  pthread_mutex_lock(destroy_worker->destroy_mutex);
+
+  list_start =
+    list = destroy_worker->destroy_list;
+  destroy_worker->destroy_list = NULL;
+  
+  pthread_mutex_unlock(destroy_worker->destroy_mutex);
+
+  while(list != NULL){
+    AGS_DESTROY_ENTRY(list->data)->destroy_func(AGS_DESTROY_ENTRY(list->data)->ptr);
+
+    list = list->next;
+  }
+
+  g_list_free(list_start);
+
+  nanosleep(destroy_worker->destroy_interval,
+	    NULL);
+}
+
+/**
+ * ags_destroy_entry_alloc:
+ * @ptr: a pointer
+ * @destroy_func: the @ptr's destroy function
+ * 
+ * Allocated a destroy entry.
+ * 
+ * Returns: the allocated #AgsDestroyEntry
+ * 
+ * Since: 0.7.122.8
+ */
+AgsDestroyEntry*
+ags_destroy_entry_alloc(gpointer ptr, AgsDestroyFunc destroy_func)
+{
+  AgsDestroyEntry *destroy_entry;
+
+  destroy_entry = (AgsDestroyEntry *) malloc(sizeof(AgsDestroyEntry));
+
+  destroy_entry->ptr = ptr;
+  destroy_entry->destroy_func = destroy_func;
+}
+
+/**
+ * ags_destroy_worker_add:
+ * @destroy_worker:
+ * @ptr:
+ * @destroy_func:
+ * 
+ * Add @ptr for destruction using @destroy_func.
+ * 
+ * Since: 0.7.122.8
+ */
+void
+ags_destroy_worker_add(AgsDestroyWorker *destroy_worker,
+		       gpointer ptr, AgsDestroyFunc destroy_func)
+{
+  AgsDestroyEntry *destroy_entry;
+
+  if(destroy_worker == NULL ||
+     ptr == NULL ||
+     destroy_func == NULL){
+    return;
+  }
+
+  destroy_entry = ags_destroy_entry_alloc(ptr, destroy_func);
+  
+  pthread_mutex_lock(destroy_worker->destroy_mutex);
+
+  destroy_worker->destroy_list = g_list_prepend(destroy_worker->destroy_list,
+						destroy_entry);
+  
+  pthread_mutex_unlock(destroy_worker->destroy_mutex);
+}
+
+/**
+ * ags_destroy_worker_new:
+ *
+ * Create a new #AgsDestroyWorker.
+ *
+ * Returns: the new #AgsDestroyWorker
+ *
+ * Since: 0.7.122.8
+ */
+AgsDestroyWorker*
+ags_destroy_worker_new()
+{
+  AgsDestroyWorker *destroy_worker;
+  
+  destroy_worker = (AgsDestroyWorker *) g_object_new(AGS_TYPE_DESTROY_WORKER,
+						     NULL);
+
+  return(destroy_worker);
+}
diff --git a/ags/thread/ags_destroy_worker.h b/ags/thread/ags_destroy_worker.h
new file mode 100644
index 0000000..3466630
--- /dev/null
+++ b/ags/thread/ags_destroy_worker.h
@@ -0,0 +1,79 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_DESTROY_WORKER_H__
+#define __AGS_DESTROY_WORKER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <pthread.h>
+#include <time.h>
+
+#include <ags/thread/ags_worker_thread.h>
+
+#define AGS_TYPE_DESTROY_WORKER                (ags_destroy_worker_get_type())
+#define AGS_DESTROY_WORKER(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_DESTROY_WORKER, AgsDestroyWorker))
+#define AGS_DESTROY_WORKER_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST(class, AGS_TYPE_DESTROY_WORKER, AgsDestroyWorkerClass))
+#define AGS_IS_DESTROY_WORKER(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_DESTROY_WORKER))
+#define AGS_IS_DESTROY_WORKER_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_DESTROY_WORKER))
+#define AGS_DESTROY_WORKER_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS(obj, AGS_TYPE_DESTROY_WORKER, AgsDestroyWorkerClass))
+
+#define AGS_DESTROY_ENTRY(ptr) ((AgsDestroyEntry *) (ptr))
+
+typedef struct _AgsDestroyWorker AgsDestroyWorker;
+typedef struct _AgsDestroyWorkerClass AgsDestroyWorkerClass;
+typedef struct _AgsDestroyEntry AgsDestroyEntry;
+
+typedef void (*AgsDestroyFunc)(gpointer ptr);
+
+struct _AgsDestroyWorker
+{
+  AgsWorkerThread worker_thread;
+
+  struct timespec *destroy_interval;
+  
+  pthread_mutex_t *destroy_mutex;
+  pthread_mutexattr_t *destroy_mutexattr;
+
+  GList *destroy_list;
+};
+
+struct _AgsDestroyWorkerClass
+{
+  AgsWorkerThreadClass worker_thread;
+};
+
+struct _AgsDestroyEntry
+{
+  gpointer ptr;
+  
+  void (*destroy_func)(gpointer ptr);
+};
+
+GType ags_destroy_worker_get_type();
+
+AgsDestroyEntry* ags_destroy_entry_alloc(gpointer ptr, AgsDestroyFunc destroy_func);
+
+void ags_destroy_worker_add(AgsDestroyWorker *destroy_worker,
+			    gpointer ptr, AgsDestroyFunc destroy_func);
+
+AgsDestroyWorker* ags_destroy_worker_new();
+
+#endif /*__AGS_DESTROY_WORKER_H__*/
diff --git a/ags/thread/ags_mutex_manager.c b/ags/thread/ags_mutex_manager.c
index c25b9a3..5e8875d 100644
--- a/ags/thread/ags_mutex_manager.c
+++ b/ags/thread/ags_mutex_manager.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/thread/ags_mutex_manager.h b/ags/thread/ags_mutex_manager.h
index 196ba60..d8c76b0 100644
--- a/ags/thread/ags_mutex_manager.h
+++ b/ags/thread/ags_mutex_manager.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/thread/ags_polling_thread.c b/ags/thread/ags_polling_thread.c
index b05fb47..826a0ea 100644
--- a/ags/thread/ags_polling_thread.c
+++ b/ags/thread/ags_polling_thread.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/thread/ags_polling_thread.h b/ags/thread/ags_polling_thread.h
index 8c0e76d..c10cfbd 100644
--- a/ags/thread/ags_polling_thread.h
+++ b/ags/thread/ags_polling_thread.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/thread/ags_returnable_thread.c b/ags/thread/ags_returnable_thread.c
index da31861..fd7ee3a 100644
--- a/ags/thread/ags_returnable_thread.c
+++ b/ags/thread/ags_returnable_thread.c
@@ -190,7 +190,7 @@ ags_returnable_thread_disconnect(AgsConnectable *connectable)
 
 void
 ags_returnable_thread_finalize(GObject *gobject)
-{  
+{
   pthread_mutex_destroy(AGS_RETURNABLE_THREAD(gobject)->reset_mutex);
   free(AGS_RETURNABLE_THREAD(gobject)->reset_mutex);
   
@@ -238,7 +238,7 @@ ags_returnable_thread_run(AgsThread *thread)
   }
 
   if(unref_thread){
-    g_object_unref(thread);
+    //    g_object_unref(thread);
   }
 }
 
diff --git a/ags/thread/ags_task_thread.c b/ags/thread/ags_task_thread.c
index ce93814..3ce155e 100644
--- a/ags/thread/ags_task_thread.c
+++ b/ags/thread/ags_task_thread.c
@@ -579,7 +579,7 @@ ags_task_thread_append_task(AgsTaskThread *task_thread, AgsTask *task)
 		       task);
 
   thread = ags_thread_pool_pull(task_thread->thread_pool);
-  g_object_ref(thread);
+  //  g_object_ref(thread);
   
   pthread_mutex_lock(AGS_RETURNABLE_THREAD(thread)->reset_mutex);
 
@@ -660,7 +660,7 @@ ags_task_thread_append_tasks(AgsTaskThread *task_thread, GList *list)
 		       list);
 
   thread = ags_thread_pool_pull(task_thread->thread_pool);
-  g_object_ref(thread);
+  //  g_object_ref(thread);
 
   /* set safe data and run */
   pthread_mutex_lock(AGS_RETURNABLE_THREAD(thread)->reset_mutex);
diff --git a/ags/thread/ags_thread-posix.c b/ags/thread/ags_thread-posix.c
index 6538dc6..580bc48 100644
--- a/ags/thread/ags_thread-posix.c
+++ b/ags/thread/ags_thread-posix.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -26,6 +26,7 @@
 #include <ags/object/ags_async_queue.h>
 
 #include <ags/thread/ags_mutex_manager.h>
+#include <ags/thread/ags_condition_manager.h>
 #include <ags/thread/ags_returnable_thread.h>
 
 #include <stdlib.h>
@@ -193,7 +194,7 @@ ags_thread_class_init(AgsThreadClass *thread)
    * AgsThread::clock:
    * @thread: the #AgsThread
    *
-   * The ::clock signal is invoked every thread tic.
+   * The ::clock() signal is invoked every thread tic.
    *
    * Returns: the number of cycles to perform
    * 
@@ -213,7 +214,7 @@ ags_thread_class_init(AgsThreadClass *thread)
    * AgsThread::start:
    * @thread: the #AgsThread
    *
-   * The ::start signal is invoked as thread started.
+   * The ::start() signal is invoked as thread started.
    * 
    * Since: 0.5.0
    */
@@ -230,7 +231,7 @@ ags_thread_class_init(AgsThreadClass *thread)
    * AgsThread::run:
    * @thread: the #AgsThread
    *
-   * The ::run signal is invoked during run loop.
+   * The ::run() signal is invoked during run loop.
    * 
    * Since: 0.5.0
    */
@@ -247,7 +248,7 @@ ags_thread_class_init(AgsThreadClass *thread)
    * AgsThread::suspend:
    * @thread: the #AgsThread
    *
-   * The ::suspend signal is invoked during suspending.
+   * The ::suspend() signal is invoked during suspending.
    * 
    * Since: 0.5.0
    */
@@ -263,9 +264,8 @@ ags_thread_class_init(AgsThreadClass *thread)
   /**
    * AgsThread::resume:
    * @thread: the #AgsThread
-   * @recall_id: the appropriate #AgsRecallID
    *
-   * The ::resume signal is invoked during resuming.
+   * The ::resume() signal is invoked during resuming.
    * 
    * Since: 0.5.0
    */
@@ -281,9 +281,8 @@ ags_thread_class_init(AgsThreadClass *thread)
   /**
    * AgsThread::timelock:
    * @thread: the #AgsThread
-   * @recall_id: the appropriate #AgsRecallID
    *
-   * The ::timelock signal is invoked as standard compution
+   * The ::timelock() signal is invoked as standard compution
    * time exceeded.
    * 
    * Since: 0.5.0
@@ -300,9 +299,8 @@ ags_thread_class_init(AgsThreadClass *thread)
   /**
    * AgsThread::stop:
    * @thread: the #AgsThread
-   * @recall_id: the appropriate #AgsRecallID
    *
-   * The ::stop signal is invoked as @thread stopped.
+   * The ::stop() signal is invoked as @thread stopped.
    * 
    * Since: 0.5.0
    */
@@ -322,7 +320,7 @@ ags_thread_class_init(AgsThreadClass *thread)
    * @time_cycle: the cycles duration
    * @time_spent: the time spent
    *
-   * The ::interrupted signal is invoked as @thread should resume from interrupt.
+   * The ::interrupted() signal is invoked as @thread should resume from interrupt.
    *
    * Returns: the time spent
    *
@@ -352,9 +350,11 @@ void
 ags_thread_init(AgsThread *thread)
 {
   AgsMutexManager *mutex_manager;
-
+  AgsConditionManager *condition_manager;
+  
   pthread_mutex_t *application_mutex;
   pthread_mutex_t *mutex;
+  pthread_cond_t *cond;
   pthread_mutexattr_t *attr;
 
   int err;
@@ -390,6 +390,21 @@ ags_thread_init(AgsThread *thread)
   
   pthread_mutex_unlock(application_mutex);
 
+  /* the condition */
+  cond = (pthread_cond_t *) malloc(sizeof(pthread_cond_t));
+  pthread_cond_init(cond, NULL);
+
+  condition_manager = ags_mutex_manager_get_instance();
+  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+  
+  pthread_mutex_lock(application_mutex);
+
+  ags_condition_manager_insert(condition_manager,
+			       (GObject *) thread,
+			       cond);
+  
+  pthread_mutex_unlock(application_mutex);
+  
   /* fields */
   g_atomic_int_set(&(thread->flags),
 		   0);
@@ -533,6 +548,14 @@ ags_thread_set_property(GObject *gobject,
       thread->freq = freq;
       thread->delay = (guint) ceil((AGS_THREAD_HERTZ_JIFFIE / thread->freq) / (AGS_THREAD_HERTZ_JIFFIE / AGS_THREAD_MAX_PRECISION));
       thread->tic_delay = 0;
+
+      if((AGS_THREAD_INTERMEDIATE_POST_SYNC & (g_atomic_int_get(&(thread->flags)))) != 0){
+	thread->tic_delay = thread->delay;
+      }else if((AGS_THREAD_INTERMEDIATE_PRE_SYNC & (g_atomic_int_get(&(thread->flags)))) != 0){
+	thread->tic_delay = 1;
+      }else{
+	thread->tic_delay = 0;
+      }
     }
     break;
   default:
@@ -598,8 +621,10 @@ ags_thread_finalize(GObject *gobject)
 {
   AgsThread *thread, *parent;
   AgsMutexManager *mutex_manager;
-
+  AgsConditionManager *condition_manager;
+  
   gboolean running;
+  gboolean do_exit;
   
   pthread_t *thread_ptr;
   pthread_attr_t *thread_attr;
@@ -610,6 +635,12 @@ ags_thread_finalize(GObject *gobject)
 
   thread = AGS_THREAD(gobject);
 
+  if(thread == ags_thread_self()){
+    do_exit = TRUE;
+  }else{
+    do_exit = FALSE;
+  }
+  
   thread_attr = thread->thread_attr;
   thread_ptr = thread->thread;
 
@@ -634,6 +665,8 @@ ags_thread_finalize(GObject *gobject)
 
   /*  */
   mutex_manager = ags_mutex_manager_get_instance();
+  condition_manager = ags_condition_manager_get_instance();
+
   application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
   
   pthread_mutex_lock(application_mutex);
@@ -641,7 +674,10 @@ ags_thread_finalize(GObject *gobject)
   ags_mutex_manager_remove(mutex_manager,
 			   (GObject *) thread);
   
-  /*  */
+  ags_condition_manager_remove(condition_manager,
+			       (GObject *) thread);
+  
+  /*  */  
   free(thread->computing_time);
 
   /*  */
@@ -649,7 +685,7 @@ ags_thread_finalize(GObject *gobject)
   free(thread->barrier[1]);
 
   free(thread->barrier);
-  
+    
   /*  */
   pthread_attr_getstack(thread_attr,
 			&stackaddr, &stacksize);
@@ -660,7 +696,7 @@ ags_thread_finalize(GObject *gobject)
 
   pthread_cond_destroy(thread->cond);
   free(thread->cond);
-
+  
   /*  */
   pthread_mutex_lock(thread->start_mutex);
 
@@ -694,6 +730,7 @@ ags_thread_finalize(GObject *gobject)
   pthread_cond_destroy(thread->timer_cond);
   free(thread->timer_cond);
   
+  
   /* call parent */
   G_OBJECT_CLASS(ags_thread_parent_class)->finalize(gobject);
 
@@ -713,7 +750,9 @@ ags_thread_finalize(GObject *gobject)
     free(stackaddr);
   }
   
-  pthread_exit(NULL);
+  if(do_exit){
+    pthread_exit(NULL);
+  }
 }
 
 void
@@ -1678,6 +1717,10 @@ ags_thread_next_parent_locked(AgsThread *thread, AgsThread *parent)
 {
   AgsThread *current;
 
+  if(thread == NULL){
+    return(NULL);
+  }
+  
   current = g_atomic_pointer_get(&(thread->parent));
 
   while(current != parent){
@@ -1706,6 +1749,10 @@ ags_thread_next_sibling_locked(AgsThread *thread)
 {
   AgsThread *current;
 
+  if(thread == NULL){
+    return(NULL);
+  }
+  
   current = ags_thread_first(thread);
 
   while(current != NULL){
@@ -1715,7 +1762,7 @@ ags_thread_next_sibling_locked(AgsThread *thread)
       continue;
     }
 
-    if((AGS_THREAD_WAITING_FOR_SIBLING & (g_atomic_int_get(&(thread->sync_flags)))) != 0){
+    if((AGS_THREAD_WAITING_FOR_SIBLING & (g_atomic_int_get(&(current->sync_flags)))) != 0){
       return(current);
     }
 
@@ -1741,13 +1788,17 @@ ags_thread_next_children_locked(AgsThread *thread)
   auto AgsThread* ags_thread_next_children_locked_recursive(AgsThread *thread);
 
   AgsThread* ags_thread_next_children_locked_recursive(AgsThread *child){
-    AgsThread *current;
+    AgsThread *current, *retval;
 
     current = ags_thread_last(child);
 
     while(current != NULL){
-      ags_thread_next_children_locked_recursive(g_atomic_pointer_get(&(current->children)));
-
+      retval = ags_thread_next_children_locked_recursive(g_atomic_pointer_get(&(current->children)));
+      
+      if(retval != NULL){
+	return(retval);
+      }
+      
       if((AGS_THREAD_WAITING_FOR_PARENT & (g_atomic_int_get(&(current->sync_flags)))) != 0){
 	return(current);
       }
@@ -1758,7 +1809,11 @@ ags_thread_next_children_locked(AgsThread *thread)
     return(NULL);
   }
 
-  return(ags_thread_next_children_locked(g_atomic_pointer_get(&(thread->children))));
+  if(thread == NULL){
+    return(NULL);
+  }
+  
+  return(ags_thread_next_children_locked_recursive(g_atomic_pointer_get(&(thread->children))));
 }
 
 /**
@@ -1888,6 +1943,8 @@ ags_thread_unlock_parent(AgsThread *thread, AgsThread *parent)
     return;
   }
 
+  ags_thread_unlock(thread);
+
   current = g_atomic_pointer_get(&(thread->parent));
 
   while(current != parent){
@@ -1923,6 +1980,8 @@ ags_thread_unlock_sibling(AgsThread *thread)
     return;
   }
 
+  ags_thread_unlock(thread);
+  
   current = ags_thread_first(thread);
 
   while(current != NULL){
@@ -1990,7 +2049,13 @@ ags_thread_unlock_children(AgsThread *thread)
       current = g_atomic_pointer_get(&(current->prev));
     }
   }
+
+  if(thread == NULL){
+    return;
+  }
   
+  ags_thread_unlock(thread);
+
   ags_thread_unlock_children_recursive(g_atomic_pointer_get(&(thread->children)));
 }
 
@@ -2242,16 +2307,6 @@ ags_thread_signal_children(AgsThread *thread, gboolean broadcast)
   ags_thread_signal_children(g_atomic_pointer_get(&(thread->children)), broadcast);
 }
 
-/**
- * ags_thread_clock:
- * @thread: the #AgsThread instance
- *
- * Clock the thread.
- *
- * Returns: the cycles to be performed
- * 
- * Since: 0.6.42
- */
 guint
 ags_thread_real_clock(AgsThread *thread)
 {
@@ -2286,26 +2341,33 @@ ags_thread_real_clock(AgsThread *thread)
 	 g_atomic_pointer_get(&(thread->parent)) != NULL){
 	AgsThread *chaos_tree;
 	
-	chaos_tree = ags_thread_chaos_tree(thread);
+	chaos_tree = main_loop;//ags_thread_chaos_tree(thread);
+
+	/* ordinary sync */
+	thread->tic_delay = chaos_tree->tic_delay;
 
-	/* set tic delay */
 	if((AGS_THREAD_INTERMEDIATE_PRE_SYNC & (g_atomic_int_get(&(thread->flags)))) != 0){
-	  /* intermediate pre sync */
-	  if(chaos_tree->tic_delay > 0){
-	    thread->tic_delay = chaos_tree->tic_delay - 1;
+	  if(thread->freq >= AGS_THREAD_MAX_PRECISION){
+	    thread->tic_delay = 0;
 	  }else{
-	    thread->tic_delay = thread->delay;
+	    if(thread->tic_delay < thread->delay){
+	      thread->tic_delay++;
+	    }else{
+	      thread->tic_delay = 0;
+	    }
 	  }
-	}else if((AGS_THREAD_INTERMEDIATE_POST_SYNC & (g_atomic_int_get(&(thread->flags)))) != 0){
-	  /* intermediate post sync */
-	  if(chaos_tree->tic_delay < thread->delay){
-	    thread->tic_delay = chaos_tree->tic_delay + 1;
-	  }else{
+	}
+	
+	if((AGS_THREAD_INTERMEDIATE_POST_SYNC & (g_atomic_int_get(&(thread->flags)))) != 0){
+	  if(thread->freq >= AGS_THREAD_MAX_PRECISION){
 	    thread->tic_delay = 0;
+	  }else{
+	    if(thread->tic_delay > 0){
+	      thread->tic_delay--;
+	    }else{
+	      thread->tic_delay = thread->delay;
+	    }
 	  }
-	}else{
-	  /* ordinary sync */
-	  thread->tic_delay = chaos_tree->tic_delay;
 	}
 	
 	g_atomic_int_or(&(thread->flags),
@@ -2376,9 +2438,11 @@ ags_thread_real_clock(AgsThread *thread)
 	  ags_async_queue_set_run(AGS_ASYNC_QUEUE(async_queue),
 				  FALSE);
 	}
+	
+	async_queue_running = ((AGS_THREAD_RUNNING & (g_atomic_int_get(&(async_queue->flags)))) != 0) ? TRUE: FALSE;
+      }else{
+	async_queue_running = FALSE;
       }
-
-      async_queue_running = ((AGS_THREAD_RUNNING & (g_atomic_int_get(&(async_queue->flags)))) != 0) ? TRUE: FALSE;
       
       ags_main_loop_set_last_sync(AGS_MAIN_LOOP(main_loop), thread->current_tic);
       ags_main_loop_set_tic(AGS_MAIN_LOOP(main_loop), next_tic);
@@ -2605,9 +2669,9 @@ ags_thread_real_clock(AgsThread *thread)
  *
  * Clock the thread.
  *
- * Returns: the number of cycles to perform.
+ * Returns: the cycles to be performed
  * 
- * Since: 0.4.0
+ * Since: 0.6.42
  */
 guint
 ags_thread_clock(AgsThread *thread)
@@ -2784,6 +2848,7 @@ ags_thread_loop(void *ptr)
   pthread_mutex_t *mutex;
   
   thread = (AgsThread *) ptr;
+  g_object_ref(thread);
   
   pthread_once(&ags_thread_key_once, ags_thread_self_create);
   pthread_setspecific(ags_thread_key, thread);
@@ -2832,7 +2897,8 @@ ags_thread_loop(void *ptr)
       start_queue_next = start_queue->next;
       
       queued_thread = (AgsThread *) start_queue->data;
-
+      g_object_ref(queued_thread);
+      
       /*  */
       ags_thread_start(queued_thread);
 
@@ -2842,8 +2908,34 @@ ags_thread_loop(void *ptr)
 
 	pthread_mutex_lock(ags_main_loop_get_tree_lock(AGS_MAIN_LOOP(main_loop)));
 
+	/* ordinary sync */
 	queued_thread->tic_delay = thread->tic_delay;
 
+	if((AGS_THREAD_INTERMEDIATE_PRE_SYNC & (g_atomic_int_get(&(queued_thread->flags)))) != 0){
+	  if(queued_thread->freq >= AGS_THREAD_MAX_PRECISION){
+	    queued_thread->tic_delay = 0;
+	  }else{
+	    if(queued_thread->tic_delay < queued_thread->delay){
+	      queued_thread->tic_delay++;
+	    }else{
+	      queued_thread->tic_delay = 0;
+	    }
+	  }
+	}
+	
+	if((AGS_THREAD_INTERMEDIATE_POST_SYNC & (g_atomic_int_get(&(queued_thread->flags)))) != 0){
+	  if(queued_thread->freq >= AGS_THREAD_MAX_PRECISION){
+	    queued_thread->tic_delay = 0;
+	  }else{
+	    if(queued_thread->tic_delay > 0){
+	      queued_thread->tic_delay--;
+	    }else{
+	      queued_thread->tic_delay = queued_thread->delay;
+	    }
+	  }
+	}
+
+	/*  */
 	pthread_mutex_unlock(ags_main_loop_get_tree_lock(AGS_MAIN_LOOP(main_loop)));
 	
 	g_atomic_int_set(&(queued_thread->start_wait),
@@ -2857,7 +2949,8 @@ ags_thread_loop(void *ptr)
       }
       
       pthread_mutex_unlock(queued_thread->start_mutex);
-
+      g_object_unref(queued_thread);
+      
       start_queue = start_queue_next;
     }
 
@@ -3088,14 +3181,43 @@ ags_thread_loop(void *ptr)
     }    
   }
 
-  g_object_ref(thread);
+  //  g_object_ref(thread);
   
   pthread_mutex_lock(ags_main_loop_get_tree_lock(AGS_MAIN_LOOP(main_loop)));
 
   if((AGS_THREAD_INITIAL_RUN & (g_atomic_int_get(&(thread->flags)))) != 0  ||
      (AGS_THREAD_INITIAL_SYNC & (g_atomic_int_get(&(thread->flags)))) != 0){
-    thread->current_tic = ags_main_loop_get_tic(AGS_MAIN_LOOP(main_loop));    
+    AgsThread *chaos_tree;
+	
+    chaos_tree = main_loop;//ags_thread_chaos_tree(thread);
+
+    /* ordinary sync */
+    thread->tic_delay = chaos_tree->tic_delay;
 
+    if((AGS_THREAD_INTERMEDIATE_PRE_SYNC & (g_atomic_int_get(&(thread->flags)))) != 0){
+      if(thread->freq >= AGS_THREAD_MAX_PRECISION){
+	thread->tic_delay = 0;
+      }else{
+	if(thread->tic_delay > 0){
+	  thread->tic_delay--;
+	}else{
+	  thread->tic_delay = thread->delay;
+	}
+      }
+    }
+	
+    if((AGS_THREAD_INTERMEDIATE_POST_SYNC & (g_atomic_int_get(&(thread->flags)))) != 0){
+      if(thread->freq >= AGS_THREAD_MAX_PRECISION){
+	thread->tic_delay = 0;
+      }else{
+	if(thread->tic_delay < thread->delay){
+	  thread->tic_delay++;
+	}else{
+	  thread->tic_delay = 0;
+	}
+      }
+    }
+	
     g_atomic_int_and(&(thread->flags),
 		     (~AGS_THREAD_INITIAL_RUN));
 
@@ -3161,7 +3283,8 @@ ags_thread_loop(void *ptr)
   g_message("thread finished\0");
 #endif  
   
-  g_object_ref(thread);
+  g_object_unref(thread);
+  //  g_object_ref(thread);
   
   /* exit thread */
   pthread_exit(NULL);
diff --git a/ags/thread/ags_thread-posix.h b/ags/thread/ags_thread-posix.h
index ea734f9..2fce978 100644
--- a/ags/thread/ags_thread-posix.h
+++ b/ags/thread/ags_thread-posix.h
@@ -31,6 +31,8 @@
 #define _GNU_SOURCE
 #include <pthread.h>
 
+#include <time.h>
+
 #define AGS_TYPE_THREAD                (ags_thread_get_type())
 #define AGS_THREAD(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_THREAD, AgsThread))
 #define AGS_THREAD_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST(class, AGS_TYPE_THREAD, AgsThreadClass))
@@ -45,8 +47,8 @@
 
 #define AGS_THREAD_HERTZ_JIFFIE (1000.0)
 #define AGS_THREAD_YIELD_JIFFIE (2.0)
-#define AGS_THREAD_DEFAULT_JIFFIE (1000.0)
-#define AGS_THREAD_MAX_PRECISION (1000.0)
+#define AGS_THREAD_DEFAULT_JIFFIE (250.0)
+#define AGS_THREAD_MAX_PRECISION (250.0)
 
 #define AGS_THREAD_DEFAULT_ATTACK (1.0)
 
diff --git a/ags/thread/ags_thread_application_context.c b/ags/thread/ags_thread_application_context.c
index 35051c4..0fdc09f 100644
--- a/ags/thread/ags_thread_application_context.c
+++ b/ags/thread/ags_thread_application_context.c
@@ -57,6 +57,9 @@ void ags_thread_application_context_disconnect(AgsConnectable *connectable);
 AgsThread* ags_thread_application_context_get_main_loop(AgsConcurrencyProvider *concurrency_provider);
 AgsThread* ags_thread_application_context_get_task_thread(AgsConcurrencyProvider *concurrency_provider);
 AgsThreadPool* ags_thread_application_context_get_thread_pool(AgsConcurrencyProvider *concurrency_provider);
+GList* ags_thread_application_context_get_worker(AgsConcurrencyProvider *concurrency_provider);
+void ags_thread_application_context_set_worker(AgsConcurrencyProvider *concurrency_provider,
+					       GList *worker);
 void ags_thread_application_context_finalize(GObject *gobject);
 
 void ags_thread_application_context_load_config(AgsApplicationContext *application_context);
@@ -206,6 +209,8 @@ ags_thread_application_context_concurrency_provider_interface_init(AgsConcurrenc
   concurrency_provider->get_main_loop = ags_thread_application_context_get_main_loop;
   concurrency_provider->get_task_thread = ags_thread_application_context_get_task_thread;
   concurrency_provider->get_thread_pool = ags_thread_application_context_get_thread_pool;
+  concurrency_provider->get_worker = ags_thread_application_context_get_worker;
+  concurrency_provider->set_worker = ags_thread_application_context_set_worker;
 }
 
 void
@@ -236,7 +241,10 @@ ags_thread_application_context_init(AgsThreadApplicationContext *thread_applicat
 
   /* AgsAutosaveThread */
   thread_application_context->autosave_thread = NULL;
-  
+
+  /* AgsWorkerThread */
+  thread_application_context->worker = NULL;
+
   /* AgsThreadPool */
   thread_application_context->thread_pool = AGS_TASK_THREAD(AGS_APPLICATION_CONTEXT(thread_application_context)->task_thread)->thread_pool;
 }
@@ -379,6 +387,19 @@ ags_thread_application_context_get_thread_pool(AgsConcurrencyProvider *concurren
   return((AgsThreadPool *) AGS_THREAD_APPLICATION_CONTEXT(concurrency_provider)->thread_pool);
 }
 
+GList*
+ags_thread_application_context_get_worker(AgsConcurrencyProvider *concurrency_provider)
+{
+  return(AGS_THREAD_APPLICATION_CONTEXT(concurrency_provider)->worker);
+}
+
+void
+ags_thread_application_context_set_worker(AgsConcurrencyProvider *concurrency_provider,
+					  GList *worker)
+{
+  AGS_THREAD_APPLICATION_CONTEXT(concurrency_provider)->worker = worker;
+}
+
 void
 ags_thread_application_context_finalize(GObject *gobject)
 {
diff --git a/ags/thread/ags_thread_application_context.h b/ags/thread/ags_thread_application_context.h
index a6f6087..f61f9ce 100644
--- a/ags/thread/ags_thread_application_context.h
+++ b/ags/thread/ags_thread_application_context.h
@@ -40,8 +40,8 @@
 #define AGS_IS_THREAD_APPLICATION_CONTEXT_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_THREAD_APPLICATION_CONTEXT))
 #define AGS_THREAD_APPLICATION_CONTEXT_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS(obj, AGS_TYPE_THREAD_APPLICATION_CONTEXT, AgsThreadApplicationContextClass))
 
-#define AGS_THREAD_BUILD_ID "Thu Apr  2 13:04:21 GMT 2015\0"
-#define AGS_THREAD_DEFAULT_VERSION "0.4.3\0"
+#define AGS_THREAD_DEFAULT_VERSION "0.7.122.8\0"
+#define AGS_THREAD_BUILD_ID "Tue Mar 21 20:03:29 CET 2017\0"
 
 typedef struct _AgsThreadApplicationContext AgsThreadApplicationContext;
 typedef struct _AgsThreadApplicationContextClass AgsThreadApplicationContextClass;
@@ -58,6 +58,8 @@ struct _AgsThreadApplicationContext
 
   AgsThread *autosave_thread;
   AgsThreadPool *thread_pool;
+
+  GList *worker;
 };
 
 struct _AgsThreadApplicationContextClass
diff --git a/ags/thread/ags_thread_pool.h b/ags/thread/ags_thread_pool.h
index ec57ef1..227a899 100644
--- a/ags/thread/ags_thread_pool.h
+++ b/ags/thread/ags_thread_pool.h
@@ -23,6 +23,8 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include <pthread.h>
+
 #ifdef AGS_USE_LINUX_THREADS
 #include <ags/thread/ags_thread-kthreads.h>
 #else
diff --git a/ags/thread/ags_worker_thread.c b/ags/thread/ags_worker_thread.c
new file mode 100644
index 0000000..54f19bb
--- /dev/null
+++ b/ags/thread/ags_worker_thread.c
@@ -0,0 +1,364 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ags/thread/ags_worker_thread.h>
+
+#include <ags/object/ags_connectable.h>
+
+void ags_worker_thread_class_init(AgsWorkerThreadClass *worker_thread);
+void ags_worker_thread_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_worker_thread_init(AgsWorkerThread *worker_thread);
+void ags_worker_thread_connect(AgsConnectable *connectable);
+void ags_worker_thread_disconnect(AgsConnectable *connectable);
+void ags_worker_thread_finalize(GObject *gobject);
+
+void ags_worker_thread_start(AgsThread *thread);
+void ags_worker_thread_run(AgsThread *thread);
+void ags_worker_thread_stop(AgsThread *thread);
+
+void* ags_woker_thread_do_poll_loop(void *ptr);
+
+/**
+ * SECTION:ags_worker_thread
+ * @short_description: worker thread
+ * @title: AgsWorkerThread
+ * @section_id:
+ * @include: ags/thread/ags_worker_thread.h
+ *
+ * The #AgsWorkerThread does non-realtime work. You might want
+ * to synchronize to the run signal within your ::do_poll() method.
+ */
+
+enum{
+  DO_POLL,
+  LAST_SIGNAL,
+};
+
+static gpointer ags_worker_thread_parent_class = NULL;
+static guint worker_thread_signals[LAST_SIGNAL];
+
+GType
+ags_worker_thread_get_type()
+{
+  static GType ags_type_worker_thread = 0;
+
+  if(!ags_type_worker_thread){
+    static const GTypeInfo ags_worker_thread_info = {
+      sizeof (AgsWorkerThreadClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_worker_thread_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof (AgsWorkerThread),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_worker_thread_init,
+    };
+
+    static const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_worker_thread_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    ags_type_worker_thread = g_type_register_static(AGS_TYPE_THREAD,
+						    "AgsWorkerThread\0",
+						    &ags_worker_thread_info,
+						    0);
+    
+    g_type_add_interface_static(ags_type_worker_thread,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+  }
+  
+  return (ags_type_worker_thread);
+}
+
+void
+ags_worker_thread_class_init(AgsWorkerThreadClass *worker_thread)
+{
+  GObjectClass *gobject;
+  AgsThreadClass *thread;
+
+  ags_worker_thread_parent_class = g_type_class_peek_parent(worker_thread);
+
+  /* GObject */
+  gobject = (GObjectClass *) worker_thread;
+
+  gobject->finalize = ags_worker_thread_finalize;
+
+  /* AgsThread */
+  thread = (AgsThreadClass *) worker_thread;
+
+  thread->start = ags_worker_thread_start;
+  thread->run = ags_worker_thread_run;
+  thread->stop = ags_worker_thread_stop;
+
+  /* AgsWorkerThread */
+  worker_thread->do_poll = NULL;
+  
+  /* signals */
+  /**
+   * AgsWorkerThread::do-poll:
+   * @thread: the #AgsWorkerThread
+   *
+   * The ::do-poll() signal runs independently of ::run() but
+   * might be synchronized using a conditional lock.
+   * 
+   * Since: 0.7.122.8
+   */
+  worker_thread_signals[DO_POLL] =
+    g_signal_new("do-poll\0",
+		 G_TYPE_FROM_CLASS (thread),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET (AgsWorkerThreadClass, do_poll),
+		 NULL, NULL,
+		 g_cclosure_marshal_VOID__VOID,
+		 G_TYPE_NONE, 0);
+}
+
+void
+ags_worker_thread_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  connectable->connect = ags_worker_thread_connect;
+  connectable->disconnect = ags_worker_thread_disconnect;
+}
+
+void
+ags_worker_thread_init(AgsWorkerThread *worker_thread)
+{
+  AgsThread *thread;
+
+  thread = (AgsThread *) worker_thread;
+  thread->freq = AGS_WORKER_THREAD_DEFAULT_JIFFIE;
+  
+  g_atomic_int_set(&(worker_thread->flags),
+		   0);
+
+  /* synchronization */
+  worker_thread->run_mutexattr = (pthread_mutexattr_t *) malloc(sizeof(pthread_mutexattr_t));
+
+  pthread_mutexattr_init(worker_thread->run_mutexattr);
+  pthread_mutexattr_settype(worker_thread->run_mutexattr,
+			    PTHREAD_MUTEX_RECURSIVE);
+
+  worker_thread->run_mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
+  pthread_mutex_init(worker_thread->run_mutex, worker_thread->run_mutexattr);
+
+  worker_thread->run_cond = (pthread_cond_t *) malloc(sizeof(pthread_cond_t));
+  pthread_cond_init(worker_thread->run_cond, NULL);
+
+  /* worker thread */
+  worker_thread->worker_thread = (pthread_t *) malloc(sizeof(pthread_t));  
+}
+
+void
+ags_worker_thread_connect(AgsConnectable *connectable)
+{
+  /* empty */
+}
+
+void
+ags_worker_thread_disconnect(AgsConnectable *connectable)
+{
+  /* empty */
+}
+
+void
+ags_worker_thread_finalize(GObject *gobject)
+{
+  AgsWorkerThread *worker_thread;
+  
+  gboolean running;
+  gboolean do_exit;
+  
+  pthread_t *thread_ptr;
+  pthread_attr_t *thread_attr;
+
+  void *stackaddr;
+  size_t stacksize;
+
+  worker_thread = AGS_WORKER_THREAD(gobject);
+
+  if(worker_thread == ags_thread_self()){
+    do_exit = TRUE;
+  }else{
+    do_exit = FALSE;
+  }
+  
+  thread_attr = worker_thread->worker_thread_attr;
+  thread_ptr = worker_thread->worker_thread;
+
+  running = ((AGS_WORKER_THREAD_RUNNING & (g_atomic_int_get(&(worker_thread->flags)))) != 0) ? TRUE: FALSE;
+
+  /*  */
+  pthread_attr_getstack(thread_attr,
+			&stackaddr, &stacksize);
+  
+  /* run mutex and condition */
+  pthread_mutex_destroy(worker_thread->run_mutex);
+  free(worker_thread->run_mutex);
+
+  pthread_cond_destroy(worker_thread->run_cond);
+  free(worker_thread->run_cond);
+
+  /* call parent */
+  G_OBJECT_CLASS(ags_worker_thread_parent_class)->finalize(gobject);
+
+  if(running){
+    pthread_detach(*thread_ptr);
+  }
+
+  pthread_attr_destroy(thread_attr);
+  free(thread_attr);
+
+  //  free(*thread_ptr);
+  free(thread_ptr);
+
+  if(stackaddr != NULL){
+    free(stackaddr);
+  }
+  
+  if(do_exit){
+    pthread_exit(NULL);
+  }
+}
+
+void
+ags_worker_thread_start(AgsThread *thread)
+{
+  AgsWorkerThread *worker_thread;
+
+  worker_thread = AGS_WORKER_THREAD(thread);
+  
+  /*  */
+  if((AGS_THREAD_SINGLE_LOOP & (g_atomic_int_get(&(thread->flags)))) == 0){
+    AGS_THREAD_CLASS(ags_worker_thread_parent_class)->start(thread);
+  }
+
+  g_atomic_int_or(&(worker_thread->flags),
+		  AGS_WORKER_THREAD_RUNNING);
+
+  pthread_create(worker_thread->worker_thread, worker_thread->worker_thread_attr,
+		 ags_woker_thread_do_poll_loop, worker_thread);
+}
+
+void
+ags_worker_thread_run(AgsThread *thread)
+{
+  AgsWorkerThread *worker_thread;
+
+  worker_thread = AGS_WORKER_THREAD(thread);
+  
+  /* synchronization point */
+  if((AGS_WORKER_THREAD_RUN_WAIT & (g_atomic_int_get(&(worker_thread->flags)))) != 0 &&
+     (AGS_WORKER_THREAD_RUN_DONE & (g_atomic_int_get(&(worker_thread->flags)))) == 0){
+    pthread_mutex_lock(worker_thread->run_mutex);
+
+    g_atomic_int_or(&(worker_thread->flags),
+		    AGS_WORKER_THREAD_RUN_SYNC);
+    
+    while((AGS_WORKER_THREAD_RUN_WAIT & (g_atomic_int_get(&(worker_thread->flags)))) != 0 &&
+	  (AGS_WORKER_THREAD_RUN_DONE & (g_atomic_int_get(&(worker_thread->flags)))) == 0){
+      pthread_cond_wait(worker_thread->run_cond,
+			worker_thread->run_mutex);
+    }
+
+    g_atomic_int_and(&(worker_thread->flags),
+		     (~(AGS_WORKER_THREAD_RUN_WAIT |
+			AGS_WORKER_THREAD_RUN_DONE)));
+
+    pthread_mutex_unlock(worker_thread->run_mutex);
+  }
+}
+
+void
+ags_worker_thread_stop(AgsThread *thread)
+{
+  AgsWorkerThread *worker_thread;
+
+  worker_thread = AGS_WORKER_THREAD(thread);
+
+  g_atomic_int_and(&(worker_thread->flags),
+		   (~(AGS_WORKER_THREAD_RUNNING)));
+  
+  /* call parent */
+  AGS_THREAD_CLASS(ags_worker_thread_parent_class)->stop(thread);  
+}
+
+/**
+ * ags_woker_thread_do_poll_loop:
+ * @ptr: the #AgsWorkerThread
+ * 
+ * Do loop and invoke ags_worker_thread_do_poll() unless flag
+ * AGS_WORKER_THREAD_RUNNING was unset.
+ * 
+ * Since: 0.7.122.8
+ */
+void*
+ags_woker_thread_do_poll_loop(void *ptr)
+{
+  AgsWorkerThread *worker_thread;
+
+  worker_thread = (AgsWorkerThread *) ptr;
+  
+  while((AGS_WORKER_THREAD_RUNNING & (g_atomic_int_get(&(worker_thread->flags)))) != 0){
+    ags_worker_thread_do_poll(worker_thread);
+  }
+  
+  pthread_exit(NULL);
+}
+
+/**
+ * ags_worker_thread_do_poll:
+ * @worker_thread: the #AgsWorkerThread
+ *
+ * Do poll your work. It is called of the worker thread.
+ *
+ * Since: 0.7.122.8
+ */
+void
+ags_worker_thread_do_poll(AgsWorkerThread *worker_thread)
+{
+  g_return_if_fail(AGS_IS_WORKER_THREAD(worker_thread));
+  g_object_ref(worker_thread);
+  g_signal_emit(worker_thread,
+		worker_thread_signals[DO_POLL], 0);
+  g_object_unref(worker_thread);
+}
+
+/**
+ * ags_worker_thread_new:
+ *
+ * Create a new #AgsWorkerThread.
+ *
+ * Returns: the new #AgsWorkerThread
+ *
+ * Since: 0.7.122.8
+ */
+AgsWorkerThread*
+ags_worker_thread_new()
+{
+  AgsWorkerThread *worker_thread;
+  
+  worker_thread = (AgsWorkerThread *) g_object_new(AGS_TYPE_WORKER_THREAD,
+						   NULL);
+
+  return(worker_thread);
+}
diff --git a/ags/thread/ags_worker_thread.h b/ags/thread/ags_worker_thread.h
new file mode 100644
index 0000000..1e07ef8
--- /dev/null
+++ b/ags/thread/ags_worker_thread.h
@@ -0,0 +1,81 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_WORKER_THREAD_H__
+#define __AGS_WORKER_THREAD_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#ifdef AGS_USE_LINUX_THREADS
+#include <ags/thread/ags_thread-kthreads.h>
+#else
+#include <ags/thread/ags_thread-posix.h>
+#endif 
+
+#define AGS_TYPE_WORKER_THREAD                (ags_worker_thread_get_type())
+#define AGS_WORKER_THREAD(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_WORKER_THREAD, AgsWorkerThread))
+#define AGS_WORKER_THREAD_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST(class, AGS_TYPE_WORKER_THREAD, AgsWorkerThreadClass))
+#define AGS_IS_WORKER_THREAD(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_WORKER_THREAD))
+#define AGS_IS_WORKER_THREAD_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_WORKER_THREAD))
+#define AGS_WORKER_THREAD_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS(obj, AGS_TYPE_WORKER_THREAD, AgsWorkerThreadClass))
+
+#define AGS_WORKER_THREAD_DEFAULT_JIFFIE (AGS_THREAD_MAX_PRECISION)
+
+typedef struct _AgsWorkerThread AgsWorkerThread;
+typedef struct _AgsWorkerThreadClass AgsWorkerThreadClass;
+
+typedef enum{
+  AGS_WORKER_THREAD_RUNNING    = 1,
+  AGS_WORKER_THREAD_RUN_WAIT   = 1 <<  1,
+  AGS_WORKER_THREAD_RUN_DONE   = 1 <<  2,
+  AGS_WORKER_THREAD_RUN_SYNC   = 1 <<  3,
+}AgsWorkerThreadFlags;
+
+struct _AgsWorkerThread
+{
+  AgsThread thread;
+
+  volatile guint flags;
+
+  pthread_mutex_t *run_mutex;
+  pthread_mutexattr_t *run_mutexattr;
+  
+  pthread_cond_t *run_cond;
+
+  pthread_t *worker_thread;
+  pthread_attr_t *worker_thread_attr;
+};
+
+struct _AgsWorkerThreadClass
+{
+  AgsThreadClass thread;
+
+  void (*do_poll)(AgsWorkerThread *worker_thread);
+};
+
+GType ags_worker_thread_get_type();
+
+void* ags_woker_thread_do_poll_loop(void *ptr);
+
+void ags_worker_thread_do_poll(AgsWorkerThread *worker_thread);
+
+AgsWorkerThread* ags_worker_thread_new();
+
+#endif /*__AGS_WORKER_THREAD_H__*/
diff --git a/ags/audio/thread/ags_recycling_thread_callbacks.c b/ags/util/ags_destroy_util.c
similarity index 75%
copy from ags/audio/thread/ags_recycling_thread_callbacks.c
copy to ags/util/ags_destroy_util.c
index 64e6c73..866f1cc 100644
--- a/ags/audio/thread/ags_recycling_thread_callbacks.c
+++ b/ags/util/ags_destroy_util.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -16,10 +16,16 @@
  * You should have received a copy of the GNU General Public License
  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
  */
-#include <ags/audio/thread/ags_recycling_thread_callbacks.h>
+
+#include <ags/util/ags_destroy_util.h>
 
 void
-ags_recycling_thread_iterate_callback(AgsRecyclingThread *thread, gpointer user_data)
+ags_destroy_util_dispose_and_unref(GObject *gobject)
 {
-  
+  if(gobject == NULL){
+    return;
+  }
+
+  g_object_run_dispose(gobject);
+  g_object_unref(gobject);
 }
diff --git a/ags/plugin/ags_plugin_stock.h b/ags/util/ags_destroy_util.h
similarity index 79%
copy from ags/plugin/ags_plugin_stock.h
copy to ags/util/ags_destroy_util.h
index 670c32c..9a5230f 100644
--- a/ags/plugin/ags_plugin_stock.h
+++ b/ags/util/ags_destroy_util.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -17,12 +17,12 @@
  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __AGS_PLUGIN_STOCK_H__
-#define __AGS_PLUGIN_STOCK_H__
+#ifndef __AGS_DESTROY_UTIL_H__
+#define __AGS_DESTROY_UTIL_H__
 
 #include <glib.h>
 #include <glib-object.h>
 
-#define AGS_PLUGIN_NAME_VOLUME "ags-volume\0"
+void ags_destroy_util_dispose_and_unref(GObject *gobject);
 
-#endif /*__AGS_PLUGIN_STOCK_H__*/
+#endif /*__AGS_DESTROY_UTIL_H__*/
diff --git a/ags/util/ags_id_generator.c b/ags/util/ags_id_generator.c
index c86fb55..1bb1d73 100644
--- a/ags/util/ags_id_generator.c
+++ b/ags/util/ags_id_generator.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -16,6 +16,7 @@
  * You should have received a copy of the GNU General Public License
  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
  */
+
 #include <ags/util/ags_id_generator.h>
 
 #include <stdlib.h>
diff --git a/ags/util/ags_id_generator.h b/ags/util/ags_id_generator.h
index 66d6ddd..dec924e 100644
--- a/ags/util/ags_id_generator.h
+++ b/ags/util/ags_id_generator.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
diff --git a/ags/widget/ags_container.c b/ags/util/ags_list_util.c
similarity index 57%
copy from ags/widget/ags_container.c
copy to ags/util/ags_list_util.c
index 444479d..7676364 100644
--- a/ags/widget/ags_container.c
+++ b/ags/util/ags_list_util.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -17,34 +17,42 @@
  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <ags/widget/ags_container.h>
+#include <ags/util/ags_list_util.h>
 
-/**
- * SECTION:ags_container
- * @short_description: Complete GtkContainer
- * @title: AgsContainer
- * @section_id:
- * @include: ags/widget/ags_container.h
- *
- * Functions completing #GtkContainer API.
- */
-
-/**
- * ags_container_remove_all:
- * @container: the #GtkContainer
- * 
- * Adds all #GtkWidget pointed by #GList to @container. 
- *
- * Since: 0.4
- */
-void
-ags_container_add_all(GtkContainer *container,
-		      GList *list)
+GList*
+ags_list_util_find_type(GList *list,
+			GType gtype)
 {
+  if(gtype == G_TYPE_NONE){
+    return(NULL);
+  }
+  
   while(list != NULL){
-    gtk_container_add(container,
-		      GTK_WIDGET(list->data));
+    if(g_type_is_a(list->data,
+		   gtype)){
+      return(list);
+    }
+    
+    list = list->next;
+  }
+  
+  return(NULL);
+}
+
+GList*
+ags_list_util_copy_and_ref(GList *list)
+{
+  GList *list_start;
 
+  list = 
+    list_start = g_list_copy(list);
+  
+  while(list != NULL){
+    g_object_ref(list->data);
+    
     list = list->next;
   }
+
+  return(list_start);
 }
+
diff --git a/ags/X/ags_history_browser_callbacks.h b/ags/util/ags_list_util.h
similarity index 75%
copy from ags/X/ags_history_browser_callbacks.h
copy to ags/util/ags_list_util.h
index ccbe5fa..74a4745 100644
--- a/ags/X/ags_history_browser_callbacks.h
+++ b/ags/util/ags_list_util.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -17,14 +17,14 @@
  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __AGS_HISTORY_BROWSER_CALLBACKS_H__
-#define __AGS_HISTORY_BROWSER_CALLBACKS_H__
+#ifndef __AGS_LIST_UTIL_H__
+#define __AGS_LIST_UTIL_H__
 
 #include <glib.h>
 #include <glib-object.h>
-#include <gtk/gtk.h>
 
-#include <ags/X/ags_history_browser.h>
+GList* ags_list_util_find_type(GList *list,
+			       GType gtype);
+GList* ags_list_util_copy_and_ref(GList *list);
 
-
-#endif /*__AGS_HISTORY_BROWSER_CALLBACKS_H__*/
+#endif /*__AGS_LIST_UTIL_H__*/
diff --git a/ags/widget/ags_dial.c b/ags/widget/ags_dial.c
index 538245d..4390581 100644
--- a/ags/widget/ags_dial.c
+++ b/ags/widget/ags_dial.c
@@ -223,6 +223,13 @@ ags_dial_class_init(AgsDialClass *dial)
   widget->show = ags_dial_show;
 
   /* properties */
+  /**
+   * AgsDial:adjustment:
+   *
+   * The adjustment storing current value and boundaries.
+   * 
+   * Since: 0.7.21
+   */
   param_spec = g_param_spec_object("adjustment\0",
 				   "assigned adjustment\0",
 				   "The adjustment it is assigned with\0",
@@ -331,20 +338,21 @@ ags_dial_init(AgsDial *dial)
   gtk_widget_set_style((GtkWidget *) dial,
 		       dial_style);
 
-  dial->flags = AGS_DIAL_WITH_BUTTONS;
+  dial->flags = (AGS_DIAL_WITH_BUTTONS |
+		 AGS_DIAL_SEEMLESS_MODE);
 
   dial->adjustment = NULL;
 
-  dial->radius = 8;
+  dial->radius = AGS_DIAL_DEFAULT_RADIUS;
   dial->scale_precision = AGS_DIAL_DEFAULT_PRECISION;
   dial->scale_max_precision = AGS_DIAL_DEFAULT_PRECISION;
-  dial->outline_strength = 4;
+  dial->outline_strength = AGS_DIAL_DEFAULT_OUTLINE_STRENGTH;
 
   dial->font_size = 6;
-  dial->button_width = 10;
+  dial->button_width = AGS_DIAL_DEFAULT_BUTTON_WIDTH;
   dial->button_height = 0;
-  dial->margin_left = 4.0;
-  dial->margin_right = 4.0;
+  dial->margin_left = AGS_DIAL_DEFAULT_MARGIN;
+  dial->margin_right = AGS_DIAL_DEFAULT_MARGIN;
 
   dial->tolerance = 0.9;
   dial->negated_tolerance = 1.1;
@@ -739,20 +747,25 @@ void
 ags_dial_size_request(GtkWidget *widget,
 		      GtkRequisition *requisition)
 {
-  GTK_WIDGET_CLASS(ags_dial_parent_class)->size_request(widget, requisition);
+  requisition->height = AGS_DIAL_DEFAULT_HEIGHT;
+  requisition->width = AGS_DIAL_DEFAULT_WIDTH;
 
-  /* implement me */
-  //TODO:JK:
+  //TODO:JK: improve me
 }
 
 void
 ags_dial_size_allocate(GtkWidget *widget,
 		       GtkAllocation *allocation)
-{
-  GTK_WIDGET_CLASS(ags_dial_parent_class)->size_allocate(widget, allocation);
+{  
+  allocation->height = AGS_DIAL_DEFAULT_HEIGHT;
+  allocation->width = AGS_DIAL_DEFAULT_WIDTH;
+  
+  widget->allocation = *allocation;
 
-  /* implement me */
-  //TODO:JK:
+  //TODO:JK: improve me
+
+  GTK_WIDGET_CLASS(ags_dial_parent_class)->size_allocate(widget,
+							 allocation);
 }
 
 gboolean
@@ -986,7 +999,10 @@ ags_dial_motion_notify(GtkWidget *widget,
 		       GdkEventMotion *event)
 {
   AgsDial *dial;
+
   auto void ags_dial_motion_notify_do_dial();
+  auto void ags_dial_motion_notify_do_seemless_dial();
+  
   void ags_dial_motion_notify_do_dial(){
     GtkAdjustment *adjustment;
 
@@ -1042,28 +1058,207 @@ ags_dial_motion_notify(GtkWidget *widget,
     }
   }
 
-  //  GTK_WIDGET_CLASS(ags_dial_parent_class)->motion_notify_event(widget, event);
+  void ags_dial_motion_notify_do_seemless_dial(){
+    GtkAdjustment *adjustment;
 
-  dial = AGS_DIAL(widget);
+    cairo_t *cr;
+    
+    gdouble radius;
+    gdouble border_left, border_top;
+    gdouble range;
+    gdouble a0, quarter;
+    gdouble x0, y0, x1, y1;
+    gdouble translated_x;
+    gboolean x_toggled, y_toggled;
+    
+    //TODO:JK: optimize me
+    adjustment = dial->adjustment;
 
-  if((AGS_DIAL_MOTION_CAPTURING & (dial->flags)) != 0){
-    if((AGS_DIAL_MOTION_CAPTURING_INIT & (dial->flags)) != 0){
-      dial->current_x = event->x;
-      dial->current_y = event->y;
+    range = (dial->adjustment->upper - dial->adjustment->lower);
+
+    if(range == 0.0){
+      return;
+    }
+    
+    radius = dial->radius;
 
-      dial->flags &= (~AGS_DIAL_MOTION_CAPTURING_INIT);
+    border_left = 0.0;
+    border_top = 0.0;
+    
+    x1 = event->x - (1.0 + dial->button_width + dial->margin_left + radius + border_left);
+    y1 = event->y - (dial->outline_strength + radius + border_top);
+    y1 *= -1.0;    
+
+    x_toggled = FALSE;
+    y_toggled = FALSE;
+    
+    if(x1 < 0.0){
+      x_toggled = TRUE;
+    }
+
+    if(y1 < 0.0){
+      y_toggled = TRUE;
+    }
+
+    if(radius == 0.0){
+      return;
+    }
+
+    //FIXME:JK: ugly hack
+    x1 = round(x1 + 1.0);
+    y1 = round(y1 - 1.0);
+
+    if(x1 == 0.0 &&
+       y1 == 0.0){
+      return;
+    }else if(x1 == 0.0){
+      a0 = 1.0;
+
+#if 0
+      x0 = 0.0;
+      y0 = 1.0 * radius;
+#endif
+    }else if(y1 == 0.0){
+      a0 = 0.0;
 
-      ags_dial_motion_notify_do_dial();
+#if 0
+      x0 = 1.0 * radius;
+      y0 = 0.0;
+#endif
     }else{
-      dial->gravity_x = dial->current_x;
-      dial->gravity_y = dial->current_y;
-      dial->current_x = event->x;
-      dial->current_y = event->y;
+      a0 = y1 / x1;
+#if 0
+      x0 = cos(a0) * radius;
+      y0 = sin(a0) * radius;
+#endif
+    }
+
+    /* origin correction */
+#if 0
+    if(x_toggled && y_toggled){
+      if(x0 > 0.0){
+	x0 *= -1.0;
+      }
+      
+      if(y0 > 0.0){
+	y0 *= -1.0;
+      }
+    }else if(y_toggled){
+      if(x0 < 0.0){
+	x0 *= -1.0;
+      }
+      
+      if(y0 > 0.0){
+	y0 *= -1.0;
+      }
+    }else if(x_toggled){
+      if(y0 < 0.0){
+	y0 *= -1.0;
+      }
+
+      if(x0 > 0.0){
+	x0 *= -1.0;
+      }
+    }else{
+      if(x0 < 0.0){
+	x0 *= -1.0;
+      }
+      
+      if(y0 < 0.0){
+	y0 *= -1.0;
+      }
+    }
+#endif
 
-      ags_dial_motion_notify_do_dial();
+    if(a0 > 2.0 * M_PI / 4.0){
+      a0 = (2.0 * M_PI / 4.0);
+    }else if(a0 < -2.0 * M_PI / 4.0){
+      a0 = (-2.0 * M_PI / 4.0);
+    }
+    
+    /* translated_x */
+    translated_x = a0 * radius;
+    
+    quarter =  (2.0 * M_PI / 4.0) * radius;
+    
+    if(x_toggled && y_toggled){
+      if(translated_x < 0.0){
+	translated_x = quarter + translated_x;
+      }else{
+	translated_x = quarter - translated_x;
+      }
+    }else if(y_toggled){
+      if(translated_x < 0.0){
+	translated_x *= -1.0;
+      }
+      
+      translated_x += 3.0 * quarter;
+    }else if(x_toggled){
+      if(translated_x < 0.0){
+	translated_x *= -1.0;
+      }
+      
+      translated_x += quarter;
+    }else{
+      if(translated_x < 0.0){
+	translated_x = quarter + translated_x;
+      }else{
+	translated_x = quarter - translated_x;
+      }
+      
+      translated_x += 2.0 * quarter;
+    }
+        
+    translated_x = ((4.0 / 3.0) * range) / (4.0 * quarter) * translated_x;
+    translated_x -= (range / 3.0 / 2.0);
+    translated_x = adjustment->lower + translated_x;  
+
+    if(translated_x < adjustment->lower){
+      translated_x = adjustment->lower;
+    }else if(translated_x > adjustment->upper){
+      translated_x = adjustment->upper;
     }
+
+    gtk_adjustment_set_value(adjustment,
+    			     translated_x);
+    ags_dial_draw(dial);
   }
 
+  //  GTK_WIDGET_CLASS(ags_dial_parent_class)->motion_notify_event(widget, event);
+  dial = AGS_DIAL(widget);
+  
+  if((AGS_DIAL_MOTION_CAPTURING & (dial->flags)) != 0){
+    if((AGS_DIAL_SEEMLESS_MODE & (dial->flags)) != 0){
+      if((AGS_DIAL_MOTION_CAPTURING_INIT & (dial->flags)) != 0){
+	dial->current_x = event->x;
+	dial->current_y = event->y;
+      }else{
+	dial->gravity_x = dial->current_x;
+	dial->gravity_y = dial->current_y;
+	dial->current_x = event->x;
+	dial->current_y = event->y;
+      }
+
+      ags_dial_motion_notify_do_seemless_dial();
+    }else{
+      if((AGS_DIAL_MOTION_CAPTURING_INIT & (dial->flags)) != 0){
+	dial->current_x = event->x;
+	dial->current_y = event->y;
+
+	dial->flags &= (~AGS_DIAL_MOTION_CAPTURING_INIT);
+
+	ags_dial_motion_notify_do_dial();
+      }else{
+	dial->gravity_x = dial->current_x;
+	dial->gravity_y = dial->current_y;
+	dial->current_x = event->x;
+	dial->current_y = event->y;
+
+	ags_dial_motion_notify_do_dial();
+      }
+    }
+  }
+  
   return(FALSE);
 }
 
@@ -1115,19 +1310,30 @@ ags_dial_draw(AgsDial *dial)
 
   button_width = dial->button_width;
   button_height = dial->button_height;
-  
+
   /* clear bg */
   cairo_set_source_rgb(cr,
-		       dial_style->bg[0].red / white_gc,
-		       dial_style->bg[0].green / white_gc,
-		       dial_style->bg[0].blue / white_gc);
+		       dial_style->fg[0].red / white_gc,
+		       dial_style->fg[0].green / white_gc,
+		       dial_style->fg[0].blue / white_gc);
 
   cairo_rectangle(cr,
 		  0.0, 0.0,
-		  2.0 * (dial->radius + button_width) + outline_strength + margin_left + margin_right, 2.0 * (dial->radius + outline_strength));
+		  widget->allocation.width, widget->allocation.height);
   cairo_fill(cr);
-  
+
   if((AGS_DIAL_WITH_BUTTONS & (dial->flags)) != 0){
+    /* bg */
+    cairo_set_source_rgb(cr,
+			 dial_style->bg[0].red / white_gc,
+			 dial_style->bg[0].green / white_gc,
+			 dial_style->bg[0].blue / white_gc);
+
+    cairo_rectangle(cr,
+		    0.0, (2.0 * radius) - button_height + outline_strength - 1.0,
+		    button_width + 2.0, button_height + 2.0);
+    cairo_fill(cr);
+    
     /* draw controller button down */
     cairo_set_source_rgb(cr,
 			 dial_style->fg[0].red / white_gc,
@@ -1139,6 +1345,7 @@ ags_dial_draw(AgsDial *dial)
     cairo_rectangle(cr,
 		    1.0, (2.0 * radius) - button_height + outline_strength,
 		    button_width, button_height);
+    cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
     cairo_stroke(cr);
 
     cairo_move_to (cr,
@@ -1149,6 +1356,18 @@ ags_dial_draw(AgsDial *dial)
 
   
   if((AGS_DIAL_WITH_BUTTONS & (dial->flags)) != 0){
+    /* bg */
+    cairo_set_source_rgb(cr,
+			 dial_style->bg[0].red / white_gc,
+			 dial_style->bg[0].green / white_gc,
+			 dial_style->bg[0].blue / white_gc);
+
+    cairo_rectangle(cr,
+		    (2.0 * radius) + button_width + margin_left + margin_right,
+		    (2.0 * radius) - button_height + outline_strength - 1.0,
+		    button_width + 2.0, button_height + 2.0);
+    cairo_fill(cr);
+
     /* draw controller button up */
     cairo_set_source_rgb(cr,
 			 dial_style->fg[0].red / white_gc,
@@ -1182,6 +1401,20 @@ ags_dial_draw(AgsDial *dial)
 	    1.0 * M_PI);
   cairo_stroke(cr);
   */
+
+  /* bg */
+  cairo_set_source_rgb(cr,
+		       dial_style->bg[0].red / white_gc,
+		       dial_style->bg[0].green / white_gc,
+		       dial_style->bg[0].blue / white_gc);
+  
+  cairo_arc(cr,
+	    1.0 + button_width + margin_left + radius,
+	    radius + outline_strength,
+	    radius + outline_strength - 1.25,
+	    -1.0 * M_PI,
+	    1.0 * M_PI);
+  cairo_fill(cr);
   
   /* background */
   cairo_set_source_rgb(cr,
@@ -1214,12 +1447,12 @@ ags_dial_draw(AgsDial *dial)
 		-1 * cos((0.35 * M_PI) / (0.65 * M_PI)) + radius + 2.0 * outline_strength - 1.0);
   cairo_close_path(cr);
 
-  cairo_arc (cr,
-	     1.0 + button_width + margin_left + radius,
-	     radius + outline_strength,
-	     radius,
-	     0.35 * M_PI,
-	     0.65 * M_PI);
+  cairo_arc(cr,
+	    1.0 + button_width + margin_left + radius,
+	    radius + outline_strength,
+	    radius,
+	    0.35 * M_PI,
+	    0.65 * M_PI);
   cairo_fill(cr);
 
   cairo_line_to(cr,
@@ -1233,12 +1466,12 @@ ags_dial_draw(AgsDial *dial)
 		radius + 2.0 * outline_strength - 1.0);
   cairo_close_path(cr);
 
-  cairo_arc (cr,
-	     1.0 + button_width + margin_left + radius,
-	     radius + outline_strength,
-	     radius,
-	     -0.65 * M_PI,
-	     -0.35 * M_PI);
+  cairo_arc(cr,
+	    1.0 + button_width + margin_left + radius,
+	    radius + outline_strength,
+	    radius,
+	    -0.65 * M_PI,
+	    -0.35 * M_PI);
   cairo_fill(cr);
 
   /* outline */
@@ -1248,12 +1481,12 @@ ags_dial_draw(AgsDial *dial)
 		       dial_style->fg[0].blue / white_gc);
   //  cairo_set_line_width(cr, 1.0 - (2.0 / M_PI));
   cairo_set_line_width(cr, 1.0);
-  cairo_arc (cr,
-	     1.0 + button_width + margin_left + radius,
-	     radius + outline_strength,
-	     radius,
-	     -1.0 * M_PI,
-	     1.0 * M_PI);
+  cairo_arc(cr,
+	    1.0 + button_width + margin_left + radius,
+	    radius + outline_strength,
+	    radius,
+	    -1.0 * M_PI,
+	    1.0 * M_PI);
   cairo_stroke(cr);
 
   /* scale */
@@ -1274,12 +1507,12 @@ ags_dial_draw(AgsDial *dial)
   scale_width /= (radius + outline_strength);
 
   for(i = 0; i <= scale_precision; i++){
-    cairo_arc (cr,
-	       1.0 + button_width + margin_left + radius,
-	       radius + outline_strength,
-	       radius + outline_strength / M_PI,
-	       starter_angle + ((gdouble) i * scale_inverted_width) + ((gdouble) i * scale_width),
-	       starter_angle + ((gdouble) i * scale_inverted_width) + ((gdouble) i * scale_width) + scale_width);
+    cairo_arc(cr,
+	      1.0 + button_width + margin_left + radius,
+	      radius + outline_strength,
+	      radius + outline_strength / M_PI,
+	      starter_angle + ((gdouble) i * scale_inverted_width) + ((gdouble) i * scale_width),
+	      starter_angle + ((gdouble) i * scale_inverted_width) + ((gdouble) i * scale_width) + scale_width);
     cairo_stroke(cr);
   }
 
@@ -1292,13 +1525,8 @@ ags_dial_draw(AgsDial *dial)
   }
 
   /* this is odd */
-  if(dial->adjustment->lower < 0.0 && dial->adjustment->upper < 0.0){
-    translated_value = (gdouble) scale_precision * (dial->adjustment->value - dial->adjustment->lower) / range;
-  }else if(dial->adjustment->lower < 0.0){
-    translated_value = (gdouble) scale_precision * (dial->adjustment->value - dial->adjustment->lower) / range;
-  }else{
-    translated_value = (gdouble) scale_precision * (dial->adjustment->value - dial->adjustment->lower) / range;
-  }
+  translated_value = (dial->adjustment->value - dial->adjustment->lower);
+  translated_value = (gdouble) scale_precision * (translated_value / range);
 
   //  g_message("value: %f\nupper: %f\ntranslated_value: %f\n\0", GTK_RANGE(dial)->adjustment->value, GTK_RANGE(dial)->adjustment->upper, translated_value);
   cairo_set_line_width(cr, 4.0);
@@ -1307,12 +1535,12 @@ ags_dial_draw(AgsDial *dial)
 		       dial_style->fg[0].green / white_gc,
 		       dial_style->fg[0].blue / white_gc);
 
-  cairo_arc (cr,
-	     1.0 + button_width + margin_left + radius,
-	     radius + outline_strength,
-	     radius - (outline_strength + 4.0) / M_PI,
-	     starter_angle + (translated_value * scale_inverted_width) + (translated_value * scale_width),
-	     starter_angle + (translated_value * scale_inverted_width) + (translated_value * scale_width) + scale_width);
+  cairo_arc(cr,
+	    1.0 + button_width + margin_left + radius,
+	    radius + outline_strength,
+	    radius - (outline_strength + 4.0) / M_PI,
+	    starter_angle + (translated_value * scale_inverted_width) + (translated_value * scale_width),
+	    starter_angle + (translated_value * scale_inverted_width) + (translated_value * scale_width) + scale_width);
   cairo_stroke(cr);
 
   cairo_destroy(cr);
diff --git a/ags/widget/ags_dial.h b/ags/widget/ags_dial.h
index 7f13f3a..3c4f7ba 100644
--- a/ags/widget/ags_dial.h
+++ b/ags/widget/ags_dial.h
@@ -33,6 +33,14 @@
 
 #define AGS_DIAL_DEFAULT_PRECISION (8.0)
 
+#define AGS_DIAL_DEFAULT_RADIUS (8)
+#define AGS_DIAL_DEFAULT_OUTLINE_STRENGTH (4)
+#define AGS_DIAL_DEFAULT_BUTTON_WIDTH (10)
+#define AGS_DIAL_DEFAULT_MARGIN (4.0)
+
+#define AGS_DIAL_DEFAULT_HEIGHT (2 * (AGS_DIAL_DEFAULT_RADIUS + AGS_DIAL_DEFAULT_OUTLINE_STRENGTH + 1))
+#define AGS_DIAL_DEFAULT_WIDTH (2 * (AGS_DIAL_DEFAULT_BUTTON_WIDTH + AGS_DIAL_DEFAULT_MARGIN + AGS_DIAL_DEFAULT_RADIUS + AGS_DIAL_DEFAULT_OUTLINE_STRENGTH + 2))
+
 typedef struct _AgsDial AgsDial;
 typedef struct _AgsDialClass AgsDialClass;
 
diff --git a/ags/widget/ags_hindicator.c b/ags/widget/ags_hindicator.c
index 54e6dd2..37e43d8 100644
--- a/ags/widget/ags_hindicator.c
+++ b/ags/widget/ags_hindicator.c
@@ -23,7 +23,25 @@ void ags_hindicator_class_init(AgsHIndicatorClass *indicator);
 void ags_hindicator_init(AgsHIndicator *indicator);
 void ags_hindicator_show(GtkWidget *widget);
 
+gboolean ags_hindicator_expose(GtkWidget *widget,
+			       GdkEventExpose *event);
+gboolean ags_hindicator_configure(GtkWidget *widget,
+				  GdkEventConfigure *event);
+
+void ags_hindicator_draw(AgsHIndicator *indicator);
+
+/**
+ * SECTION:ags_hindicator
+ * @short_description: A horizontal indicator widget
+ * @title: AgsHIndicator
+ * @section_id:
+ * @include: ags/widget/ags_hindicator.h
+ *
+ * #AgsHIndicator is a widget visualizing a #GtkAdjustment.
+ */
+
 static gpointer ags_hindicator_parent_class = NULL;
+GtkStyle *indicator_style;
 
 GType
 ags_hindicator_get_type(void)
@@ -57,22 +75,141 @@ ags_hindicator_class_init(AgsHIndicatorClass *indicator)
   GtkWidgetClass *widget;
 
   ags_hindicator_parent_class = g_type_class_peek_parent(indicator);
+
+  /* GtkWidgetClass */
+  widget = (GtkWidgetClass *) indicator;
+
+  widget->expose_event = ags_hindicator_expose;
+  widget->configure_event = ags_hindicator_configure;
 }
 
 void
 ags_hindicator_init(AgsHIndicator *indicator)
 {
-  g_object_set(G_OBJECT(indicator),
-	       "app-paintable\0", TRUE,
-	       NULL);
+  gtk_widget_set_size_request((GtkWidget *) indicator,
+			      100,
+			      16);
+}
+gboolean
+ags_hindicator_configure(GtkWidget *widget,
+			 GdkEventConfigure *event)
+{
+  ags_hindicator_draw((AgsHIndicator *) widget);
+
+  return(FALSE);
+}
+
+gboolean
+ags_hindicator_expose(GtkWidget *widget,
+		     GdkEventExpose *event)
+{
+  ags_hindicator_draw((AgsHIndicator *) widget);
+
+  return(FALSE);
 }
 
+void
+ags_hindicator_draw(AgsHIndicator *indicator)
+{
+  GtkWidget *widget;
+  
+  GtkAdjustment *adjustment;
+  GtkStyle *indicator_style;
+  cairo_t *cr;
+  
+  gdouble value;
+  guint width, height;
+  guint segment_width, segment_height;
+  guint padding;
+  guint i;
+
+  static const gdouble white_gc = 65535.0;
+
+  widget = GTK_WIDGET(indicator);
+  indicator_style = gtk_widget_get_style(widget);
+  
+  adjustment = AGS_INDICATOR(indicator)->adjustment;
+
+  if(adjustment == NULL){
+    return;
+  }
+  //  g_message("draw %f\0", adjustment->value);
+
+  cr = gdk_cairo_create(widget->window);
+
+  if(cr == NULL){
+    return;
+  }
+  
+  width = 100;
+  height = 16;
+
+  segment_width = 7;
+  segment_height = height;
+
+  padding = 3;
+
+  cairo_surface_flush(cairo_get_target(cr));
+  cairo_push_group(cr);
+
+  for(i = 0; i < width / (segment_width + padding); i++){
+    if(adjustment->value > 0.0 &&
+       (1.0 / adjustment->value * i < (width / (segment_width + padding)))){
+      /* active */
+      cairo_set_source_rgb(cr,
+			   indicator_style->light[0].red / white_gc,
+			   indicator_style->light[0].green / white_gc,
+			   indicator_style->light[0].blue / white_gc);
+    }else{
+      /* normal */
+      cairo_set_source_rgb(cr,
+			   indicator_style->dark[0].red / white_gc,
+			   indicator_style->dark[0].green / white_gc,
+			   indicator_style->dark[0].blue / white_gc);
+    }
+
+    cairo_rectangle(cr,
+		    width - i * (segment_width + padding) - segment_width, 0,
+		    segment_width, segment_height);
+    cairo_fill(cr);
+
+    /* outline */
+    cairo_set_source_rgb(cr,
+			 indicator_style->fg[0].red / white_gc,
+			 indicator_style->fg[0].green / white_gc,
+			 indicator_style->fg[0].blue / white_gc);
+    cairo_rectangle(cr,
+		    width - i * (segment_width + padding) - segment_width, 0,
+		    segment_width, segment_height);
+    cairo_stroke(cr);
+  }
+
+  cairo_pop_group_to_source(cr);
+  cairo_paint(cr);
+
+  cairo_surface_mark_dirty(cairo_get_target(cr));
+  cairo_destroy(cr);
+}
+
+/**
+ * ags_hindicator_new:
+ *
+ * Creates an #AgsHIndicator.
+ *
+ * Returns: a new #AgsHIndicator
+ *
+ * Since: 0.7.128
+ */
 AgsHIndicator*
 ags_hindicator_new()
 {
   AgsHIndicator *indicator;
+  GtkAdjustment *adjustment;
+
+  adjustment = (GtkAdjustment *) gtk_adjustment_new(0.0, 0.0, 1.0, 0.1, 0.1, 0.0);
 
   indicator = (AgsHIndicator *) g_object_new(AGS_TYPE_HINDICATOR,
+					     "adjustment\0", adjustment,
 					     NULL);
   
   return(indicator);
diff --git a/ags/widget/ags_hindicator.h b/ags/widget/ags_hindicator.h
index 48614a5..f7dff43 100644
--- a/ags/widget/ags_hindicator.h
+++ b/ags/widget/ags_hindicator.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -22,16 +22,17 @@
 
 #include <glib.h>
 #include <glib-object.h>
+
 #include <gtk/gtk.h>
 
 #include "ags_indicator.h"
 
 #define AGS_TYPE_HINDICATOR                (ags_hindicator_get_type())
-#define AGS_HINDICATOR(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_INDICATOR, AgsHIndicator))
-#define AGS_HINDICATOR_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_INDICATOR, AgsHIndicatorClass))
-#define AGS_IS_HINDICATOR(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), AGS_TYPE_INDICATOR))
-#define AGS_IS_HINDICATOR_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_INDICATOR))
-#define AGS_HINDICATOR_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_INDICATOR, AgsHIndicatorClass))
+#define AGS_HINDICATOR(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_HINDICATOR, AgsHIndicator))
+#define AGS_HINDICATOR_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_HINDICATOR, AgsHIndicatorClass))
+#define AGS_IS_HINDICATOR(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), AGS_TYPE_HINDICATOR))
+#define AGS_IS_HINDICATOR_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_HINDICATOR))
+#define AGS_HINDICATOR_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_HINDICATOR, AgsHIndicatorClass))
 
 typedef struct _AgsHIndicator AgsHIndicator;
 typedef struct _AgsHIndicatorClass AgsHIndicatorClass;
@@ -43,7 +44,7 @@ struct _AgsHIndicator
 
 struct _AgsHIndicatorClass
 {
-  GtkWidgetClass indicator;
+  AgsIndicatorClass indicator;
 };
 
 GType ags_hindicator_get_type(void);
@@ -51,4 +52,3 @@ GType ags_hindicator_get_type(void);
 AgsHIndicator* ags_hindicator_new();
 
 #endif /*__AGS_HINDICATOR_H__*/
-
diff --git a/ags/widget/ags_hled_array.c b/ags/widget/ags_hled_array.c
new file mode 100644
index 0000000..d2981c4
--- /dev/null
+++ b/ags/widget/ags_hled_array.c
@@ -0,0 +1,98 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ags_hled_array.h"
+
+void ags_hled_array_class_init(AgsHLedArrayClass *hled_array);
+void ags_hled_array_init(AgsHLedArray *hled_array);
+
+/**
+ * SECTION:ags_hled_array
+ * @short_description: A horizontal led array widget
+ * @title: AgsHLedArray
+ * @section_id:
+ * @include: ags/widget/ags_hled_array.h
+ *
+ * #AgsHLedArray is a widget representing an array of horizontal leds.
+ */
+
+static gpointer ags_hled_array_parent_class = NULL;
+
+GType
+ags_hled_array_get_type(void)
+{
+  static GType ags_type_hled_array = 0;
+
+  if(!ags_type_hled_array){
+    static const GTypeInfo ags_hled_array_info = {
+      sizeof(AgsHLedArrayClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_hled_array_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof(AgsHLedArray),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_hled_array_init,
+    };
+
+    ags_type_hled_array = g_type_register_static(AGS_TYPE_LED_ARRAY,
+						 "AgsHLedArray\0",
+						 &ags_hled_array_info,
+						 0);
+  }
+
+  return(ags_type_hled_array);
+}
+
+void
+ags_hled_array_class_init(AgsHLedArrayClass *hled_array)
+{
+  /* empty */
+}
+
+void
+ags_hled_array_init(AgsHLedArray *hled_array)
+{
+  AGS_LED_ARRAY(hled_array)->box = gtk_hbox_new(FALSE,
+						0);
+  gtk_container_add(hled_array,
+		    AGS_LED_ARRAY(hled_array)->box);
+  gtk_widget_show(AGS_LED_ARRAY(hled_array)->box);
+}
+
+/**
+ * ags_hled_array_new:
+ *
+ * Creates an #AgsHLedArray.
+ *
+ * Returns: a new #AgsHLedArray
+ *
+ * Since: 0.7.122.7
+ */
+AgsHLedArray*
+ags_hled_array_new()
+{
+  AgsHLedArray *hled_array;
+
+  hled_array = (AgsHLedArray *) g_object_new(AGS_TYPE_HLED_ARRAY,
+					     NULL);
+  
+  return(hled_array);
+}
diff --git a/ags/widget/ags_hled_array.h b/ags/widget/ags_hled_array.h
new file mode 100644
index 0000000..bae81c0
--- /dev/null
+++ b/ags/widget/ags_hled_array.h
@@ -0,0 +1,54 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_HLED_ARRAY_H__
+#define __AGS_HLED_ARRAY_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+#include "ags_led_array.h"
+
+#define AGS_TYPE_HLED_ARRAY                (ags_hled_array_get_type())
+#define AGS_HLED_ARRAY(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_HLED_ARRAY, AgsHLedArray))
+#define AGS_HLED_ARRAY_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_HLED_ARRAY, AgsHLedArrayClass))
+#define AGS_IS_HLED_ARRAY(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), AGS_TYPE_HLED_ARRAY))
+#define AGS_IS_HLED_ARRAY_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_HLED_ARRAY))
+#define AGS_HLED_ARRAY_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_HLED_ARRAY, AgsHLedArrayClass))
+
+typedef struct _AgsHLedArray AgsHLedArray;
+typedef struct _AgsHLedArrayClass AgsHLedArrayClass;
+
+struct _AgsHLedArray
+{
+  AgsLedArray led_array;
+};
+
+struct _AgsHLedArrayClass
+{
+  AgsLedArrayClass led_array;
+};
+
+GType ags_hled_array_get_type(void);
+
+AgsHLedArray* ags_hled_array_new();
+
+#endif /*__AGS_HLED_ARRAY_H__*/
diff --git a/ags/widget/ags_indicator.c b/ags/widget/ags_indicator.c
index 94d8f28..c9648a3 100644
--- a/ags/widget/ags_indicator.c
+++ b/ags/widget/ags_indicator.c
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -107,6 +107,13 @@ ags_indicator_class_init(AgsIndicatorClass *indicator)
   widget->show = ags_indicator_show;
 
   /* properties */
+  /**
+   * AgsIndicator:adjustment:
+   *
+   * The adjustment giving indicator value.
+   * 
+   * Since: 0.7.21
+   */
   param_spec = g_param_spec_object("adjustment\0",
 				   "assigned adjustment\0",
 				   "The adjustment it is assigned with\0",
@@ -127,7 +134,8 @@ ags_indicator_init(AgsIndicator *indicator)
   gtk_widget_set_style((GtkWidget *) indicator,
 		       indicator_style);
 
-  indicator->adjustment = NULL;
+  indicator->adjustment = (GtkAdjustment *) gtk_adjustment_new(0.0, 0.0, 10.0, 1.0, 1.0, 10.0);
+  g_object_ref(indicator->adjustment);
 }
 
 void
@@ -179,7 +187,9 @@ ags_indicator_get_property(GObject *gobject,
 
   switch(prop_id){
   case PROP_ADJUSTMENT:
-    g_value_set_object(value, indicator->adjustment);
+    {
+      g_value_set_object(value, indicator->adjustment);
+    }
     break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
diff --git a/ags/widget/ags_led.c b/ags/widget/ags_led.c
index bb59560..0e8bb09 100644
--- a/ags/widget/ags_led.c
+++ b/ags/widget/ags_led.c
@@ -24,17 +24,17 @@
 
 void ags_led_class_init(AgsLedClass *led);
 void ags_led_init(AgsLed *led);
-void ags_led_show(GtkWidget *widget);
 
+void ags_led_size_request(AgsLed *led,
+			  GtkRequisition *requisition);
+void ags_led_size_allocate(AgsLed *led,
+			   GtkAllocation *allocation);
 void ags_led_realize(GtkWidget *widget);
 gint ags_led_expose(GtkWidget *widget,
 		     GdkEventExpose *event);
-void ags_led_size_request(GtkWidget *widget,
-			   GtkRequisition   *requisition);
-void ags_led_size_allocate(GtkWidget *widget,
-			    GtkAllocation *allocation);
 gboolean ags_led_expose(GtkWidget *widget,
 			 GdkEventExpose *event);
+void ags_led_show(GtkWidget *widget);
 
 void ags_led_draw(AgsLed *led);
 
@@ -87,6 +87,8 @@ ags_led_class_init(AgsLedClass *led)
 
   widget = (GtkWidgetClass *) led;
 
+  widget->size_request = ags_led_size_request;
+  widget->size_allocate = ags_led_size_allocate;
   widget->realize = ags_led_realize;
   widget->expose_event = ags_led_expose;
   widget->show = ags_led_show;
@@ -106,6 +108,24 @@ ags_led_init(AgsLed *led)
 }
 
 void
+ags_led_size_allocate(AgsLed *led,
+		      GtkAllocation *allocation)
+{
+  GTK_WIDGET(led)->allocation = *allocation;  
+
+  allocation->width = AGS_LED_DEFAULT_WIDTH;
+  allocation->height = AGS_LED_DEFAULT_HEIGHT;
+}
+
+void
+ags_led_size_request(AgsLed *led,
+		     GtkRequisition *requisition)
+{
+  requisition->height = AGS_LED_DEFAULT_HEIGHT;
+  requisition->width = AGS_LED_DEFAULT_WIDTH;
+}
+
+void
 ags_led_realize(GtkWidget *widget)
 {
   GdkWindowAttr attributes;
diff --git a/ags/widget/ags_led.h b/ags/widget/ags_led.h
index ff90375..9e67128 100644
--- a/ags/widget/ags_led.h
+++ b/ags/widget/ags_led.h
@@ -1,5 +1,5 @@
 /* GSequencer - Advanced GTK Sequencer
- * Copyright (C) 2005-2015 Joël Krähemann
+ * Copyright (C) 2005-2017 Joël Krähemann
  *
  * This file is part of GSequencer.
  *
@@ -22,6 +22,7 @@
 
 #include <glib.h>
 #include <glib-object.h>
+
 #include <gtk/gtk.h>
 
 #define AGS_TYPE_LED                (ags_led_get_type())
@@ -31,6 +32,9 @@
 #define AGS_IS_LED_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_LED))
 #define AGS_LED_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_LED, AgsLedClass))
 
+#define AGS_LED_DEFAULT_WIDTH (12)
+#define AGS_LED_DEFAULT_HEIGHT (8)
+
 typedef struct _AgsLed AgsLed;
 typedef struct _AgsLedClass AgsLedClass;
 
diff --git a/ags/widget/ags_led_array.c b/ags/widget/ags_led_array.c
new file mode 100644
index 0000000..a1225f3
--- /dev/null
+++ b/ags/widget/ags_led_array.c
@@ -0,0 +1,329 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ags_led_array.h"
+
+void ags_led_array_class_init(AgsLedArrayClass *led_array);
+void ags_led_array_init(AgsLedArray *led_array);
+void ags_led_array_set_property(GObject *gobject,
+				guint prop_id,
+				const GValue *value,
+				GParamSpec *param_spec);
+void ags_led_array_get_property(GObject *gobject,
+				guint prop_id,
+				GValue *value,
+				GParamSpec *param_spec);
+
+/**
+ * SECTION:ags_led_array
+ * @short_description: A led array widget
+ * @title: AgsLedArray
+ * @section_id:
+ * @include: ags/widget/ags_led_array.h
+ *
+ * #AgsLedArray is a widget representing an array of leds.
+ */
+
+enum{
+  PROP_0,
+  PROP_LED_WIDTH,
+  PROP_LED_HEIGHT,
+  PROP_LED_COUNT,
+};
+
+static gpointer ags_led_array_parent_class = NULL;
+
+GtkStyle *led_array_style;
+
+GType
+ags_led_array_get_type(void)
+{
+  static GType ags_type_led_array = 0;
+
+  if(!ags_type_led_array){
+    static const GTypeInfo ags_led_array_info = {
+      sizeof(AgsLedArrayClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_led_array_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof(AgsLedArray),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_led_array_init,
+    };
+
+    ags_type_led_array = g_type_register_static(GTK_TYPE_ALIGNMENT,
+						"AgsLedArray\0",
+						&ags_led_array_info,
+						0);
+  }
+
+  return(ags_type_led_array);
+}
+
+void
+ags_led_array_class_init(AgsLedArrayClass *led_array)
+{
+  GObjectClass *gobject;
+  GParamSpec *param_spec;
+
+  ags_led_array_parent_class = g_type_class_peek_parent(led_array);
+
+  /* GObjectClass */
+  gobject = (GObjectClass *) led_array;
+
+  gobject->set_property = ags_led_array_set_property;
+  gobject->get_property = ags_led_array_get_property;
+
+  /* properties */
+  /**
+   * AgsLedArray:led-width:
+   *
+   * The width of one led.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_uint("led-width\0",
+				 "width of led\0",
+				 "The width of one led\0",
+				 0,
+				 G_MAXUINT,
+				 0,
+				 G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_LED_WIDTH,
+				  param_spec);
+
+  /**
+   * AgsLedArray:led-height:
+   *
+   * The height of one led.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_uint("led-height\0",
+				 "height of led\0",
+				 "The height of one led\0",
+				 0,
+				 G_MAXUINT,
+				 0,
+				 G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_LED_HEIGHT,
+				  param_spec);
+
+  /**
+   * AgsLedArray:led-count:
+   *
+   * The count of leds available.
+   * 
+   * Since: 0.7.122.7
+   */
+  param_spec = g_param_spec_uint("led-count\0",
+				 "count of leds\0",
+				 "The count of leds available\0",
+				 0,
+				 G_MAXUINT,
+				 0,
+				 G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_LED_COUNT,
+				  param_spec);
+}
+
+void
+ags_led_array_init(AgsLedArray *led_array)
+{
+  gtk_widget_set_style((GtkWidget *) led_array,
+		       led_array_style);
+
+  led_array->led_width = 12;
+  led_array->led_height = 10;
+  
+  led_array->led = NULL;
+  led_array->led_count = 0;
+}
+
+void
+ags_led_array_set_property(GObject *gobject,
+			   guint prop_id,
+			   const GValue *value,
+			   GParamSpec *param_spec)
+{
+  AgsLedArray *led_array;
+
+  led_array = AGS_LED_ARRAY(gobject);
+
+  switch(prop_id){
+  case PROP_LED_COUNT:
+    {
+      guint led_count;
+      
+      led_count = g_value_get_uint(value);
+
+      ags_led_array_set_led_count(led_array,
+				  led_count);
+    }
+    break;
+  case PROP_LED_WIDTH:
+    {
+      guint led_width;
+      
+      led_array->led_width = g_value_get_uint(value);
+    }
+    break;
+  case PROP_LED_HEIGHT:
+    {
+      guint led_height;
+      
+      led_array->led_height = g_value_get_uint(value);
+    }
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  }
+}
+
+void
+ags_led_array_get_property(GObject *gobject,
+			   guint prop_id,
+			   GValue *value,
+			   GParamSpec *param_spec)
+{
+  AgsLedArray *led_array;
+
+  led_array = AGS_LED_ARRAY(gobject);
+
+  switch(prop_id){
+  case PROP_LED_COUNT:
+    {
+      g_value_set_uint(value, led_array->led_count);
+    }
+    break;
+  case PROP_LED_WIDTH:
+    {
+      g_value_set_uint(value, led_array->led_width);
+    }
+    break;
+  case PROP_LED_HEIGHT:
+    {
+      g_value_set_uint(value, led_array->led_height);
+    }
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  }
+}
+
+void
+ags_led_array_set_led_count(AgsLedArray *led_array,
+			    guint led_count)
+{
+  guint i;
+  
+  if(led_array == NULL ||
+     led_array->led_count == led_count){
+    return;
+  }
+
+  if(led_count < led_array->led_count){
+    /* shrink */
+    for(i = led_count; i < led_array->led_count; i++){
+      gtk_widget_destroy(led_array->led[i]);
+    }
+
+    if(led_array->led == NULL){
+      led_array->led = (AgsLed **) malloc(led_count * sizeof(AgsLed *));
+    }else{
+      led_array->led = (AgsLed **) realloc(led_array->led,
+					   led_count * sizeof(AgsLed *));
+    }
+  }else{
+    /* grow */
+    if(led_array->led == NULL){
+      led_array->led = (AgsLed **) malloc(led_count * sizeof(AgsLed *));
+    }else{
+      led_array->led = (AgsLed **) realloc(led_array->led,
+					   led_count * sizeof(AgsLed *));
+    }
+    
+    for(i = led_array->led_count; i < led_count; i++){
+      led_array->led[i] = ags_led_new();
+      gtk_widget_set_size_request((GtkWidget *) led_array->led[i],
+				  led_array->led_width, led_array->led_height);
+      gtk_box_pack_start(led_array->box,
+			 led_array->led[i],
+			 TRUE, FALSE,
+			 0);
+      gtk_widget_show(led_array->led[i]);
+    }
+  }
+
+  led_array->led_count = led_count;
+}
+
+void
+ags_led_array_unset_all(AgsLedArray *led_array)
+{
+  guint i;
+
+  if(led_array == NULL){
+    return;
+  }
+  
+  for(i = 0; i < led_array->led_count; i++){
+    ags_led_unset_active(led_array->led[i]);
+  }
+}
+
+void
+ags_led_array_set_nth(AgsLedArray *led_array,
+		      guint nth)
+{
+  if(led_array == NULL ||
+     nth >= led_array->led_count){
+    return;
+  }
+  
+  ags_led_set_active(led_array->led[nth]);
+}
+
+/**
+ * ags_led_array_new:
+ *
+ * Creates an #AgsLedArray. Note, use rather its implementation #AgsVLedArray or
+ * #AgsHLedArray.
+ *
+ * Returns: a new #AgsLedArray
+ *
+ * Since: 0.7.122.7
+ */
+AgsLedArray*
+ags_led_array_new()
+{
+  AgsLedArray *led_array;
+
+  led_array = (AgsLedArray *) g_object_new(AGS_TYPE_LED_ARRAY,
+					   NULL);
+  
+  return(led_array);
+}
diff --git a/ags/widget/ags_led_array.h b/ags/widget/ags_led_array.h
new file mode 100644
index 0000000..81cba90
--- /dev/null
+++ b/ags/widget/ags_led_array.h
@@ -0,0 +1,75 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_LED_ARRAY_H__
+#define __AGS_LED_ARRAY_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+#include "ags_led.h"
+
+#define AGS_TYPE_LED_ARRAY                (ags_led_array_get_type())
+#define AGS_LED_ARRAY(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_LED_ARRAY, AgsLedArray))
+#define AGS_LED_ARRAY_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_LED_ARRAY, AgsLedArrayClass))
+#define AGS_IS_LED_ARRAY(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), AGS_TYPE_LED_ARRAY))
+#define AGS_IS_LED_ARRAY_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_LED_ARRAY))
+#define AGS_LED_ARRAY_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_LED_ARRAY, AgsLedArrayClass))
+
+typedef struct _AgsLedArray AgsLedArray;
+typedef struct _AgsLedArrayClass AgsLedArrayClass;
+
+typedef enum{
+  AGS_LED_ARRAY_ACTIVE        = 1,
+}AgsLedArrayFlags;
+
+struct _AgsLedArray
+{
+  GtkAlignment alignment;
+
+  guint flags;
+
+  GtkBox *box;
+
+  guint led_width;
+  guint led_height;
+  
+  AgsLed **led;
+  guint led_count;
+};
+
+struct _AgsLedArrayClass
+{
+  GtkAlignmentClass alignment;
+};
+
+GType ags_led_array_get_type(void);
+
+void ags_led_array_set_led_count(AgsLedArray *led_array,
+				 guint led_count);
+
+void ags_led_array_unset_all(AgsLedArray *led_array);
+void ags_led_array_set_nth(AgsLedArray *led_array,
+			   guint nth);
+
+AgsLedArray* ags_led_array_new();
+
+#endif /*__AGS_LED_ARRAY_H__*/
diff --git a/ags/widget/ags_vindicator.c b/ags/widget/ags_vindicator.c
index bf0ebb7..1bf20a0 100644
--- a/ags/widget/ags_vindicator.c
+++ b/ags/widget/ags_vindicator.c
@@ -131,6 +131,10 @@ ags_vindicator_draw(AgsVIndicator *indicator)
   
   adjustment = AGS_INDICATOR(indicator)->adjustment;
 
+  if(adjustment == NULL){
+    return;
+  }
+  
   //  g_message("draw %f\0", adjustment->value);
 
   cr = gdk_cairo_create(widget->window);
diff --git a/ags/widget/ags_vindicator.h b/ags/widget/ags_vindicator.h
index cd34f1e..5d789be 100644
--- a/ags/widget/ags_vindicator.h
+++ b/ags/widget/ags_vindicator.h
@@ -22,16 +22,17 @@
 
 #include <glib.h>
 #include <glib-object.h>
+
 #include <gtk/gtk.h>
 
 #include "ags_indicator.h"
 
 #define AGS_TYPE_VINDICATOR                (ags_vindicator_get_type())
-#define AGS_VINDICATOR(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_INDICATOR, AgsVIndicator))
-#define AGS_VINDICATOR_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_INDICATOR, AgsVIndicatorClass))
-#define AGS_IS_VINDICATOR(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), AGS_TYPE_INDICATOR))
-#define AGS_IS_VINDICATOR_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_INDICATOR))
-#define AGS_VINDICATOR_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_INDICATOR, AgsVIndicatorClass))
+#define AGS_VINDICATOR(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_VINDICATOR, AgsVIndicator))
+#define AGS_VINDICATOR_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_VINDICATOR, AgsVIndicatorClass))
+#define AGS_IS_VINDICATOR(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), AGS_TYPE_VINDICATOR))
+#define AGS_IS_VINDICATOR_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_VINDICATOR))
+#define AGS_VINDICATOR_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_VINDICATOR, AgsVIndicatorClass))
 
 typedef struct _AgsVIndicator AgsVIndicator;
 typedef struct _AgsVIndicatorClass AgsVIndicatorClass;
@@ -43,7 +44,7 @@ struct _AgsVIndicator
 
 struct _AgsVIndicatorClass
 {
-  GtkWidgetClass indicator;
+  AgsIndicatorClass indicator;
 };
 
 GType ags_vindicator_get_type(void);
diff --git a/ags/widget/ags_vled_array.c b/ags/widget/ags_vled_array.c
new file mode 100644
index 0000000..05cb5b7
--- /dev/null
+++ b/ags/widget/ags_vled_array.c
@@ -0,0 +1,98 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ags_vled_array.h"
+
+void ags_vled_array_class_init(AgsVLedArrayClass *vled_array);
+void ags_vled_array_init(AgsVLedArray *vled_array);
+
+/**
+ * SECTION:ags_vled_array
+ * @short_description: A vertical led array widget
+ * @title: AgsVLedArray
+ * @section_id:
+ * @include: ags/widget/ags_vled_array.h
+ *
+ * #AgsVLedArray is a widget representing an array of vertical leds.
+ */
+
+static gpointer ags_vled_array_parent_class = NULL;
+
+GType
+ags_vled_array_get_type(void)
+{
+  static GType ags_type_vled_array = 0;
+
+  if(!ags_type_vled_array){
+    static const GTypeInfo ags_vled_array_info = {
+      sizeof(AgsVLedArrayClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_vled_array_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof(AgsVLedArray),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_vled_array_init,
+    };
+
+    ags_type_vled_array = g_type_register_static(AGS_TYPE_LED_ARRAY,
+						 "AgsVLedArray\0",
+						 &ags_vled_array_info,
+						 0);
+  }
+
+  return(ags_type_vled_array);
+}
+
+void
+ags_vled_array_class_init(AgsVLedArrayClass *vled_array)
+{
+  /* empty */
+}
+
+void
+ags_vled_array_init(AgsVLedArray *vled_array)
+{
+  AGS_LED_ARRAY(vled_array)->box = gtk_vbox_new(FALSE,
+						0);
+  gtk_container_add(vled_array,
+		    AGS_LED_ARRAY(vled_array)->box);
+  gtk_widget_show(AGS_LED_ARRAY(vled_array)->box);
+}
+
+/**
+ * ags_vled_array_new:
+ *
+ * Creates an #AgsVLedArray.
+ *
+ * Returns: a new #AgsVLedArray
+ *
+ * Since: 0.7.122.7
+ */
+AgsVLedArray*
+ags_vled_array_new()
+{
+  AgsVLedArray *vled_array;
+
+  vled_array = (AgsVLedArray *) g_object_new(AGS_TYPE_VLED_ARRAY,
+					     NULL);
+  
+  return(vled_array);
+}
diff --git a/ags/widget/ags_vled_array.h b/ags/widget/ags_vled_array.h
new file mode 100644
index 0000000..5b5f3a8
--- /dev/null
+++ b/ags/widget/ags_vled_array.h
@@ -0,0 +1,54 @@
+/* GSequencer - Advanced GTK Sequencer
+ * Copyright (C) 2005-2017 Joël Krähemann
+ *
+ * This file is part of GSequencer.
+ *
+ * GSequencer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AGS_VLED_ARRAY_H__
+#define __AGS_VLED_ARRAY_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+#include "ags_led_array.h"
+
+#define AGS_TYPE_VLED_ARRAY                (ags_vled_array_get_type())
+#define AGS_VLED_ARRAY(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_VLED_ARRAY, AgsVLedArray))
+#define AGS_VLED_ARRAY_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_VLED_ARRAY, AgsVLedArrayClass))
+#define AGS_IS_VLED_ARRAY(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), AGS_TYPE_VLED_ARRAY))
+#define AGS_IS_VLED_ARRAY_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_VLED_ARRAY))
+#define AGS_VLED_ARRAY_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_VLED_ARRAY, AgsVLedArrayClass))
+
+typedef struct _AgsVLedArray AgsVLedArray;
+typedef struct _AgsVLedArrayClass AgsVLedArrayClass;
+
+struct _AgsVLedArray
+{
+  AgsLedArray led_array;
+};
+
+struct _AgsVLedArrayClass
+{
+  AgsLedArrayClass led_array;
+};
+
+GType ags_vled_array_get_type(void);
+
+AgsVLedArray* ags_vled_array_new();
+
+#endif /*__AGS_VLED_ARRAY_H__*/
diff --git a/ags_functional_note_edit_test.xml b/ags_functional_note_edit_test.xml
new file mode 100644
index 0000000..a730042
--- /dev/null
+++ b/ags_functional_note_edit_test.xml
@@ -0,0 +1,1451 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ags-simple-file id="47f08086-140a-11e7-8e46-24be05e12b31" version="0.7.122.12" build-id="CEST 13-10-2015 04:33">
+  <ags-sf-config id="47f0819e-140a-11e7-8e46-24be05e12b31" version="0.7.0" build-id="CEST 13-10-2015 01:19"><![CDATA[[generic]
+disable-feature=experimental
+autosave-thread=false
+segmentation=4/4
+engine-mode=performance
+
+[soundcard-0]
+backend=alsa
+buffer-size=1024
+pcm-channels=2
+format=16
+samplerate=44100
+device=hw:0,0
+
+[thread]
+model=super-threaded
+super-threaded-scope=channel
+lock-global=ags-thread
+lock-parent=ags-recycling-thread
+
+[recall]
+auto-sense=true
+]]></ags-sf-config>
+  <ags-sf-window filename="/home/joelkraehemann/nongnu/gsequencer/ags_functional_note_edit_test.xml" bpm="120.000000" loop="true" loop-start="0.000000" loop-end="4.000000">
+    <ags-sf-machine-list>
+      <ags-sf-machine id="47f08432-140a-11e7-8e46-24be05e12b31" type="AgsPanel" name="Default 0" soundcard-device="hw:0,0" bank_0="0" bank_1="0" channels="2" output-pads="1" input-pads="1">
+        <ags-sf-pad-list is-output="false">
+          <ags-sf-pad id="47f08586-140a-11e7-8e46-24be05e12b31" nth-pad="0" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f08630-140a-11e7-8e46-24be05e12b31" nth-line="0" soundcard-device="hw:0,0" is-grouped="true" link="xpath=//ags-sf-line[@id='47f0bd62-140a-11e7-8e46-24be05e12b31']">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkCheckButton" value="false" specifier="./muted[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f08b80-140a-11e7-8e46-24be05e12b31" nth-line="1" soundcard-device="hw:0,0" is-grouped="true" link="xpath=//ags-sf-line[@id='47f0be66-140a-11e7-8e46-24be05e12b31']">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkCheckButton" value="false" specifier="./muted[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+        </ags-sf-pad-list>
+        <ags-sf-notation-list>
+          <ags-sf-notation channel="0"/>
+          <ags-sf-notation channel="1"/>
+        </ags-sf-notation-list>
+      </ags-sf-machine>
+      <ags-sf-machine id="47f094ae-140a-11e7-8e46-24be05e12b31" type="AgsMixer" name="Default 0" soundcard-device="hw:0,0" bank_0="0" bank_1="0" channels="2" output-pads="1" input-pads="8">
+        <ags-sf-pad-list is-output="false">
+          <ags-sf-pad id="47f095b2-140a-11e7-8e46-24be05e12b31" nth-pad="0" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f09634-140a-11e7-8e46-24be05e12b31" nth-line="0" soundcard-device="hw:0,0" is-grouped="true" link="xpath=//ags-sf-line[@id='47f11672-140a-11e7-8e46-24be05e12b31']">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="0.174000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f09a1c-140a-11e7-8e46-24be05e12b31" nth-line="1" soundcard-device="hw:0,0" is-grouped="true" link="xpath=//ags-sf-line[@id='47f1178a-140a-11e7-8e46-24be05e12b31']">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="0.174000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f09cd8-140a-11e7-8e46-24be05e12b31" nth-pad="1" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f09d6e-140a-11e7-8e46-24be05e12b31" nth-line="2" soundcard-device="hw:0,0" is-grouped="true" link="xpath=//ags-sf-line[@id='47f144c6-140a-11e7-8e46-24be05e12b31']">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="0.261000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0a3cc-140a-11e7-8e46-24be05e12b31" nth-line="3" soundcard-device="hw:0,0" is-grouped="true" link="xpath=//ags-sf-line[@id='47f14688-140a-11e7-8e46-24be05e12b31']">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="0.261000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0a5d4-140a-11e7-8e46-24be05e12b31" nth-pad="2" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0a688-140a-11e7-8e46-24be05e12b31" nth-line="4" soundcard-device="hw:0,0" is-grouped="true" link="xpath=//ags-sf-line[@id='47f167a8-140a-11e7-8e46-24be05e12b31']">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="0.217000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0a926-140a-11e7-8e46-24be05e12b31" nth-line="5" soundcard-device="hw:0,0" is-grouped="true" link="xpath=//ags-sf-line[@id='47f1688e-140a-11e7-8e46-24be05e12b31']">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="0.217000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0ab74-140a-11e7-8e46-24be05e12b31" nth-pad="3" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0ac28-140a-11e7-8e46-24be05e12b31" nth-line="6" soundcard-device="hw:0,0" is-grouped="true">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0adfe-140a-11e7-8e46-24be05e12b31" nth-line="7" soundcard-device="hw:0,0" is-grouped="true">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0af48-140a-11e7-8e46-24be05e12b31" nth-pad="4" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0aff2-140a-11e7-8e46-24be05e12b31" nth-line="8" soundcard-device="hw:0,0" is-grouped="true">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0b16e-140a-11e7-8e46-24be05e12b31" nth-line="9" soundcard-device="hw:0,0" is-grouped="true">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0b2ae-140a-11e7-8e46-24be05e12b31" nth-pad="5" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0b33a-140a-11e7-8e46-24be05e12b31" nth-line="10" soundcard-device="hw:0,0" is-grouped="true">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0b4ca-140a-11e7-8e46-24be05e12b31" nth-line="11" soundcard-device="hw:0,0" is-grouped="true">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0b60a-140a-11e7-8e46-24be05e12b31" nth-pad="6" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0b696-140a-11e7-8e46-24be05e12b31" nth-line="12" soundcard-device="hw:0,0" is-grouped="true">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0b812-140a-11e7-8e46-24be05e12b31" nth-line="13" soundcard-device="hw:0,0" is-grouped="true">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0b9a2-140a-11e7-8e46-24be05e12b31" nth-pad="7" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0ba2e-140a-11e7-8e46-24be05e12b31" nth-line="14" soundcard-device="hw:0,0" is-grouped="true">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0bbaa-140a-11e7-8e46-24be05e12b31" nth-line="15" soundcard-device="hw:0,0" is-grouped="true">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+        </ags-sf-pad-list>
+        <ags-sf-pad-list is-output="true">
+          <ags-sf-pad nth-pad="0">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0bd62-140a-11e7-8e46-24be05e12b31" nth-line="0" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f08630-140a-11e7-8e46-24be05e12b31']"/>
+              <ags-sf-line id="47f0be66-140a-11e7-8e46-24be05e12b31" nth-line="1" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f08b80-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+        </ags-sf-pad-list>
+        <ags-sf-notation-list>
+          <ags-sf-notation channel="0"/>
+          <ags-sf-notation channel="1"/>
+        </ags-sf-notation-list>
+        <ags-sf-automation-list>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="void" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="14" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="14" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="14" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="14" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="15" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="15" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="15" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="15" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="12" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="12" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="12" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="12" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="13" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="13" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="13" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="13" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="10" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="10" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="10" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="10" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="11" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="11" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="11" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="11" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="8" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="8" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="8" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="8" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="9" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="9" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="9" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="9" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="6" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="6" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="6" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="6" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="7" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="7" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="7" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="7" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="4" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="4" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="4" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="4" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="5" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="5" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="5" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="5" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="2" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="2" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="2" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="2" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="3" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="3" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="3" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="3" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="1" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="1" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="1" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="1" channel-type="AgsInput" control-name="./muted[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+        </ags-sf-automation-list>
+      </ags-sf-machine>
+      <ags-sf-machine id="47f0d734-140a-11e7-8e46-24be05e12b31" type="AgsDrum" name="Default 0" soundcard-device="hw:0,0" bank_0="0" bank_1="0" reverse-mapping="true" channels="2" output-pads="1" input-pads="16" length="16">
+        <ags-sf-pad-list is-output="false">
+          <ags-sf-pad id="47f0d874-140a-11e7-8e46-24be05e12b31" nth-pad="0" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0d932-140a-11e7-8e46-24be05e12b31" nth-line="0" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/909_xOver_1.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0db58-140a-11e7-8e46-24be05e12b31" nth-line="1" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/909_xOver_1.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0dd2e-140a-11e7-8e46-24be05e12b31" nth-pad="1" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0dda6-140a-11e7-8e46-24be05e12b31" nth-line="2" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/am_sine_01_2.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0df68-140a-11e7-8e46-24be05e12b31" nth-line="3" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/am_sine_01_2.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0e12a-140a-11e7-8e46-24be05e12b31" nth-pad="2" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0e1ca-140a-11e7-8e46-24be05e12b31" nth-line="4" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/chh_01.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0e396-140a-11e7-8e46-24be05e12b31" nth-line="5" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/chh_01.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0e544-140a-11e7-8e46-24be05e12b31" nth-pad="3" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0e5c6-140a-11e7-8e46-24be05e12b31" nth-line="6" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/chh_02.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0e788-140a-11e7-8e46-24be05e12b31" nth-line="7" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/chh_02.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0e918-140a-11e7-8e46-24be05e12b31" nth-pad="4" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0e99a-140a-11e7-8e46-24be05e12b31" nth-line="8" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/drum_01.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0eb34-140a-11e7-8e46-24be05e12b31" nth-line="9" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/drum_01.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0ecc4-140a-11e7-8e46-24be05e12b31" nth-pad="5" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0ed3c-140a-11e7-8e46-24be05e12b31" nth-line="10" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/drum_08_01.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0eeea-140a-11e7-8e46-24be05e12b31" nth-line="11" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/drum_08_01.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0f07a-140a-11e7-8e46-24be05e12b31" nth-pad="6" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0f0fc-140a-11e7-8e46-24be05e12b31" nth-line="12" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/fx_18-2.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0f28c-140a-11e7-8e46-24be05e12b31" nth-line="13" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/fx_18-2.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0f41c-140a-11e7-8e46-24be05e12b31" nth-pad="7" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0f49e-140a-11e7-8e46-24be05e12b31" nth-line="14" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/juno6_ohh_soft.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0f656-140a-11e7-8e46-24be05e12b31" nth-line="15" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/juno6_ohh_soft.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0f7f0-140a-11e7-8e46-24be05e12b31" nth-pad="8" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0f87c-140a-11e7-8e46-24be05e12b31" nth-line="16" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/juno6_perc_01.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0fa16-140a-11e7-8e46-24be05e12b31" nth-line="17" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/juno6_perc_01.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0fbb0-140a-11e7-8e46-24be05e12b31" nth-pad="9" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0fc32-140a-11e7-8e46-24be05e12b31" nth-line="18" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/juno6_xO_7.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f0fdea-140a-11e7-8e46-24be05e12b31" nth-line="19" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/juno6_xO_7.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f0ff7a-140a-11e7-8e46-24be05e12b31" nth-pad="10" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f0fffc-140a-11e7-8e46-24be05e12b31" nth-line="20" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/sim_k02-0.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f10196-140a-11e7-8e46-24be05e12b31" nth-line="21" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/sim_k02-0.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f10330-140a-11e7-8e46-24be05e12b31" nth-pad="11" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f103b2-140a-11e7-8e46-24be05e12b31" nth-line="22" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/sw_01.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f10556-140a-11e7-8e46-24be05e12b31" nth-line="23" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/sw_01.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f106fa-140a-11e7-8e46-24be05e12b31" nth-pad="12" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f1077c-140a-11e7-8e46-24be05e12b31" nth-line="24" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/synth_01.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f10916-140a-11e7-8e46-24be05e12b31" nth-line="25" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/synth_01.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f10aa6-140a-11e7-8e46-24be05e12b31" nth-pad="13" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f10b28-140a-11e7-8e46-24be05e12b31" nth-line="26" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/tom_01.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f10cb8-140a-11e7-8e46-24be05e12b31" nth-line="27" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/tom_01.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f10e48-140a-11e7-8e46-24be05e12b31" nth-pad="14" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f10eca-140a-11e7-8e46-24be05e12b31" nth-line="28" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/xp909_clap1.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f1108c-140a-11e7-8e46-24be05e12b31" nth-line="29" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/xp909_clap1.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f11226-140a-11e7-8e46-24be05e12b31" nth-pad="15" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f112a8-140a-11e7-8e46-24be05e12b31" nth-line="30" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/xp909_tom1.wav" file-channel="0">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+              <ags-sf-line id="47f1142e-140a-11e7-8e46-24be05e12b31" nth-line="31" soundcard-device="hw:0,0" is-grouped="true" filename="file:///usr/share/hydrogen/data/drumkits/Synthie-1/xp909_tom1.wav" file-channel="1">
+                <ags-sf-effect-list>
+                  <ags-sf-effect filename="" effect="">
+                    <ags-sf-control control-type="GtkVScale" value="1.000000" specifier="./volume[0]"/>
+                  </ags-sf-effect>
+                </ags-sf-effect-list>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+        </ags-sf-pad-list>
+        <ags-sf-pad-list is-output="true">
+          <ags-sf-pad id="47f115d2-140a-11e7-8e46-24be05e12b31" nth-pad="0" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f11672-140a-11e7-8e46-24be05e12b31" nth-line="0" soundcard-device="hw:0,0" is-grouped="true" link="xpath=//ags-sf-line[@id='47f09634-140a-11e7-8e46-24be05e12b31']"/>
+              <ags-sf-line id="47f1178a-140a-11e7-8e46-24be05e12b31" nth-line="1" soundcard-device="hw:0,0" is-grouped="true" link="xpath=//ags-sf-line[@id='47f09a1c-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+        </ags-sf-pad-list>
+        <ags-sf-notation-list>
+          <ags-sf-notation channel="0">
+            <ags-sf-note x0="0" x1="1" y="0"/>
+            <ags-sf-note x0="8" x1="9" y="0"/>
+            <ags-sf-note x0="16" x1="17" y="0"/>
+            <ags-sf-note x0="24" x1="25" y="0"/>
+            <ags-sf-note x0="32" x1="33" y="0"/>
+            <ags-sf-note x0="40" x1="41" y="0"/>
+            <ags-sf-note x0="48" x1="49" y="0"/>
+            <ags-sf-note x0="56" x1="57" y="0"/>
+          </ags-sf-notation>
+          <ags-sf-notation channel="1">
+            <ags-sf-note x0="0" x1="1" y="0"/>
+            <ags-sf-note x0="8" x1="9" y="0"/>
+            <ags-sf-note x0="16" x1="17" y="0"/>
+            <ags-sf-note x0="24" x1="25" y="0"/>
+            <ags-sf-note x0="32" x1="33" y="0"/>
+            <ags-sf-note x0="40" x1="41" y="0"/>
+            <ags-sf-note x0="48" x1="49" y="0"/>
+            <ags-sf-note x0="56" x1="57" y="0"/>
+          </ags-sf-notation>
+        </ags-sf-notation-list>
+        <ags-sf-automation-list>
+          <ags-sf-automation line="30" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="30" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="31" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="31" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="28" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="28" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="29" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="29" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="26" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="26" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="27" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="27" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="24" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="24" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="25" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="25" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="22" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="22" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="23" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="23" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="20" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="20" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="21" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="21" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="18" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="18" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="19" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="19" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="16" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="16" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="17" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="17" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="14" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="14" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="15" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="15" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="12" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="12" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="13" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="13" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="10" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="10" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="11" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="11" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="8" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="8" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="9" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="9" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="6" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="6" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="7" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="7" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="4" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="4" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="5" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="5" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="2" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="2" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="3" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="3" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="0" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="1" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+          <ags-sf-automation line="1" channel-type="AgsInput" control-name="./volume[0]">
+            <ags-sf-acceleration x="0" y="0.000000"/>
+            <ags-sf-acceleration x="1228800" y="0.000000"/>
+          </ags-sf-automation>
+        </ags-sf-automation-list>
+      </ags-sf-machine>
+      <ags-sf-machine id="47f12aa4-140a-11e7-8e46-24be05e12b31" type="AgsMatrix" name="Default 0" soundcard-device="hw:0,0" bank_0="0" bank_1="0" channels="1" output-pads="2" input-pads="16" length="16">
+        <ags-sf-pad-list is-output="false">
+          <ags-sf-pad nth-pad="0">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f12c0c-140a-11e7-8e46-24be05e12b31" nth-line="0" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f14e1c-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="1">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f12d06-140a-11e7-8e46-24be05e12b31" nth-line="1" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f15376-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="2">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f12e1e-140a-11e7-8e46-24be05e12b31" nth-line="2" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f154a2-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="3">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f12f04-140a-11e7-8e46-24be05e12b31" nth-line="3" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f15588-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="4">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f1301c-140a-11e7-8e46-24be05e12b31" nth-line="4" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f156a0-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="5">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f13102-140a-11e7-8e46-24be05e12b31" nth-line="5" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f15786-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="6">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f132e2-140a-11e7-8e46-24be05e12b31" nth-line="6" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f158b2-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="7">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f133e6-140a-11e7-8e46-24be05e12b31" nth-line="7" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f15984-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="8">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f134d6-140a-11e7-8e46-24be05e12b31" nth-line="8" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f15a9c-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="9">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f135f8-140a-11e7-8e46-24be05e12b31" nth-line="9" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f15b78-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="10">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f13706-140a-11e7-8e46-24be05e12b31" nth-line="10" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f15c90-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="11">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f13814-140a-11e7-8e46-24be05e12b31" nth-line="11" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f15d62-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="12">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f138fa-140a-11e7-8e46-24be05e12b31" nth-line="12" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f15e84-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="13">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f13a26-140a-11e7-8e46-24be05e12b31" nth-line="13" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f15f60-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="14">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f1400c-140a-11e7-8e46-24be05e12b31" nth-line="14" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f1606e-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="15">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f1414c-140a-11e7-8e46-24be05e12b31" nth-line="15" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f161a4-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+        </ags-sf-pad-list>
+        <ags-sf-pad-list is-output="true">
+          <ags-sf-pad nth-pad="0">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f144c6-140a-11e7-8e46-24be05e12b31" nth-line="0" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f09d6e-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="1">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f14688-140a-11e7-8e46-24be05e12b31" nth-line="1" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f0a3cc-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+        </ags-sf-pad-list>
+        <ags-sf-notation-list>
+          <ags-sf-notation channel="0">
+            <ags-sf-note x0="0" x1="1" y="9"/>
+            <ags-sf-note x0="4" x1="5" y="9"/>
+            <ags-sf-note x0="8" x1="9" y="9"/>
+            <ags-sf-note x0="12" x1="13" y="9"/>
+            <ags-sf-note x0="16" x1="17" y="9"/>
+            <ags-sf-note x0="20" x1="21" y="9"/>
+            <ags-sf-note x0="24" x1="25" y="8"/>
+            <ags-sf-note x0="28" x1="29" y="9"/>
+            <ags-sf-note x0="32" x1="33" y="9"/>
+            <ags-sf-note x0="36" x1="37" y="9"/>
+            <ags-sf-note x0="40" x1="41" y="9"/>
+            <ags-sf-note x0="44" x1="45" y="9"/>
+            <ags-sf-note x0="48" x1="49" y="9"/>
+            <ags-sf-note x0="52" x1="53" y="9"/>
+            <ags-sf-note x0="56" x1="57" y="8"/>
+            <ags-sf-note x0="60" x1="61" y="9"/>
+          </ags-sf-notation>
+        </ags-sf-notation-list>
+      </ags-sf-machine>
+      <ags-sf-machine id="47f149a8-140a-11e7-8e46-24be05e12b31" type="AgsSynth" name="Default 0" soundcard-device="hw:0,0" bank_0="0" bank_1="0" channels="1" output-pads="16" input-pads="2">
+        <ags-sf-pad-list is-output="false">
+          <ags-sf-pad id="47f14ad4-140a-11e7-8e46-24be05e12b31" nth-pad="0" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f14b56-140a-11e7-8e46-24be05e12b31" nth-line="0" soundcard-device="hw:0,0" is-grouped="true">
+                <ags-oscillator wave="0" attack="0.000000" length="3200.000000" frequency="27.500000" phase="0.000000" volume="0.200000"/>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad id="47f14c6e-140a-11e7-8e46-24be05e12b31" nth-pad="1" group="true" mute="false" solo="false">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f14d18-140a-11e7-8e46-24be05e12b31" nth-line="1" soundcard-device="hw:0,0" is-grouped="true">
+                <ags-oscillator wave="0" attack="0.000000" length="3200.000000" frequency="27.500000" phase="0.000000" volume="0.200000"/>
+              </ags-sf-line>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+        </ags-sf-pad-list>
+        <ags-sf-pad-list is-output="true">
+          <ags-sf-pad nth-pad="0">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f14e1c-140a-11e7-8e46-24be05e12b31" nth-line="0" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f12c0c-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="1">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f15376-140a-11e7-8e46-24be05e12b31" nth-line="1" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f12d06-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="2">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f154a2-140a-11e7-8e46-24be05e12b31" nth-line="2" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f12e1e-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="3">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f15588-140a-11e7-8e46-24be05e12b31" nth-line="3" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f12f04-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="4">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f156a0-140a-11e7-8e46-24be05e12b31" nth-line="4" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f1301c-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="5">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f15786-140a-11e7-8e46-24be05e12b31" nth-line="5" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f13102-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="6">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f158b2-140a-11e7-8e46-24be05e12b31" nth-line="6" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f132e2-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="7">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f15984-140a-11e7-8e46-24be05e12b31" nth-line="7" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f133e6-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="8">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f15a9c-140a-11e7-8e46-24be05e12b31" nth-line="8" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f134d6-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="9">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f15b78-140a-11e7-8e46-24be05e12b31" nth-line="9" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f135f8-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="10">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f15c90-140a-11e7-8e46-24be05e12b31" nth-line="10" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f13706-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="11">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f15d62-140a-11e7-8e46-24be05e12b31" nth-line="11" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f13814-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="12">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f15e84-140a-11e7-8e46-24be05e12b31" nth-line="12" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f138fa-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="13">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f15f60-140a-11e7-8e46-24be05e12b31" nth-line="13" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f13a26-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="14">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f1606e-140a-11e7-8e46-24be05e12b31" nth-line="14" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f1400c-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+          <ags-sf-pad nth-pad="15">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f161a4-140a-11e7-8e46-24be05e12b31" nth-line="15" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f1414c-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+        </ags-sf-pad-list>
+        <ags-sf-notation-list>
+          <ags-sf-notation channel="0"/>
+        </ags-sf-notation-list>
+      </ags-sf-machine>
+      <ags-sf-machine id="47f16294-140a-11e7-8e46-24be05e12b31" type="AgsFFPlayer" name="Default 0" soundcard-device="hw:0,0" bank_0="0" bank_1="0" reverse-mapping="true" channels="2" output-pads="1" input-pads="3" audio-start-mapping="0" audio-end-mapping="128" midi-start-mapping="0" midi-end-mapping="128" filename="/usr/share/sounds/sf2/FluidR3_GM.sf2" preset="Synth Brass 4" instrument="Synth Brass2/GS">
+        <ags-sf-pad-list is-output="true">
+          <ags-sf-pad nth-pad="0">
+            <ags-sf-line-list>
+              <ags-sf-line id="47f167a8-140a-11e7-8e46-24be05e12b31" nth-line="0" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f0a688-140a-11e7-8e46-24be05e12b31']"/>
+              <ags-sf-line id="47f1688e-140a-11e7-8e46-24be05e12b31" nth-line="1" soundcard-device="hw:0,0" link="xpath=//ags-sf-line[@id='47f0a926-140a-11e7-8e46-24be05e12b31']"/>
+            </ags-sf-line-list>
+          </ags-sf-pad>
+        </ags-sf-pad-list>
+        <ags-sf-notation-list>
+          <ags-sf-notation channel="0">
+            <ags-sf-note x0="0" x1="4" y="2"/>
+            <ags-sf-note x0="4" x1="8" y="0"/>
+            <ags-sf-note x0="8" x1="12" y="2"/>
+            <ags-sf-note x0="12" x1="16" y="1"/>
+            <ags-sf-note x0="16" x1="20" y="0"/>
+            <ags-sf-note x0="20" x1="24" y="2"/>
+            <ags-sf-note x0="24" x1="28" y="1"/>
+            <ags-sf-note x0="28" x1="32" y="2"/>
+            <ags-sf-note x0="32" x1="36" y="1"/>
+            <ags-sf-note x0="36" x1="40" y="0"/>
+            <ags-sf-note x0="40" x1="44" y="2"/>
+            <ags-sf-note x0="44" x1="48" y="1"/>
+            <ags-sf-note x0="48" x1="52" y="2"/>
+            <ags-sf-note x0="52" x1="56" y="0"/>
+            <ags-sf-note x0="56" x1="60" y="2"/>
+            <ags-sf-note x0="60" x1="64" y="1"/>
+          </ags-sf-notation>
+          <ags-sf-notation channel="1">
+            <ags-sf-note x0="0" x1="4" y="2"/>
+            <ags-sf-note x0="4" x1="8" y="0"/>
+            <ags-sf-note x0="8" x1="12" y="2"/>
+            <ags-sf-note x0="12" x1="16" y="1"/>
+            <ags-sf-note x0="16" x1="20" y="0"/>
+            <ags-sf-note x0="20" x1="24" y="2"/>
+            <ags-sf-note x0="24" x1="28" y="1"/>
+            <ags-sf-note x0="28" x1="32" y="2"/>
+            <ags-sf-note x0="32" x1="36" y="1"/>
+            <ags-sf-note x0="36" x1="40" y="0"/>
+            <ags-sf-note x0="40" x1="44" y="2"/>
+            <ags-sf-note x0="44" x1="48" y="1"/>
+            <ags-sf-note x0="48" x1="52" y="2"/>
+            <ags-sf-note x0="52" x1="56" y="0"/>
+            <ags-sf-note x0="56" x1="60" y="2"/>
+            <ags-sf-note x0="60" x1="64" y="1"/>
+          </ags-sf-notation>
+        </ags-sf-notation-list>
+      </ags-sf-machine>
+    </ags-sf-machine-list>
+    <ags-sf-editor zoom="1:4"/>
+    <ags-sf-automation-editor zoom="1:1"/>
+  </ags-sf-window>
+</ags-simple-file>
diff --git a/configure b/configure
index f471488..47196ef 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.69 for gsequencer 0.7.122.
+# Generated by GNU Autoconf 2.69 for gsequencer 0.7.122.16.
 #
 # Report bugs to <jkraehemann-guest at users.alioth.debian.org>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='gsequencer'
 PACKAGE_TARNAME='gsequencer'
-PACKAGE_VERSION='0.7.122'
-PACKAGE_STRING='gsequencer 0.7.122'
+PACKAGE_VERSION='0.7.122.16'
+PACKAGE_STRING='gsequencer 0.7.122.16'
 PACKAGE_BUGREPORT='jkraehemann-guest at users.alioth.debian.org'
 PACKAGE_URL=''
 
@@ -1436,7 +1436,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 gsequencer 0.7.122 to adapt to many kinds of systems.
+\`configure' configures gsequencer 0.7.122.16 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1511,7 +1511,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of gsequencer 0.7.122:";;
+     short | recursive ) echo "Configuration of gsequencer 0.7.122.16:";;
    esac
   cat <<\_ACEOF
 
@@ -1698,7 +1698,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-gsequencer configure 0.7.122
+gsequencer configure 0.7.122.16
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2175,7 +2175,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 gsequencer $as_me 0.7.122, which was
+It was created by gsequencer $as_me 0.7.122.16, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3041,7 +3041,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='gsequencer'
- VERSION='0.7.122'
+ VERSION='0.7.122.16'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -12881,7 +12881,7 @@ _ACEOF
 
 fi
 
-for ac_header in argz.h fcntl.h float.h inttypes.h langinfo.h libintl.h limits.h locale.h malloc.h netinet/in.h stddef.h stdint.h stdio_ext.h stdlib.h string.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h unistd.h gmp.h ladspa.h dssi.h lv2.h
+for ac_header in argz.h fcntl.h float.h inttypes.h langinfo.h libintl.h limits.h locale.h malloc.h netinet/in.h stddef.h stdint.h stdio_ext.h stdlib.h string.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h unistd.h ladspa.h dssi.h lv2.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -15849,10 +15849,8 @@ fi
 
 
 
-ac_config_files="$ac_config_files Makefile docs/reference/libags/Makefile docs/reference/libags_audio/Makefile docs/reference/libags_gui/Makefile libags.pc libags_audio.pc libags_gui.pc"
+ac_config_files="$ac_config_files Makefile docs/reference/libags/Makefile docs/reference/libags-audio/Makefile docs/reference/libags-gui/Makefile docs/reference/libgsequencer/Makefile libags.pc libags_audio.pc libags_gui.pc libgsequencer.pc"
 
-# docs/reference/libgsequencer/Makefile
-# libgsequencer.pc
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -16408,7 +16406,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by gsequencer $as_me 0.7.122, which was
+This file was extended by gsequencer $as_me 0.7.122.16, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -16474,7 +16472,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-gsequencer config.status 0.7.122
+gsequencer config.status 0.7.122.16
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -16891,11 +16889,13 @@ do
     "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
     "docs/reference/libags/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/libags/Makefile" ;;
-    "docs/reference/libags_audio/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/libags_audio/Makefile" ;;
-    "docs/reference/libags_gui/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/libags_gui/Makefile" ;;
+    "docs/reference/libags-audio/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/libags-audio/Makefile" ;;
+    "docs/reference/libags-gui/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/libags-gui/Makefile" ;;
+    "docs/reference/libgsequencer/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/libgsequencer/Makefile" ;;
     "libags.pc") CONFIG_FILES="$CONFIG_FILES libags.pc" ;;
     "libags_audio.pc") CONFIG_FILES="$CONFIG_FILES libags_audio.pc" ;;
     "libags_gui.pc") CONFIG_FILES="$CONFIG_FILES libags_gui.pc" ;;
+    "libgsequencer.pc") CONFIG_FILES="$CONFIG_FILES libgsequencer.pc" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
diff --git a/configure.ac b/configure.ac
index 226f5d5..762da5c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ([2.69])
-AC_INIT([gsequencer],[0.7.122],[jkraehemann-guest at users.alioth.debian.org])
+AC_INIT([gsequencer],[0.7.122.16],[jkraehemann-guest at users.alioth.debian.org])
 AM_INIT_AUTOMAKE([subdir-objects])
 AC_CONFIG_SRCDIR([config.h.in])
 AC_CONFIG_HEADERS([ags/config.h])
@@ -57,7 +57,7 @@ AC_CHECK_LIB([rt], [main])
 # Checks for header files.
 AC_PATH_X
 AC_FUNC_ALLOCA
-AC_CHECK_HEADERS([argz.h fcntl.h float.h inttypes.h langinfo.h libintl.h limits.h locale.h malloc.h netinet/in.h stddef.h stdint.h stdio_ext.h stdlib.h string.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h unistd.h gmp.h ladspa.h dssi.h lv2.h])
+AC_CHECK_HEADERS([argz.h fcntl.h float.h inttypes.h langinfo.h libintl.h limits.h locale.h malloc.h netinet/in.h stddef.h stdint.h stdio_ext.h stdlib.h string.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h unistd.h ladspa.h dssi.h lv2.h])
 
 # Checks for typedefs, structures, and compiler characteristics.
 AC_CHECK_HEADER_STDBOOL
@@ -187,12 +187,12 @@ AM_EXTRA_RECURSIVE_TARGETS([ags-docs])
 AC_CONFIG_FILES([
 Makefile
 docs/reference/libags/Makefile
-docs/reference/libags_audio/Makefile
-docs/reference/libags_gui/Makefile
+docs/reference/libags-audio/Makefile
+docs/reference/libags-gui/Makefile
+docs/reference/libgsequencer/Makefile
 libags.pc
 libags_audio.pc
-libags_gui.pc])
-# docs/reference/libgsequencer/Makefile
-# libgsequencer.pc
+libags_gui.pc
+libgsequencer.pc])
 
 AC_OUTPUT
diff --git a/docs/reference/libags_audio/Makefile.am b/docs/reference/libags-audio/Makefile.am
similarity index 100%
rename from docs/reference/libags_audio/Makefile.am
rename to docs/reference/libags-audio/Makefile.am
diff --git a/docs/reference/libags_audio/Makefile.in b/docs/reference/libags-audio/Makefile.in
similarity index 99%
rename from docs/reference/libags_audio/Makefile.in
rename to docs/reference/libags-audio/Makefile.in
index 58bb931..0496291 100644
--- a/docs/reference/libags_audio/Makefile.in
+++ b/docs/reference/libags-audio/Makefile.in
@@ -98,7 +98,7 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-subdir = docs/reference/libags_audio
+subdir = docs/reference/libags-audio
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \
 	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
@@ -686,9 +686,9 @@ $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am $(top_srcdir)/gtk-doc.make $(am__c
 	      exit 1;; \
 	  esac; \
 	done; \
-	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/reference/libags_audio/Makefile'; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/reference/libags-audio/Makefile'; \
 	$(am__cd) $(top_srcdir) && \
-	  $(AUTOMAKE) --gnu docs/reference/libags_audio/Makefile
+	  $(AUTOMAKE) --gnu docs/reference/libags-audio/Makefile
 Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
 	@case '$?' in \
 	  *config.status*) \
diff --git a/docs/reference/libags_audio/git.mk b/docs/reference/libags-audio/git.mk
similarity index 100%
rename from docs/reference/libags_audio/git.mk
rename to docs/reference/libags-audio/git.mk
diff --git a/docs/reference/libags_audio/gtk-doc.make b/docs/reference/libags-audio/gtk-doc.make
similarity index 100%
rename from docs/reference/libags_audio/gtk-doc.make
rename to docs/reference/libags-audio/gtk-doc.make
diff --git a/docs/reference/libags_audio/libags_audio-overrides.txt b/docs/reference/libags-audio/libags_audio-overrides.txt
similarity index 100%
rename from docs/reference/libags_audio/libags_audio-overrides.txt
rename to docs/reference/libags-audio/libags_audio-overrides.txt
diff --git a/docs/reference/libags_audio/libags_audio-sections.txt b/docs/reference/libags-audio/libags_audio-sections.txt
similarity index 100%
rename from docs/reference/libags_audio/libags_audio-sections.txt
rename to docs/reference/libags-audio/libags_audio-sections.txt
diff --git a/docs/reference/libags_audio/libags_audio.types b/docs/reference/libags-audio/libags_audio.types
similarity index 100%
rename from docs/reference/libags_audio/libags_audio.types
rename to docs/reference/libags-audio/libags_audio.types
diff --git a/docs/reference/libags_audio/libags_audio.xml b/docs/reference/libags-audio/libags_audio.xml
similarity index 100%
rename from docs/reference/libags_audio/libags_audio.xml
rename to docs/reference/libags-audio/libags_audio.xml
diff --git a/docs/reference/libags_gui/Makefile.am b/docs/reference/libags-gui/Makefile.am
similarity index 100%
rename from docs/reference/libags_gui/Makefile.am
rename to docs/reference/libags-gui/Makefile.am
diff --git a/docs/reference/libags_gui/Makefile.in b/docs/reference/libags-gui/Makefile.in
similarity index 99%
rename from docs/reference/libags_gui/Makefile.in
rename to docs/reference/libags-gui/Makefile.in
index 56cac00..444d38c 100644
--- a/docs/reference/libags_gui/Makefile.in
+++ b/docs/reference/libags-gui/Makefile.in
@@ -98,7 +98,7 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-subdir = docs/reference/libags_gui
+subdir = docs/reference/libags-gui
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \
 	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
@@ -683,9 +683,9 @@ $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am $(top_srcdir)/gtk-doc.make $(am__c
 	      exit 1;; \
 	  esac; \
 	done; \
-	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/reference/libags_gui/Makefile'; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/reference/libags-gui/Makefile'; \
 	$(am__cd) $(top_srcdir) && \
-	  $(AUTOMAKE) --gnu docs/reference/libags_gui/Makefile
+	  $(AUTOMAKE) --gnu docs/reference/libags-gui/Makefile
 Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
 	@case '$?' in \
 	  *config.status*) \
diff --git a/docs/reference/libags_gui/git.mk b/docs/reference/libags-gui/git.mk
similarity index 100%
rename from docs/reference/libags_gui/git.mk
rename to docs/reference/libags-gui/git.mk
diff --git a/docs/reference/libags_gui/gtk-doc.make b/docs/reference/libags-gui/gtk-doc.make
similarity index 100%
rename from docs/reference/libags_gui/gtk-doc.make
rename to docs/reference/libags-gui/gtk-doc.make
diff --git a/docs/reference/libags_gui/libags_gui-overrides.txt b/docs/reference/libags-gui/libags_gui-overrides.txt
similarity index 100%
rename from docs/reference/libags_gui/libags_gui-overrides.txt
rename to docs/reference/libags-gui/libags_gui-overrides.txt
diff --git a/docs/reference/libags_gui/libags_gui-sections.txt b/docs/reference/libags-gui/libags_gui-sections.txt
similarity index 100%
rename from docs/reference/libags_gui/libags_gui-sections.txt
rename to docs/reference/libags-gui/libags_gui-sections.txt
diff --git a/docs/reference/libags_gui/libags_gui.types b/docs/reference/libags-gui/libags_gui.types
similarity index 100%
rename from docs/reference/libags_gui/libags_gui.types
rename to docs/reference/libags-gui/libags_gui.types
diff --git a/docs/reference/libags_gui/libags_gui.xml b/docs/reference/libags-gui/libags_gui.xml
similarity index 91%
rename from docs/reference/libags_gui/libags_gui.xml
rename to docs/reference/libags-gui/libags_gui.xml
index 67f4c35..0bebbdf 100644
--- a/docs/reference/libags_gui/libags_gui.xml
+++ b/docs/reference/libags-gui/libags_gui.xml
@@ -23,15 +23,14 @@
     <xi:include href="xml/ags_dial.xml"/>
     <xi:include href="xml/ags_expander.xml"/>
     <xi:include href="xml/ags_expander_set.xml"/>
-    <xi:include href="xml/ags_hindicator.xml"/>
-    <xi:include href="xml/ags_htimebar.xml"/>
     <xi:include href="xml/ags_indicator.xml"/>
+    <xi:include href="xml/ags_hindicator.xml"/>
+    <xi:include href="xml/ags_vindicator.xml"/>
     <xi:include href="xml/ags_led.xml"/>
     <xi:include href="xml/ags_ruler.xml"/>
-    <xi:include href="xml/ags_table.xml"/>
-    <xi:include href="xml/ags_timebar.xml"/>
-    <xi:include href="xml/ags_vindicator.xml"/>
-    <xi:include href="xml/ags_waveform.xml"/>
+    <xi:include href="xml/ags_led_array.xml"/>
+    <xi:include href="xml/ags_hled_array.xml"/>
+    <xi:include href="xml/ags_vled_array.xml"/>
   </chapter>
   
   <chapter id="object-tree">
diff --git a/docs/reference/libgsequencer/Makefile.am b/docs/reference/libgsequencer/Makefile.am
index d88001d..9393fd1 100644
--- a/docs/reference/libgsequencer/Makefile.am
+++ b/docs/reference/libgsequencer/Makefile.am
@@ -34,7 +34,7 @@ MKHTML_OPTIONS=
 
 # Extra options to supply to gtkdoc-fixref. Normally not needed.
 # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
-FIXXREF_OPTIONS=
+FIXXREF_OPTIONS=--extra-dir=../libags/html --extra-dir=../libags-audio/html --extra-dir=../libags-gui/html
 
 # Used for dependencies. The docs will be rebuilt if any of these change.
 # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
diff --git a/docs/reference/libgsequencer/Makefile.in b/docs/reference/libgsequencer/Makefile.in
index 159b0af..78bf109 100644
--- a/docs/reference/libgsequencer/Makefile.in
+++ b/docs/reference/libgsequencer/Makefile.in
@@ -432,6 +432,8 @@ PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 RANLIB = @RANLIB@
+SAMPLERATE_CFLAGS = @SAMPLERATE_CFLAGS@
+SAMPLERATE_LIBS = @SAMPLERATE_LIBS@
 SED = @SED@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
@@ -535,7 +537,7 @@ MKHTML_OPTIONS =
 
 # Extra options to supply to gtkdoc-fixref. Normally not needed.
 # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
-FIXXREF_OPTIONS = 
+FIXXREF_OPTIONS = --extra-dir=../libags/html --extra-dir=../libags-audio/html --extra-dir=../libags-gui/html
 
 # Used for dependencies. The docs will be rebuilt if any of these change.
 # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
diff --git a/docs/reference/libgsequencer/libgsequencer.xml b/docs/reference/libgsequencer/libgsequencer.xml
index 25ce12b..98cfd94 100644
--- a/docs/reference/libgsequencer/libgsequencer.xml
+++ b/docs/reference/libgsequencer/libgsequencer.xml
@@ -20,17 +20,29 @@
     <releaseinfo>
       for libgsequencer.
       The latest version of this documentation can be found on-line at
-      <ulink role="online-location" url="http://nongnu.org/gsequencer/libgsequencer/index.html">http://nongnu.org/gsequencer/libgsequencer/</ulink>.
+      <ulink role="online-location" url="http://nongnu.org/gsequencer/api/libgsequencer/index.html">http://nongnu.org/gsequencer/api/libgsequencer/</ulink>.
     </releaseinfo>
   </bookinfo>
-
+  
   <part id="lib">
     <title>GSequencer UI Library</title>
 
     <xi:include href="xml/ags_audio_preferences.xml"/>
     <xi:include href="xml/ags_audio_preferences_callbacks.xml"/>
+
+    <xi:include href="xml/ags_automation_area.xml"/>
+    <xi:include href="xml/ags_automation_edit.xml"/>
+    <xi:include href="xml/ags_automation_edit_callbacks.xml"/>
+    <xi:include href="xml/ags_automation_editor.xml"/>
+    <xi:include href="xml/ags_automation_editor_callbacks.xml"/>
+    <xi:include href="xml/ags_automation_toolbar.xml"/>
+    <xi:include href="xml/ags_automation_toolbar_callbacks.xml"/>
+    <xi:include href="xml/ags_automation_window.xml"/>
+
     <xi:include href="xml/ags_bulk_member.xml"/>
     <xi:include href="xml/ags_bulk_member_callbacks.xml"/>
+    <xi:include href="xml/ags_connection_editor.xml"/>
+    <xi:include href="xml/ags_connection_editor_callbacks.xml"/>
     <xi:include href="xml/ags_dssi_browser.xml"/>
     <xi:include href="xml/ags_dssi_browser_callbacks.xml"/>
     <xi:include href="xml/ags_editor.xml"/>
@@ -42,6 +54,8 @@
     <xi:include href="xml/ags_effect_line.xml"/>
     <xi:include href="xml/ags_effect_line_callbacks.xml"/>
     <xi:include href="xml/ags_effect_pad.xml"/>
+    <xi:include href="xml/ags_export_soundcard.xml"/>
+    <xi:include href="xml/ags_export_soundcard_callbacks.xml"/>
     <xi:include href="xml/ags_export_window.xml"/>
     <xi:include href="xml/ags_export_window_callbacks.xml"/>
     <xi:include href="xml/ags_generic_preferences.xml"/>
@@ -76,8 +90,16 @@
     <xi:include href="xml/ags_midi_dialog_callbacks.xml"/>
     <xi:include href="xml/ags_midi_import_wizard.xml"/>
     <xi:include href="xml/ags_midi_import_wizard_callbacks.xml"/>
+    <xi:include href="xml/ags_midi_preferences.xml"/>
+    <xi:include href="xml/ags_midi_preferences_callbacks.xml"/>
     <xi:include href="xml/ags_navigation.xml"/>
     <xi:include href="xml/ags_navigation_callbacks.xml"/>
+    <xi:include href="xml/ags_output_collection_editor.xml"/>
+    <xi:include href="xml/ags_output_collection_editor_callbacks.xml"/>
+    <xi:include href="xml/ags_output_editor.xml"/>
+    <xi:include href="xml/ags_output_editor_callbacks.xml"/>
+    <xi:include href="xml/ags_output_listing_editor.xml"/>
+    <xi:include href="xml/ags_output_listing_editor_callbacks.xml"/>
     <xi:include href="xml/ags_pad.xml"/>
     <xi:include href="xml/ags_pad_callbacks.xml"/>
     <xi:include href="xml/ags_pad_editor.xml"/>
@@ -94,9 +116,13 @@
     <xi:include href="xml/ags_property_editor_callbacks.xml"/>
     <xi:include href="xml/ags_property_listing_editor.xml"/>
     <xi:include href="xml/ags_resize_editor.xml"/>
+    <xi:include href="xml/ags_sequencer_editor.xml"/>
+    <xi:include href="xml/ags_sequencer_editor_callbacks.xml"/>
     <xi:include href="xml/ags_server_preferences.xml"/>
     <xi:include href="xml/ags_sf2_chooser.xml"/>
     <xi:include href="xml/ags_sf2_chooser_callbacks.xml"/>
+    <xi:include href="xml/ags_soundcard_editor.xml"/>
+    <xi:include href="xml/ags_soundcard_editor_callbacks.xml"/>
     <xi:include href="xml/ags_track_collection.xml"/>
     <xi:include href="xml/ags_track_collection_mapper.xml"/>
     <xi:include href="xml/ags_window.xml"/>
@@ -150,7 +176,6 @@
       <xi:include href="xml/ags_drum_output_line.xml"/>
       <xi:include href="xml/ags_drum_output_line_callbacks.xml"/>
       <xi:include href="xml/ags_drum_output_pad.xml"/>
-      <xi:include href="xml/ags_drum_output_pad_callbacks.xml"/>
       <xi:include href="xml/ags_dssi_bridge.xml"/>
       <xi:include href="xml/ags_dssi_bridge_callbacks.xml"/>
       <xi:include href="xml/ags_ffplayer.xml"/>
@@ -176,6 +201,7 @@
       <xi:include href="xml/ags_panel.xml"/>
       <xi:include href="xml/ags_panel_callbacks.xml"/>
       <xi:include href="xml/ags_panel_input_line.xml"/>
+      <xi:include href="xml/ags_panel_input_line_callbacks.xml"/>
       <xi:include href="xml/ags_panel_input_pad.xml"/>
       <xi:include href="xml/ags_pattern_box.xml"/>
       <xi:include href="xml/ags_pattern_box_callbacks.xml"/>
@@ -201,13 +227,18 @@
 
     <chapter id="task">
       <title>GUI tasks</title>
-
+  
       <xi:include href="xml/ags_add_bulk_member.xml"/>
       <xi:include href="xml/ags_add_line_member.xml"/>
+      <xi:include href="xml/ags_add_sequencer_editor_jack.xml"/>
+      <xi:include href="xml/ags_add_soundcard_editor_jack.xml"/>
       <xi:include href="xml/ags_blink_cell_pattern_cursor.xml"/>
       <xi:include href="xml/ags_change_indicator.xml"/>
       <xi:include href="xml/ags_change_tact.xml"/>
       <xi:include href="xml/ags_display_tact.xml"/>
+      <xi:include href="xml/ags_remove_sequencer_editor_jack.xml"/>
+      <xi:include href="xml/ags_remove_soundcard_editor_jack.xml"/>
+      <xi:include href="xml/ags_resize_editor.xml"/>
       <xi:include href="xml/ags_scroll_on_play.xml"/>
       <xi:include href="xml/ags_simple_file_read.xml"/>
       <xi:include href="xml/ags_simple_file_write.xml"/>
diff --git a/functional-tests.mk b/functional-tests.mk
new file mode 100644
index 0000000..d839587
--- /dev/null
+++ b/functional-tests.mk
@@ -0,0 +1,81 @@
+noinst_LTLIBRARIES = libgsequencer_test.la
+
+# functional tests
+check_PROGRAMS += \
+	ags_functional_audio_test \
+	ags_functional_machine_add_and_destroy_test \
+	ags_functional_panel_test \
+	ags_functional_mixer_test \
+	ags_functional_drum_test \
+	ags_functional_matrix_test \
+	ags_functional_synth_test \
+	ags_functional_ffplayer_test \
+	ags_functional_note_edit_test
+
+# functional test util library
+libgsequencer_test_la_SOURCES = ags/test/X/gsequencer_setup_util.c ags/test/X/gsequencer_setup_util.h ags/test/X/ags_functional_test_util.c ags/test/X/ags_functional_test_util.h ags/test/X/libgsequencer.h
+libgsequencer_test_la_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+libgsequencer_test_la_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+libgsequencer_test_la_LIBADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional audio test
+ags_functional_audio_test_SOURCES = ags/test/audio/ags_functional_audio_test.c
+ags_functional_audio_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_functional_audio_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_audio_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# functional machine add and destroy test
+ags_functional_machine_add_and_destroy_test_SOURCES = ags/test/X/ags_functional_machine_add_and_destroy_test.c
+ags_functional_machine_add_and_destroy_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_machine_add_and_destroy_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_machine_add_and_destroy_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_machine_add_and_destroy_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional panel test
+ags_functional_panel_test_SOURCES = ags/test/X/machine/ags_functional_panel_test.c
+ags_functional_panel_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_panel_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_panel_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_panel_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional mixer test
+ags_functional_mixer_test_SOURCES = ags/test/X/machine/ags_functional_mixer_test.c
+ags_functional_mixer_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_mixer_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_mixer_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_mixer_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional drum test
+ags_functional_drum_test_SOURCES = ags/test/X/machine/ags_functional_drum_test.c
+ags_functional_drum_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_drum_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_drum_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_drum_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional matrix test
+ags_functional_matrix_test_SOURCES = ags/test/X/machine/ags_functional_matrix_test.c
+ags_functional_matrix_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_matrix_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_matrix_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_matrix_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional synth test
+ags_functional_synth_test_SOURCES = ags/test/X/machine/ags_functional_synth_test.c
+ags_functional_synth_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_synth_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_synth_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_synth_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional ffplayer test
+ags_functional_ffplayer_test_SOURCES = ags/test/X/machine/ags_functional_ffplayer_test.c
+ags_functional_ffplayer_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_ffplayer_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_ffplayer_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_ffplayer_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
+
+# functional note edit test
+ags_functional_note_edit_test_SOURCES = ags/test/X/ags_functional_note_edit_test.c
+ags_functional_note_edit_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_functional_note_edit_test_CPPFLAGS = -DSRCDIR=\"$(top_srcdir)\"
+ags_functional_note_edit_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_functional_note_edit_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la libgsequencer_test.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)
diff --git a/gsequencer.1.xml b/gsequencer.1.xml
index a4c86ed..66dcf3b 100644
--- a/gsequencer.1.xml
+++ b/gsequencer.1.xml
@@ -31,6 +31,7 @@
       <arg>--help</arg>
       <arg>--version</arg>
       <arg>--single-thread</arg>
+      <arg>--no-builtin-theme</arg>
       <arg rep='repeat'>--filename <replaceable>file</replaceable></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
@@ -68,6 +69,12 @@
         </listitem>
       </varlistentry>
       <varlistentry>
+        <term><option>--no-builtin-theme</option></term>
+        <listitem>
+          <para>Disable built-in theme in order to display default theme.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
         <term><option>--filename file</option></term>
         <listitem>
           <para>Open file from command line.</para>
diff --git a/gsequencer.desktop.in b/gsequencer.desktop.in
index cc5f447..20972d4 100644
--- a/gsequencer.desktop.in
+++ b/gsequencer.desktop.in
@@ -5,5 +5,5 @@ Terminal=false
 Exec=gsequencer
 Icon=@datadir@/gsequencer/icons/ags.xpm
 Name=Advanced Gtk+ Sequencer
-Categories=AudioVideo;Audio;
-Keywords=audio,sequencer,notation,editor,midi,synth,mixing,effects
+Categories=AudioVideo;Audio;GTK;
+Keywords=audio;sequencer;notation;editor;midi;synth;mixing;effects;
diff --git a/gsequencer.share/styles/ags.rc b/gsequencer.share/styles/ags.rc
new file mode 100644
index 0000000..8a48a48
--- /dev/null
+++ b/gsequencer.share/styles/ags.rc
@@ -0,0 +1,110 @@
+# GTK theme
+pixmap_path "/usr/share/icons/hicolor"
+
+gtk-icon-theme-name = "gnome"
+gtk_color_scheme = "fg_color:#c0ddff\nbg_color:#203f4c"
+gtk_color_scheme = "base_color:#000000"
+gtk_color_scheme = "text_color:#ddfcff"
+gtk_color_scheme = "selected_fg_color:#220200\nselected_bg_color:#000020"
+gtk_color_scheme = "tooltip_bg_color:#000000\ntooltip_fg_color: #c0ddff"
+
+style "default"
+{	
+	GtkScrollbar::has-backward-stepper = 1
+	GtkScrollbar::has-forward-stepper = 1
+	GtkScrollbar::stepper-size = 14
+
+	GtkScale::slider-length = 31
+	GtkScale::slider-width = 14
+
+	engine "clearlooks" {}
+}
+
+style "default_widget" = "default"
+{
+	bg[PRELIGHT] = { 0.25, 0.25, 1.0 }
+	fg[PRELIGHT] = { 0.125, 0.5, 1.0 }
+	bg[ACTIVE] = { 0.0, 0.0, 0.125 }
+	fg[ACTIVE] = { 0.25, 0.875, 1.0 }
+	bg[NORMAL] = { 0.125, 0.25, 0.3 }
+	fg[NORMAL] = { 0.66, 0.87, 1.0 }
+	bg[INSENSITIVE] = { 0.25, 0.25, 0.25 }
+	fg[INSENSITIVE] = { 0.0, 0.0, 1.0 }
+
+	base[NORMAL] = { 0.0, 0.0, 0.0 }
+	base[ACTIVE] = { 0.0, 0.0, 0.0 }
+
+	text[NORMAL] = { 0.87, 0.99, 1.0 }
+	text[ACTIVE] = { 0.13, 0.01, 0.0 }
+}
+
+style "inverse_widget" = "default"
+{
+	bg[PRELIGHT] = { 0.125, 0.5, 1.0 }
+	fg[PRELIGHT] = { 0.0, 0.0, 1.0 }
+	bg[ACTIVE] = { 0.25, 0.875, 1.0 }
+	fg[ACTIVE] = { 0.0, 0.0, 0.125 }
+	bg[NORMAL] = { 0.66, 0.87, 1.0 }
+	fg[NORMAL] = { 0.125, 0.25, 0.3 }
+	bg[INSENSITIVE] = { 0.0, 0.0, 1.0 }
+	fg[INSENSITIVE] = { 0.25, 0.25, 0.25 }
+
+	base[NORMAL] = { 1.0, 1.0, 1.0 }
+	base[ACTIVE] = { 1.0, 1.0, 1.0 }
+
+	text[NORMAL] = { 0.13, 0.01, 0.0 }
+	text[ACTIVE] = { 0.87, 0.99, 1.0 }
+}
+
+style "scale_widget" = "inverse_widget"
+{
+	fg[NORMAL] = { 0.75, 0.75, 1.0 }
+	fg[ACTIVE] = { 0.66, 0.87, 1.0 }
+}
+
+style "main_window" = "default_widget"
+{
+	bg[NORMAL] = { 0.125, 0.25, 0.3 }
+	fg[NORMAL] = { 0.87, 0.99, 1.0 }
+}
+
+widget_class "AgsWindow*" style "main_window"
+widget_class "AgsAutomationWindow*" style "main_window"
+widget_class "GtkWindow*" style "main_window"
+widget_class "AgsPreferences*" style "main_window"
+widget_class "AgsExportWindow*" style "main_window"
+widget_class "AgsMachineEditor*" style "main_window"
+widget_class "AgsMidiDialog*" style "main_window"
+widget_class "AgsConnectionEditor*" style "main_window"
+widget_class "AgsMachineSelection*" style "main_window"
+widget_class "AgsPluginBrowser*" style "main_window"
+widget_class "Gtk*Dialog*" style "main_window"
+
+widget_class "*GtkLabel*" style "default_widget"
+
+widget_class "*GtkMenuShell*" style "inverse_widget"
+widget_class "*GtkHandleBox*" style "default_widget"
+
+widget_class "*AgsToolbar*" style "inverse_widget"
+widget_class "*AgsAutomationToolbar*" style "inverse_widget"
+widget_class "*AgsMenuBar*" style "inverse_widget"
+widget_class "*AgsNotebook*" style "default_widget"
+widget_class "*AgsNaviation*" style "inverse_widget"
+
+widget_class "*GtkMenu*" style "inverse_widget"
+widget_class "*Gtk*Scale*" style "scale_widget"
+widget_class "*Gtk*Scrollbar*" style "inverse_widget"
+widget_class "*GtkButton*" style "inverse_widget"
+widget_class "*GtkToggleButton*" style "inverse_widget"
+widget_class "*GtkRadioButton*" style "default_widget"
+widget_class "*GtkCheckButton*" style "default_widget"
+widget_class "*GtkMenuToolButton*" style "default_widget"
+widget_class "*GtkEntry*" style "default_widget"
+widget_class "*GtkTextView*" style "default_widget"
+widget_class "*AgsLed*" style "inverse_widget"
+widget_class "*AgsDial*" style "inverse_widget"
+widget_class "*Ags*Indicator*" style "inverse_widget"
+widget_class "*GtkArrow" style "default_widget"
+widget_class "*GtkComboBox*" style "inverse_widget"
+
+widget "*.ags-navigation-expander" style "default_widget"
diff --git a/libags.sym b/libags.sym
index fe4bdf8..448fd5c 100644
--- a/libags.sym
+++ b/libags.sym
@@ -1,14 +1,25 @@
 ags_id_generator_create_uuid
-ags_log_get_type
-ags_log_add_message
-ags_log_get_messages
-ags_log_get_instance
-ags_log_new
+ags_list_util_find_type
+ags_list_util_copy_and_ref
+ags_destroy_util_dispose_and_unref
 ags_turtle_manager_get_type
 ags_turtle_manager_find
 ags_turtle_manager_add
 ags_turtle_manager_get_instance
 ags_turtle_manager_new
+ags_log_get_type
+ags_log_add_message
+ags_log_get_messages
+ags_log_get_instance
+ags_log_new
+ags_endian_swap_float
+ags_time_get_uptime_from_offset
+ags_complex_get_type
+ags_complex_alloc
+ags_complex_copy
+ags_complex_free
+ags_complex_get
+ags_complex_set
 ags_turtle_get_type
 ags_turtle_read_iriref
 ags_turtle_read_pname_ns
@@ -43,6 +54,13 @@ ags_turtle_find_xpath_with_context_node
 ags_turtle_string_convert
 ags_turtle_load
 ags_turtle_new
+ags_string_util_escape_single_quote
+ags_strv_length
+ags_strv_contains
+ags_parameter_grow
+ags_conversion_get_type
+ags_conversion_convert
+ags_conversion_new
 ags_function_get_type
 ags_function_find_literals
 ags_function_literal_solve
@@ -55,83 +73,7 @@ ags_function_symbolic_translate_value
 ags_function_substitute_values
 ags_function_translate_value
 ags_function_new
-ags_time_get_uptime_from_offset
-ags_endian_swap_float
-ags_string_util_escape_single_quote
-ags_strv_length
-ags_strv_contains
-ags_parameter_grow
-ags_complex_get_type
-ags_complex_alloc
-ags_complex_copy
-ags_complex_free
-ags_complex_get
-ags_complex_set
-ags_conversion_get_type
-ags_conversion_convert
-ags_conversion_new
 ags_application_context
-ags_connectable_get_type
-ags_connectable_add_to_registry
-ags_connectable_remove_from_registry
-ags_connectable_update
-ags_connectable_is_ready
-ags_connectable_is_connected
-ags_connectable_connect
-ags_connectable_disconnect
-ags_connectable_connect_scope
-ags_connectable_disconnect_scope
-ags_connection_get_type
-ags_connection_find_type
-ags_connection_find_type_and_data_object_type
-ags_connection_new
-ags_sequencer_get_type
-ags_sequencer_set_application_context
-ags_sequencer_get_application_context
-ags_sequencer_set_application_mutex
-ags_sequencer_get_application_mutex
-ags_sequencer_set_device
-ags_sequencer_get_device
-ags_sequencer_list_cards
-ags_sequencer_is_starting
-ags_sequencer_is_playing
-ags_sequencer_is_recording
-ags_sequencer_play_init
-ags_sequencer_play
-ags_sequencer_record_init
-ags_sequencer_record
-ags_sequencer_stop
-ags_sequencer_tic
-ags_sequencer_offset_changed
-ags_sequencer_get_buffer
-ags_sequencer_get_next_buffer
-ags_sequencer_set_bpm
-ags_sequencer_get_bpm
-ags_sequencer_set_delay_factor
-ags_sequencer_get_delay_factor
-ags_sequencer_set_note_offset
-ags_sequencer_get_note_offset
-ags_sequencer_set_audio
-ags_sequencer_get_audio
-ags_application_context_get_type
-ags_application_context_load_config
-ags_application_context_register_types
-ags_application_read
-ags_application_write
-ags_application_context_add_sibling
-ags_application_context_remove_sibling
-ags_application_context_find_default
-ags_application_context_find_main_loop
-ags_application_context_quit
-ags_application_context_get_instance
-ags_application_context_new
-ags_concurrent_tree_get_type
-ags_concurrent_tree_set_parent_locked
-ags_concurrent_tree_get_parent_locked
-ags_concurrent_tree_get_lock
-ags_concurrent_tree_get_parent_lock
-ags_concurrent_tree_lock_context
-ags_concurrent_tree_unlock_context
 ags_tree_iterator_get_type
 ags_tree_iterator_set_inverse_mode
 ags_tree_iterator_is_inverse_mode
@@ -139,21 +81,6 @@ ags_tree_iterator_iterate
 ags_tree_iterator_iterate_nested
 ags_tree_iterator_safe_iterate
 ags_tree_iterator_safe_iterate_nested
-ags_async_queue_get_type
-ags_async_queue_increment_wait_ref
-ags_async_queue_get_wait_ref
-ags_async_queue_set_run_mutex
-ags_async_queue_get_run_mutex
-ags_async_queue_set_run_cond
-ags_async_queue_get_run_cond
-ags_async_queue_set_run
-ags_async_queue_is_run
-ags_portlet_get_type
-ags_portlet_get_port
-ags_portlet_set_port
-ags_portlet_list_safe_properties
-ags_portlet_safe_get_property
-ags_portlet_safe_set_property
 ags_soundcard_get_type
 ags_soundcard_set_application_context
 ags_soundcard_get_application_context
@@ -197,6 +124,103 @@ ags_soundcard_get_loop
 ags_soundcard_get_loop_offset
 ags_soundcard_set_audio
 ags_soundcard_get_audio
+ags_connection_manager_get_type
+ags_connection_manager_get_connection
+ags_connection_manager_add_connection
+ags_connection_manager_remove_connection
+ags_connection_manager_get_instance
+ags_connection_manager_new
+ags_plugin_get_type
+ags_plugin_get_name
+ags_plugin_set_name
+ags_plugin_get_version
+ags_plugin_set_version
+ags_plugin_get_build_id
+ags_plugin_set_build_id
+ags_plugin_get_xml_type
+ags_plugin_set_xml_type
+ags_plugin_get_ports
+ags_plugin_set_ports
+ags_plugin_read
+ags_plugin_write
+ags_connectable_get_type
+ags_connectable_add_to_registry
+ags_connectable_remove_from_registry
+ags_connectable_update
+ags_connectable_is_ready
+ags_connectable_is_connected
+ags_connectable_connect
+ags_connectable_disconnect
+ags_connectable_connect_scope
+ags_connectable_disconnect_scope
+ags_packable_get_type
+ags_packable_pack
+ags_packable_unpack
+ags_seekable_get_type
+ags_seekable_seek
+ags_main_loop_get_type
+ags_main_loop_get_tree_lock
+ags_main_loop_set_application_context
+ags_main_loop_get_application_context
+ags_main_loop_set_async_queue
+ags_main_loop_get_async_queue
+ags_main_loop_set_tic
+ags_main_loop_get_tic
+ags_main_loop_set_last_sync
+ags_main_loop_get_last_sync
+ags_main_loop_interrupt
+ags_main_loop_monitor
+ags_main_loop_change_frequency
+ags_concurrent_tree_get_type
+ags_concurrent_tree_set_parent_locked
+ags_concurrent_tree_get_parent_locked
+ags_concurrent_tree_get_lock
+ags_concurrent_tree_get_parent_lock
+ags_concurrent_tree_lock_context
+ags_concurrent_tree_unlock_context
+ags_sequencer_get_type
+ags_sequencer_set_application_context
+ags_sequencer_get_application_context
+ags_sequencer_set_application_mutex
+ags_sequencer_get_application_mutex
+ags_sequencer_set_device
+ags_sequencer_get_device
+ags_sequencer_list_cards
+ags_sequencer_is_starting
+ags_sequencer_is_playing
+ags_sequencer_is_recording
+ags_sequencer_play_init
+ags_sequencer_play
+ags_sequencer_record_init
+ags_sequencer_record
+ags_sequencer_stop
+ags_sequencer_tic
+ags_sequencer_offset_changed
+ags_sequencer_get_buffer
+ags_sequencer_get_next_buffer
+ags_sequencer_set_bpm
+ags_sequencer_get_bpm
+ags_sequencer_set_delay_factor
+ags_sequencer_get_delay_factor
+ags_sequencer_set_note_offset
+ags_sequencer_get_note_offset
+ags_sequencer_set_audio
+ags_sequencer_get_audio
+ags_portlet_get_type
+ags_portlet_get_port
+ags_portlet_set_port
+ags_portlet_list_safe_properties
+ags_portlet_safe_get_property
+ags_portlet_safe_set_property
+ags_async_queue_get_type
+ags_async_queue_increment_wait_ref
+ags_async_queue_get_wait_ref
+ags_async_queue_set_run_mutex
+ags_async_queue_get_run_mutex
+ags_async_queue_set_run_cond
+ags_async_queue_get_run_cond
+ags_async_queue_set_run
+ags_async_queue_is_run
 ags_distributed_manager_get_type
 ags_distributed_manager_set_url
 ags_distributed_manager_get_url
@@ -210,11 +234,10 @@ ags_distributed_manager_register_soundcard
 ags_distributed_manager_unregister_soundcard
 ags_distributed_manager_register_sequencer
 ags_distributed_manager_unregister_sequencer
-ags_mutable_get_type
-ags_mutable_set_muted
-ags_dynamic_connectable_get_type
-ags_dynamic_connectable_connect_dynamic
-ags_dynamic_connectable_disconnect_dynamic
+ags_connection_get_type
+ags_connection_find_type
+ags_connection_find_type_and_data_object_type
+ags_connection_new
 ags_tactable_get_type
 ags_tactable_get_sequencer_duration
 ags_tactable_get_notation_duration
@@ -224,12 +247,27 @@ ags_tactable_change_sequencer_duration
 ags_tactable_change_notation_duration
 ags_tactable_change_tact
 ags_tactable_change_bpm
-ags_packable_get_type
-ags_packable_pack
-ags_packable_unpack
-ags_countable_get_type
-ags_countable_get_notation_counter
-ags_countable_get_sequencer_counter
+ags_dynamic_connectable_get_type
+ags_dynamic_connectable_connect_dynamic
+ags_dynamic_connectable_disconnect_dynamic
+ags_mutable_get_type
+ags_mutable_set_muted
+ags_application_context_get_type
+ags_application_context_load_config
+ags_application_context_register_types
+ags_application_read
+ags_application_write
+ags_application_context_add_sibling
+ags_application_context_remove_sibling
+ags_application_context_find_default
+ags_application_context_find_main_loop
+ags_application_context_quit
+ags_application_context_get_instance
+ags_application_context_new
+ags_applicable_get_type
+ags_applicable_set_update
+ags_applicable_apply
+ags_applicable_reset
 ags_config_get_type
 ags_config_load_defaults
 ags_config_load_from_file
@@ -241,43 +279,9 @@ ags_config_save
 ags_config_clear
 ags_config_get_instance
 ags_config_new
-ags_plugin_get_type
-ags_plugin_get_name
-ags_plugin_set_name
-ags_plugin_get_version
-ags_plugin_set_version
-ags_plugin_get_build_id
-ags_plugin_set_build_id
-ags_plugin_get_xml_type
-ags_plugin_set_xml_type
-ags_plugin_get_ports
-ags_plugin_set_ports
-ags_plugin_read
-ags_plugin_write
-ags_applicable_get_type
-ags_applicable_set_update
-ags_applicable_apply
-ags_applicable_reset
-ags_seekable_get_type
-ags_seekable_seek
-ags_main_loop_get_type
-ags_main_loop_get_tree_lock
-ags_main_loop_set_application_context
-ags_main_loop_get_application_context
-ags_main_loop_set_async_queue
-ags_main_loop_get_async_queue
-ags_main_loop_set_tic
-ags_main_loop_get_tic
-ags_main_loop_set_last_sync
-ags_main_loop_get_last_sync
-ags_main_loop_interrupt
-ags_main_loop_monitor
-ags_connection_manager_get_type
-ags_connection_manager_get_connection
-ags_connection_manager_add_connection
-ags_connection_manager_remove_connection
-ags_connection_manager_get_instance
-ags_connection_manager_new
+ags_countable_get_type
+ags_countable_get_notation_counter
+ags_countable_get_sequencer_counter
 g_cclosure_user_marshal_MARSHAL_H__
 g_cclosure_user_marshal_MARSHAL_H__
 g_cclosure_user_marshal_VOID__BOOLEAN_POINTER
@@ -334,6 +338,31 @@ g_cclosure_user_marshal_OBJECT__STRING_STRING_STRING
 g_cclosure_user_marshal_OBJECT__OBJECT_POINTER_POINTER
 g_cclosure_user_marshal_OBJECT__OBJECT_OBJECT
 g_cclosure_user_marshal_MARSHAL_H__
+ags_file_launch_get_type
+ags_file_launch_start
+ags_file_launch_new
+ags_file_lookup_get_type
+ags_file_lookup_find_by_node
+ags_file_lookup_find_by_reference
+ags_file_lookup_resolve
+ags_file_lookup_new
+ags_file_id_ref_get_type
+ags_file_id_ref_resolved
+ags_file_id_ref_new
+ags_file_util_read_value
+ags_file_util_write_value
+ags_file_util_read_parameter
+ags_file_util_write_parameter
+ags_file_util_read_dependency
+ags_file_util_write_dependency
+ags_file_util_read_object
+ags_file_util_write_object
+ags_file_util_read_history
+ags_file_util_write_history
+ags_file_read_file_link
+ags_file_write_file_link
+ags_file_read_file_link_list
+ags_file_write_file_link_list
 ags_file_get_type
 ags_file_str2md5
 ags_file_add_id_ref
@@ -358,30 +387,5 @@ ags_file_write_config
 ags_file_read_application_context
 ags_file_write_application_context
 ags_file_new
-ags_file_id_ref_get_type
-ags_file_id_ref_resolved
-ags_file_id_ref_new
-ags_file_lookup_get_type
-ags_file_lookup_find_by_node
-ags_file_lookup_find_by_reference
-ags_file_lookup_resolve
-ags_file_lookup_new
-ags_file_util_read_value
-ags_file_util_write_value
-ags_file_util_read_parameter
-ags_file_util_write_parameter
-ags_file_util_read_dependency
-ags_file_util_write_dependency
-ags_file_util_read_object
-ags_file_util_write_object
-ags_file_util_read_history
-ags_file_util_write_history
-ags_file_read_file_link
-ags_file_write_file_link
-ags_file_read_file_link_list
-ags_file_write_file_link_list
 ags_file_link_get_type
 ags_file_link_new
-ags_file_launch_get_type
-ags_file_launch_start
-ags_file_launch_new
diff --git a/libags_audio.sym b/libags_audio.sym
index 425b316..6498f12 100644
--- a/libags_audio.sym
+++ b/libags_audio.sym
@@ -1,36 +1,20 @@
-ags_lv2_conversion_get_type
-ags_lv2_conversion_new
-ags_base_plugin_get_type
-ags_port_descriptor_alloc
-ags_port_descriptor_free
-ags_base_plugin_find_filename
-ags_base_plugin_find_effect
-ags_base_plugin_sort
-ags_base_plugin_apply_port_group_by_prefix
-ags_base_plugin_instantiate
-ags_base_plugin_connect_port
-ags_base_plugin_activate
-ags_base_plugin_deactivate
-ags_base_plugin_run
-ags_base_plugin_load_plugin
-ags_base_plugin_new
+ags_lv2_uri_map_manager_get_type
+ags_lv2_uri_map_manager_insert
+ags_lv2_uri_map_manager_remove
+ags_lv2_uri_map_manager_lookup
+ags_lv2_uri_map_manager_load_default
+ags_lv2_uri_map_manager_uri_to_id
+ags_lv2_uri_map_manager_get_instance
+ags_lv2_uri_map_manager_new
 ags_ladspa_plugin_get_type
 ags_ladspa_plugin_new
-ags_ladspa_manager_get_type
-ags_ladspa_manager_get_filenames
-ags_ladspa_manager_find_ladspa_plugin
-ags_ladspa_manager_load_blacklist
-ags_ladspa_manager_load_file
-ags_ladspa_manager_load_default_directory
-ags_ladspa_manager_get_instance
-ags_ladspa_manager_new
-ags_ladspa_conversion_get_type
-ags_ladspa_conversion_new
-ags_lv2_log_manager_get_type
-ags_lv2_log_manager_printf
-ags_lv2_log_manager_vprintf
-ags_lv2_log_manager_get_instance
-ags_lv2_log_manager_new
+ags_lv2_worker_manager_get_type
+ags_lv2_worker_manager_pull_worker
+ags_lv2_worker_manager_get_instance
+ags_lv2_worker_manager_new
+ags_dssi_plugin_get_type
+ags_dssi_plugin_change_program
+ags_dssi_plugin_new
 ags_lv2_urid_manager_get_type
 ags_lv2_urid_manager_insert
 ags_lv2_urid_manager_remove
@@ -40,6 +24,39 @@ ags_lv2_urid_manager_map
 ags_lv2_urid_manager_unmap
 ags_lv2_urid_manager_get_instance
 ags_lv2_urid_manager_new
+ags_lv2_worker_get_type
+ags_lv2_worker_alloc_response_data
+ags_lv2_worker_free_response_data
+ags_lv2_worker_respond
+ags_lv2_worker_schedule_work
+ags_lv2_worker_safe_run
+ags_lv2_worker_interrupted_callback
+ags_lv2_worker_new
+ags_lv2ui_plugin_get_type
+ags_lv2ui_plugin_find_gui_uri
+ags_lv2ui_plugin_new
+ags_lv2ui_manager_get_type
+ags_lv2ui_manager_get_filenames
+ags_lv2ui_manager_find_lv2ui_plugin
+ags_lv2ui_manager_find_lv2ui_plugin_with_index
+ags_lv2ui_manager_load_blacklist
+ags_lv2ui_manager_load_file
+ags_lv2ui_manager_load_default_directory
+ags_lv2ui_manager_get_instance
+ags_lv2ui_manager_new
+ags_ladspa_conversion_get_type
+ags_ladspa_conversion_new
+ags_lv2_plugin_get_type
+ags_lv2_plugin_alloc_event_buffer
+ags_lv2_plugin_concat_event_buffer
+ags_lv2_plugin_event_buffer_append_midi
+ags_lv2_plugin_clear_event_buffer
+ags_lv2_plugin_alloc_atom_sequence
+ags_lv2_plugin_concat_atom_sequence
+ags_lv2_plugin_atom_sequence_append_midi
+ags_lv2_plugin_clear_atom_sequence
+ags_lv2_plugin_find_pname
+ags_lv2_plugin_new
 ags_plugin_factory_get_type
 ags_plugin_factory_read_file
 ags_plugin_factory_list_by_name
@@ -48,6 +65,13 @@ ags_plugin_factory_create
 ags_plugin_factory_get_instance
 ags_plugin_factory_new_from_file
 ags_plugin_factory_new
+ags_lv2_conversion_get_type
+ags_lv2_conversion_new
+ags_lv2_event_manager_get_type
+ags_lv2_event_manager_lv2_event_ref
+ags_lv2_event_manager_lv2_event_unref
+ags_lv2_event_manager_get_instance
+ags_lv2_event_manager_new
 ags_dssi_manager_get_type
 ags_dssi_manager_get_filenames
 ags_dssi_manager_find_dssi_plugin
@@ -56,430 +80,129 @@ ags_dssi_manager_load_file
 ags_dssi_manager_load_default_directory
 ags_dssi_manager_get_instance
 ags_dssi_manager_new
-ags_lv2_worker_manager_get_type
-ags_lv2_worker_manager_pull_worker
-ags_lv2_worker_manager_get_instance
-ags_lv2_worker_manager_new
-ags_lv2ui_manager_get_type
-ags_lv2ui_manager_get_filenames
-ags_lv2ui_manager_find_lv2ui_plugin
-ags_lv2ui_manager_load_blacklist
-ags_lv2ui_manager_load_file
-ags_lv2ui_manager_load_default_directory
-ags_lv2ui_manager_get_instance
-ags_lv2ui_manager_new
-ags_lv2_uri_map_manager_get_type
-ags_lv2_uri_map_manager_insert
-ags_lv2_uri_map_manager_remove
-ags_lv2_uri_map_manager_lookup
-ags_lv2_uri_map_manager_load_default
-ags_lv2_uri_map_manager_uri_to_id
-ags_lv2_uri_map_manager_get_instance
-ags_lv2_uri_map_manager_new
-ags_lv2_worker_get_type
-ags_lv2_worker_alloc_response_data
-ags_lv2_worker_free_response_data
-ags_lv2_worker_respond
-ags_lv2_worker_schedule_work
-ags_lv2_worker_safe_run
-ags_lv2_worker_interrupted_callback
-ags_lv2_worker_new
-ags_dssi_plugin_get_type
-ags_dssi_plugin_change_program
-ags_dssi_plugin_new
-ags_lv2ui_plugin_get_type
-ags_lv2ui_plugin_new
+ags_ladspa_manager_get_type
+ags_ladspa_manager_get_filenames
+ags_ladspa_manager_find_ladspa_plugin
+ags_ladspa_manager_load_blacklist
+ags_ladspa_manager_load_file
+ags_ladspa_manager_load_default_directory
+ags_ladspa_manager_get_instance
+ags_ladspa_manager_new
+ags_base_plugin_get_type
+ags_port_descriptor_alloc
+ags_port_descriptor_free
+ags_port_descriptor_find_symbol
+ags_base_plugin_find_filename
+ags_base_plugin_find_effect
+ags_base_plugin_find_ui_effect_index
+ags_base_plugin_sort
+ags_base_plugin_apply_port_group_by_prefix
+ags_base_plugin_instantiate
+ags_base_plugin_connect_port
+ags_base_plugin_activate
+ags_base_plugin_deactivate
+ags_base_plugin_run
+ags_base_plugin_load_plugin
+ags_base_plugin_new
+ags_lv2_preset_get_type
+ags_lv2_port_preset_alloc
+ags_lv2_port_preset_free
+ags_lv2_preset_parse_turtle
+ags_lv2_preset_find_preset_label
+ags_lv2_preset_new
 ags_lv2_manager_get_type
 ags_lv2_manager_get_filenames
 ags_lv2_manager_find_lv2_plugin
 ags_lv2_manager_load_blacklist
 ags_lv2_manager_load_file
+ags_lv2_manager_load_preset
 ags_lv2_manager_load_default_directory
 ags_lv2_manager_get_instance
 ags_lv2_manager_new
-ags_lv2_event_manager_get_type
-ags_lv2_event_manager_lv2_event_ref
-ags_lv2_event_manager_lv2_event_unref
-ags_lv2_event_manager_get_instance
-ags_lv2_event_manager_new
-ags_lv2_plugin_get_type
-ags_lv2_plugin_alloc_event_buffer
-ags_lv2_plugin_concat_event_buffer
-ags_lv2_plugin_event_buffer_append_midi
-ags_lv2_plugin_clear_event_buffer
-ags_lv2_plugin_alloc_atom_sequence
-ags_lv2_plugin_concat_atom_sequence
-ags_lv2_plugin_atom_sequence_append_midi
-ags_lv2_plugin_clear_atom_sequence
-ags_lv2_plugin_new
-ags_audio_application_context_get_type
-ags_audio_application_context_new
-ags_automation_get_type
-ags_automation_find_port
-ags_automation_find_near_timestamp
-ags_automation_add_acceleration
-ags_automation_remove_acceleration_at_position
-ags_automation_get_selection
-ags_automation_is_acceleration_selected
-ags_automation_find_point
-ags_automation_find_region
-ags_automation_free_selection
-ags_automation_add_point_to_selection
-ags_automation_remove_point_from_selection
-ags_automation_add_region_to_selection
-ags_automation_remove_region_from_selection
-ags_automation_add_all_to_selection
-ags_automation_copy_selection
-ags_automation_cut_selection
-ags_automation_merge_clipboard
-ags_automation_insert_from_clipboard
-ags_automation_get_current
-ags_automation_get_specifier_unique
-ags_automation_find_specifier
-ags_automation_find_specifier_with_type_and_line
-ags_automation_get_value
-ags_automation_new
-ags_audio_signal_get_type
-ags_stream_alloc
-ags_stream_free
-ags_audio_signal_set_samplerate
-ags_audio_signal_set_buffer_size
-ags_audio_signal_set_format
-ags_audio_signal_get_length_till_current
-ags_audio_signal_add_stream
-ags_audio_signal_stream_resize
-ags_audio_signal_stream_safe_resize
-ags_audio_signal_realloc_buffer_size
-ags_audio_signal_duplicate_stream
-ags_audio_signal_get_template
-ags_audio_signal_get_stream_current
-ags_audio_signal_get_by_recall_id
-ags_audio_signal_tile
-ags_audio_signal_scale
-ags_audio_signal_feed
-ags_audio_signal_envelope
-ags_audio_signal_new
-ags_audio_signal_new_with_length
-ags_note_get_type
-ags_note_find_prev
-ags_note_find_next
-ags_note_to_raw_midi
-ags_note_to_seq_event
-ags_note_from_raw_midi
-ags_note_from_seq_event
-ags_note_duplicate
-ags_note_new
-ags_note_new_with_offset
-ags_audio_connection_get_type
-ags_audio_connection_find
-ags_audio_connection_new
-ags_recall_lv2_run_get_type
-ags_recall_lv2_run_new
-ags_synth_util_sin_s8
-ags_synth_util_sin_s16
-ags_synth_util_sin_s24
-ags_synth_util_sin_s32
-ags_synth_util_sin_s64
-ags_synth_util_sin_float
-ags_synth_util_sin_double
-ags_synth_util_sawtooth_s8
-ags_synth_util_sawtooth_s16
-ags_synth_util_sawtooth_s24
-ags_synth_util_sawtooth_s32
-ags_synth_util_sawtooth_s64
-ags_synth_util_sawtooth_float
-ags_synth_util_sawtooth_double
-ags_synth_util_triangle_s8
-ags_synth_util_triangle_s16
-ags_synth_util_triangle_s24
-ags_synth_util_triangle_s32
-ags_synth_util_triangle_s64
-ags_synth_util_triangle_float
-ags_synth_util_triangle_double
-ags_synth_util_square_s8
-ags_synth_util_square_s16
-ags_synth_util_square_s24
-ags_synth_util_square_s32
-ags_synth_util_square_s64
-ags_synth_util_square_float
-ags_synth_util_square_double
-ags_synth_util_sin
-ags_synth_util_sawtooth
-ags_synth_util_triangle
-ags_synth_util_square
-ags_midiin_get_type
-ags_midiin_error_quark
-ags_midiin_new
-ags_recycling_thread_iterate_callback
-ags_audio_loop_get_type
-ags_audio_loop_add_audio
-ags_audio_loop_remove_audio
-ags_audio_loop_add_channel
-ags_audio_loop_remove_channel
-ags_audio_loop_add_recall
-ags_audio_loop_remove_recall
-ags_audio_loop_new
-ags_soundcard_thread_get_type
-ags_soundcard_thread_find_soundcard
-ags_soundcard_thread_new
-ags_export_thread_get_type
-ags_export_thread_find_soundcard
-ags_export_thread_new
-ags_iterator_thread_get_type
-ags_iterator_thread_children_ready
-ags_iterator_thread_new
-ags_recycling_thread_get_type
-ags_recycling_thread_worker_alloc
-ags_recycling_thread_add_worker
-ags_recycling_thread_remove_worker
-ags_recycling_thread_play_channel
-ags_recycling_thread_play_audio
-ags_recycling_thread_find_child
-ags_recycling_thread_fifo
-ags_recycling_thread_new
-ags_channel_thread_get_type
-ags_channel_thread_new
-ags_record_thread_get_type
-ags_record_thread_new
-ags_sequencer_thread_get_type
-ags_sequencer_thread_interval_timeout
-ags_sequencer_thread_find_sequencer
-ags_sequencer_thread_new
-ags_audio_thread_get_type
-ags_audio_thread_new
-ags_recall_dssi_run_get_type
-ags_recall_dssi_run_new
-ags_recall_channel_run_dummy_get_type
-ags_recall_channel_run_dummy_new
-ags_fifoout_get_type
-ags_fifoout_error_quark
-ags_fifoout_adjust_delay_and_attack
-ags_fifoout_realloc_buffer
-ags_fifoout_new
-ags_recall_id_get_type
-ags_recall_id_get_run_stage
-ags_recall_id_set_run_stage
-ags_recall_id_unset_run_stage
-ags_recall_id_find_recycling_context
-ags_recall_id_find_parent_recycling_context
-ags_recall_id_new
-ags_output_get_type
-ags_output_find_first_input_recycling
-ags_output_find_last_input_recycling
-ags_output_new
-ags_recall_channel_run_get_type
-ags_recall_channel_run_run_order_changed
-ags_recall_channel_run_get_run_order
-ags_recall_channel_run_new
+ags_lv2_log_manager_get_type
+ags_lv2_log_manager_printf
+ags_lv2_log_manager_vprintf
+ags_lv2_log_manager_get_instance
+ags_lv2_log_manager_new
 ags_playback_get_type
+ags_playback_set_channel_thread
+ags_playback_get_channel_thread
+ags_playback_set_iterator_thread
+ags_playback_get_iterator_thread
+ags_playback_set_recycling_thread
+ags_playback_get_recycling_thread
+ags_playback_set_recall_id
+ags_playback_get_recall_id
 ags_playback_find_source
 ags_playback_new
-ags_recall_dependency_get_type
-ags_recall_dependency_find_dependency
-ags_recall_dependency_find_dependency_by_provider
-ags_recall_dependency_resolve
-ags_recall_dependency_new
-ags_recall_get_type
-ags_recall_set_flags
-ags_recall_load_automation
-ags_recall_unload_automation
-ags_recall_resolve_dependencies
-ags_recall_child_added
-ags_recall_run_init_pre
-ags_recall_run_init_inter
-ags_recall_run_init_post
-ags_recall_automate
-ags_recall_run_pre
-ags_recall_run_inter
-ags_recall_run_post
-ags_recall_stop_persistent
-ags_recall_done
-ags_recall_cancel
-ags_recall_remove
-ags_recall_is_done
-ags_recall_duplicate
-ags_recall_set_recall_id
-ags_recall_set_soundcard_recursive
-ags_recall_notify_dependency
-ags_recall_add_dependency
-ags_recall_remove_dependency
-ags_recall_get_dependencies
-ags_recall_remove_child
-ags_recall_add_child
-ags_recall_get_children
-ags_recall_get_by_effect
-ags_recall_find_recall_id_with_effect
-ags_recall_find_type
-ags_recall_find_template
-ags_recall_template_find_type
-ags_recall_template_find_all_type
-ags_recall_find_type_with_recycling_context
-ags_recall_find_recycling_context
-ags_recall_find_provider
-ags_recall_template_find_provider
-ags_recall_find_provider_with_recycling_context
-ags_recall_run_init
-ags_recall_handler_alloc
-ags_recall_add_handler
-ags_recall_remove_handler
-ags_recall_lock_port
-ags_recall_unlock_port
-ags_recall_new
-ags_init_channel_get_type
-ags_init_channel_new
-ags_remove_soundcard_get_type
-ags_remove_soundcard_new
-ags_remove_audio_signal_get_type
-ags_remove_audio_signal_new
-ags_add_audio_get_type
-ags_add_audio_new
-ags_remove_audio_get_type
-ags_remove_audio_new
-ags_remove_recall_container_get_type
-ags_remove_recall_container_new
-ags_cancel_audio_get_type
-ags_cancel_audio_new
-ags_remove_recall_get_type
-ags_remove_recall_new
-ags_add_note_get_type
-ags_add_note_new
-ags_resize_audio_get_type
-ags_resize_audio_new
-ags_link_channel_get_type
-ags_link_channel_new
-ags_append_audio_get_type
-ags_append_audio_new
-ags_set_audio_channels_get_type
-ags_set_audio_channels_new
-ags_remove_note_get_type
-ags_remove_note_new
-ags_start_sequencer_get_type
-ags_start_sequencer_new
-ags_apply_synth_get_type
-ags_apply_synth_new
-ags_append_audio_threaded_get_type
-ags_append_audio_threaded_new
-ags_export_output_get_type
-ags_export_output_new
-ags_unref_audio_signal_get_type
-ags_unref_audio_signal_new
-ags_free_selection_get_type
-ags_free_selection_new
-ags_add_recall_container_get_type
-ags_add_recall_container_new
-ags_set_muted_get_type
-ags_set_muted_new
-ags_apply_bpm_get_type
-ags_apply_bpm_new
-ags_apply_tact_get_type
-ags_apply_tact_new
-ags_apply_sequencer_length_get_type
-ags_apply_sequencer_length_new
-ags_notify_soundcard_get_type
-ags_notify_soundcard_new
-ags_cancel_channel_get_type
-ags_cancel_channel_new
-ags_init_audio_get_type
-ags_init_audio_new
-ags_seek_soundcard_get_type
-ags_seek_soundcard_new
-ags_append_recall_get_type
-ags_append_recall_new
-ags_add_soundcard_get_type
-ags_add_soundcard_new
-ags_apply_presets_get_type
-ags_apply_presets_soundcard
-ags_apply_presets_new
-ags_add_recall_get_type
-ags_add_recall_new
-ags_add_effect_get_type
-ags_add_effect_new
-ags_save_file_get_type
-ags_save_file_new
-ags_tic_device_get_type
-ags_tic_device_new
-ags_change_soundcard_get_type
-ags_change_soundcard_new
-ags_append_channel_get_type
-ags_append_channel_new
-ags_remove_point_from_selection_get_type
-ags_remove_point_from_selection_new
-ags_add_point_to_selection_get_type
-ags_add_point_to_selection_new
-ags_set_samplerate_get_type
-ags_set_samplerate_new
-ags_set_buffer_size_get_type
-ags_set_buffer_size_new
-ags_set_format_get_type
-ags_set_format_new
-ags_switch_buffer_flag_get_type
-ags_switch_buffer_flag_new
-ags_cancel_recall_get_type
-ags_cancel_recall_new
-ags_add_region_to_selection_get_type
-ags_add_region_to_selection_new
-ags_open_sf2_sample_get_type
-ags_open_sf2_sample_new
-ags_add_audio_signal_get_type
-ags_add_audio_signal_new
-ags_toggle_pattern_bit_get_type
-ags_toggle_pattern_bit_refresh_gui
-ags_toggle_pattern_bit_new
-ags_reset_audio_connection_get_type
-ags_reset_audio_connection_new
-ags_start_soundcard_get_type
-ags_start_soundcard_new
-ags_open_single_file_get_type
-ags_open_single_file_new
-ags_open_file_get_type
-ags_open_file_new
-ags_set_input_device_get_type
-ags_set_input_device_new
-ags_remove_region_from_selection_get_type
-ags_remove_region_from_selection_new
-ags_set_output_device_get_type
-ags_set_output_device_new
-ags_sound_provider_get_type
-ags_sound_provider_set_soundcard
-ags_sound_provider_get_soundcard
-ags_sound_provider_set_default_soundcard_thread
-ags_sound_provider_get_default_soundcard_thread
-ags_sound_provider_set_sequencer
-ags_sound_provider_get_sequencer
-ags_sound_provider_set_distributed_manager
-ags_sound_provider_get_distributed_manager
-ags_loop_channel_get_type
-ags_loop_channel_new
-ags_envelope_recycling_get_type
-ags_envelope_recycling_new
-ags_play_notation_audio_get_type
-ags_play_notation_audio_new
-ags_volume_channel_run_get_type
-ags_volume_channel_run_new
-ags_mute_recycling_get_type
-ags_mute_recycling_new
-ags_envelope_channel_run_get_type
-ags_envelope_channel_run_new
-ags_count_beats_audio_get_type
-ags_count_beats_audio_new
+ags_notation_get_type
+ags_notation_find_near_timestamp
+ags_notation_add_note
+ags_notation_remove_note_at_position
+ags_notation_get_selection
+ags_notation_is_note_selected
+ags_notation_find_point
+ags_notation_find_region
+ags_notation_free_selection
+ags_notation_add_all_to_selection
+ags_notation_add_point_to_selection
+ags_notation_remove_point_from_selection
+ags_notation_add_region_to_selection
+ags_notation_remove_region_from_selection
+ags_notation_copy_selection
+ags_notation_cut_selection
+ags_notation_insert_from_clipboard
+ags_notation_get_current
+ags_notation_new
+ags_recall_recycling_dummy_get_type
+ags_recall_recycling_dummy_new
+ags_acceleration_get_type
+ags_acceleration_duplicate
+ags_acceleration_new
+ags_midiin_get_type
+ags_midiin_error_quark
+ags_midiin_new
+ags_buffer_audio_signal_get_type
+ags_buffer_audio_signal_new
+ags_prepare_recycling_get_type
+ags_prepare_recycling_new
+ags_prepare_channel_run_get_type
+ags_prepare_channel_run_new
 ags_play_channel_run_get_type
 ags_play_channel_run_new
-ags_route_dssi_audio_get_type
-ags_route_dssi_audio_new
-ags_mute_audio_get_type
-ags_mute_audio_new
-ags_peak_recycling_get_type
-ags_peak_recycling_new
-ags_buffer_channel_run_get_type
-ags_buffer_channel_run_new
+ags_play_channel_run_master_get_type
+ags_play_channel_run_master_streamer_free
+ags_play_channel_run_master_streamer_alloc
+ags_play_channel_run_master_find_streamer
+ags_play_channel_run_master_new
+ags_feed_channel_run_get_type
+ags_feed_channel_run_new
+ags_copy_audio_signal_get_type
+ags_copy_audio_signal_new
 ags_play_channel_get_type
 ags_play_channel_new
-ags_stream_channel_run_get_type
-ags_stream_channel_run_new
+ags_envelope_recycling_get_type
+ags_envelope_recycling_new
+ags_copy_recycling_get_type
+ags_copy_recycling_new
 ags_mute_channel_run_get_type
 ags_mute_channel_run_new
-ags_play_audio_get_type
-ags_play_audio_new
+ags_delay_audio_run_get_type
+ags_delay_audio_run_notation_alloc_output
+ags_delay_audio_run_notation_alloc_input
+ags_delay_audio_run_notation_count
+ags_delay_audio_run_sequencer_alloc_output
+ags_delay_audio_run_sequencer_alloc_input
+ags_delay_audio_run_sequencer_count
+ags_delay_audio_run_new
+ags_envelope_channel_run_get_type
+ags_envelope_channel_run_new
+ags_route_lv2_audio_get_type
+ags_route_lv2_audio_new
+ags_buffer_channel_run_get_type
+ags_buffer_channel_run_new
+ags_play_notation_audio_get_type
+ags_play_notation_audio_new
 ags_count_beats_audio_run_get_type
 ags_count_beats_audio_run_notation_start
 ags_count_beats_audio_run_notation_loop
@@ -488,228 +211,123 @@ ags_count_beats_audio_run_sequencer_start
 ags_count_beats_audio_run_sequencer_loop
 ags_count_beats_audio_run_sequencer_stop
 ags_count_beats_audio_run_new
-ags_mute_channel_get_type
-ags_mute_channel_new
-ags_buffer_audio_signal_get_type
-ags_buffer_audio_signal_new
-ags_mute_audio_signal_get_type
-ags_mute_audio_signal_new
+ags_envelope_channel_get_type
+ags_envelope_channel_new
+ags_volume_audio_signal_get_type
+ags_volume_audio_signal_new
 ags_peak_audio_signal_get_type
 ags_peak_audio_signal_new
-ags_feed_channel_run_get_type
-ags_feed_channel_run_new
-ags_volume_recycling_get_type
-ags_volume_recycling_new
-ags_copy_pattern_channel_get_type
-ags_copy_pattern_channel_template_find_source_and_destination
-ags_copy_pattern_channel_new
+ags_copy_pattern_channel_run_get_type
+ags_copy_pattern_channel_run_new
+ags_volume_channel_get_type
+ags_volume_channel_new
+ags_volume_channel_run_get_type
+ags_volume_channel_run_new
+ags_mute_recycling_get_type
+ags_mute_recycling_new
+ags_envelope_audio_signal_get_type
+ags_envelope_audio_signal_new
+ags_feed_recycling_get_type
+ags_feed_recycling_new
+ags_mute_audio_signal_get_type
+ags_mute_audio_signal_new
+ags_buffer_recycling_get_type
+ags_buffer_recycling_new
+ags_play_audio_signal_get_type
+ags_play_audio_signal_new
+ags_record_midi_audio_get_type
+ags_record_midi_audio_new
+ags_play_pattern_audio_run_get_type
+ags_play_pattern_audio_run_new
+ags_play_note_get_type
+ags_play_note_new
+ags_route_dssi_audio_get_type
+ags_route_dssi_audio_new
+ags_feed_channel_get_type
+ags_feed_channel_new
+ags_peak_recycling_get_type
+ags_peak_recycling_new
+ags_copy_pattern_audio_get_type
+ags_copy_pattern_audio_new
+ags_route_dssi_audio_run_get_type
+ags_route_dssi_audio_run_new
+ags_stream_channel_get_type
+ags_stream_channel_new
+ags_peak_channel_run_get_type
+ags_peak_channel_run_new
 ags_delay_audio_get_type
 ags_delay_audio_notation_duration_changed
 ags_delay_audio_sequencer_duration_changed
 ags_delay_audio_new
-ags_play_notation_audio_run_get_type
-ags_play_notation_audio_run_new
-ags_envelope_channel_get_type
-ags_envelope_channel_new
-ags_play_recycling_get_type
-ags_play_recycling_new
-ags_envelope_audio_signal_get_type
-ags_envelope_audio_signal_new
 ags_loop_channel_run_get_type
 ags_loop_channel_run_new
-ags_copy_notation_audio_run_get_type
-ags_copy_notation_audio_run_new
-ags_play_note_get_type
-ags_play_note_new
-ags_record_midi_audio_run_get_type
-ags_record_midi_audio_run_new
-ags_buffer_recycling_get_type
-ags_buffer_recycling_new
-ags_copy_audio_signal_get_type
-ags_copy_audio_signal_new
-ags_copy_pattern_channel_run_get_type
-ags_copy_pattern_channel_run_new
-ags_buffer_channel_get_type
-ags_buffer_channel_new
-ags_peak_channel_get_type
-ags_peak_channel_retrieve_peak
-ags_peak_channel_new
-ags_peak_channel_run_get_type
-ags_peak_channel_run_new
+ags_stream_channel_run_get_type
+ags_stream_channel_run_new
 ags_copy_channel_get_type
 ags_copy_channel_new
+ags_copy_channel_run_get_type
+ags_copy_channel_run_new
+ags_mute_audio_run_get_type
+ags_mute_audio_run_new
+ags_buffer_channel_get_type
+ags_buffer_channel_new
 ags_stream_recycling_get_type
 ags_stream_recycling_new
-ags_route_lv2_audio_get_type
-ags_route_lv2_audio_new
-ags_feed_channel_get_type
-ags_feed_channel_new
-ags_copy_pattern_audio_get_type
-ags_copy_pattern_audio_new
-ags_play_audio_signal_get_type
-ags_play_audio_signal_new
-ags_route_dssi_audio_run_get_type
-ags_route_dssi_audio_run_new
+ags_route_lv2_audio_run_get_type
+ags_route_lv2_audio_run_new
 ags_stream_get_type
 ags_stream
 ags_stream_new
-ags_volume_audio_signal_get_type
-ags_volume_audio_signal_new
-ags_route_lv2_audio_run_get_type
-ags_route_lv2_audio_run_new
-ags_record_midi_audio_get_type
-ags_record_midi_audio_new
-ags_stream_channel_get_type
-ags_stream_channel_new
-ags_play_audio_file_get_type
-ags_play_audio_file_new
-ags_mute_audio_run_get_type
-ags_mute_audio_run_new
-ags_copy_recycling_get_type
-ags_copy_recycling_new
-ags_delay_audio_run_get_type
-ags_delay_audio_run_notation_alloc_output
-ags_delay_audio_run_notation_alloc_input
-ags_delay_audio_run_notation_count
-ags_delay_audio_run_sequencer_alloc_output
-ags_delay_audio_run_sequencer_alloc_input
-ags_delay_audio_run_sequencer_count
-ags_delay_audio_run_new
-ags_copy_channel_run_get_type
-ags_copy_channel_run_new
-ags_play_channel_run_master_get_type
-ags_play_channel_run_master_streamer_free
-ags_play_channel_run_master_streamer_alloc
-ags_play_channel_run_master_find_streamer
-ags_play_channel_run_master_new
-ags_feed_recycling_get_type
-ags_feed_recycling_new
+ags_record_midi_audio_run_get_type
+ags_record_midi_audio_run_new
+ags_play_audio_get_type
+ags_play_audio_new
+ags_prepare_audio_signal_get_type
+ags_prepare_audio_signal_new
 ags_feed_audio_signal_get_type
 ags_feed_audio_signal_new
 ags_stream_audio_signal_get_type
 ags_stream_audio_signal_new
+ags_copy_notation_audio_run_get_type
+ags_copy_notation_audio_run_new
+ags_play_notation_audio_run_get_type
+ags_play_notation_audio_run_new
+ags_loop_channel_get_type
+ags_loop_channel_new
+ags_play_pattern_audio_get_type
+ags_play_pattern_audio_new
 ags_copy_notation_audio_get_type
 ags_copy_notation_audio_new
+ags_prepare_channel_get_type
+ags_prepare_channel_new
+ags_mute_channel_get_type
+ags_mute_channel_new
+ags_copy_pattern_channel_get_type
+ags_copy_pattern_channel_template_find_source_and_destination
+ags_copy_pattern_channel_new
+ags_volume_recycling_get_type
+ags_volume_recycling_new
+ags_mute_audio_get_type
+ags_mute_audio_new
+ags_count_beats_audio_get_type
+ags_count_beats_audio_new
 ags_copy_pattern_audio_run_get_type
 ags_copy_pattern_audio_run_new
-ags_volume_channel_get_type
-ags_volume_channel_new
-ags_playback_domain_get_type
-ags_playback_domain_new
-ags_jack_devout_get_type
-ags_jack_devout_error_quark
-ags_jack_devout_switch_buffer_flag
-ags_jack_devout_adjust_delay_and_attack
-ags_jack_devout_realloc_buffer
-ags_jack_devout_new
-ags_jack_client_get_type
-ags_jack_client_find_uuid
-ags_jack_client_find
-ags_jack_client_open
-ags_jack_client_add_device
-ags_jack_client_remove_device
-ags_jack_client_add_port
-ags_jack_client_remove_port
-ags_jack_client_activate
-ags_jack_client_deactivate
-ags_jack_client_new
-ags_jack_server_get_type
-ags_jack_server_find_url
-ags_jack_server_find_client
-ags_jack_server_find_port
-ags_jack_server_add_client
-ags_jack_server_remove_client
-ags_jack_server_connect_client
-ags_jack_server_new
-ags_jack_port_get_type
-ags_jack_port_find
-ags_jack_port_register
-ags_jack_port_unregister
-ags_jack_port_new
-ags_jack_midiin_get_type
-ags_jack_midiin_error_quark
-ags_jack_midiin_new
-ags_message_key_on
-ags_message_key_off
-ags_message_key_pressure
-ags_message_change_parameter
-ags_message_change_mode
-ags_message_pitch_bend
-ags_message_set_bpm
-ags_message_set_delay_factor
-ags_recycling_get_type
-ags_recycling_set_soundcard
-ags_recycling_add_audio_signal
-ags_recycling_remove_audio_signal
-ags_recycling_create_audio_signal_with_defaults
-ags_recycling_create_audio_signal_with_frame_count
-ags_recycling_position
-ags_recycling_find_next_channel
-ags_recycling_new
-ags_recall_recycling_dummy_get_type
-ags_recall_recycling_dummy_new
-ags_pattern_get_type
-ags_pattern_find_near_timestamp
-ags_pattern_set_dim
-ags_pattern_is_empty
-ags_pattern_get_bit
-ags_pattern_toggle_bit
-ags_pattern_new
-ags_channel_get_type
-ags_channel_error_quark
-ags_channel_find_recall
-ags_channel_first
-ags_channel_last
-ags_channel_nth
-ags_channel_pad_first
-ags_channel_pad_last
-ags_channel_pad_nth
-ags_channel_first_with_recycling
-ags_channel_last_with_recycling
-ags_channel_prev_with_recycling
-ags_channel_next_with_recycling
-ags_channel_set_soundcard
-ags_channel_set_samplerate
-ags_channel_set_buffer_size
-ags_channel_set_format
-ags_channel_add_remote_channel
-ags_channel_remove_remote_channel
-ags_channel_add_recall_id
-ags_channel_remove_recall_id
-ags_channel_add_recall_container
-ags_channel_remove_recall_container
-ags_channel_add_recall
-ags_channel_remove_recall
-ags_channel_add_pattern
-ags_channel_remove_pattern
-ags_channel_add_effect
-ags_channel_remove_effect
-ags_channel_safe_resize_audio_signal
-ags_channel_duplicate_recall
-ags_channel_resolve_recall
-ags_channel_init_recall
-ags_channel_play
-ags_channel_done
-ags_channel_cancel
-ags_channel_remove
-ags_channel_recall_id_set
-ags_channel_find_port
-ags_channel_set_link
-ags_channel_set_recycling
-ags_channel_recursive_reset_recycling_context
-ags_channel_recycling_changed
-ags_channel_recursive_set_property
-ags_channel_recursive_play_init
-ags_channel_recursive_play_threaded
-ags_channel_recursive_play
-ags_channel_tillrecycling_cancel
-ags_channel_recursive_reset_recall_ids
-ags_channel_new
-ags_recall_audio_run_get_type
-ags_recall_audio_run_new
-ags_recall_channel_get_type
-ags_recall_channel_find_channel
-ags_recall_channel_new
+ags_peak_channel_get_type
+ags_peak_channel_retrieve_peak
+ags_peak_channel_new
+ags_play_audio_file_get_type
+ags_play_audio_file_new
+ags_play_recycling_get_type
+ags_play_recycling_new
+ags_synth_generator_get_type
+ags_synth_generator_new
+ags_recall_ladspa_get_type
+ags_recall_ladspa_load
+ags_recall_ladspa_load_ports
+ags_recall_ladspa_load_conversion
+ags_recall_ladspa_find
+ags_recall_ladspa_new
 ags_recycling_context_get_type
 ags_recycling_context_replace
 ags_recycling_context_add
@@ -724,6 +342,134 @@ ags_recycling_context_remove_child
 ags_recycling_context_get_child_recall_id
 ags_recycling_context_reset_recycling
 ags_recycling_context_new
+ags_recall_audio_signal_get_type
+ags_recall_audio_signal_new
+ags_recall_channel_run_get_type
+ags_recall_channel_run_run_order_changed
+ags_recall_channel_run_get_run_order
+ags_recall_channel_run_new
+ags_ipatch_get_type
+ags_ipatch_check_suffix
+ags_ipatch_new
+ags_audio_file_get_type
+ags_audio_file_check_suffix
+ags_audio_file_open
+ags_audio_file_open_from_data
+ags_audio_file_rw_open
+ags_audio_file_close
+ags_audio_file_read_audio_signal
+ags_audio_file_seek
+ags_audio_file_write
+ags_audio_file_flush
+ags_audio_file_new
+ags_sndfile_get_type
+ags_sndfile_new
+ags_ipatch_sf2_reader_get_type
+ags_ipatch_sf2_reader_new
+ags_file_read_soundcard
+ags_file_write_soundcard
+ags_file_read_soundcard_list
+ags_file_write_soundcard_list
+ags_file_read_playback
+ags_file_write_playback
+ags_file_read_playback_list
+ags_file_write_playback_list
+ags_file_read_audio
+ags_file_write_audio
+ags_file_read_audio_list
+ags_file_write_audio_list
+ags_file_read_channel
+ags_file_write_channel
+ags_file_read_channel_list
+ags_file_write_channel_list
+ags_file_read_input
+ags_file_write_input
+ags_file_read_output
+ags_file_write_output
+ags_file_read_recall
+ags_file_write_recall
+ags_file_read_recall_list
+ags_file_write_recall_list
+ags_file_read_recall_container
+ags_file_write_recall_container
+ags_file_read_recall_container_list
+ags_file_write_recall_container_list
+ags_file_read_recall_audio
+ags_file_write_recall_audio
+ags_file_read_recall_audio_run
+ags_file_write_recall_audio_run
+ags_file_read_recall_channel
+ags_file_write_recall_channel
+ags_file_read_recall_channel_run
+ags_file_write_recall_channel_run
+ags_file_read_recall_recycling
+ags_file_write_recall_recycling
+ags_file_read_recall_audio_signal
+ags_file_write_recall_audio_signal
+ags_file_read_port
+ags_file_write_port
+ags_file_read_port_list
+ags_file_write_port_list
+ags_file_read_recycling
+ags_file_write_recycling
+ags_file_read_recycling_list
+ags_file_write_recycling_list
+ags_file_read_audio_signal
+ags_file_write_audio_signal
+ags_file_read_audio_signal_list
+ags_file_write_audio_signal_list
+ags_file_read_stream
+ags_file_write_stream
+ags_file_read_stream_list
+ags_file_write_stream_list
+ags_file_read_pattern
+ags_file_write_pattern
+ags_file_read_pattern_list
+ags_file_write_pattern_list
+ags_file_read_pattern_data
+ags_file_write_pattern_data
+ags_file_read_pattern_data_list
+ags_file_write_pattern_data_list
+ags_file_read_notation
+ags_file_write_notation
+ags_file_read_notation_list
+ags_file_write_notation_list
+ags_file_read_note
+ags_file_write_note
+ags_file_read_note_list
+ags_file_write_note_list
+ags_file_read_automation
+ags_file_write_automation
+ags_file_read_automation_list
+ags_file_write_automation_list
+ags_file_read_acceleration
+ags_file_write_acceleration
+ags_file_read_acceleration_list
+ags_file_write_acceleration_list
+ags_file_read_task
+ags_file_write_task
+ags_file_read_task_list
+ags_file_write_task_list
+ags_file_read_embedded_audio
+ags_file_write_embedded_audio
+ags_file_read_embedded_audio_list
+ags_file_write_embedded_audio_list
+ags_ipatch_dls2_reader_get_type
+ags_ipatch_dls2_reader_new
+ags_audio_file_link_get_type
+ags_audio_file_link_new
+ags_remote_input_get_type
+ags_remote_input_new
+ags_remote_output_get_type
+ags_remote_output_new
+ags_remote_channel_get_type
+ags_remote_channel_error_quark
+ags_remote_channel_new
+ags_recall_factory_get_type
+ags_recall_factory_create
+ags_recall_factory_remove
+ags_recall_factory_get_instance
+ags_recall_factory_new
 ags_playable_get_type
 ags_playable_error_quark
 ags_playable_open
@@ -745,6 +491,92 @@ ags_playable_flush
 ags_playable_seek
 ags_playable_close
 ags_playable_read_audio_signal
+ags_input_get_type
+ags_input_open_file
+ags_input_apply_synth
+ags_input_is_active
+ags_input_next_active
+ags_input_new
+ags_recall_channel_run_dummy_get_type
+ags_recall_channel_run_dummy_new
+ags_output_get_type
+ags_output_find_first_input_recycling
+ags_output_find_last_input_recycling
+ags_output_new
+ags_devout_get_type
+ags_devout_error_quark
+ags_devout_switch_buffer_flag
+ags_devout_adjust_delay_and_attack
+ags_devout_realloc_buffer
+ags_devout_new
+ags_recall_ladspa_run_get_type
+ags_recall_ladspa_run_new
+ags_audio_get_type
+ags_audio_set_soundcard
+ags_audio_set_flags
+ags_audio_unset_flags
+ags_audio_check_connection
+ags_audio_set_audio_channels
+ags_audio_set_pads
+ags_audio_set_samplerate
+ags_audio_set_buffer_size
+ags_audio_set_format
+ags_audio_set_sequence_length
+ags_audio_add_audio_connection
+ags_audio_remove_audio_connection
+ags_audio_add_notation
+ags_audio_remove_notation
+ags_audio_add_automation
+ags_audio_remove_automation
+ags_audio_add_recall_id
+ags_audio_remove_recall_id
+ags_audio_add_recycling_context
+ags_audio_remove_recycling_context
+ags_audio_add_recall_container
+ags_audio_remove_recall_container
+ags_audio_add_recall
+ags_audio_remove_recall
+ags_audio_recall_change_state
+ags_audio_init_run
+ags_audio_duplicate_recall
+ags_audio_init_recall
+ags_audio_resolve_recall
+ags_audio_is_playing
+ags_audio_play
+ags_audio_tact
+ags_audio_done
+ags_audio_cancel
+ags_audio_remove
+ags_audio_find_port
+ags_audio_open_files
+ags_audio_recursive_set_property
+ags_audio_recursive_play_init
+ags_audio_new
+ags_automation_get_type
+ags_automation_find_port
+ags_automation_find_near_timestamp
+ags_automation_add_acceleration
+ags_automation_remove_acceleration_at_position
+ags_automation_get_selection
+ags_automation_is_acceleration_selected
+ags_automation_find_point
+ags_automation_find_region
+ags_automation_free_selection
+ags_automation_add_point_to_selection
+ags_automation_remove_point_from_selection
+ags_automation_add_region_to_selection
+ags_automation_remove_region_from_selection
+ags_automation_add_all_to_selection
+ags_automation_copy_selection
+ags_automation_cut_selection
+ags_automation_merge_clipboard
+ags_automation_insert_from_clipboard
+ags_automation_get_current
+ags_automation_get_specifier_unique
+ags_automation_find_specifier
+ags_automation_find_specifier_with_type_and_line
+ags_automation_get_value
+ags_automation_new
 ags_audio_buffer_util_format_from_soundcard
 ags_audio_buffer_util_get_copy_mode
 ags_audio_buffer_util_clear_float
@@ -824,27 +656,107 @@ ags_audio_buffer_util_copy_double_to_s64
 ags_audio_buffer_util_copy_double_to_float
 ags_audio_buffer_util_copy_double_to_double
 ags_audio_buffer_util_copy_buffer_to_buffer
-ags_recall_audio_signal_get_type
-ags_recall_audio_signal_new
-ags_notation_get_type
-ags_notation_find_near_timestamp
-ags_notation_add_note
-ags_notation_remove_note_at_position
-ags_notation_get_selection
-ags_notation_is_note_selected
-ags_notation_find_point
-ags_notation_find_region
-ags_notation_free_selection
-ags_notation_add_all_to_selection
-ags_notation_add_point_to_selection
-ags_notation_remove_point_from_selection
-ags_notation_add_region_to_selection
-ags_notation_remove_region_from_selection
-ags_notation_copy_selection
-ags_notation_cut_selection
-ags_notation_insert_from_clipboard
-ags_notation_get_current
-ags_notation_new
+ags_recall_channel_get_type
+ags_recall_channel_find_channel
+ags_recall_channel_new
+ags_pattern_get_type
+ags_pattern_find_near_timestamp
+ags_pattern_set_dim
+ags_pattern_is_empty
+ags_pattern_get_bit
+ags_pattern_toggle_bit
+ags_pattern_new
+ags_note_get_type
+ags_note_find_prev
+ags_note_find_next
+ags_note_to_raw_midi
+ags_note_to_seq_event
+ags_note_from_raw_midi
+ags_note_from_seq_event
+ags_note_duplicate
+ags_note_new
+ags_note_new_with_offset
+ags_channel_iter_alloc
+ags_channel_iter_free
+ags_channel_iter_prev
+ags_channel_iter_next
+ags_synth_util_sin_s8
+ags_synth_util_sin_s16
+ags_synth_util_sin_s24
+ags_synth_util_sin_s32
+ags_synth_util_sin_s64
+ags_synth_util_sin_float
+ags_synth_util_sin_double
+ags_synth_util_sawtooth_s8
+ags_synth_util_sawtooth_s16
+ags_synth_util_sawtooth_s24
+ags_synth_util_sawtooth_s32
+ags_synth_util_sawtooth_s64
+ags_synth_util_sawtooth_float
+ags_synth_util_sawtooth_double
+ags_synth_util_triangle_s8
+ags_synth_util_triangle_s16
+ags_synth_util_triangle_s24
+ags_synth_util_triangle_s32
+ags_synth_util_triangle_s64
+ags_synth_util_triangle_float
+ags_synth_util_triangle_double
+ags_synth_util_square_s8
+ags_synth_util_square_s16
+ags_synth_util_square_s24
+ags_synth_util_square_s32
+ags_synth_util_square_s64
+ags_synth_util_square_float
+ags_synth_util_square_double
+ags_synth_util_sin
+ags_synth_util_sawtooth
+ags_synth_util_triangle
+ags_synth_util_square
+ags_recall_dssi_run_get_type
+ags_recall_dssi_run_new
+ags_recycling_get_type
+ags_recycling_set_soundcard
+ags_recycling_add_audio_signal
+ags_recycling_remove_audio_signal
+ags_recycling_create_audio_signal_with_defaults
+ags_recycling_create_audio_signal_with_frame_count
+ags_recycling_position
+ags_recycling_find_next_channel
+ags_recycling_is_active
+ags_recycling_new
+ags_jack_midiin_get_type
+ags_jack_midiin_error_quark
+ags_jack_midiin_new
+ags_jack_server_get_type
+ags_jack_server_find_url
+ags_jack_server_find_client
+ags_jack_server_find_port
+ags_jack_server_add_client
+ags_jack_server_remove_client
+ags_jack_server_connect_client
+ags_jack_server_new
+ags_jack_port_get_type
+ags_jack_port_find
+ags_jack_port_register
+ags_jack_port_unregister
+ags_jack_port_new
+ags_jack_devout_get_type
+ags_jack_devout_error_quark
+ags_jack_devout_switch_buffer_flag
+ags_jack_devout_adjust_delay_and_attack
+ags_jack_devout_realloc_buffer
+ags_jack_devout_new
+ags_jack_client_get_type
+ags_jack_client_find_uuid
+ags_jack_client_find
+ags_jack_client_open
+ags_jack_client_add_device
+ags_jack_client_remove_device
+ags_jack_client_add_port
+ags_jack_client_remove_port
+ags_jack_client_activate
+ags_jack_client_deactivate
+ags_jack_client_new
 ags_port_get_type
 ags_port_safe_read
 ags_port_safe_write
@@ -853,140 +765,133 @@ ags_port_safe_get_property
 ags_port_safe_set_property
 ags_port_find_specifier
 ags_port_new
-ags_recall_ladspa_get_type
-ags_recall_ladspa_load
-ags_recall_ladspa_load_ports
-ags_recall_ladspa_load_conversion
-ags_recall_ladspa_find
-ags_recall_ladspa_new
-ags_channel_iter_alloc
-ags_channel_iter_free
-ags_channel_iter_prev
-ags_channel_iter_next
 ags_recall_dssi_get_type
 ags_recall_dssi_load
 ags_recall_dssi_load_ports
 ags_recall_dssi_load_conversion
 ags_recall_dssi_find
 ags_recall_dssi_new
-ags_recall_ladspa_run_get_type
-ags_recall_ladspa_run_new
-ags_input_get_type
-ags_input_open_file
-ags_input_apply_synth
-ags_input_new
-ags_synth_generator_get_type
-ags_synth_generator_new
-ags_audio_file_link_get_type
-ags_audio_file_link_new
-ags_audio_file_get_type
-ags_audio_file_check_suffix
-ags_audio_file_open
-ags_audio_file_open_from_data
-ags_audio_file_rw_open
-ags_audio_file_close
-ags_audio_file_read_audio_signal
-ags_audio_file_seek
-ags_audio_file_write
-ags_audio_file_flush
-ags_audio_file_new
-ags_sndfile_get_type
-ags_sndfile_new
-ags_ipatch_dls2_reader_get_type
-ags_ipatch_dls2_reader_new
-ags_ipatch_get_type
-ags_ipatch_check_suffix
-ags_ipatch_new
-ags_file_read_soundcard
-ags_file_write_soundcard
-ags_file_read_soundcard_list
-ags_file_write_soundcard_list
-ags_file_read_playback
-ags_file_write_playback
-ags_file_read_playback_list
-ags_file_write_playback_list
-ags_file_read_audio
-ags_file_write_audio
-ags_file_read_audio_list
-ags_file_write_audio_list
-ags_file_read_channel
-ags_file_write_channel
-ags_file_read_channel_list
-ags_file_write_channel_list
-ags_file_read_input
-ags_file_write_input
-ags_file_read_output
-ags_file_write_output
-ags_file_read_recall
-ags_file_write_recall
-ags_file_read_recall_list
-ags_file_write_recall_list
-ags_file_read_recall_container
-ags_file_write_recall_container
-ags_file_read_recall_container_list
-ags_file_write_recall_container_list
-ags_file_read_recall_audio
-ags_file_write_recall_audio
-ags_file_read_recall_audio_run
-ags_file_write_recall_audio_run
-ags_file_read_recall_channel
-ags_file_write_recall_channel
-ags_file_read_recall_channel_run
-ags_file_write_recall_channel_run
-ags_file_read_recall_recycling
-ags_file_write_recall_recycling
-ags_file_read_recall_audio_signal
-ags_file_write_recall_audio_signal
-ags_file_read_port
-ags_file_write_port
-ags_file_read_port_list
-ags_file_write_port_list
-ags_file_read_recycling
-ags_file_write_recycling
-ags_file_read_recycling_list
-ags_file_write_recycling_list
-ags_file_read_audio_signal
-ags_file_write_audio_signal
-ags_file_read_audio_signal_list
-ags_file_write_audio_signal_list
-ags_file_read_stream
-ags_file_write_stream
-ags_file_read_stream_list
-ags_file_write_stream_list
-ags_file_read_pattern
-ags_file_write_pattern
-ags_file_read_pattern_list
-ags_file_write_pattern_list
-ags_file_read_pattern_data
-ags_file_write_pattern_data
-ags_file_read_pattern_data_list
-ags_file_write_pattern_data_list
-ags_file_read_notation
-ags_file_write_notation
-ags_file_read_notation_list
-ags_file_write_notation_list
-ags_file_read_note
-ags_file_write_note
-ags_file_read_note_list
-ags_file_write_note_list
-ags_file_read_automation
-ags_file_write_automation
-ags_file_read_automation_list
-ags_file_write_automation_list
-ags_file_read_acceleration
-ags_file_write_acceleration
-ags_file_read_acceleration_list
-ags_file_write_acceleration_list
-ags_file_read_task
-ags_file_write_task
-ags_file_read_task_list
-ags_file_write_task_list
-ags_file_read_embedded_audio
-ags_file_write_embedded_audio
-ags_file_read_embedded_audio_list
-ags_file_write_embedded_audio_list
-ags_ipatch_sf2_reader_get_type
-ags_ipatch_sf2_reader_new
+ags_recall_recycling_get_type
+ags_recall_recycling_get_child_source
+ags_recall_recycling_new
+ags_append_audio_get_type
+ags_append_audio_new
+ags_apply_synth_get_type
+ags_apply_synth_new
+ags_tic_device_get_type
+ags_tic_device_new
+ags_resize_audio_get_type
+ags_resize_audio_new
+ags_set_muted_get_type
+ags_set_muted_new
+ags_apply_sequencer_length_get_type
+ags_apply_sequencer_length_new
+ags_apply_tact_get_type
+ags_apply_tact_new
+ags_apply_bpm_get_type
+ags_apply_bpm_new
+ags_init_audio_get_type
+ags_init_audio_new
+ags_cancel_channel_get_type
+ags_cancel_channel_new
+ags_free_selection_get_type
+ags_free_selection_new
+ags_open_single_file_get_type
+ags_open_single_file_new
+ags_append_audio_threaded_get_type
+ags_append_audio_threaded_new
+ags_apply_presets_get_type
+ags_apply_presets_soundcard
+ags_apply_presets_new
+ags_clear_buffer_get_type
+ags_clear_buffer_new
+ags_remove_region_from_selection_get_type
+ags_remove_region_from_selection_new
+ags_remove_recall_container_get_type
+ags_remove_recall_container_new
+ags_init_channel_get_type
+ags_init_channel_new
+ags_add_effect_get_type
+ags_add_effect_new
+ags_open_file_get_type
+ags_open_file_new
+ags_add_soundcard_get_type
+ags_add_soundcard_new
+ags_cancel_recall_get_type
+ags_cancel_recall_new
+ags_append_channel_get_type
+ags_append_channel_new
+ags_change_soundcard_get_type
+ags_change_soundcard_new
+ags_set_output_device_get_type
+ags_set_output_device_new
+ags_add_region_to_selection_get_type
+ags_add_region_to_selection_new
+ags_remove_recall_get_type
+ags_remove_recall_new
+ags_add_point_to_selection_get_type
+ags_add_point_to_selection_new
+ags_remove_audio_signal_get_type
+ags_remove_audio_signal_new
+ags_set_samplerate_get_type
+ags_set_samplerate_new
+ags_switch_buffer_flag_get_type
+ags_switch_buffer_flag_new
+ags_reset_audio_connection_get_type
+ags_reset_audio_connection_new
+ags_remove_audio_get_type
+ags_remove_audio_new
+ags_remove_note_get_type
+ags_remove_note_new
+ags_save_file_get_type
+ags_save_file_new
+ags_add_note_get_type
+ags_add_note_new
+ags_remove_point_from_selection_get_type
+ags_remove_point_from_selection_new
+ags_set_audio_channels_get_type
+ags_set_audio_channels_new
+ags_export_output_get_type
+ags_export_output_new
+ags_append_recall_get_type
+ags_append_recall_new
+ags_set_input_device_get_type
+ags_set_input_device_new
+ags_unref_audio_signal_get_type
+ags_unref_audio_signal_new
+ags_add_recall_get_type
+ags_add_recall_new
+ags_seek_soundcard_get_type
+ags_seek_soundcard_new
+ags_set_format_get_type
+ags_set_format_new
+ags_cancel_audio_get_type
+ags_cancel_audio_new
+ags_add_audio_get_type
+ags_add_audio_new
+ags_set_buffer_size_get_type
+ags_set_buffer_size_new
+ags_add_recall_container_get_type
+ags_add_recall_container_new
+ags_open_sf2_sample_get_type
+ags_open_sf2_sample_new
+ags_remove_soundcard_get_type
+ags_remove_soundcard_new
+ags_link_channel_get_type
+ags_link_channel_new
+ags_add_audio_signal_get_type
+ags_add_audio_signal_new
+ags_toggle_pattern_bit_get_type
+ags_toggle_pattern_bit_refresh_gui
+ags_toggle_pattern_bit_new
+ags_start_sequencer_get_type
+ags_start_sequencer_new
+ags_notify_soundcard_get_type
+ags_notify_soundcard_new
+ags_start_soundcard_get_type
+ags_start_soundcard_new
+ags_recall_audio_run_get_type
+ags_recall_audio_run_new
 ags_recall_container_get_type
 ags_recall_container_get_recall_audio
 ags_recall_container_get_recall_audio_run
@@ -994,6 +899,271 @@ ags_recall_container_get_recall_channel
 ags_recall_container_get_recall_channel_run
 ags_recall_container_find
 ags_recall_container_new
+ags_record_thread_get_type
+ags_record_thread_new
+ags_audio_thread_get_type
+ags_audio_thread_new
+ags_audio_loop_get_type
+ags_audio_loop_add_audio
+ags_audio_loop_remove_audio
+ags_audio_loop_add_channel
+ags_audio_loop_remove_channel
+ags_audio_loop_add_recall
+ags_audio_loop_remove_recall
+ags_audio_loop_new
+ags_soundcard_thread_get_type
+ags_soundcard_thread_find_soundcard
+ags_soundcard_thread_new
+ags_sequencer_thread_get_type
+ags_sequencer_thread_interval_timeout
+ags_sequencer_thread_find_sequencer
+ags_sequencer_thread_new
+ags_export_thread_get_type
+ags_export_thread_find_soundcard
+ags_export_thread_new
+ags_recycling_thread_get_type
+ags_recycling_thread_worker_alloc
+ags_recycling_thread_add_worker
+ags_recycling_thread_remove_worker
+ags_recycling_thread_play_channel
+ags_recycling_thread_play_audio
+ags_recycling_thread_find_child
+ags_recycling_thread_fifo
+ags_recycling_thread_new
+ags_channel_thread_get_type
+ags_channel_thread_new
+ags_iterator_thread_get_type
+ags_iterator_thread_children_ready
+ags_iterator_thread_new
+ags_recycling_thread_iterate_callback
+ags_recall_lv2_get_type
+ags_recall_lv2_load
+ags_recall_lv2_load_ports
+ags_recall_lv2_load_conversion
+ags_recall_lv2_find
+ags_recall_lv2_new
+ags_fifoout_get_type
+ags_fifoout_error_quark
+ags_fifoout_adjust_delay_and_attack
+ags_fifoout_realloc_buffer
+ags_fifoout_new
+ags_recall_get_type
+ags_recall_set_flags
+ags_recall_load_automation
+ags_recall_unload_automation
+ags_recall_resolve_dependencies
+ags_recall_child_added
+ags_recall_run_init_pre
+ags_recall_run_init_inter
+ags_recall_run_init_post
+ags_recall_automate
+ags_recall_run_pre
+ags_recall_run_inter
+ags_recall_run_post
+ags_recall_stop_persistent
+ags_recall_done
+ags_recall_cancel
+ags_recall_remove
+ags_recall_is_done
+ags_recall_duplicate
+ags_recall_set_recall_id
+ags_recall_set_soundcard_recursive
+ags_recall_notify_dependency
+ags_recall_add_dependency
+ags_recall_remove_dependency
+ags_recall_get_dependencies
+ags_recall_remove_child
+ags_recall_add_child
+ags_recall_get_children
+ags_recall_get_by_effect
+ags_recall_find_recall_id_with_effect
+ags_recall_find_type
+ags_recall_find_template
+ags_recall_template_find_type
+ags_recall_template_find_all_type
+ags_recall_find_type_with_recycling_context
+ags_recall_find_recycling_context
+ags_recall_find_provider
+ags_recall_template_find_provider
+ags_recall_find_provider_with_recycling_context
+ags_recall_run_init
+ags_recall_handler_alloc
+ags_recall_add_handler
+ags_recall_remove_handler
+ags_recall_lock_port
+ags_recall_unlock_port
+ags_recall_new
+ags_recall_lv2_run_get_type
+ags_recall_lv2_run_new
+ags_playback_domain_get_type
+ags_playback_domain_set_audio_thread
+ags_playback_domain_get_audio_thread
+ags_playback_domain_add_playback
+ags_playback_domain_remove_playback
+ags_playback_domain_new
+ags_sound_provider_get_type
+ags_sound_provider_set_soundcard
+ags_sound_provider_get_soundcard
+ags_sound_provider_set_default_soundcard_thread
+ags_sound_provider_get_default_soundcard_thread
+ags_sound_provider_set_sequencer
+ags_sound_provider_get_sequencer
+ags_sound_provider_set_distributed_manager
+ags_sound_provider_get_distributed_manager
+ags_recall_audio_get_type
+ags_recall_audio_new
+ags_channel_get_type
+ags_channel_error_quark
+ags_channel_find_recall
+ags_channel_first
+ags_channel_last
+ags_channel_nth
+ags_channel_pad_first
+ags_channel_pad_last
+ags_channel_pad_nth
+ags_channel_first_with_recycling
+ags_channel_last_with_recycling
+ags_channel_prev_with_recycling
+ags_channel_next_with_recycling
+ags_channel_set_soundcard
+ags_channel_set_samplerate
+ags_channel_set_buffer_size
+ags_channel_set_format
+ags_channel_add_remote_channel
+ags_channel_remove_remote_channel
+ags_channel_add_recall_id
+ags_channel_remove_recall_id
+ags_channel_add_recall_container
+ags_channel_remove_recall_container
+ags_channel_add_recall
+ags_channel_remove_recall
+ags_channel_add_pattern
+ags_channel_remove_pattern
+ags_channel_add_effect
+ags_channel_remove_effect
+ags_channel_safe_resize_audio_signal
+ags_channel_duplicate_recall
+ags_channel_resolve_recall
+ags_channel_init_recall
+ags_channel_play
+ags_channel_done
+ags_channel_cancel
+ags_channel_remove
+ags_channel_recall_id_set
+ags_channel_find_port
+ags_channel_set_link
+ags_channel_set_recycling
+ags_channel_recursive_reset_recycling_context
+ags_channel_recycling_changed
+ags_channel_recursive_set_property
+ags_channel_recursive_play_init
+ags_channel_recursive_play_threaded
+ags_channel_recursive_play
+ags_channel_tillrecycling_cancel
+ags_channel_recursive_reset_recall_ids
+ags_channel_new
+ags_audio_signal_get_type
+ags_stream_alloc
+ags_stream_free
+ags_audio_signal_set_samplerate
+ags_audio_signal_set_buffer_size
+ags_audio_signal_set_format
+ags_audio_signal_get_length_till_current
+ags_audio_signal_add_stream
+ags_audio_signal_stream_resize
+ags_audio_signal_stream_safe_resize
+ags_audio_signal_realloc_buffer_size
+ags_audio_signal_duplicate_stream
+ags_audio_signal_get_template
+ags_audio_signal_get_stream_current
+ags_audio_signal_get_by_recall_id
+ags_audio_signal_tile
+ags_audio_signal_scale
+ags_audio_signal_feed
+ags_audio_signal_envelope
+ags_audio_signal_is_active
+ags_audio_signal_new
+ags_audio_signal_new_with_length
+ags_audio_application_context_get_type
+ags_audio_application_context_new
+ags_audio_connection_get_type
+ags_audio_connection_find
+ags_audio_connection_new
+ags_message_key_on
+ags_message_key_off
+ags_message_key_pressure
+ags_message_change_parameter
+ags_message_change_mode
+ags_message_pitch_bend
+ags_message_set_bpm
+ags_message_set_delay_factor
+ags_recall_id_get_type
+ags_recall_id_get_run_stage
+ags_recall_id_set_run_stage
+ags_recall_id_unset_run_stage
+ags_recall_id_find_recycling_context
+ags_recall_id_find_parent_recycling_context
+ags_recall_id_new
+ags_recall_dependency_get_type
+ags_recall_dependency_find_dependency
+ags_recall_dependency_find_dependency_by_provider
+ags_recall_dependency_resolve
+ags_recall_dependency_new
+ags_midi_builder_get_type
+ags_midi_builder_header_alloc
+ags_midi_builder_header_free
+ags_midi_builder_track_alloc
+ags_midi_builder_track_free
+ags_midi_builder_track_find_delta_time_with_track_name
+ags_midi_builder_track_insert_midi_message
+ags_midi_builder_track_get_delta_time_offset
+ags_midi_builder_midi_putc
+ags_midi_builder_on_error
+ags_midi_builder_append_header
+ags_midi_builder_append_track
+ags_midi_builder_append_key_on
+ags_midi_builder_append_key_off
+ags_midi_builder_append_key_pressure
+ags_midi_builder_append_change_parameter
+ags_midi_builder_append_change_pitch_bend
+ags_midi_builder_append_change_program
+ags_midi_builder_append_change_pressure
+ags_midi_builder_append_sysex
+ags_midi_builder_append_quarter_frame
+ags_midi_builder_append_song_position
+ags_midi_builder_append_song_select
+ags_midi_builder_append_tune_request
+ags_midi_builder_append_sequence_number
+ags_midi_builder_append_smtpe
+ags_midi_builder_append_tempo
+ags_midi_builder_append_time_signature
+ags_midi_builder_append_key_signature
+ags_midi_builder_append_sequencer_meta_event
+ags_midi_builder_append_text_event
+ags_midi_builder_append_xml_node
+ags_midi_builder_from_xml_doc
+ags_midi_builder_build
+ags_midi_builder_new
+ags_midi_util_is_key_on
+ags_midi_util_is_key_off
+ags_midi_util_is_key_pressure
+ags_midi_util_is_change_parameter
+ags_midi_util_is_pitch_bend
+ags_midi_util_is_change_program
+ags_midi_util_is_change_pressure
+ags_midi_util_is_sysex
+ags_midi_util_is_quarter_frame
+ags_midi_util_is_song_position
+ags_midi_util_is_song_select
+ags_midi_util_is_tune_request
+ags_midi_util_is_meta_event
+ags_midi_util_to_smf
+ags_midi_util_envelope_to_velocity
+ags_midi_util_velocity_to_envelope
+ags_midi_util_envelope_to_pressure
+ags_midi_util_pressure_to_envelope
+ags_midi_util_delta_time_to_offset
+ags_midi_util_offset_to_delta_time
 ags_midi_parser_get_type
 ags_midi_parser_read_gint16
 ags_midi_parser_read_gint24
@@ -1029,26 +1199,39 @@ ags_midi_parser_sequencer_meta_event
 ags_midi_parser_meta_misc
 ags_midi_parser_text_event
 ags_midi_parser_new
-ags_midi_util_is_key_on
-ags_midi_util_is_key_off
-ags_midi_util_is_key_pressure
-ags_midi_util_is_change_parameter
-ags_midi_util_is_pitch_bend
-ags_midi_util_is_change_program
-ags_midi_util_is_change_pressure
-ags_midi_util_is_sysex
-ags_midi_util_is_quarter_frame
-ags_midi_util_is_song_position
-ags_midi_util_is_song_select
-ags_midi_util_is_tune_request
-ags_midi_util_is_meta_event
-ags_midi_util_to_smf
-ags_midi_util_envelope_to_velocity
-ags_midi_util_velocity_to_envelope
-ags_midi_util_envelope_to_pressure
-ags_midi_util_pressure_to_envelope
-ags_midi_util_delta_time_to_offset
-ags_midi_util_offset_to_delta_time
+ags_midi_file_writer_get_type
+ags_midi_file_writer_write_bytes
+ags_midi_file_writer_write_channel_message
+ags_midi_file_writer_write_status_message
+ags_midi_file_writer_new
+ags_midi_file_get_type
+ags_midi_file_open
+ags_midi_file_open_from_data
+ags_midi_file_rw_open
+ags_midi_file_close
+ags_midi_file_read
+ags_midi_file_write
+ags_midi_file_seek
+ags_midi_file_flush
+ags_midi_file_read_gint16
+ags_midi_file_read_gint24
+ags_midi_file_read_gint32
+ags_midi_file_read_varlength
+ags_midi_file_read_text
+ags_midi_file_write_gint16
+ags_midi_file_write_gint24
+ags_midi_file_write_gint32
+ags_midi_file_write_varlength
+ags_midi_file_write_text
+ags_midi_file_read_header
+ags_midi_file_write_header
+ags_midi_file_read_track_data
+ags_midi_file_write_track_data
+ags_midi_file_new
+ags_midi_file_reader_get_type
+ags_midi_file_reader_read_channel_message
+ags_midi_file_reader_read_status_message
+ags_midi_file_reader_new
 ags_midi_buffer_util_get_varlength_size
 ags_midi_buffer_util_put_varlength
 ags_midi_buffer_util_get_varlength
@@ -1104,144 +1287,3 @@ ags_midi_buffer_util_put_end_of_track
 ags_midi_buffer_util_get_end_of_track
 ags_midi_buffer_util_seek_message
 ags_midi_buffer_util_decode
-ags_midi_builder_get_type
-ags_midi_builder_header_alloc
-ags_midi_builder_header_free
-ags_midi_builder_track_alloc
-ags_midi_builder_track_free
-ags_midi_builder_track_find_delta_time_with_track_name
-ags_midi_builder_track_insert_midi_message
-ags_midi_builder_track_get_delta_time_offset
-ags_midi_builder_midi_putc
-ags_midi_builder_on_error
-ags_midi_builder_append_header
-ags_midi_builder_append_track
-ags_midi_builder_append_key_on
-ags_midi_builder_append_key_off
-ags_midi_builder_append_key_pressure
-ags_midi_builder_append_change_parameter
-ags_midi_builder_append_change_pitch_bend
-ags_midi_builder_append_change_program
-ags_midi_builder_append_change_pressure
-ags_midi_builder_append_sysex
-ags_midi_builder_append_quarter_frame
-ags_midi_builder_append_song_position
-ags_midi_builder_append_song_select
-ags_midi_builder_append_tune_request
-ags_midi_builder_append_sequence_number
-ags_midi_builder_append_smtpe
-ags_midi_builder_append_tempo
-ags_midi_builder_append_time_signature
-ags_midi_builder_append_key_signature
-ags_midi_builder_append_sequencer_meta_event
-ags_midi_builder_append_text_event
-ags_midi_builder_append_xml_node
-ags_midi_builder_from_xml_doc
-ags_midi_builder_build
-ags_midi_builder_new
-ags_midi_file_get_type
-ags_midi_file_open
-ags_midi_file_open_from_data
-ags_midi_file_rw_open
-ags_midi_file_close
-ags_midi_file_read
-ags_midi_file_write
-ags_midi_file_seek
-ags_midi_file_flush
-ags_midi_file_read_gint16
-ags_midi_file_read_gint24
-ags_midi_file_read_gint32
-ags_midi_file_read_varlength
-ags_midi_file_read_text
-ags_midi_file_write_gint16
-ags_midi_file_write_gint24
-ags_midi_file_write_gint32
-ags_midi_file_write_varlength
-ags_midi_file_write_text
-ags_midi_file_read_header
-ags_midi_file_write_header
-ags_midi_file_read_track_data
-ags_midi_file_write_track_data
-ags_midi_file_new
-ags_midi_file_writer_get_type
-ags_midi_file_writer_write_bytes
-ags_midi_file_writer_write_channel_message
-ags_midi_file_writer_write_status_message
-ags_midi_file_writer_new
-ags_midi_file_reader_get_type
-ags_midi_file_reader_read_channel_message
-ags_midi_file_reader_read_status_message
-ags_midi_file_reader_new
-ags_remote_channel_get_type
-ags_remote_channel_error_quark
-ags_remote_channel_new
-ags_remote_output_get_type
-ags_remote_output_new
-ags_remote_input_get_type
-ags_remote_input_new
-ags_recall_audio_get_type
-ags_recall_audio_new
-ags_acceleration_get_type
-ags_acceleration_duplicate
-ags_acceleration_new
-ags_recall_factory_get_type
-ags_recall_factory_create
-ags_recall_factory_remove
-ags_recall_factory_get_instance
-ags_recall_factory_new
-ags_recall_recycling_get_type
-ags_recall_recycling_get_child_source
-ags_recall_recycling_new
-ags_recall_lv2_get_type
-ags_recall_lv2_load
-ags_recall_lv2_load_ports
-ags_recall_lv2_load_conversion
-ags_recall_lv2_find
-ags_recall_lv2_new
-ags_devout_get_type
-ags_devout_error_quark
-ags_devout_switch_buffer_flag
-ags_devout_adjust_delay_and_attack
-ags_devout_realloc_buffer
-ags_devout_new
-ags_audio_get_type
-ags_audio_set_soundcard
-ags_audio_set_flags
-ags_audio_unset_flags
-ags_audio_check_connection
-ags_audio_set_audio_channels
-ags_audio_set_pads
-ags_audio_set_samplerate
-ags_audio_set_buffer_size
-ags_audio_set_format
-ags_audio_set_sequence_length
-ags_audio_add_audio_connection
-ags_audio_remove_audio_connection
-ags_audio_add_notation
-ags_audio_remove_notation
-ags_audio_add_automation
-ags_audio_remove_automation
-ags_audio_add_recall_id
-ags_audio_remove_recall_id
-ags_audio_add_recycling_context
-ags_audio_remove_recycling_context
-ags_audio_add_recall_container
-ags_audio_remove_recall_container
-ags_audio_add_recall
-ags_audio_remove_recall
-ags_audio_recall_change_state
-ags_audio_init_run
-ags_audio_duplicate_recall
-ags_audio_init_recall
-ags_audio_resolve_recall
-ags_audio_is_playing
-ags_audio_play
-ags_audio_tact
-ags_audio_done
-ags_audio_cancel
-ags_audio_remove
-ags_audio_find_port
-ags_audio_open_files
-ags_audio_recursive_set_property
-ags_audio_recursive_play_init
-ags_audio_new
diff --git a/libags_gui.sym b/libags_gui.sym
index d3ea17c..041686a 100644
--- a/libags_gui.sym
+++ b/libags_gui.sym
@@ -1,15 +1,38 @@
-ags_container_add_all
-ags_dial_get_type
-ags_dial_draw
-ags_dial_value_changed
-ags_dial_new
-ags_vindicator_get_type
-ags_vindicator_new
+ags_htimebar_new
+ags_expander_set_get_type
+ags_expander_set_child_alloc
+ags_expander_set_child_find
+ags_expander_set_set_flags
+ags_expander_set_add
+ags_expander_set_remove
+ags_expander_set_new
 ags_indicator_get_type
 ags_indicator_new
-ags_timebar_new
+ags_ruler_get_type
+ags_ruler_new
+ags_expander_get_type
+ags_expander_child_alloc
+ags_expander_child_find
+ags_expander_add
+ags_expander_remove
+ags_expander_new
+ags_vindicator_get_type
+ags_vindicator_new
+ags_hindicator_get_type
+ags_hindicator_new
+ags_hled_array_get_type
+ags_hled_array_new
+ags_vled_array_get_type
+ags_vled_array_new
+ags_container_add_all
 ags_table_get_type
 ags_table_new
+ags_waveform_get_type
+ags_waveform_new
+ags_led_get_type
+ags_led_set_active
+ags_led_unset_active
+ags_led_new
 ags_cartesian_get_type
 ags_plot_alloc
 ags_plot_free
@@ -26,27 +49,13 @@ ags_cartesian_linear_y_label_func
 ags_cartesian_reallocate_label
 ags_cartesian_fill_label
 ags_cartesian_new
-ags_led_get_type
-ags_led_set_active
-ags_led_unset_active
-ags_led_new
-ags_waveform_get_type
-ags_waveform_new
-ags_ruler_get_type
-ags_ruler_new
-ags_expander_get_type
-ags_expander_child_alloc
-ags_expander_child_find
-ags_expander_add
-ags_expander_remove
-ags_expander_new
-ags_expander_set_get_type
-ags_expander_set_child_alloc
-ags_expander_set_child_find
-ags_expander_set_set_flags
-ags_expander_set_add
-ags_expander_set_remove
-ags_expander_set_new
-ags_htimebar_new
-ags_hindicator_get_type
-ags_hindicator_new
+ags_led_array_get_type
+ags_led_array_set_led_count
+ags_led_array_unset_all
+ags_led_array_set_nth
+ags_led_array_new
+ags_dial_get_type
+ags_dial_draw
+ags_dial_value_changed
+ags_dial_new
+ags_timebar_new
diff --git a/libags_server.sym b/libags_server.sym
index 8d93dd5..badd662 100644
--- a/libags_server.sym
+++ b/libags_server.sym
@@ -1,13 +1,18 @@
-ags_remote_task_get_type
-ags_remote_task_launch
-ags_remote_task_launch_timed
-ags_remote_task_new
+ags_service_provider_get_type
+ags_service_provider_set_registry
+ags_service_provider_get_registry
+ags_service_provider_set_server
+ags_service_provider_get_server
 ags_server_get_type
 ags_server_start
 ags_server_lookup
 ags_server_create_object
 ags_server_object_set_property
 ags_server_new
+ags_remote_task_get_type
+ags_remote_task_launch
+ags_remote_task_launch_timed
+ags_remote_task_new
 ags_registry_get_type
 ags_registry_entry_alloc
 ags_registry_add
@@ -16,8 +21,3 @@ ags_registry_entry_bulk
 ags_registry_new
 ags_server_application_context_get_type
 ags_server_application_context_new
-ags_service_provider_get_type
-ags_service_provider_set_registry
-ags_service_provider_get_registry
-ags_service_provider_set_server
-ags_service_provider_get_server
diff --git a/libags_thread.sym b/libags_thread.sym
index d9bc337..3791330 100644
--- a/libags_thread.sym
+++ b/libags_thread.sym
@@ -1,22 +1,48 @@
+ags_condition_manager_get_type
+ags_condition_manager_get_application_condition
+ags_condition_manager_insert
+ags_condition_manager_remove
+ags_condition_manager_lookup
+ags_condition_manager_get_instance
+ags_condition_manager_new
+ags_history_get_type
+ags_history_new
+ags_timestamp_factory_get_type
+ags_timestamp_factory_create
+ags_timestamp_factory_get_instance
+ags_timestamp_factory_new
+ags_mutex_manager_get_type
+ags_mutex_manager_get_application_mutex
+ags_mutex_manager_insert
+ags_mutex_manager_remove
+ags_mutex_manager_lookup
+ags_mutex_manager_get_instance
+ags_mutex_manager_new
+ags_file_read_thread
+ags_file_write_thread
+ags_file_read_thread_list
+ags_file_write_thread_list
+ags_file_read_thread_pool
+ags_file_write_thread_pool
+ags_file_read_timestamp
+ags_file_write_timestamp
+ags_file_read_timestamp_list
+ags_file_write_timestamp_list
 ags_thread_application_context_get_type
 ags_thread_application_context_register_types
 ags_thread_application_context_new
-ags_autosave_thread_get_type
-ags_autosave_thread_new
-ags_returnable_thread_get_type
-ags_returnable_thread_safe_run
-ags_returnable_thread_connect_safe_run
-ags_returnable_thread_disconnect_safe_run
-ags_returnable_thread_new
-ags_task_thread_get_type
-ags_task_thread_append_task
-ags_task_thread_append_tasks
-ags_task_thread_append_cyclic_task
-ags_task_thread_remove_cyclic_task
-ags_task_thread_clear_cache
-ags_task_thread_new
-ags_generic_main_loop_get_type
-ags_generic_main_loop_new
+ags_concurrency_provider_get_type
+ags_concurrency_provider_get_mutex_manager
+ags_concurrency_provider_get_main_loop
+ags_concurrency_provider_get_task_thread
+ags_concurrency_provider_get_thread_pool
+ags_concurrency_provider_get_worker
+ags_concurrency_provider_set_worker
+ags_timestamp_get_type
+ags_timestamp_new
+ags_task_completion_get_type
+ags_task_completion_complete
+ags_task_completion_new
 ags_thread_get_type
 ags_thread_resume_handler
 ags_thread_suspend_handler
@@ -70,56 +96,53 @@ ags_thread_self
 ags_thread_chaos_tree
 ags_thread_is_chaos_tree
 ags_thread_new
-ags_task_completion_get_type
-ags_task_completion_complete
-ags_task_completion_new
-ags_timestamp_factory_get_type
-ags_timestamp_factory_create
-ags_timestamp_factory_get_instance
-ags_timestamp_factory_new
-ags_timestamp_get_type
-ags_timestamp_new
-ags_polling_thread_get_type
-ags_polling_thread_fd_position
-ags_polling_thread_add_poll_fd
-ags_polling_thread_remove_poll_fd
-ags_polling_thread_new
-ags_history_get_type
-ags_history_new
+ags_autosave_thread_get_type
+ags_autosave_thread_new
+ags_returnable_thread_get_type
+ags_returnable_thread_safe_run
+ags_returnable_thread_connect_safe_run
+ags_returnable_thread_disconnect_safe_run
+ags_returnable_thread_new
+ags_task_get_type
+ags_task_launch
+ags_task_failure
+ags_task_new
 ags_poll_fd_get_type
 ags_poll_fd_dispatch
 ags_poll_fd_new
-ags_single_thread_get_type
-ags_single_thread_new
-ags_mutex_manager_get_type
-ags_mutex_manager_get_application_mutex
-ags_mutex_manager_insert
-ags_mutex_manager_remove
-ags_mutex_manager_lookup
-ags_mutex_manager_get_instance
-ags_mutex_manager_new
-ags_file_read_thread
-ags_file_write_thread
-ags_file_read_thread_list
-ags_file_write_thread_list
-ags_file_read_thread_pool
-ags_file_write_thread_pool
-ags_file_read_timestamp
-ags_file_write_timestamp
-ags_file_read_timestamp_list
-ags_file_write_timestamp_list
-ags_timestamp_thread_get_type
-ags_timestamp_thread_new
-ags_concurrency_provider_get_type
-ags_concurrency_provider_get_mutex_manager
-ags_concurrency_provider_get_main_loop
-ags_concurrency_provider_get_task_thread
-ags_concurrency_provider_get_thread_pool
+ags_generic_main_loop_get_type
+ags_generic_main_loop_new
 ags_thread_pool_get_type
 ags_thread_pool_pull
 ags_thread_pool_start
 ags_thread_pool_new
-ags_task_get_type
-ags_task_launch
-ags_task_failure
-ags_task_new
+ags_single_thread_get_type
+ags_single_thread_new
+ags_polling_thread_get_type
+ags_polling_thread_fd_position
+ags_polling_thread_add_poll_fd
+ags_polling_thread_remove_poll_fd
+ags_polling_thread_new
+ags_timestamp_thread_get_type
+ags_timestamp_thread_new
+ags_worker_thread_get_type
+ags_woker_thread_do_poll_loop
+ags_worker_thread_do_poll
+ags_worker_thread_new
+ags_task_thread_get_type
+ags_task_thread_append_task
+ags_task_thread_append_tasks
+ags_task_thread_append_cyclic_task
+ags_task_thread_remove_cyclic_task
+ags_task_thread_clear_cache
+ags_task_thread_new
+ags_destroy_worker_get_type
+ags_destroy_entry_alloc
+ags_destroy_worker_add
+ags_destroy_worker_new
+ags_condition_manager_get_type
+ags_condition_manager_insert
+ags_condition_manager_remove
+ags_condition_manager_lookup
+ags_condition_manager_get_instance
+ags_condition_manager_new
diff --git a/unit-tests.mk b/unit-tests.mk
new file mode 100644
index 0000000..32930ca
--- /dev/null
+++ b/unit-tests.mk
@@ -0,0 +1,100 @@
+# unit tests
+check_PROGRAMS += \
+	ags_thread_test \
+	ags_turtle_test \
+	ags_audio_application_context_test \
+	ags_devout_test \
+	ags_audio_test \
+	ags_channel_test \
+	ags_recycling_test \
+	ags_audio_signal_test \
+	ags_recall_test \
+	ags_pattern_test \
+	ags_notation_test \
+	ags_automation_test \
+	ags_midi_buffer_util_test \
+	ags_xorg_application_context_test
+
+# thread unit test
+ags_thread_test_SOURCES = ags/test/thread/ags_thread_test.c
+ags_thread_test_CFLAGS = $(CFLAGS) $(LIBXML2_CFLAGS) $(GOBJECT_CFLAGS)
+ags_thread_test_LDFLAGS = -lcunit -lm -pthread -lrt $(LDFLAGS) $(LIBXML2_LIBS) $(GOBJECT_LIBS)
+ags_thread_test_LDADD = libags_thread.la libags.la
+
+# turtle unit test
+ags_turtle_test_SOURCES = ags/test/lib/ags_turtle_test.c
+ags_turtle_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_turtle_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_turtle_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# audio application context unit test
+ags_audio_application_context_test_SOURCES = ags/test/audio/ags_audio_application_context_test.c
+ags_audio_application_context_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_audio_application_context_test_LDFLAGS = $(LDFLAGS) -pthread
+ags_audio_application_context_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# devout unit test
+ags_devout_test_SOURCES = ags/test/audio/ags_devout_test.c
+ags_devout_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_devout_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_devout_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# audio unit test
+ags_audio_test_SOURCES = ags/test/audio/ags_audio_test.c
+ags_audio_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_audio_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_audio_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# channel unit test
+ags_channel_test_SOURCES = ags/test/audio/ags_channel_test.c
+ags_channel_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_channel_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_channel_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# recycling unit test
+ags_recycling_test_SOURCES = ags/test/audio/ags_recycling_test.c
+ags_recycling_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_recycling_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_recycling_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# audio signal unit test
+ags_audio_signal_test_SOURCES = ags/test/audio/ags_audio_signal_test.c
+ags_audio_signal_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_audio_signal_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_audio_signal_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# recall unit test
+ags_recall_test_SOURCES = ags/test/audio/ags_recall_test.c
+ags_recall_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_recall_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_recall_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lrt -lm $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# pattern unit test
+ags_pattern_test_SOURCES = ags/test/audio/ags_pattern_test.c
+ags_pattern_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_pattern_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_pattern_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lm -lrt $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# notation unit test
+ags_notation_test_SOURCES = ags/test/audio/ags_notation_test.c
+ags_notation_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_notation_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_notation_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lm -lrt $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# automation unit test
+ags_automation_test_SOURCES = ags/test/audio/ags_automation_test.c
+ags_automation_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_automation_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_automation_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lm -lrt $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# midi buffer util unit test
+ags_midi_buffer_util_test_SOURCES = ags/test/audio/midi/ags_midi_buffer_util_test.c
+ags_midi_buffer_util_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS)
+ags_midi_buffer_util_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_midi_buffer_util_test_LDADD = libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lm -lrt  $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS)
+
+# xorg application context unit test
+ags_xorg_application_context_test_SOURCES = ags/test/X/ags_xorg_application_context_test.c
+ags_xorg_application_context_test_CFLAGS = $(CFLAGS) $(LIBAO_CFLAGS) $(LIBASOUND2_CFLAGS) $(LIBXML2_CFLAGS) $(SNDFILE_CFLAGS) $(LIBINSTPATCH_CFLAGS) $(GOBJECT_CFLAGS) $(JACK_CFLAGS) $(FONTCONFIG_CFLAGS) $(GDKPIXBUF_CFLAGS) $(CAIRO_CFLAGS) $(GTK_CFLAGS)
+ags_xorg_application_context_test_LDFLAGS = -pthread $(LDFLAGS)
+ags_xorg_application_context_test_LDADD = libgsequencer.la libags_audio.la libags_server.la libags_gui.la libags_thread.la libags.la -lcunit -lm -lrt $(LIBAO_LIBS) $(LIBASOUND2_LIBS) $(LIBXML2_LIBS) $(SNDFILE_LIBS) $(LIBINSTPATCH_LIBS) $(GOBJECT_LIBS) $(JACK_LIBS) $(FONTCONFIG_LIBS) $(GDKPIXBUF_LIBS) $(CAIRO_LIBS) $(GTK_LIBS)

-- 
gsequencer packaging



More information about the pkg-multimedia-commits mailing list