[SCM] gsequencer/master: merged patches by topic
jkraehemann-guest at users.alioth.debian.org
jkraehemann-guest at users.alioth.debian.org
Sun Feb 5 18:07:25 UTC 2017
The following commit has been merged in the master branch:
commit 5236e4f04bf2d9c9d3d2f6dd92aad5bb9f5f86b3
Author: Joël Krähemann <jkraehemann-guest at users.alioth.debian.org>
Date: Sun Feb 5 19:06:07 2017 +0100
merged patches by topic
diff --git a/debian/patches/wish-recall-audio.patch b/debian/patches/improved-disable-output-port-automation.patch
similarity index 60%
rename from debian/patches/wish-recall-audio.patch
rename to debian/patches/improved-disable-output-port-automation.patch
index a2f3526..172c3af 100644
--- a/debian/patches/wish-recall-audio.patch
+++ b/debian/patches/improved-disable-output-port-automation.patch
@@ -17,3 +17,18 @@ Last-Update: 2017-02-02
if(ags_automation_find_port(audio->automation,
automation_port->data) == NULL){
current = ags_automation_new((GObject *) audio,
+--- a/ags/audio/ags_recall_channel.c
++++ b/ags/audio/ags_recall_channel.c
+@@ -425,6 +425,12 @@
+ }
+
+ 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/debian/patches/improved-enable-builtin-port-automation.patch b/debian/patches/improved-enable-builtin-port-automation.patch
new file mode 100644
index 0000000..78a7857
--- /dev/null
+++ b/debian/patches/improved-enable-builtin-port-automation.patch
@@ -0,0 +1,400 @@
+Description: This is a wishlist patch. It uses the modified AgsPort type of
+ ags-mute recall in order to use the built-in effect by automation.
+Author: Joël Krähmann <jkraehemann at gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-02-02
+--- a/ags/audio/recall/ags_mute_audio_signal.c
++++ b/ags/audio/recall/ags_mute_audio_signal.c
+@@ -245,21 +245,21 @@
+ /* 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 */
+--- 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);
+@@ -43,6 +45,8 @@
+
+ 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
+@@ -181,20 +185,26 @@
+
+ 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;
++
++ 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);
+
+- /* */
++ /* set port */
+ AGS_RECALL(mute_audio)->port = port;
+ }
+
+@@ -262,9 +272,20 @@
+ 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
+@@ -311,12 +332,45 @@
+ {
+ 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:
+ *
+--- 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);
+@@ -43,6 +45,8 @@
+
+ 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
+@@ -181,19 +185,26 @@
+
+ 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;
+
++ 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);
+
++ /* set port */
+ AGS_RECALL(mute_channel)->port = port;
+ }
+
+@@ -260,9 +271,20 @@
+ 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
+@@ -309,12 +331,45 @@
+ {
+ 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:
+ *
+--- a/ags/audio/recall/ags_volume_audio_signal.c
++++ b/ags/audio/recall/ags_volume_audio_signal.c
+@@ -231,10 +231,10 @@
+ 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);
++ volume = g_value_get_float(&value);
+
+ for(i = 0; i < buffer_size; i++){
+ switch(AGS_RECALL_AUDIO_SIGNAL(recall)->source->format){
+--- 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);
+@@ -40,6 +41,8 @@
+ void ags_volume_channel_set_ports(AgsPlugin *plugin, GList *port);
+ void ags_volume_channel_finalize(GObject *gobject);
+
++static AgsPortDescriptor* ags_volume_channel_get_volume_port_descriptor();
++
+ /**
+ * SECTION:ags_volume_channel
+ * @short_description: volumes channel
+@@ -174,15 +177,20 @@
+ "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);
+
+- volume_channel->volume->port_value.ags_port_double = 1.0;
++ volume_channel->volume->port_value.ags_port_float = 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);
+
++ /* set port */
+ AGS_RECALL(volume_channel)->port = port;
+ }
+
+@@ -249,9 +257,20 @@
+ 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
+@@ -293,6 +312,38 @@
+ 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/debian/patches/improved-generic-output-widget.patch b/debian/patches/improved-generic-output-widget.patch
new file mode 100644
index 0000000..64c0319
--- /dev/null
+++ b/debian/patches/improved-generic-output-widget.patch
@@ -0,0 +1,2604 @@
+Description: This is a wishlist patch. It changes the recall handler to the
+ generic callback, introduced in view of plugin output ports. It is responsible
+ for redrawing visible feedback.
+Author: Joël Krähmann <jkraehemann at gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-02-02
+--- a/ags/X/machine/ags_drum_input_line.c
++++ b/ags/X/machine/ags_drum_input_line.c
+@@ -101,7 +101,7 @@
+ 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 @@
+ 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);
+
+@@ -446,7 +446,7 @@
+ 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->callback = G_CALLBACK(ags_line_output_port_run_post_callback);
+ recall_handler->data = (gpointer) line;
+
+ ags_recall_add_handler(AGS_RECALL(play_peak_channel_run), recall_handler);
+@@ -462,7 +462,7 @@
+ 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->callback = G_CALLBACK(ags_line_output_port_run_post_callback);
+ recall_handler->data = (gpointer) line;
+
+ ags_recall_add_handler(AGS_RECALL(recall_peak_channel_run), recall_handler);
+--- 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 @@
+ 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 @@
+ 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 @@
+ 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 @@
+ {
+ 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 @@
+ 0);
+
+ effect_bulk->plugin_browser = (GtkDialog *) ags_plugin_browser_new((GtkWidget *) effect_bulk);
++
++ effect_bulk->queued_drawing = NULL;
+ }
+
+ void
+@@ -698,6 +712,41 @@
+ }
+
+ 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 +764,17 @@
+ }
+ }
+
++/**
++ * 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)
+@@ -731,6 +791,36 @@
+ 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 +838,7 @@
+ AgsRecallContainer *recall_container;
+ AgsRecallChannelRunDummy *recall_channel_run_dummy;
+ AgsRecallLadspa *recall_ladspa;
++ AgsRecallHandler *recall_handler;
+
+ AgsAddRecallContainer *add_recall_container;
+ AgsAddRecall *add_recall;
+@@ -769,6 +860,8 @@
+ guint pads, audio_channels;
+ gdouble step;
+ guint port_count;
++ gboolean has_output_port;
++
+ guint x, y;
+ guint i, j;
+ guint k;
+@@ -838,6 +931,8 @@
+
+ task = NULL;
+ retport = NULL;
++
++ has_output_port = FALSE;
+
+ for(i = 0; i < pads; i++){
+ for(j = 0; j < audio_channels; j++){
+@@ -858,6 +953,7 @@
+ 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 +968,10 @@
+
+ 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{
+@@ -905,6 +1005,17 @@
+ FALSE);
+ ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
+
++ /* recall handler of output port */
++ if(has_output_port){
++ recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
++
++ recall_handler->signal_name = "run-post\0";
++ recall_handler->callback = G_CALLBACK(ags_effect_bulk_output_port_run_post_callback);
++ recall_handler->data = (gpointer) effect_bulk;
++
++ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
++ }
++
+ /* ladspa recall */
+ recall_container = ags_recall_container_new();
+ ags_audio_add_recall_container(effect_bulk->audio,
+@@ -961,6 +1072,17 @@
+ FALSE);
+ ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
+
++ /* recall handler of output port */
++ if(has_output_port){
++ recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
++
++ recall_handler->signal_name = "run-post\0";
++ recall_handler->callback = G_CALLBACK(ags_effect_bulk_output_port_run_post_callback);
++ recall_handler->data = (gpointer) effect_bulk;
++
++ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
++ }
++
+ /* iterate */
+ pthread_mutex_lock(channel_mutex);
+
+@@ -1010,9 +1132,17 @@
+ }
+
+ 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;
+@@ -1129,6 +1259,13 @@
+
+ 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 +1313,7 @@
+ AgsRecallContainer *recall_container;
+ AgsRecallChannelRunDummy *recall_channel_run_dummy;
+ AgsRecallDssi *recall_dssi;
++ AgsRecallHandler *recall_handler;
+
+ AgsAddRecallContainer *add_recall_container;
+ AgsAddRecall *add_recall;
+@@ -1197,6 +1335,8 @@
+ guint pads, audio_channels;
+ gdouble step;
+ guint port_count;
++ gboolean has_output_port;
++
+ guint x, y;
+ guint i, j;
+ guint k;
+@@ -1266,6 +1406,8 @@
+
+ task = NULL;
+ retport = NULL;
++
++ has_output_port = FALSE;
+
+ for(i = 0; i < pads; i++){
+ for(j = 0; j < audio_channels; j++){
+@@ -1313,6 +1455,10 @@
+ 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 +1484,18 @@
+ (GObject *) recall_channel_run_dummy,
+ TRUE);
+ ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
++
++ /* recall handler of output port */
++ if(has_output_port){
++ recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
++
++ recall_handler->signal_name = "run-post\0";
++ recall_handler->callback = G_CALLBACK(ags_effect_bulk_output_port_run_post_callback);
++ recall_handler->data = (gpointer) effect_bulk;
+
++ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
++ }
++
+ /* dssi recall */
+ recall_container = ags_recall_container_new();
+ ags_audio_add_recall_container(effect_bulk->audio,
+@@ -1401,6 +1558,17 @@
+ FALSE);
+ ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
+
++ /* recall handler of output port */
++ if(has_output_port){
++ recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
++
++ recall_handler->signal_name = "run-post\0";
++ recall_handler->callback = G_CALLBACK(ags_effect_bulk_output_port_run_post_callback);
++ recall_handler->data = (gpointer) effect_bulk;
++
++ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
++ }
++
+ /* iterate */
+ pthread_mutex_lock(channel_mutex);
+
+@@ -1448,9 +1616,17 @@
+ }
+
+ 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;
+@@ -1571,6 +1747,13 @@
+ #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 +1797,7 @@
+ AgsRecallContainer *recall_container;
+ AgsRecallChannelRunDummy *recall_channel_run_dummy;
+ AgsRecallLv2 *recall_lv2;
++ AgsRecallHandler *recall_handler;
+
+ AgsAddRecallContainer *add_recall_container;
+ AgsAddRecall *add_recall;
+@@ -1641,6 +1825,8 @@
+ gdouble step;
+ guint pads, audio_channels;
+ guint port_count;
++ gboolean has_output_port;
++
+ guint x, y;
+ guint i, j;
+ guint k;
+@@ -1712,6 +1898,8 @@
+
+ task = NULL;
+ retport = NULL;
++
++ has_output_port = FALSE;
+
+ for(i = 0; i < pads; i++){
+ for(j = 0; j < audio_channels; j++){
+@@ -1761,6 +1949,10 @@
+ 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);
+@@ -1787,6 +1979,17 @@
+ TRUE);
+ ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
+
++ /* recall handler of output port */
++ if(has_output_port){
++ recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
++
++ recall_handler->signal_name = "run-post\0";
++ recall_handler->callback = G_CALLBACK(ags_effect_bulk_output_port_run_post_callback);
++ recall_handler->data = (gpointer) effect_bulk;
++
++ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
++ }
++
+ /* lv2 recall */
+ recall_container = ags_recall_container_new();
+ ags_audio_add_recall_container(effect_bulk->audio,
+@@ -1850,7 +2053,18 @@
+ (GObject *) recall_channel_run_dummy,
+ FALSE);
+ ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
+-
++
++ /* recall handler of output port */
++ if(has_output_port){
++ recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
++
++ recall_handler->signal_name = "run-post\0";
++ recall_handler->callback = G_CALLBACK(ags_effect_bulk_output_port_run_post_callback);
++ recall_handler->data = (gpointer) effect_bulk;
++
++ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
++ }
++
+ /* iterate */
+ pthread_mutex_lock(channel_mutex);
+
+@@ -1898,9 +2112,17 @@
+ }
+
+ 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;
+@@ -1980,6 +2202,13 @@
+ 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 +2441,16 @@
+ }
+
+ 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 +2881,29 @@
+ }
+
+ /**
++ * 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
+--- 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,7 +19,18 @@
+
+ #include <ags/X/ags_effect_bulk_callbacks.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_machine.h>
++#include <ags/X/ags_bulk_member.h>
+ #include <ags/X/ags_plugin_browser.h>
+
+ void
+@@ -149,3 +160,129 @@
+ pads_old);
+ }
+ }
++
++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)){
++ GtkAdjustment *adjustment;
++
++ gdouble average_peak;
++
++ child = GTK_BIN(list->data)->child;
++
++ average_peak = 0.0;
++
++ /* copy port list */
++ port_start = g_list_concat(g_list_copy(AGS_BULK_MEMBER(list->data)->bulk_port),
++ g_list_copy(AGS_BULK_MEMBER(list->data)->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,
++ AGS_BULK_MEMBER(list->data)->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 */
++ 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);
++
++ /* 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();
++}
+--- 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 @@
+ 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__*/
+--- a/ags/X/ags_effect_bulk.h
++++ b/ags/X/ags_effect_bulk.h
+@@ -76,6 +76,8 @@
+
+ GList *plugin;
+ GtkDialog *plugin_browser;
++
++ GList *queued_drawing;
+ };
+
+ struct _AgsEffectBulkClass
+@@ -112,6 +114,7 @@
+
+ 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_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);
+
+--- 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 @@
+ 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 @@
+ 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 @@
+ 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 @@
+ 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 @@
+ GTK_WIDGET(effect_line->table),
+ FALSE, FALSE,
+ 0);
++
++ effect_line->queued_drawing = NULL;
+ }
+
+ void
+@@ -537,6 +554,25 @@
+ 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,
+@@ -547,6 +583,8 @@
+ AgsAddLineMember *add_line_member;
+ GtkAdjustment *adjustment;
+
++ AgsRecallHandler *recall_handler;
++
+ AgsLadspaPlugin *ladspa_plugin;
+
+ AgsMutexManager *mutex_manager;
+@@ -558,11 +596,17 @@
+
+ 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 +626,6 @@
+ 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 +634,44 @@
+
+ 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,8 +684,25 @@
+ 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);
+
+ /* load ports */
+@@ -641,9 +729,17 @@
+ }
+
+ 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;
++ }
+ }
+
+ if(control_type_name != NULL){
+@@ -754,6 +850,13 @@
+ 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
+@@ -792,6 +895,8 @@
+ AgsAddLineMember *add_line_member;
+ GtkAdjustment *adjustment;
+
++ AgsRecallHandler *recall_handler;
++
+ AgsLv2Plugin *lv2_plugin;
+
+ AgsMutexManager *mutex_manager;
+@@ -803,12 +908,18 @@
+
+ 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 +938,6 @@
+ 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 +946,49 @@
+
+ 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 +996,27 @@
+ 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);
++
+ /* load ports */
+ port_descriptor = AGS_BASE_PLUGIN(lv2_plugin)->port;
+
+@@ -887,9 +1042,17 @@
+ }
+
+ 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;
++ }
+ }
+
+ if(control_type_name != NULL){
+@@ -975,6 +1138,13 @@
+ 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
+@@ -1163,6 +1333,10 @@
+ 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 +1349,12 @@
+ 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;
+@@ -1327,6 +1507,29 @@
+ }
+
+ /**
++ * 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
+ *
+--- a/ags/X/ags_effect_line_callbacks.c
++++ b/ags/X/ags_effect_line_callbacks.c
+@@ -22,8 +22,7 @@
+ #include <ags/object/ags_application_context.h>
+ #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 +40,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,8 +59,6 @@
+ #include <ags/X/ags_dssi_browser.h>
+ #include <ags/X/ags_lv2_browser.h>
+
+-#include <ags/X/task/ags_change_indicator.h>
+-
+ void
+ ags_effect_line_remove_recall_callback(AgsRecall *recall, AgsEffectLine *effect_line)
+ {
+@@ -162,6 +161,21 @@
+ 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,
+@@ -238,4 +252,134 @@
+
+ /* 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)){
++ GtkAdjustment *adjustment;
++
++ AgsPort *current;
++
++ gdouble average_peak;
++ gdouble lower, upper;
++ gdouble range;
++ gdouble peak;
++
++ GValue value = {0,};
++
++ child = GTK_BIN(list->data)->child;
++
++ average_peak = 0.0;
++
++ /* play port */
++ current = AGS_LINE_MEMBER(list->data)->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,
++ AGS_LINE_MEMBER(list->data)->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 */
++ 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);
++
++ /* 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 = AGS_LINE_MEMBER(list->data)->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);
++
++ /* 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();
+ }
+--- a/ags/X/ags_effect_line_callbacks.h
++++ b/ags/X/ags_effect_line_callbacks.h
+@@ -38,4 +38,7 @@
+ 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__*/
+--- a/ags/X/ags_effect_line.h
++++ b/ags/X/ags_effect_line.h
+@@ -63,6 +63,8 @@
+ GtkLabel *label;
+
+ GtkTable *table;
++
++ GList *queued_drawing;
+ };
+
+ struct _AgsEffectLineClass
+@@ -98,6 +100,8 @@
+ 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__*/
+--- a/ags/X/file/ags_gui_file_xml.c
++++ b/ags/X/file/ags_gui_file_xml.c
+@@ -2100,7 +2100,7 @@
+ 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->callback = G_CALLBACK(ags_line_output_port_run_post_callback);
+ recall_handler->data = (gpointer) line;
+
+ ags_recall_add_handler(AGS_RECALL(play_peak_channel_run), recall_handler);
+@@ -2116,7 +2116,7 @@
+ 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->callback = G_CALLBACK(ags_line_output_port_run_post_callback);
+ recall_handler->data = (gpointer) line;
+
+ ags_recall_add_handler(AGS_RECALL(recall_peak_channel_run), recall_handler);
+--- a/ags/X/ags_ladspa_browser.c
++++ b/ags/X/ags_ladspa_browser.c
+@@ -357,6 +357,58 @@
+ }
+
+ /**
++ * 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.
+--- a/ags/X/ags_ladspa_browser_callbacks.c
++++ b/ags/X/ags_ladspa_browser_callbacks.c
+@@ -180,15 +180,29 @@
+ 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++;
+--- a/ags/X/ags_ladspa_browser.h
++++ b/ags/X/ags_ladspa_browser.h
+@@ -56,8 +56,12 @@
+ 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();
+--- 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 @@
+ 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 @@
+ 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 @@
+ 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);
+ }
+
+@@ -743,6 +760,8 @@
+ AgsLineMember *line_member;
+ GtkAdjustment *adjustment;
+
++ AgsRecallHandler *recall_handler;
++
+ AgsLadspaPlugin *ladspa_plugin;
+
+ AgsMutexManager *mutex_manager;
+@@ -754,11 +773,17 @@
+
+ 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(),
+@@ -778,10 +803,6 @@
+ 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);
+
+@@ -790,18 +811,49 @@
+
+ pthread_mutex_unlock(application_mutex);
+
+- /* find ports */
++ /* play - 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);
++ /* 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_line_output_port_run_post_callback);
++ recall_handler->data = (gpointer) 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(line->channel->recall,
+ filename,
+@@ -809,8 +861,25 @@
+ 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_line_output_port_run_post_callback);
++ recall_handler->data = (gpointer) line;
++
++ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
++ }
++
++ g_list_free(recall_start);
++
+ pthread_mutex_unlock(channel_mutex);
+
+ /* load ports */
+@@ -818,7 +887,7 @@
+
+ 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;
+@@ -830,9 +899,17 @@
+ guint step_count;
+
+ 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;
++ }
+ }
+
+ if(control_type_name != NULL){
+@@ -943,8 +1020,15 @@
+ 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
+@@ -977,6 +1061,8 @@
+ AgsLineMember *line_member;
+ GtkAdjustment *adjustment;
+
++ AgsRecallHandler *recall_handler;
++
+ AgsLv2Plugin *lv2_plugin;
+
+ AgsMutexManager *mutex_manager;
+@@ -991,12 +1077,18 @@
+
+ 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);
+@@ -1015,10 +1107,6 @@
+ 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);
+
+@@ -1027,7 +1115,7 @@
+
+ pthread_mutex_unlock(application_mutex);
+
+- /* find ports */
++ /* play - find ports */
+ pthread_mutex_lock(channel_mutex);
+
+ recall_start =
+@@ -1044,8 +1132,32 @@
+ 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_line_output_port_run_post_callback);
++ recall_handler->data = (gpointer) 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(line->channel->recall,
+ filename,
+@@ -1053,10 +1165,27 @@
+ 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_line_output_port_run_post_callback);
++ recall_handler->data = (gpointer) line;
++
++ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
++ }
+
++ g_list_free(recall_start);
++
++ pthread_mutex_unlock(channel_mutex);
++
+ /* load ports */
+ port_descriptor = AGS_BASE_PLUGIN(lv2_plugin)->port;
+
+@@ -1075,9 +1204,17 @@
+ guint step_count;
+
+ 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;
++ }
+ }
+
+ if(control_type_name != NULL){
+@@ -1163,6 +1300,12 @@
+ 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
+@@ -1348,6 +1491,10 @@
+ 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 +1507,12 @@
+ 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);
+
+@@ -1544,7 +1697,7 @@
+ gboolean
+ ags_line_indicator_queue_draw_timeout(GtkWidget *widget)
+ {
+- if(g_hash_table_lookup(ags_indicator_queue_draw,
++ if(g_hash_table_lookup(ags_line_indicator_queue_draw,
+ widget) != NULL){
+ gtk_widget_queue_draw(widget);
+
+--- 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,8 +61,6 @@
+ #include <ags/X/ags_dssi_browser.h>
+ #include <ags/X/ags_lv2_browser.h>
+
+-#include <ags/X/task/ags_change_indicator.h>
+-
+ int
+ ags_line_parent_set_callback(GtkWidget *widget, GtkObject *old_parent, AgsLine *line)
+ {
+@@ -231,8 +232,23 @@
+ 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 +284,8 @@
+ }
+
+ /* free lists */
+- g_list_free(description_start);
+- g_list_free(port_control_start);
++ g_list_free(description_start);
++ g_list_free(port_control_start);
+ }
+ }
+
+@@ -339,72 +355,124 @@
+ }
+
+ void
+-ags_line_peak_run_post_callback(AgsRecall *peak_channel_run,
+- AgsLine *line)
++ags_line_output_port_run_post_callback(AgsRecall *recall,
++ AgsLine *line)
+ {
+ GtkWidget *child;
+
+- AgsPort *port;
+-
+- AgsMutexManager *mutex_manager;
+- AgsTaskThread *task_thread;
+-
+ GList *list, *list_start;
+-
+- gdouble peak;
+-
+- GValue value = {0,};
+-
+- 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);
+
++ /* 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_VINDICATOR ||
++ AGS_LINE_MEMBER(list->data)->widget_type == AGS_TYPE_HINDICATOR ||
++ AGS_LINE_MEMBER(list->data)->widget_type == AGS_TYPE_LED)){
+ GtkAdjustment *adjustment;
+
+- child = GTK_BIN(list->data)->child;
++ AgsPort *current;
++
++ gdouble average_peak;
++ gdouble lower, upper;
++ gdouble range;
++ gdouble peak;
+
+- /* get port */
+- pthread_mutex_lock(application_mutex);
++ GValue value = {0,};
+
+- channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+- (GObject *) line->channel);
++ child = GTK_BIN(list->data)->child;
++
++ average_peak = 0.0;
+
+- pthread_mutex_unlock(application_mutex);
++ /* play port */
++ current = AGS_LINE_MEMBER(list->data)->port;
+
+- pthread_mutex_lock(channel_mutex);
++ if(current == NULL){
++ list = list->next;
++
++ continue;
++ }
++
++ /* check if output port and specifier matches */
++ pthread_mutex_lock(current->mutex);
+
+- port = AGS_PEAK_CHANNEL(AGS_RECALL_CHANNEL_RUN(peak_channel_run)->recall_channel)->peak;
++ if((AGS_PORT_IS_OUTPUT & (current->flags)) == 0 ||
++ current->port_descriptor == NULL ||
++ g_ascii_strcasecmp(current->specifier,
++ AGS_LINE_MEMBER(list->data)->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);
+
+- pthread_mutex_unlock(channel_mutex);
++ /* get range */
++ range = upper - lower;
+
+- /* get peak */
+- g_value_init(&value, G_TYPE_DOUBLE);
+- ags_port_safe_read(port,
++ /* play port - read value */
++ g_value_init(&value, G_TYPE_FLOAT);
++ ags_port_safe_read(current,
+ &value);
+-
+- peak = g_value_get_double(&value);
++
++ peak = g_value_get_float(&value);
+ g_value_unset(&value);
+
+- /* apply */
+- g_object_get(child,
+- "adjustment\0", &adjustment,
+- NULL);
++ /* 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);
++ }
+
+- gtk_adjustment_set_value(adjustment,
+- peak);
++ /* recall port */
++ current = AGS_LINE_MEMBER(list->data)->recall_port;
+
+- break;
++ /* 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);
++
++ /* 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;
+--- a/ags/X/ags_line_callbacks.h
++++ b/ags/X/ags_line_callbacks.h
+@@ -45,8 +45,8 @@
+ AgsLine *line);
+
+ /* AgsRecall - recall */
+-void ags_line_peak_run_post_callback(AgsRecall *peak_channel,
+- AgsLine *line);
++void ags_line_output_port_run_post_callback(AgsRecall *recall,
++ AgsLine *line);
+
+ void ags_line_copy_pattern_done(AgsRecall *recall,
+ AgsLine *line);
+--- a/ags/X/ags_line.h
++++ b/ags/X/ags_line.h
+@@ -72,6 +72,8 @@
+ AgsExpander *expander;
+
+ GtkWidget *indicator;
++
++ GList *queued_drawing;
+ };
+
+ struct _AgsLineClass
+--- 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>
+@@ -553,7 +555,10 @@
+ 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 */
+--- a/ags/X/ags_lv2_browser.c
++++ b/ags/X/ags_lv2_browser.c
+@@ -355,6 +355,58 @@
+ }
+
+ /**
++ * 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.
+--- a/ags/X/ags_lv2_browser_callbacks.c
++++ b/ags/X/ags_lv2_browser_callbacks.c
+@@ -160,15 +160,29 @@
+ 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++;
+--- a/ags/X/ags_lv2_browser.h
++++ b/ags/X/ags_lv2_browser.h
+@@ -56,8 +56,12 @@
+ 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();
+--- a/ags/X/machine/ags_mixer_input_line.c
++++ b/ags/X/machine/ags_mixer_input_line.c
+@@ -62,7 +62,7 @@
+ 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 @@
+ 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);
+
+@@ -270,7 +270,7 @@
+ 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->callback = G_CALLBACK(ags_line_output_port_run_post_callback);
+ recall_handler->data = (gpointer) line;
+
+ ags_recall_add_handler(AGS_RECALL(play_peak_channel_run), recall_handler);
+@@ -286,7 +286,7 @@
+ 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->callback = G_CALLBACK(ags_line_output_port_run_post_callback);
+ recall_handler->data = (gpointer) line;
+
+ ags_recall_add_handler(AGS_RECALL(recall_peak_channel_run), recall_handler);
+--- a/ags/audio/ags_recall_dssi.c
++++ b/ags/audio/ags_recall_dssi.c
+@@ -640,6 +640,12 @@
+ "port-value-type\0", G_TYPE_FLOAT,
+ NULL);
+ 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;
++ }
+
+ current->port_descriptor = port_descriptor->data;
+ ags_recall_dssi_load_conversion(recall_dssi,
+--- a/ags/audio/ags_recall_lv2.c
++++ b/ags/audio/ags_recall_lv2.c
+@@ -440,10 +440,11 @@
+ 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);
+ }
+
+@@ -767,7 +768,13 @@
+ "port-value-is-pointer\0", FALSE,
+ "port-value-type\0", G_TYPE_FLOAT,
+ NULL);
+-
++
++ 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;
++ }
++
+ current->port_descriptor = port_descriptor->data;
+ ags_recall_lv2_load_conversion(recall_lv2,
+ (GObject *) current,
+--- 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>
+@@ -49,6 +51,8 @@
+ void ags_peak_channel_set_ports(AgsPlugin *plugin, GList *port);
+ void ags_peak_channel_finalize(GObject *gobject);
+
++static AgsPortDescriptor* ags_peak_channel_get_peak_port_descriptor();
++
+ /**
+ * SECTION:ags_peak_channel
+ * @short_description: peaks channel
+@@ -171,6 +175,8 @@
+ 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,17 +185,25 @@
+
+ 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);
+
++ 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);
+
+ /* set port */
+@@ -452,14 +466,14 @@
+ current_value = scale_precision * (atan(1.0 / 440.0) / sin(current_value / 22000.0));
+ }
+
+- g_value_init(&value, G_TYPE_DOUBLE);
++ 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);
+@@ -469,6 +483,38 @@
+ 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/debian/patches/wish-hindicator.patch b/debian/patches/mangle-indicator-widget.patch
similarity index 93%
rename from debian/patches/wish-hindicator.patch
rename to debian/patches/mangle-indicator-widget.patch
index 2090b5d..9e746b4 100644
--- a/debian/patches/wish-hindicator.patch
+++ b/debian/patches/mangle-indicator-widget.patch
@@ -178,3 +178,14 @@ Last-Update: 2017-02-02
NULL);
return(indicator);
+--- a/ags/widget/ags_indicator.c
++++ b/ags/widget/ags_indicator.c
+@@ -127,7 +127,7 @@
+ 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);
+ }
+
+ void
diff --git a/debian/patches/wish-recall-h.patch b/debian/patches/mangle-output-port.patch
similarity index 72%
rename from debian/patches/wish-recall-h.patch
rename to debian/patches/mangle-output-port.patch
index 5b98b8f..cfb1c61 100644
--- a/debian/patches/wish-recall-h.patch
+++ b/debian/patches/mangle-output-port.patch
@@ -14,3 +14,13 @@ Last-Update: 2017-02-02
}AgsRecallFlags;
typedef enum{
+--- a/ags/audio/ags_port.h
++++ b/ags/audio/ags_port.h
+@@ -43,6 +43,7 @@
+ typedef enum{
+ AGS_PORT_CONVERT_ALWAYS = 1,
+ AGS_PORT_USE_LADSPA_FLOAT = 1 << 1,
++ AGS_PORT_IS_OUTPUT = 1 << 2,
+ }AgsPortFlags;
+
+ struct _AgsPort
diff --git a/debian/patches/series b/debian/patches/series
index 21c1b39..8b9fd6d 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,3 +1,8 @@
+improved-disable-output-port-automation.patch
+improved-enable-builtin-port-automation.patch
+improved-generic-output-widget.patch
+mangle-indicator-widget.patch
+mangle-output-port.patch
fix-souncard-editor-callbacks.patch
fix-export-thread.patch
fix-gsequencer-main.patch
@@ -7,42 +12,6 @@ fix-record-midi-audio-run.patch
fix-audio-loop.patch
fix-main-loop-c.patch
fix-main-loop-h.patch
-wish-line-c.patch
-wish-effect-line-c.patch
-wish-indicator.patch
-wish-recall-channel.patch
-wish-recall-audio.patch
-wish-gui-file.patch
-wish-port-h.patch
-wish-recall-lv2.patch
-wish-recall-h.patch
-wish-recall-dssi.patch
-wish-peak-channel.patch
-wish-mixer-input-line.patch
-wish-lv2-browser-callbacks.patch
-wish-lv2-browser-h.patch
-wish-ladspa-browser-h.patch
-wish-lv2-browser-c.patch
-wish-line-member.patch
-wish-line-h.patch
-wish-line-callbacks-h.patch
-wish-line-callbacks-c.patch
-wish-ladspa-browser-callbacks.patch
-wish-ladspa-browser-c.patch
-wish-hindicator.patch
-wish-effect-line-h.patch
-wish-effect-line-callbacks-h.patch
-wish-effect-line-callbacks-c.patch
-wish-effect-bulk-h.patch
-wish-effect-bulk-callbacks-h.patch
-wish-effect-bulk-callbacks-c.patch
-wish-effect-bulk-c.patch
-wish-drum-input-line.patch
-wish-volume-channel.patch
-wish-volume-audio-signal.patch
-wish-mute-channel.patch
-wish-mute-audio.patch
-wish-mute-audio-signal.patch
fix-jack-midiin.patch
fix-xorg-application-context.patch
fix-makefile-am.patch
diff --git a/debian/patches/wish-drum-input-line.patch b/debian/patches/wish-drum-input-line.patch
deleted file mode 100644
index 670b975..0000000
--- a/debian/patches/wish-drum-input-line.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-Description: This is a wishlist patch. It changes the recall handler to the
- generic callback, introduced in view of plugin output ports. It is responsible
- for redrawing visible feedback.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/machine/ags_drum_input_line.c
-+++ b/ags/X/machine/ags_drum_input_line.c
-@@ -101,7 +101,7 @@
- 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 @@
- 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);
-
-@@ -446,7 +446,7 @@
- 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->callback = G_CALLBACK(ags_line_output_port_run_post_callback);
- recall_handler->data = (gpointer) line;
-
- ags_recall_add_handler(AGS_RECALL(play_peak_channel_run), recall_handler);
-@@ -462,7 +462,7 @@
- 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->callback = G_CALLBACK(ags_line_output_port_run_post_callback);
- recall_handler->data = (gpointer) line;
-
- ags_recall_add_handler(AGS_RECALL(recall_peak_channel_run), recall_handler);
diff --git a/debian/patches/wish-effect-bulk-c.patch b/debian/patches/wish-effect-bulk-c.patch
deleted file mode 100644
index d5dc4fb..0000000
--- a/debian/patches/wish-effect-bulk-c.patch
+++ /dev/null
@@ -1,540 +0,0 @@
-Description: This is a wishlist patch. It creates the output widgets available
- in AgsLadspaBridge, AgsDssiBridge and AgsLv2Bridge or anyhow related to effect
- bulk.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- 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 @@
- 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 @@
- 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 @@
- 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 @@
- {
- 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 @@
- 0);
-
- effect_bulk->plugin_browser = (GtkDialog *) ags_plugin_browser_new((GtkWidget *) effect_bulk);
-+
-+ effect_bulk->queued_drawing = NULL;
- }
-
- void
-@@ -698,6 +712,41 @@
- }
-
- 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 +764,17 @@
- }
- }
-
-+/**
-+ * 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)
-@@ -731,6 +791,36 @@
- 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 +838,7 @@
- AgsRecallContainer *recall_container;
- AgsRecallChannelRunDummy *recall_channel_run_dummy;
- AgsRecallLadspa *recall_ladspa;
-+ AgsRecallHandler *recall_handler;
-
- AgsAddRecallContainer *add_recall_container;
- AgsAddRecall *add_recall;
-@@ -769,6 +860,8 @@
- guint pads, audio_channels;
- gdouble step;
- guint port_count;
-+ gboolean has_output_port;
-+
- guint x, y;
- guint i, j;
- guint k;
-@@ -838,6 +931,8 @@
-
- task = NULL;
- retport = NULL;
-+
-+ has_output_port = FALSE;
-
- for(i = 0; i < pads; i++){
- for(j = 0; j < audio_channels; j++){
-@@ -858,6 +953,7 @@
- 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 +968,10 @@
-
- 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{
-@@ -905,6 +1005,17 @@
- FALSE);
- ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
-
-+ /* recall handler of output port */
-+ if(has_output_port){
-+ recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
-+
-+ recall_handler->signal_name = "run-post\0";
-+ recall_handler->callback = G_CALLBACK(ags_effect_bulk_output_port_run_post_callback);
-+ recall_handler->data = (gpointer) effect_bulk;
-+
-+ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
-+ }
-+
- /* ladspa recall */
- recall_container = ags_recall_container_new();
- ags_audio_add_recall_container(effect_bulk->audio,
-@@ -961,6 +1072,17 @@
- FALSE);
- ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
-
-+ /* recall handler of output port */
-+ if(has_output_port){
-+ recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
-+
-+ recall_handler->signal_name = "run-post\0";
-+ recall_handler->callback = G_CALLBACK(ags_effect_bulk_output_port_run_post_callback);
-+ recall_handler->data = (gpointer) effect_bulk;
-+
-+ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
-+ }
-+
- /* iterate */
- pthread_mutex_lock(channel_mutex);
-
-@@ -1010,9 +1132,17 @@
- }
-
- 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;
-@@ -1129,6 +1259,13 @@
-
- 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 +1313,7 @@
- AgsRecallContainer *recall_container;
- AgsRecallChannelRunDummy *recall_channel_run_dummy;
- AgsRecallDssi *recall_dssi;
-+ AgsRecallHandler *recall_handler;
-
- AgsAddRecallContainer *add_recall_container;
- AgsAddRecall *add_recall;
-@@ -1197,6 +1335,8 @@
- guint pads, audio_channels;
- gdouble step;
- guint port_count;
-+ gboolean has_output_port;
-+
- guint x, y;
- guint i, j;
- guint k;
-@@ -1266,6 +1406,8 @@
-
- task = NULL;
- retport = NULL;
-+
-+ has_output_port = FALSE;
-
- for(i = 0; i < pads; i++){
- for(j = 0; j < audio_channels; j++){
-@@ -1313,6 +1455,10 @@
- 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 +1484,18 @@
- (GObject *) recall_channel_run_dummy,
- TRUE);
- ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
-+
-+ /* recall handler of output port */
-+ if(has_output_port){
-+ recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
-+
-+ recall_handler->signal_name = "run-post\0";
-+ recall_handler->callback = G_CALLBACK(ags_effect_bulk_output_port_run_post_callback);
-+ recall_handler->data = (gpointer) effect_bulk;
-
-+ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
-+ }
-+
- /* dssi recall */
- recall_container = ags_recall_container_new();
- ags_audio_add_recall_container(effect_bulk->audio,
-@@ -1401,6 +1558,17 @@
- FALSE);
- ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
-
-+ /* recall handler of output port */
-+ if(has_output_port){
-+ recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
-+
-+ recall_handler->signal_name = "run-post\0";
-+ recall_handler->callback = G_CALLBACK(ags_effect_bulk_output_port_run_post_callback);
-+ recall_handler->data = (gpointer) effect_bulk;
-+
-+ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
-+ }
-+
- /* iterate */
- pthread_mutex_lock(channel_mutex);
-
-@@ -1448,9 +1616,17 @@
- }
-
- 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;
-@@ -1571,6 +1747,13 @@
- #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 +1797,7 @@
- AgsRecallContainer *recall_container;
- AgsRecallChannelRunDummy *recall_channel_run_dummy;
- AgsRecallLv2 *recall_lv2;
-+ AgsRecallHandler *recall_handler;
-
- AgsAddRecallContainer *add_recall_container;
- AgsAddRecall *add_recall;
-@@ -1641,6 +1825,8 @@
- gdouble step;
- guint pads, audio_channels;
- guint port_count;
-+ gboolean has_output_port;
-+
- guint x, y;
- guint i, j;
- guint k;
-@@ -1712,6 +1898,8 @@
-
- task = NULL;
- retport = NULL;
-+
-+ has_output_port = FALSE;
-
- for(i = 0; i < pads; i++){
- for(j = 0; j < audio_channels; j++){
-@@ -1761,6 +1949,10 @@
- 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);
-@@ -1787,6 +1979,17 @@
- TRUE);
- ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
-
-+ /* recall handler of output port */
-+ if(has_output_port){
-+ recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
-+
-+ recall_handler->signal_name = "run-post\0";
-+ recall_handler->callback = G_CALLBACK(ags_effect_bulk_output_port_run_post_callback);
-+ recall_handler->data = (gpointer) effect_bulk;
-+
-+ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
-+ }
-+
- /* lv2 recall */
- recall_container = ags_recall_container_new();
- ags_audio_add_recall_container(effect_bulk->audio,
-@@ -1850,7 +2053,18 @@
- (GObject *) recall_channel_run_dummy,
- FALSE);
- ags_connectable_connect(AGS_CONNECTABLE(recall_channel_run_dummy));
--
-+
-+ /* recall handler of output port */
-+ if(has_output_port){
-+ recall_handler = (AgsRecallHandler *) malloc(sizeof(AgsRecallHandler));
-+
-+ recall_handler->signal_name = "run-post\0";
-+ recall_handler->callback = G_CALLBACK(ags_effect_bulk_output_port_run_post_callback);
-+ recall_handler->data = (gpointer) effect_bulk;
-+
-+ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
-+ }
-+
- /* iterate */
- pthread_mutex_lock(channel_mutex);
-
-@@ -1898,9 +2112,17 @@
- }
-
- 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;
-@@ -1980,6 +2202,13 @@
- 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 +2441,16 @@
- }
-
- 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 +2881,29 @@
- }
-
- /**
-+ * 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/debian/patches/wish-effect-bulk-callbacks-c.patch b/debian/patches/wish-effect-bulk-callbacks-c.patch
deleted file mode 100644
index 5550aad..0000000
--- a/debian/patches/wish-effect-bulk-callbacks-c.patch
+++ /dev/null
@@ -1,163 +0,0 @@
-Description: This is a wishlist patch. It provides update functionality of the
- output widgets available to plugins like LADSPA, DSSI or Lv2.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- 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,7 +19,18 @@
-
- #include <ags/X/ags_effect_bulk_callbacks.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_machine.h>
-+#include <ags/X/ags_bulk_member.h>
- #include <ags/X/ags_plugin_browser.h>
-
- void
-@@ -149,3 +160,129 @@
- pads_old);
- }
- }
-+
-+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)){
-+ GtkAdjustment *adjustment;
-+
-+ gdouble average_peak;
-+
-+ child = GTK_BIN(list->data)->child;
-+
-+ average_peak = 0.0;
-+
-+ /* copy port list */
-+ port_start = g_list_concat(g_list_copy(AGS_BULK_MEMBER(list->data)->bulk_port),
-+ g_list_copy(AGS_BULK_MEMBER(list->data)->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,
-+ AGS_BULK_MEMBER(list->data)->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 */
-+ 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);
-+
-+ /* 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/debian/patches/wish-effect-bulk-callbacks-h.patch b/debian/patches/wish-effect-bulk-callbacks-h.patch
deleted file mode 100644
index fe837b1..0000000
--- a/debian/patches/wish-effect-bulk-callbacks-h.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-Description: This is a wishlist patch. It provides the function declaration of
- the update functionality of output widgets.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- 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 @@
- 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/debian/patches/wish-effect-bulk-h.patch b/debian/patches/wish-effect-bulk-h.patch
deleted file mode 100644
index f0e1cbb..0000000
--- a/debian/patches/wish-effect-bulk-h.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-Description: This is a wishlist patch. It provides the declaration of redrawing
- function of output widgets.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/ags_effect_bulk.h
-+++ b/ags/X/ags_effect_bulk.h
-@@ -76,6 +76,8 @@
-
- GList *plugin;
- GtkDialog *plugin_browser;
-+
-+ GList *queued_drawing;
- };
-
- struct _AgsEffectBulkClass
-@@ -112,6 +114,7 @@
-
- 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_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/debian/patches/wish-effect-line-c.patch b/debian/patches/wish-effect-line-c.patch
deleted file mode 100644
index 29e58b3..0000000
--- a/debian/patches/wish-effect-line-c.patch
+++ /dev/null
@@ -1,450 +0,0 @@
-Description: This is a wishlist patch. It creates the output widgets available
- in provided by a plugin added by user via machine editor.
- AgsFFPlayer uses this widget to enable the user to assign plugins to input
- lines.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-03
---- 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 @@
- 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 @@
- 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 @@
- 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 @@
- 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 @@
- GTK_WIDGET(effect_line->table),
- FALSE, FALSE,
- 0);
-+
-+ effect_line->queued_drawing = NULL;
- }
-
- void
-@@ -537,6 +554,25 @@
- 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,
-@@ -547,6 +583,8 @@
- AgsAddLineMember *add_line_member;
- GtkAdjustment *adjustment;
-
-+ AgsRecallHandler *recall_handler;
-+
- AgsLadspaPlugin *ladspa_plugin;
-
- AgsMutexManager *mutex_manager;
-@@ -558,11 +596,17 @@
-
- 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 +626,6 @@
- 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 +634,44 @@
-
- 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,8 +684,25 @@
- 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);
-
- /* load ports */
-@@ -641,9 +729,17 @@
- }
-
- 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;
-+ }
- }
-
- if(control_type_name != NULL){
-@@ -754,6 +850,13 @@
- 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
-@@ -792,6 +895,8 @@
- AgsAddLineMember *add_line_member;
- GtkAdjustment *adjustment;
-
-+ AgsRecallHandler *recall_handler;
-+
- AgsLv2Plugin *lv2_plugin;
-
- AgsMutexManager *mutex_manager;
-@@ -803,12 +908,18 @@
-
- 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 +938,6 @@
- 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 +946,49 @@
-
- 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 +996,27 @@
- 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);
-+
- /* load ports */
- port_descriptor = AGS_BASE_PLUGIN(lv2_plugin)->port;
-
-@@ -887,9 +1042,17 @@
- }
-
- 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;
-+ }
- }
-
- if(control_type_name != NULL){
-@@ -975,6 +1138,13 @@
- 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
-@@ -1163,6 +1333,10 @@
- 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 +1349,12 @@
- 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;
-@@ -1327,6 +1507,29 @@
- }
-
- /**
-+ * 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/debian/patches/wish-effect-line-callbacks-c.patch b/debian/patches/wish-effect-line-callbacks-c.patch
deleted file mode 100644
index 4e684cf..0000000
--- a/debian/patches/wish-effect-line-callbacks-c.patch
+++ /dev/null
@@ -1,196 +0,0 @@
-Description: This is a wishlist patch. It provides update functionality of the
- output widgets available to plugins like LADSPA, DSSI or Lv2.
- This widget is used currently by AgsFFPlayer and AgsSynth.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/ags_effect_line_callbacks.c
-+++ b/ags/X/ags_effect_line_callbacks.c
-@@ -22,8 +22,7 @@
- #include <ags/object/ags_application_context.h>
- #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 +40,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,8 +59,6 @@
- #include <ags/X/ags_dssi_browser.h>
- #include <ags/X/ags_lv2_browser.h>
-
--#include <ags/X/task/ags_change_indicator.h>
--
- void
- ags_effect_line_remove_recall_callback(AgsRecall *recall, AgsEffectLine *effect_line)
- {
-@@ -162,6 +161,21 @@
- 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,
-@@ -238,4 +252,134 @@
-
- /* 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)){
-+ GtkAdjustment *adjustment;
-+
-+ AgsPort *current;
-+
-+ gdouble average_peak;
-+ gdouble lower, upper;
-+ gdouble range;
-+ gdouble peak;
-+
-+ GValue value = {0,};
-+
-+ child = GTK_BIN(list->data)->child;
-+
-+ average_peak = 0.0;
-+
-+ /* play port */
-+ current = AGS_LINE_MEMBER(list->data)->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,
-+ AGS_LINE_MEMBER(list->data)->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 */
-+ 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);
-+
-+ /* 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 = AGS_LINE_MEMBER(list->data)->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);
-+
-+ /* 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/debian/patches/wish-effect-line-callbacks-h.patch b/debian/patches/wish-effect-line-callbacks-h.patch
deleted file mode 100644
index b33382c..0000000
--- a/debian/patches/wish-effect-line-callbacks-h.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-Description: This is a wishlist patch. It provides the function declaration of
- the update functionality of output widgets.
- This widget is currently used by AgsFFPlayer and AgsSynth.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/ags_effect_line_callbacks.h
-+++ b/ags/X/ags_effect_line_callbacks.h
-@@ -38,4 +38,7 @@
- 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/debian/patches/wish-effect-line-h.patch b/debian/patches/wish-effect-line-h.patch
deleted file mode 100644
index 7b98604..0000000
--- a/debian/patches/wish-effect-line-h.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-Description: This is a wishlist patch. It provides the declaration of redrawing
- function of output widgets.
- This widget is currently used by AgsFFPlayer and AgsSynth.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/ags_effect_line.h
-+++ b/ags/X/ags_effect_line.h
-@@ -63,6 +63,8 @@
- GtkLabel *label;
-
- GtkTable *table;
-+
-+ GList *queued_drawing;
- };
-
- struct _AgsEffectLineClass
-@@ -98,6 +100,8 @@
- 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/debian/patches/wish-gui-file.patch b/debian/patches/wish-gui-file.patch
deleted file mode 100644
index 2501b03..0000000
--- a/debian/patches/wish-gui-file.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-Description: This is a wishlist patch. It modifies the recall callback handler
- to use the generic callback ags_line_output_port_run_post_callback().
- This is used by AgsSynthInputLine, AgsDrumInputLine and AgsMixerInputLine.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/file/ags_gui_file_xml.c
-+++ b/ags/X/file/ags_gui_file_xml.c
-@@ -2100,7 +2100,7 @@
- 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->callback = G_CALLBACK(ags_line_output_port_run_post_callback);
- recall_handler->data = (gpointer) line;
-
- ags_recall_add_handler(AGS_RECALL(play_peak_channel_run), recall_handler);
-@@ -2116,7 +2116,7 @@
- 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->callback = G_CALLBACK(ags_line_output_port_run_post_callback);
- recall_handler->data = (gpointer) line;
-
- ags_recall_add_handler(AGS_RECALL(recall_peak_channel_run), recall_handler);
diff --git a/debian/patches/wish-indicator.patch b/debian/patches/wish-indicator.patch
deleted file mode 100644
index cde6f50..0000000
--- a/debian/patches/wish-indicator.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-Description: This is a wishlist patch. It ensures that an adjustment is available.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/widget/ags_indicator.c
-+++ b/ags/widget/ags_indicator.c
-@@ -127,7 +127,7 @@
- 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);
- }
-
- void
diff --git a/debian/patches/wish-ladspa-browser-c.patch b/debian/patches/wish-ladspa-browser-c.patch
deleted file mode 100644
index 6f77e80..0000000
--- a/debian/patches/wish-ladspa-browser-c.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-Description: This is a wishlist patch. It lets you configure the output widget
- of plugins like LADSPA.
- It is used by AgsMixer, AgsDrum, AgsFFPlayer and AgsSynth.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/ags_ladspa_browser.c
-+++ b/ags/X/ags_ladspa_browser.c
-@@ -357,6 +357,58 @@
- }
-
- /**
-+ * 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/debian/patches/wish-ladspa-browser-callbacks.patch b/debian/patches/wish-ladspa-browser-callbacks.patch
deleted file mode 100644
index ec6543b..0000000
--- a/debian/patches/wish-ladspa-browser-callbacks.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-Description: This is a wishlist patch. It distinguishes between input and
- output widgets as showing the port configuration.
- It is used by AgsMixer, AgsDrum, AgsFFPlayer and AgsSynth.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/ags_ladspa_browser_callbacks.c
-+++ b/ags/X/ags_ladspa_browser_callbacks.c
-@@ -180,15 +180,29 @@
- 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/debian/patches/wish-ladspa-browser-h.patch b/debian/patches/wish-ladspa-browser-h.patch
deleted file mode 100644
index 09f995f..0000000
--- a/debian/patches/wish-ladspa-browser-h.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-Description: This is a wishlist patch. It declares the functions to configure
- the output widget of plugins like LADSPA.
- It is used by AgsMixer, AgsDrum, AgsFFPlayer and AgsSynth.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/ags_ladspa_browser.h
-+++ b/ags/X/ags_ladspa_browser.h
-@@ -56,8 +56,12 @@
- 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/debian/patches/wish-line-c.patch b/debian/patches/wish-line-c.patch
deleted file mode 100644
index 27fa477..0000000
--- a/debian/patches/wish-line-c.patch
+++ /dev/null
@@ -1,417 +0,0 @@
-Description: This is a wishlist patch. It modifies the recall callback handler
- to use the generic callback ags_line_output_port_run_post_callback().
- This is used by AgsSynthInputLine, AgsDrumInputLine, AgsMixerInputLine and
- AgsPanelInputLine.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-03
---- 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 @@
- 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 @@
- 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 @@
- 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);
- }
-
-@@ -743,6 +760,8 @@
- AgsLineMember *line_member;
- GtkAdjustment *adjustment;
-
-+ AgsRecallHandler *recall_handler;
-+
- AgsLadspaPlugin *ladspa_plugin;
-
- AgsMutexManager *mutex_manager;
-@@ -754,11 +773,17 @@
-
- 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(),
-@@ -778,10 +803,6 @@
- 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);
-
-@@ -790,18 +811,49 @@
-
- pthread_mutex_unlock(application_mutex);
-
-- /* find ports */
-+ /* play - 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);
-+ /* 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_line_output_port_run_post_callback);
-+ recall_handler->data = (gpointer) 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(line->channel->recall,
- filename,
-@@ -809,8 +861,25 @@
- 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_line_output_port_run_post_callback);
-+ recall_handler->data = (gpointer) line;
-+
-+ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
-+ }
-+
-+ g_list_free(recall_start);
-+
- pthread_mutex_unlock(channel_mutex);
-
- /* load ports */
-@@ -818,7 +887,7 @@
-
- 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;
-@@ -830,9 +899,17 @@
- guint step_count;
-
- 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;
-+ }
- }
-
- if(control_type_name != NULL){
-@@ -943,8 +1020,15 @@
- 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
-@@ -977,6 +1061,8 @@
- AgsLineMember *line_member;
- GtkAdjustment *adjustment;
-
-+ AgsRecallHandler *recall_handler;
-+
- AgsLv2Plugin *lv2_plugin;
-
- AgsMutexManager *mutex_manager;
-@@ -991,12 +1077,18 @@
-
- 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);
-@@ -1015,10 +1107,6 @@
- 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);
-
-@@ -1027,7 +1115,7 @@
-
- pthread_mutex_unlock(application_mutex);
-
-- /* find ports */
-+ /* play - find ports */
- pthread_mutex_lock(channel_mutex);
-
- recall_start =
-@@ -1044,8 +1132,32 @@
- 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_line_output_port_run_post_callback);
-+ recall_handler->data = (gpointer) 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(line->channel->recall,
- filename,
-@@ -1053,10 +1165,27 @@
- 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_line_output_port_run_post_callback);
-+ recall_handler->data = (gpointer) line;
-+
-+ ags_recall_add_handler(AGS_RECALL(recall_channel_run_dummy), recall_handler);
-+ }
-
-+ g_list_free(recall_start);
-+
-+ pthread_mutex_unlock(channel_mutex);
-+
- /* load ports */
- port_descriptor = AGS_BASE_PLUGIN(lv2_plugin)->port;
-
-@@ -1075,9 +1204,17 @@
- guint step_count;
-
- 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;
-+ }
- }
-
- if(control_type_name != NULL){
-@@ -1163,6 +1300,12 @@
- 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
-@@ -1348,6 +1491,10 @@
- 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 +1507,12 @@
- 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);
-
-@@ -1544,7 +1697,7 @@
- gboolean
- ags_line_indicator_queue_draw_timeout(GtkWidget *widget)
- {
-- if(g_hash_table_lookup(ags_indicator_queue_draw,
-+ if(g_hash_table_lookup(ags_line_indicator_queue_draw,
- widget) != NULL){
- gtk_widget_queue_draw(widget);
-
diff --git a/debian/patches/wish-line-callbacks-c.patch b/debian/patches/wish-line-callbacks-c.patch
deleted file mode 100644
index 63d3ae7..0000000
--- a/debian/patches/wish-line-callbacks-c.patch
+++ /dev/null
@@ -1,240 +0,0 @@
-Description: This is a wishlist patch. It provides the callback function
- ags_line_output_port_run_post_callback() updating the controls value.
- AgsLine is used by AgsSynthInputLine, AgsMixerInputLine and AgsDrumInputLine.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- 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,8 +61,6 @@
- #include <ags/X/ags_dssi_browser.h>
- #include <ags/X/ags_lv2_browser.h>
-
--#include <ags/X/task/ags_change_indicator.h>
--
- int
- ags_line_parent_set_callback(GtkWidget *widget, GtkObject *old_parent, AgsLine *line)
- {
-@@ -231,8 +232,23 @@
- 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 +284,8 @@
- }
-
- /* free lists */
-- g_list_free(description_start);
-- g_list_free(port_control_start);
-+ g_list_free(description_start);
-+ g_list_free(port_control_start);
- }
- }
-
-@@ -339,72 +355,124 @@
- }
-
- void
--ags_line_peak_run_post_callback(AgsRecall *peak_channel_run,
-- AgsLine *line)
-+ags_line_output_port_run_post_callback(AgsRecall *recall,
-+ AgsLine *line)
- {
- GtkWidget *child;
-
-- AgsPort *port;
--
-- AgsMutexManager *mutex_manager;
-- AgsTaskThread *task_thread;
--
- GList *list, *list_start;
--
-- gdouble peak;
--
-- GValue value = {0,};
--
-- 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);
-
-+ /* 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_VINDICATOR ||
-+ AGS_LINE_MEMBER(list->data)->widget_type == AGS_TYPE_HINDICATOR ||
-+ AGS_LINE_MEMBER(list->data)->widget_type == AGS_TYPE_LED)){
- GtkAdjustment *adjustment;
-
-- child = GTK_BIN(list->data)->child;
-+ AgsPort *current;
-+
-+ gdouble average_peak;
-+ gdouble lower, upper;
-+ gdouble range;
-+ gdouble peak;
-
-- /* get port */
-- pthread_mutex_lock(application_mutex);
-+ GValue value = {0,};
-
-- channel_mutex = ags_mutex_manager_lookup(mutex_manager,
-- (GObject *) line->channel);
-+ child = GTK_BIN(list->data)->child;
-+
-+ average_peak = 0.0;
-
-- pthread_mutex_unlock(application_mutex);
-+ /* play port */
-+ current = AGS_LINE_MEMBER(list->data)->port;
-
-- pthread_mutex_lock(channel_mutex);
-+ if(current == NULL){
-+ list = list->next;
-+
-+ continue;
-+ }
-+
-+ /* check if output port and specifier matches */
-+ pthread_mutex_lock(current->mutex);
-
-- port = AGS_PEAK_CHANNEL(AGS_RECALL_CHANNEL_RUN(peak_channel_run)->recall_channel)->peak;
-+ if((AGS_PORT_IS_OUTPUT & (current->flags)) == 0 ||
-+ current->port_descriptor == NULL ||
-+ g_ascii_strcasecmp(current->specifier,
-+ AGS_LINE_MEMBER(list->data)->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);
-
-- pthread_mutex_unlock(channel_mutex);
-+ /* get range */
-+ range = upper - lower;
-
-- /* get peak */
-- g_value_init(&value, G_TYPE_DOUBLE);
-- ags_port_safe_read(port,
-+ /* play port - read value */
-+ g_value_init(&value, G_TYPE_FLOAT);
-+ ags_port_safe_read(current,
- &value);
--
-- peak = g_value_get_double(&value);
-+
-+ peak = g_value_get_float(&value);
- g_value_unset(&value);
-
-- /* apply */
-- g_object_get(child,
-- "adjustment\0", &adjustment,
-- NULL);
-+ /* 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);
-+ }
-
-- gtk_adjustment_set_value(adjustment,
-- peak);
-+ /* recall port */
-+ current = AGS_LINE_MEMBER(list->data)->recall_port;
-
-- break;
-+ /* 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);
-+
-+ /* 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;
diff --git a/debian/patches/wish-line-callbacks-h.patch b/debian/patches/wish-line-callbacks-h.patch
deleted file mode 100644
index f235484..0000000
--- a/debian/patches/wish-line-callbacks-h.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-Description: This is a wishlist patch. It declares the callback function
- ags_line_output_port_run_post_callback() updating the controls value.
- AgsLine is used by AgsSynthInputLine, AgsMixerInputLine and AgsDrumInputLine.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/ags_line_callbacks.h
-+++ b/ags/X/ags_line_callbacks.h
-@@ -45,8 +45,8 @@
- AgsLine *line);
-
- /* AgsRecall - recall */
--void ags_line_peak_run_post_callback(AgsRecall *peak_channel,
-- AgsLine *line);
-+void ags_line_output_port_run_post_callback(AgsRecall *recall,
-+ AgsLine *line);
-
- void ags_line_copy_pattern_done(AgsRecall *recall,
- AgsLine *line);
diff --git a/debian/patches/wish-line-h.patch b/debian/patches/wish-line-h.patch
deleted file mode 100644
index b9e7df1..0000000
--- a/debian/patches/wish-line-h.patch
+++ /dev/null
@@ -1,17 +0,0 @@
-Description: This is a wishlist patch. It extends the AgsLine struct in order
- to proper redrawing of the output widget.
- This is used by AgsSynthInputLine, AgsDrumInputLine and AgsMixerInputLine.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/ags_line.h
-+++ b/ags/X/ags_line.h
-@@ -72,6 +72,8 @@
- AgsExpander *expander;
-
- GtkWidget *indicator;
-+
-+ GList *queued_drawing;
- };
-
- struct _AgsLineClass
diff --git a/debian/patches/wish-line-member.patch b/debian/patches/wish-line-member.patch
deleted file mode 100644
index 02bfede..0000000
--- a/debian/patches/wish-line-member.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-Description: This is a wishlist patch. It adds support for additional output
- widget types.
- AgsLineMember is used by AgsLine.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- 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>
-@@ -553,7 +555,10 @@
- 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 */
diff --git a/debian/patches/wish-lv2-browser-c.patch b/debian/patches/wish-lv2-browser-c.patch
deleted file mode 100644
index e4a73c7..0000000
--- a/debian/patches/wish-lv2-browser-c.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-Description: This is a wishlist patch. It lets you configure the output widget
- of plugins like Lv2.
- It is used by AgsMixer, AgsDrum, AgsFFPlayer and AgsSynth.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/ags_lv2_browser.c
-+++ b/ags/X/ags_lv2_browser.c
-@@ -355,6 +355,58 @@
- }
-
- /**
-+ * 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/debian/patches/wish-lv2-browser-callbacks.patch b/debian/patches/wish-lv2-browser-callbacks.patch
deleted file mode 100644
index 7796146..0000000
--- a/debian/patches/wish-lv2-browser-callbacks.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-Description: This is a wishlist patch. It distinguishes between input and
- output widgets as showing the port configuration.
- It is used by AgsMixer, AgsDrum, AgsFFPlayer and AgsSynth.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/ags_lv2_browser_callbacks.c
-+++ b/ags/X/ags_lv2_browser_callbacks.c
-@@ -160,15 +160,29 @@
- 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/debian/patches/wish-lv2-browser-h.patch b/debian/patches/wish-lv2-browser-h.patch
deleted file mode 100644
index 789565a..0000000
--- a/debian/patches/wish-lv2-browser-h.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-Description: This is a wishlist patch. It declares the functions to configure
- the output widget of plugins like Lv2.
- It is used by AgsMixer, AgsDrum, AgsFFPlayer and AgsSynth.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/ags_lv2_browser.h
-+++ b/ags/X/ags_lv2_browser.h
-@@ -56,8 +56,12 @@
- 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/debian/patches/wish-mixer-input-line.patch b/debian/patches/wish-mixer-input-line.patch
deleted file mode 100644
index 5fcce01..0000000
--- a/debian/patches/wish-mixer-input-line.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-Description: This is a wishlist patch. It changes the recall handler to the
- generic callback, introduced in view of plugin output ports. It is responsible
- for redrawing visible feedback.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/X/machine/ags_mixer_input_line.c
-+++ b/ags/X/machine/ags_mixer_input_line.c
-@@ -62,7 +62,7 @@
- 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 @@
- 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);
-
-@@ -270,7 +270,7 @@
- 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->callback = G_CALLBACK(ags_line_output_port_run_post_callback);
- recall_handler->data = (gpointer) line;
-
- ags_recall_add_handler(AGS_RECALL(play_peak_channel_run), recall_handler);
-@@ -286,7 +286,7 @@
- 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->callback = G_CALLBACK(ags_line_output_port_run_post_callback);
- recall_handler->data = (gpointer) line;
-
- ags_recall_add_handler(AGS_RECALL(recall_peak_channel_run), recall_handler);
diff --git a/debian/patches/wish-mute-audio-signal.patch b/debian/patches/wish-mute-audio-signal.patch
deleted file mode 100644
index 3183188..0000000
--- a/debian/patches/wish-mute-audio-signal.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-Description: This is a wishlist patch. It uses the modified AgsPort type of
- ags-mute recall in order to use the built-in effect by automation.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/audio/recall/ags_mute_audio_signal.c
-+++ b/ags/audio/recall/ags_mute_audio_signal.c
-@@ -245,21 +245,21 @@
- /* 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/debian/patches/wish-mute-audio.patch b/debian/patches/wish-mute-audio.patch
deleted file mode 100644
index a03766f..0000000
--- a/debian/patches/wish-mute-audio.patch
+++ /dev/null
@@ -1,128 +0,0 @@
-Description: This is a wishlist patch. It modifies AgsPort type of ags-mute recall
- in order to use the built-in effect by automation. Further it loads the automation
- port during ags_automation_connect().
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- 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);
-@@ -43,6 +45,8 @@
-
- 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
-@@ -181,20 +185,26 @@
-
- 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;
-+
-+ 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);
-
-- /* */
-+ /* set port */
- AGS_RECALL(mute_audio)->port = port;
- }
-
-@@ -262,9 +272,20 @@
- 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
-@@ -311,12 +332,45 @@
- {
- 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/debian/patches/wish-mute-channel.patch b/debian/patches/wish-mute-channel.patch
deleted file mode 100644
index cd16244..0000000
--- a/debian/patches/wish-mute-channel.patch
+++ /dev/null
@@ -1,127 +0,0 @@
-Description: This is a wishlist patch. It modifies AgsPort type of ags-mute recall
- in order to use the built-in effect by automation. Further it loads the automation
- port during ags_automation_connect().
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- 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);
-@@ -43,6 +45,8 @@
-
- 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
-@@ -181,19 +185,26 @@
-
- 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;
-
-+ 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);
-
-+ /* set port */
- AGS_RECALL(mute_channel)->port = port;
- }
-
-@@ -260,9 +271,20 @@
- 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
-@@ -309,12 +331,45 @@
- {
- 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/debian/patches/wish-peak-channel.patch b/debian/patches/wish-peak-channel.patch
deleted file mode 100644
index bbd4335..0000000
--- a/debian/patches/wish-peak-channel.patch
+++ /dev/null
@@ -1,126 +0,0 @@
-Description: This is a wishlist patch. It modifies AgsPort type of ags-peak recall
- in order to use with the generic callback of output widgets.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- 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>
-@@ -49,6 +51,8 @@
- void ags_peak_channel_set_ports(AgsPlugin *plugin, GList *port);
- void ags_peak_channel_finalize(GObject *gobject);
-
-+static AgsPortDescriptor* ags_peak_channel_get_peak_port_descriptor();
-+
- /**
- * SECTION:ags_peak_channel
- * @short_description: peaks channel
-@@ -171,6 +175,8 @@
- 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,17 +185,25 @@
-
- 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);
-
-+ 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);
-
- /* set port */
-@@ -452,14 +466,14 @@
- current_value = scale_precision * (atan(1.0 / 440.0) / sin(current_value / 22000.0));
- }
-
-- g_value_init(&value, G_TYPE_DOUBLE);
-+ 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);
-@@ -469,6 +483,38 @@
- 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/debian/patches/wish-port-h.patch b/debian/patches/wish-port-h.patch
deleted file mode 100644
index 741f4d3..0000000
--- a/debian/patches/wish-port-h.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-Description: This is a wishlist patch. It introduces the flag of AgsPort
- to mark it as output.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/audio/ags_port.h
-+++ b/ags/audio/ags_port.h
-@@ -43,6 +43,7 @@
- typedef enum{
- AGS_PORT_CONVERT_ALWAYS = 1,
- AGS_PORT_USE_LADSPA_FLOAT = 1 << 1,
-+ AGS_PORT_IS_OUTPUT = 1 << 2,
- }AgsPortFlags;
-
- struct _AgsPort
diff --git a/debian/patches/wish-recall-channel.patch b/debian/patches/wish-recall-channel.patch
deleted file mode 100644
index 578153a..0000000
--- a/debian/patches/wish-recall-channel.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-Description: This is a wishlist patch. It disables automation of output ports.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/audio/ags_recall_channel.c
-+++ b/ags/audio/ags_recall_channel.c
-@@ -425,6 +425,12 @@
- }
-
- 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/debian/patches/wish-recall-dssi.patch b/debian/patches/wish-recall-dssi.patch
deleted file mode 100644
index 66efe07..0000000
--- a/debian/patches/wish-recall-dssi.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-Description: This is a wishlist patch. It flags the recall with appropriate
- output port availabel in order to get detected by generic callback of output
- widgets.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/audio/ags_recall_dssi.c
-+++ b/ags/audio/ags_recall_dssi.c
-@@ -640,6 +640,12 @@
- "port-value-type\0", G_TYPE_FLOAT,
- NULL);
- 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;
-+ }
-
- current->port_descriptor = port_descriptor->data;
- ags_recall_dssi_load_conversion(recall_dssi,
diff --git a/debian/patches/wish-recall-lv2.patch b/debian/patches/wish-recall-lv2.patch
deleted file mode 100644
index 0d06c19..0000000
--- a/debian/patches/wish-recall-lv2.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-Description: This is a wishlist patch. It flags the recall with appropriate
- output port availabel in order to get detected by generic callback of output
- widgets.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/audio/ags_recall_lv2.c
-+++ b/ags/audio/ags_recall_lv2.c
-@@ -440,10 +440,11 @@
- 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);
- }
-
-@@ -767,7 +768,13 @@
- "port-value-is-pointer\0", FALSE,
- "port-value-type\0", G_TYPE_FLOAT,
- NULL);
--
-+
-+ 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;
-+ }
-+
- current->port_descriptor = port_descriptor->data;
- ags_recall_lv2_load_conversion(recall_lv2,
- (GObject *) current,
diff --git a/debian/patches/wish-volume-audio-signal.patch b/debian/patches/wish-volume-audio-signal.patch
deleted file mode 100644
index f04b570..0000000
--- a/debian/patches/wish-volume-audio-signal.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-Description: This is a wishlist patch. It uses the modified AgsPort type of
- ags-volume recall in order to use the built-in effect by automation.
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- a/ags/audio/recall/ags_volume_audio_signal.c
-+++ b/ags/audio/recall/ags_volume_audio_signal.c
-@@ -231,10 +231,10 @@
- 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);
-+ volume = g_value_get_float(&value);
-
- for(i = 0; i < buffer_size; i++){
- switch(AGS_RECALL_AUDIO_SIGNAL(recall)->source->format){
diff --git a/debian/patches/wish-volume-channel.patch b/debian/patches/wish-volume-channel.patch
deleted file mode 100644
index 1f74972..0000000
--- a/debian/patches/wish-volume-channel.patch
+++ /dev/null
@@ -1,115 +0,0 @@
-Description: This is a wishlist patch. It modifies AgsPort type of ags-volume recall
- in order to use the built-in effect by automation. Further it loads the automation
- port during ags_automation_connect().
-Author: Joël Krähmann <jkraehemann at gmail.com>
-Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
-Last-Update: 2017-02-02
---- 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);
-@@ -40,6 +41,8 @@
- void ags_volume_channel_set_ports(AgsPlugin *plugin, GList *port);
- void ags_volume_channel_finalize(GObject *gobject);
-
-+static AgsPortDescriptor* ags_volume_channel_get_volume_port_descriptor();
-+
- /**
- * SECTION:ags_volume_channel
- * @short_description: volumes channel
-@@ -174,15 +177,20 @@
- "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);
-
-- volume_channel->volume->port_value.ags_port_double = 1.0;
-+ volume_channel->volume->port_value.ags_port_float = 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);
-
-+ /* set port */
- AGS_RECALL(volume_channel)->port = port;
- }
-
-@@ -249,9 +257,20 @@
- 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
-@@ -293,6 +312,38 @@
- 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:
- *
--
gsequencer packaging
More information about the pkg-multimedia-commits
mailing list