[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