[SCM] gsequencer/master: provide patch of Bug#857910
jkraehemann-guest at users.alioth.debian.org
jkraehemann-guest at users.alioth.debian.org
Thu Mar 16 21:05:10 UTC 2017
The following commit has been merged in the master branch:
commit a193c85f64d8ff408617fe417f399ec0666b02d5
Author: Joël Krähemann <jkraehemann-guest at users.alioth.debian.org>
Date: Thu Mar 16 20:20:19 2017 +0100
provide patch of Bug#857910
diff --git a/debian/patches/fix-broken-thread-frequency.diff b/debian/patches/fix-broken-thread-frequency.diff
index 9c44ada..13138bb 100644
--- a/debian/patches/fix-broken-thread-frequency.diff
+++ b/debian/patches/fix-broken-thread-frequency.diff
@@ -223,7 +223,7 @@
#include <math.h>
-@@ -250,6 +251,9 @@
+@@ -252,6 +253,9 @@
{
GObject *soundcard;
@@ -233,7 +233,7 @@
soundcard = (GObject *) g_value_get_object(value);
if(export_thread->soundcard != NULL){
-@@ -259,9 +263,22 @@
+@@ -261,9 +265,22 @@
if(soundcard != NULL){
g_object_ref(G_OBJECT(soundcard));
@@ -336,16 +336,7 @@
#endif /*__AGS_MAIN_LOOP_H__*/
--- a/ags/audio/thread/ags_audio_loop.c
+++ b/ags/audio/thread/ags_audio_loop.c
-@@ -68,6 +68,8 @@
- guint ags_audio_loop_get_last_sync(AgsMainLoop *main_loop);
- gboolean ags_audio_loop_monitor(AgsMainLoop *main_loop,
- guint time_cycle, guint *time_spent);
-+void ags_audio_loop_change_frequency(AgsMainLoop *main_loop,
-+ gdouble frequency);
- void ags_audio_loop_finalize(GObject *gobject);
-
- void ags_audio_loop_start(AgsThread *thread);
-@@ -271,6 +273,7 @@
+@@ -292,6 +292,7 @@
main_loop->get_last_sync = ags_audio_loop_get_last_sync;
main_loop->interrupt = NULL;
main_loop->monitor = ags_audio_loop_monitor;
@@ -353,11 +344,10 @@
}
void
-@@ -592,6 +595,74 @@
- }
+@@ -694,6 +695,74 @@
}
-+void
+ void
+ags_audio_loop_change_frequency(AgsMainLoop *main_loop,
+ gdouble frequency)
+{
@@ -425,13 +415,14 @@
+ }
+}
+
- void
++void
ags_audio_loop_finalize(GObject *gobject)
{
+ AgsAudioLoop *audio_loop;
--- a/ags/audio/recall/ags_delay_audio.c
+++ b/ags/audio/recall/ags_delay_audio.c
-@@ -42,10 +42,20 @@
- void ags_delay_audio_set_ports(AgsPlugin *plugin, GList *port);
+@@ -43,10 +43,20 @@
+ void ags_delay_audio_dispose(GObject *gobject);
void ags_delay_audio_finalize(GObject *gobject);
+void ags_delay_audio_notify_audio_callback(GObject *gobject,
@@ -451,7 +442,7 @@
gdouble ags_delay_audio_get_bpm(AgsTactable *tactable);
gdouble ags_delay_audio_get_tact(AgsTactable *tactable);
gdouble ags_delay_audio_get_sequencer_duration(AgsTactable *tactable);
-@@ -55,6 +65,8 @@
+@@ -56,6 +66,8 @@
void ags_delay_audio_change_sequencer_duration(AgsTactable *tactable, gdouble duration);
void ags_delay_audio_change_notation_duration(AgsTactable *tactable, gdouble duration);
@@ -460,7 +451,7 @@
/**
* SECTION:ags_delay_audio
* @short_description: delay audio
-@@ -326,7 +338,11 @@
+@@ -328,7 +340,11 @@
AGS_RECALL(delay_audio)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
AGS_RECALL(delay_audio)->xml_type = "ags-delay-audio\0";
@@ -473,7 +464,7 @@
G_CALLBACK(ags_delay_audio_notify_soundcard_callback), NULL);
}
-@@ -590,6 +606,30 @@
+@@ -642,6 +658,30 @@
}
void
@@ -504,7 +495,7 @@
ags_delay_audio_notify_soundcard_callback(GObject *gobject,
GParamSpec *pspec,
gpointer user_data)
-@@ -606,6 +646,11 @@
+@@ -658,6 +698,11 @@
delay_audio = AGS_DELAY_AUDIO(gobject);
soundcard = AGS_RECALL(delay_audio)->soundcard;
@@ -516,7 +507,7 @@
port = NULL;
/* */
-@@ -706,6 +751,30 @@
+@@ -776,6 +821,30 @@
AGS_RECALL(delay_audio)->port = port;
}
@@ -547,7 +538,7 @@
gdouble
ags_delay_audio_get_bpm(AgsTactable *tactable)
{
-@@ -884,6 +953,59 @@
+@@ -954,6 +1023,59 @@
/* notation-duration */
g_value_reset(&value);
diff --git a/debian/patches/fix-missing-dispose.diff b/debian/patches/fix-missing-dispose.diff
new file mode 100644
index 0000000..bb4c78e
--- /dev/null
+++ b/debian/patches/fix-missing-dispose.diff
@@ -0,0 +1,9399 @@
+--- a/ags/X/ags_effect_bulk.c
++++ b/ags/X/ags_effect_bulk.c
+@@ -723,8 +723,8 @@
+
+ effect_plugin = (AgsEffectBulkPlugin *) malloc(sizeof(AgsEffectBulkPlugin));
+
+- effect_plugin->filename = filename;
+- effect_plugin->effect = effect;
++ effect_plugin->filename = g_strdup(filename);
++ effect_plugin->effect = g_strdup(effect);
+
+ effect_plugin->control_type_name = NULL;
+
+--- a/ags/audio/ags_acceleration.c
++++ b/ags/audio/ags_acceleration.c
+@@ -28,7 +28,7 @@
+ void ags_acceleration_init(AgsAcceleration *acceleration);
+ void ags_acceleration_connect(AgsConnectable *connectable);
+ void ags_acceleration_disconnect(AgsConnectable *connectable);
+-void ags_acceleration_finalize(GObject *object);
++void ags_acceleration_finalize(GObject *gobject);
+
+ /**
+ * SECTION:ags_acceleration
+@@ -112,20 +112,43 @@
+ void
+ ags_acceleration_connect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsAcceleration *acceleration;
++
++ acceleration = AGS_ACCELERATION(connectable);
++
++ if((AGS_ACCELERATION_CONNECTED & (acceleration->flags)) != 0){
++ return;
++ }
++
++ acceleration->flags |= AGS_ACCELERATION_CONNECTED;
+ }
+
+ void
+ ags_acceleration_disconnect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsAcceleration *acceleration;
++
++ acceleration = AGS_ACCELERATION(connectable);
++
++ if((AGS_ACCELERATION_CONNECTED & (acceleration->flags)) == 0){
++ return;
++ }
++
++ acceleration->flags &= (~AGS_ACCELERATION_CONNECTED);
+ }
+
+ void
+ ags_acceleration_finalize(GObject *gobject)
+ {
+- /* empty */
++ AgsAcceleration *acceleration;
+
++ acceleration = AGS_ACCELERATION(gobject);
++
++ if(acceleration->name != NULL){
++ free(acceleration->name);
++ }
++
++ /* call parent */
+ G_OBJECT_CLASS(ags_acceleration_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/audio/ags_acceleration.h
++++ b/ags/audio/ags_acceleration.h
+@@ -35,6 +35,7 @@
+
+ /**
+ * AgsAccelerationFlags:
++ * @AGS_ACCELERATION_CONNECTED: if this object is already connected
+ * @AGS_ACCELERATION_DEFAULT_START: if start is default start point
+ * @AGS_ACCELERATION_DEFAULT_END: if end is default end point
+ * @AGS_ACCELERATION_GUI: interpret x and y as GUI format
+@@ -44,13 +45,14 @@
+ * @AGS_ACCELERATION_IS_SELECTED: if the acceleration is selected
+ */
+ typedef enum{
+- AGS_ACCELERATION_DEFAULT_START = 1,
+- AGS_ACCELERATION_DEFAULT_END = 1 << 1,
+- AGS_ACCELERATION_GUI = 1 << 2,
+- AGS_ACCELERATION_RUNTIME = 1 << 3,
+- AGS_ACCELERATION_HUMAN_READABLE = 1 << 4,
+- AGS_ACCELERATION_DEFAULT_LENGTH = 1 << 5,
+- AGS_ACCELERATION_IS_SELECTED = 1 << 6,
++ AGS_ACCELERATION_CONNECTED = 1,
++ AGS_ACCELERATION_DEFAULT_START = 1 << 1,
++ AGS_ACCELERATION_DEFAULT_END = 1 << 2,
++ AGS_ACCELERATION_GUI = 1 << 3,
++ AGS_ACCELERATION_RUNTIME = 1 << 4,
++ AGS_ACCELERATION_HUMAN_READABLE = 1 << 5,
++ AGS_ACCELERATION_DEFAULT_LENGTH = 1 << 6,
++ AGS_ACCELERATION_IS_SELECTED = 1 << 7,
+ }AgsAccelerationFlags;
+
+ struct _AgsAcceleration
+--- a/ags/audio/ags_audio.h
++++ b/ags/audio/ags_audio.h
+@@ -23,6 +23,7 @@
+ #include <glib-object.h>
+
+ #include <ags/audio/ags_channel.h>
++#include <ags/audio/ags_recall_id.h>
+
+ #define AGS_TYPE_AUDIO (ags_audio_get_type ())
+ #define AGS_AUDIO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_AUDIO, AgsAudio))
+--- a/ags/audio/ags_audio_application_context.c
++++ b/ags/audio/ags_audio_application_context.c
+@@ -128,6 +128,7 @@
+ void ags_audio_application_context_set_sequencer(AgsSoundProvider *sound_provider,
+ GList *sequencer);
+ GList* ags_audio_application_context_get_distributed_manager(AgsSoundProvider *sound_provider);
++void ags_audio_application_context_dispose(GObject *gobject);
+ void ags_audio_application_context_finalize(GObject *gobject);
+
+ void ags_audio_application_context_register_types(AgsApplicationContext *application_context);
+@@ -228,6 +229,7 @@
+ gobject->set_property = ags_audio_application_context_set_property;
+ gobject->get_property = ags_audio_application_context_get_property;
+
++ gobject->dispose = ags_audio_application_context_dispose;
+ gobject->finalize = ags_audio_application_context_finalize;
+
+ /**
+@@ -315,6 +317,7 @@
+ /**/
+ config = ags_config_get_instance();
+ AGS_APPLICATION_CONTEXT(audio_application_context)->config = config;
++ g_object_ref(config);
+ g_object_set(config,
+ "application-context\0", audio_application_context,
+ NULL);
+@@ -865,6 +868,103 @@
+ }
+
+ void
++ags_audio_application_context_dispose(GObject *gobject)
++{
++ AgsAudioApplicationContext *audio_application_context;
++
++ GList *list;
++
++ audio_application_context = AGS_AUDIO_APPLICATION_CONTEXT(gobject);
++
++ /* thread pool */
++ if(audio_application_context->thread_pool != NULL){
++ g_object_unref(audio_application_context->thread_pool);
++
++ audio_application_context->thread_pool = NULL;
++ }
++
++ /* soundcard and export thread */
++ if(audio_application_context->soundcard_thread != NULL){
++ g_object_unref(audio_application_context->soundcard_thread);
++
++ audio_application_context->soundcard_thread = NULL;
++ }
++
++ if(audio_application_context->export_thread != NULL){
++ g_object_unref(audio_application_context->export_thread);
++
++ audio_application_context->export_thread = NULL;
++ }
++
++ /* server */
++ if(audio_application_context->server != NULL){
++ g_object_set(audio_application_context->server,
++ "application-context\0", NULL,
++ NULL);
++
++ g_object_unref(audio_application_context->server);
++
++ audio_application_context->server = NULL;
++ }
++
++ /* soundcard and sequencer */
++ if(audio_application_context->soundcard != NULL){
++ list = audio_application_context->soundcard;
++
++ while(list != NULL){
++ g_object_set(list->data,
++ "application-context\0", NULL,
++ NULL);
++
++ list = list->next;
++ }
++
++ g_list_free_full(audio_application_context->soundcard,
++ g_object_unref);
++
++ audio_application_context->soundcard = NULL;
++ }
++
++ if(audio_application_context->sequencer != NULL){
++ list = audio_application_context->sequencer;
++
++ while(list != NULL){
++ g_object_set(list->data,
++ "application-context\0", NULL,
++ NULL);
++
++ list = list->next;
++ }
++
++ g_list_free_full(audio_application_context->sequencer,
++ g_object_unref);
++
++ audio_application_context->sequencer = NULL;
++ }
++
++ /* distributed manager */
++ if(audio_application_context->distributed_manager != NULL){
++ list = audio_application_context->distributed_manager;
++
++ while(list != NULL){
++ g_object_set(list->data,
++ "application-context\0", NULL,
++ NULL);
++
++ list = list->next;
++ }
++
++ g_list_free_full(audio_application_context->distributed_manager,
++ g_object_unref);
++
++ audio_application_context->distributed_manager = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_audio_application_context_parent_class)->dispose(gobject);
++}
++
++void
+ ags_audio_application_context_finalize(GObject *gobject)
+ {
+ AgsAudioApplicationContext *audio_application_context;
+--- a/ags/audio/ags_audio_signal.c
++++ b/ags/audio/ags_audio_signal.c
+@@ -57,9 +57,10 @@
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec);
+-void ags_audio_signal_finalize(GObject *gobject);
+ void ags_audio_signal_connect(AgsConnectable *connectable);
+ void ags_audio_signal_disconnect(AgsConnectable *connectable);
++void ags_audio_signal_dispose(GObject *gobject);
++void ags_audio_signal_finalize(GObject *gobject);
+
+ void ags_audio_signal_real_realloc_buffer_size(AgsAudioSignal *audio_signal, guint buffer_size);
+
+@@ -145,6 +146,7 @@
+ gobject->set_property = ags_audio_signal_set_property;
+ gobject->get_property = ags_audio_signal_get_property;
+
++ gobject->dispose = ags_audio_signal_dispose;
+ gobject->finalize = ags_audio_signal_finalize;
+
+ /* properties */
+@@ -946,6 +948,70 @@
+ }
+
+ void
++ags_audio_signal_connect(AgsConnectable *connectable)
++{
++ AgsAudioSignal *audio_signal;
++
++ audio_signal = AGS_AUDIO_SIGNAL(connectable);
++
++ if((AGS_AUDIO_SIGNAL_CONNECTED & (audio_signal->flags)) != 0){
++ return;
++ }
++
++ audio_signal->flags |= AGS_AUDIO_SIGNAL_CONNECTED;
++}
++
++void
++ags_audio_signal_disconnect(AgsConnectable *connectable)
++{
++ AgsAudioSignal *audio_signal;
++
++ audio_signal = AGS_AUDIO_SIGNAL(connectable);
++
++ if((AGS_AUDIO_SIGNAL_CONNECTED & (audio_signal->flags)) == 0){
++ return;
++ }
++
++ audio_signal->flags &= (~AGS_AUDIO_SIGNAL_CONNECTED);
++}
++
++void
++ags_audio_signal_dispose(GObject *gobject)
++{
++ AgsAudioSignal *audio_signal;
++
++ audio_signal = AGS_AUDIO_SIGNAL(gobject);
++
++ /* soundcard */
++ if(audio_signal->soundcard != NULL){
++ g_object_unref(audio_signal->soundcard);
++
++ audio_signal->soundcard = NULL;
++ }
++
++ /* recycling */
++ if(audio_signal->recycling != NULL){
++ g_object_unref(audio_signal->recycling);
++
++ audio_signal->recycling = NULL;
++ }
++
++ /* recall id */
++ if(audio_signal->recall_id != NULL){
++ g_object_unref(audio_signal->recall_id);
++
++ audio_signal->recall_id = NULL;
++ }
++
++ /* note */
++ if(audio_signal->note != NULL){
++ g_object_unref(audio_signal->note);
++
++ audio_signal->note = NULL;
++ }
++}
++
++void
+ ags_audio_signal_finalize(GObject *gobject)
+ {
+ AgsAudioSignal *audio_signal;
+@@ -962,7 +1028,8 @@
+ if((AGS_AUDIO_SIGNAL_TEMPLATE & (audio_signal->flags)) != 0){
+ g_warning("AGS_AUDIO_SIGNAL_TEMPLATE: destroying\n\0");
+ }
+-
++
++ /* disconnect */
+ ids = g_signal_list_ids(AGS_TYPE_AUDIO_SIGNAL,
+ &n_ids);
+
+@@ -977,24 +1044,29 @@
+ }
+
+ g_free(ids);
+-
++
++ /* soundcard */
+ if(audio_signal->soundcard != NULL){
+ g_object_unref(audio_signal->soundcard);
+ }
+-
++
++ /* recycling */
+ if(audio_signal->recycling != NULL){
+ g_object_unref(audio_signal->recycling);
+ }
+-
++
++ /* recall id */
+ if(audio_signal->recall_id != NULL){
+ g_object_unref(audio_signal->recall_id);
+ }
+-
++
++ /* audio data */
+ if(audio_signal->stream_beginning != NULL){
+ g_list_free_full(audio_signal->stream_beginning,
+ (GDestroyNotify) ags_stream_free);
+ }
+
++ /* note */
+ if(audio_signal->note != NULL){
+ g_object_unref(audio_signal->note);
+ }
+@@ -1003,18 +1075,6 @@
+ G_OBJECT_CLASS(ags_audio_signal_parent_class)->finalize(gobject);
+ }
+
+-void
+-ags_audio_signal_connect(AgsConnectable *connectable)
+-{
+- // empty
+-}
+-
+-void
+-ags_audio_signal_disconnect(AgsConnectable *connectable)
+-{
+- // empty
+-}
+-
+ /**
+ * ags_stream_alloc:
+ * @buffer_size: the buffer size
+--- a/ags/audio/ags_audio_signal.h
++++ b/ags/audio/ags_audio_signal.h
+@@ -34,9 +34,10 @@
+ typedef struct _AgsAudioSignalClass AgsAudioSignalClass;
+
+ typedef enum{
+- AGS_AUDIO_SIGNAL_TEMPLATE = 1,
+- AGS_AUDIO_SIGNAL_PLAY_DONE = 1 << 1,
+- AGS_AUDIO_SIGNAL_STANDALONE = 1 << 2,
++ AGS_AUDIO_SIGNAL_CONNECTED = 1,
++ AGS_AUDIO_SIGNAL_TEMPLATE = 1 << 1,
++ AGS_AUDIO_SIGNAL_PLAY_DONE = 1 << 2,
++ AGS_AUDIO_SIGNAL_STANDALONE = 1 << 3,
+ }AgsAudioSignalFlags;
+
+ struct _AgsAudioSignal
+--- a/ags/audio/ags_automation.c
++++ b/ags/audio/ags_automation.c
+@@ -54,7 +54,8 @@
+ GParamSpec *param_spec);
+ void ags_automation_connect(AgsConnectable *connectable);
+ void ags_automation_disconnect(AgsConnectable *connectable);
+-void ags_automation_finalize(GObject *object);
++void ags_automation_dispose(GObject *gobject);
++void ags_automation_finalize(GObject *gobject);
+
+ void ags_automation_set_port(AgsPortlet *portlet, GObject *port);
+ GObject* ags_automation_get_port(AgsPortlet *portlet);
+@@ -155,6 +156,7 @@
+ gobject->set_property = ags_automation_set_property;
+ gobject->get_property = ags_automation_get_property;
+
++ gobject->dispose = ags_automation_dispose;
+ gobject->finalize = ags_automation_finalize;
+
+ /* properties */
+@@ -432,13 +434,51 @@
+ void
+ ags_automation_connect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsAutomation *automation;
++
++ GList *list;
++
++ automation = AGS_AUTOMATION(connectable);
++
++ if((AGS_AUTOMATION_CONNECTED & (automation->flags)) != 0){
++ return;
++ }
++
++ automation->flags |= AGS_AUTOMATION_CONNECTED;
++
++ /* acceleration */
++ list = automation->acceleration;
++
++ while(list != NULL){
++ ags_connectable_connect(AGS_CONNECTABLE(list->data));
++
++ list = list->next;
++ }
+ }
+
+ void
+ ags_automation_disconnect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsAutomation *automation;
++
++ GList *list;
++
++ automation = AGS_AUTOMATION(connectable);
++
++ if((AGS_AUTOMATION_CONNECTED & (automation->flags)) == 0){
++ return;
++ }
++
++ automation->flags &= (~AGS_AUTOMATION_CONNECTED);
++
++ /* acceleration */
++ list = automation->acceleration;
++
++ while(list != NULL){
++ ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
++
++ list = list->next;
++ }
+ }
+
+ void
+@@ -723,19 +763,103 @@
+ }
+
+ void
++ags_automation_dispose(GObject *gobject)
++{
++ AgsAutomation *automation;
++
++ GList *list;
++
++ automation = AGS_AUTOMATION(gobject);
++
++ /* timestamp */
++ if(automation->timestamp != NULL){
++ g_object_unref(automation->timestamp);
++
++ automation->timestamp = NULL;
++ }
++
++ /* audio */
++ if(automation->audio != NULL){
++ g_object_unref(automation->audio);
++
++ automation->audio = NULL;
++ }
++
++ /* source function */
++ if(automation->source_function != NULL){
++ g_object_run_dispose(automation->source_function);
++
++ g_object_unref(automation->source_function);
++
++ automation->source_function = NULL;
++ }
++
++ /* acceleration */
++ list = automation->acceleration;
++
++ while(list != NULL){
++ g_object_run_dispose(G_OBJECT(list->data));
++
++ list = list->next;
++ }
++
++ g_list_free_full(automation->acceleration,
++ g_object_unref);
++ g_list_free(automation->selection);
++
++ automation->acceleration = NULL;
++ automation->selection = NULL;
++
++ /* port */
++ if(automation->port != NULL){
++ g_object_unref(automation->port);
++
++ automation->port = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_automation_parent_class)->dispose(gobject);
++}
++
++void
+ ags_automation_finalize(GObject *gobject)
+ {
+ AgsAutomation *automation;
+
+ automation = AGS_AUTOMATION(gobject);
++
++ /* timestamp */
++ if(automation->timestamp != NULL){
++ g_object_unref(automation->timestamp);
++ }
+
++ /* audio */
+ if(automation->audio != NULL){
+ g_object_unref(automation->audio);
+ }
++
++ /* control name */
++ if(automation->control_name != NULL){
++ free(automation->control_name);
++ }
++
++ /* source function */
++ if(automation->source_function != NULL){
++ g_object_unref(automation->source_function);
++ }
+
++ /* acceleration */
+ g_list_free_full(automation->acceleration,
+ g_object_unref);
+
++ g_list_free(automation->selection);
++
++ /* port */
++ if(automation->port != NULL){
++ g_object_unref(automation->port);
++ }
++
++ /* call parent */
+ G_OBJECT_CLASS(ags_automation_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/audio/ags_input.c
++++ b/ags/audio/ags_input.c
+@@ -26,6 +26,7 @@
+ #include <ags/audio/ags_playable.h>
+ #include <ags/audio/ags_recycling.h>
+ #include <ags/audio/ags_audio_signal.h>
++#include <ags/audio/ags_synth_generator.h>
+
+ #include <ags/audio/file/ags_audio_file_link.h>
+ #include <ags/audio/file/ags_audio_file.h>
+@@ -42,7 +43,8 @@
+ GValue *value,
+ GParamSpec *param_spec);
+ void ags_input_init (AgsInput *input);
+-void ags_input_finalize (GObject *gobject);
++void ags_input_dispose(GObject *gobject);
++void ags_input_finalize(GObject *gobject);
+ void ags_input_connect(AgsConnectable *connectable);
+ void ags_input_disconnect(AgsConnectable *connectable);
+
+@@ -62,6 +64,7 @@
+ enum{
+ PROP_0,
+ PROP_FILE_LINK,
++ PROP_SYNTH_GENERATOR,
+ };
+
+ GType
+@@ -114,6 +117,7 @@
+ gobject->set_property = ags_input_set_property;
+ gobject->get_property = ags_input_get_property;
+
++ gobject->dispose = ags_input_dispose;
+ gobject->finalize = ags_input_finalize;
+
+ /* properties */
+@@ -132,6 +136,22 @@
+ g_object_class_install_property(gobject,
+ PROP_FILE_LINK,
+ param_spec);
++
++ /**
++ * AgsInput:synth-generator:
++ *
++ * An optional synth generator that might be used.
++ *
++ * Since: 0.7.122.7
++ */
++ param_spec = g_param_spec_object("synth-generator\0",
++ "the synth generator\0",
++ "The synth generator to be used\0",
++ AGS_TYPE_SYNTH_GENERATOR,
++ G_PARAM_READABLE | G_PARAM_WRITABLE);
++ g_object_class_install_property(gobject,
++ PROP_SYNTH_GENERATOR,
++ param_spec);
+ }
+
+ void
+@@ -165,7 +185,6 @@
+ switch(prop_id){
+ case PROP_FILE_LINK:
+ {
+- AgsAudioFile *audio_file;
+ AgsFileLink *file_link;
+
+ file_link = (AgsFileLink *) g_value_get_object(value);
+@@ -185,6 +204,27 @@
+ input->file_link = (GObject *) file_link;
+ }
+ break;
++ case PROP_SYNTH_GENERATOR:
++ {
++ AgsFileLink *synth_generator;
++
++ synth_generator = (AgsFileLink *) g_value_get_object(value);
++
++ if(input->synth_generator == (GObject *) synth_generator){
++ return;
++ }
++
++ if(input->synth_generator != NULL){
++ g_object_unref(G_OBJECT(input->synth_generator));
++ }
++
++ if(synth_generator != NULL){
++ g_object_ref(G_OBJECT(synth_generator));
++ }
++
++ input->synth_generator = (GObject *) synth_generator;
++ }
++ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+ break;
+@@ -203,7 +243,14 @@
+
+ switch(prop_id){
+ case PROP_FILE_LINK:
+- g_value_set_object(value, input->file_link);
++ {
++ g_value_set_object(value, input->file_link);
++ }
++ break;
++ case PROP_SYNTH_GENERATOR:
++ {
++ g_value_set_object(value, input->synth_generator);
++ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+@@ -212,16 +259,52 @@
+ }
+
+ void
++ags_input_dispose(GObject *gobject)
++{
++ AgsInput *input;
++
++ input = AGS_INPUT(gobject);
++
++ /* file link */
++ if(input->file_link != NULL){
++ g_object_run_dispose(G_OBJECT(input->file_link));
++
++ g_object_unref(G_OBJECT(input->file_link));
++
++ input->file_link = NULL;
++ }
++
++ /* synth generator */
++ if(input->synth_generator != NULL){
++ g_object_run_dispose(G_OBJECT(input->synth_generator));
++
++ g_object_unref(G_OBJECT(input->synth_generator));
++
++ input->synth_generator = NULL;
++ }
++
++ /* finalize */
++ G_OBJECT_CLASS(ags_input_parent_class)->dispose(gobject);
++}
++
++void
+ ags_input_finalize(GObject *gobject)
+ {
+ AgsInput *input;
+
+ input = AGS_INPUT(gobject);
+
++ /* file link */
+ if(input->file_link != NULL){
+ g_object_unref(G_OBJECT(input->file_link));
+ }
+
++ /* synth generator */
++ if(input->synth_generator != NULL){
++ g_object_unref(G_OBJECT(input->synth_generator));
++ }
++
++ /* finalize */
+ G_OBJECT_CLASS(ags_input_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/audio/ags_midiin.c
++++ b/ags/audio/ags_midiin.c
+@@ -72,6 +72,7 @@
+ GParamSpec *param_spec);
+ void ags_midiin_disconnect(AgsConnectable *connectable);
+ void ags_midiin_connect(AgsConnectable *connectable);
++void ags_midiin_dispose(GObject *gobject);
+ void ags_midiin_finalize(GObject *gobject);
+
+ void ags_midiin_switch_buffer_flag(AgsMidiin *midiin);
+@@ -219,6 +220,7 @@
+ gobject->set_property = ags_midiin_set_property;
+ gobject->get_property = ags_midiin_get_property;
+
++ gobject->dispose = ags_midiin_dispose;
+ gobject->finalize = ags_midiin_finalize;
+
+ /* properties */
+@@ -702,13 +704,44 @@
+ }
+
+ void
++ags_midiin_dispose(GObject *gobject)
++{
++ AgsMidiin *midiin;
++
++ GList *list;
++
++ midiin = AGS_MIDIIN(gobject);
++
++ /* audio */
++ if(midiin->audio != NULL){
++ list = midiin->audio;
++
++ while(list != NULL){
++ g_object_set(list->data,
++ "sequencer\0", NULL,
++ NULL);
++
++ list = list->next;
++ }
++
++ g_list_free_full(midiin->audio,
++ g_object_unref);
++
++ midiin->audio = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_midiin_parent_class)->dispose(gobject);
++}
++
++void
+ ags_midiin_finalize(GObject *gobject)
+ {
+ AgsMidiin *midiin;
+
+ AgsMutexManager *mutex_manager;
+
+- GList *list, *list_next;
++ GList *list;
+
+ midiin = AGS_MIDIIN(gobject);
+
+@@ -742,7 +775,18 @@
+ /* free buffer array */
+ free(midiin->buffer);
+
++ /* audio */
+ if(midiin->audio != NULL){
++ list = midiin->audio;
++
++ while(list != NULL){
++ g_object_set(list->data,
++ "sequencer\0", NULL,
++ NULL);
++
++ list = list->next;
++ }
++
+ g_list_free_full(midiin->audio,
+ g_object_unref);
+ }
+--- a/ags/audio/ags_notation.c
++++ b/ags/audio/ags_notation.c
+@@ -46,7 +46,8 @@
+ GParamSpec *param_spec);
+ void ags_notation_connect(AgsConnectable *connectable);
+ void ags_notation_disconnect(AgsConnectable *connectable);
+-void ags_notation_finalize(GObject *object);
++void ags_notation_dispose(GObject *gobject);
++void ags_notation_finalize(GObject *gobject);
+
+ void ags_notation_change_bpm(AgsTactable *tactable, gdouble new_bpm, gdouble old_bpm);
+
+@@ -156,6 +157,7 @@
+ gobject->set_property = ags_notation_set_property;
+ gobject->get_property = ags_notation_get_property;
+
++ gobject->dispose = ags_notation_dispose;
+ gobject->finalize = ags_notation_finalize;
+
+ /* properties */
+@@ -335,13 +337,51 @@
+ void
+ ags_notation_connect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsNotation *notation;
++
++ GList *list;
++
++ notation = AGS_NOTATION(connectable);
++
++ if((AGS_NOTATION_CONNECTED & (notation->flags)) != 0){
++ return;
++ }
++
++ notation->flags |= AGS_NOTATION_CONNECTED;
++
++ /* note */
++ list = notation->notes;
++
++ while(list != NULL){
++ ags_connectable_connect(AGS_CONNECTABLE(list->data));
++
++ list = list->next;
++ }
+ }
+
+ void
+ ags_notation_disconnect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsNotation *notation;
++
++ GList *list;
++
++ notation = AGS_NOTATION(connectable);
++
++ if((AGS_NOTATION_CONNECTED & (notation->flags)) == 0){
++ return;
++ }
++
++ notation->flags &= (~AGS_NOTATION_CONNECTED);
++
++ /* note */
++ list = notation->notes;
++
++ while(list != NULL){
++ ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
++
++ list = list->next;
++ }
+ }
+
+ void
+@@ -608,16 +648,107 @@
+ }
+
+ void
++ags_notation_dispose(GObject *gobject)
++{
++ AgsNotation *notation;
++
++ GList *list;
++
++ notation = AGS_NOTATION(gobject);
++
++ /* timestamp */
++ if(notation->timestamp != NULL){
++ g_object_unref(notation->timestamp);
++
++ notation->timestamp = NULL;
++ }
++
++ /* audio */
++ if(notation->audio != NULL){
++ g_object_unref(notation->audio);
++
++ notation->audio = NULL;
++ }
++
++ /* key and base note */
++ if(notation->key != NULL){
++ free(notation->key);
++
++ notation->key = NULL;
++ }
++
++ if(notation->base_note != NULL){
++ free(notation->base_note);
++
++ notation->base_note = NULL;
++ }
++
++ /* note and selection */
++ list = notation->notes;
++
++ while(list != NULL){
++ g_object_run_dispose(G_OBJECT(list->data));
++
++ list = list->next;
++ }
++
++ g_list_free_full(notation->notes,
++ g_object_unref);
++
++ g_list_free(notation->selection);
++
++ notation->notes = NULL;
++ notation->selection = NULL;
++
++ /* port */
++ if(notation->port != NULL){
++ g_object_unref(notation->port);
++
++ notation->port = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_notation_parent_class)->dispose(gobject);
++}
++
++void
+ ags_notation_finalize(GObject *gobject)
+ {
+ AgsNotation *notation;
+- GList *list, *list_next;
+
+ notation = AGS_NOTATION(gobject);
+
++ /* timestamp */
++ if(notation->timestamp != NULL){
++ g_object_unref(notation->timestamp);
++ }
++
++ /* audio */
++ if(notation->audio != NULL){
++ g_object_unref(notation->audio);
++ }
++
++ /* key and base note */
++ if(notation->key != NULL){
++ free(notation->key);
++ }
++
++ if(notation->base_note != NULL){
++ free(notation->base_note);
++ }
++
++ /* note and selection */
+ g_list_free_full(notation->notes,
+ g_object_unref);
+
++ g_list_free(notation->selection);
++
++ /* port */
++ if(notation->port != NULL){
++ g_object_unref(notation->port);
++ }
++
++ /* call parent */
+ G_OBJECT_CLASS(ags_notation_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/audio/ags_notation.h
++++ b/ags/audio/ags_notation.h
+@@ -53,8 +53,9 @@
+ typedef struct _AgsNotationClass AgsNotationClass;
+
+ typedef enum{
+- AGS_NOTATION_STICKY = 1,
+- AGS_NOTATION_PATTERN_MODE = 1 << 1,
++ AGS_NOTATION_CONNECTED = 1,
++ AGS_NOTATION_STICKY = 1 << 1,
++ AGS_NOTATION_PATTERN_MODE = 1 << 2,
+ }AgsNotationFlags;
+
+ struct _AgsNotation
+--- a/ags/audio/ags_note.c
++++ b/ags/audio/ags_note.c
+@@ -38,7 +38,7 @@
+ GParamSpec *param_spec);
+ void ags_note_connect(AgsConnectable *connectable);
+ void ags_note_disconnect(AgsConnectable *connectable);
+-void ags_note_finalize(GObject *object);
++void ags_note_finalize(GObject *gobject);
+
+ /**
+ * SECTION:ags_note
+@@ -327,13 +327,29 @@
+ void
+ ags_note_connect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsNote *note;
++
++ note = AGS_NOTE(connectable);
++
++ if((AGS_NOTE_CONNECTED & (note->flags)) != 0){
++ return;
++ }
++
++ note->flags |= AGS_NOTE_CONNECTED;
+ }
+
+ void
+ ags_note_disconnect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsNote *note;
++
++ note = AGS_NOTE(connectable);
++
++ if((AGS_NOTE_CONNECTED & (note->flags)) == 0){
++ return;
++ }
++
++ note->flags &= (~AGS_NOTE_CONNECTED);
+ }
+
+ void
+@@ -478,8 +494,16 @@
+ void
+ ags_note_finalize(GObject *gobject)
+ {
+- /* empty */
++ AgsNote *note;
+
++ note = AGS_NOTE(gobject);
++
++ /* name */
++ if(note->name != NULL){
++ free(note->name);
++ }
++
++ /* call parent */
+ G_OBJECT_CLASS(ags_note_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/audio/ags_note.h
++++ b/ags/audio/ags_note.h
+@@ -41,12 +41,13 @@
+ typedef struct _AgsNoteClass AgsNoteClass;
+
+ typedef enum{
+- AGS_NOTE_GUI = 1,
+- AGS_NOTE_RUNTIME = 1 << 1,
+- AGS_NOTE_HUMAN_READABLE = 1 << 2,
+- AGS_NOTE_DEFAULT_LENGTH = 1 << 3,
+- AGS_NOTE_IS_SELECTED = 1 << 4,
+- AGS_NOTE_FEED = 1 << 5,
++ AGS_NOTE_CONNECTED = 1,
++ AGS_NOTE_GUI = 1 << 1,
++ AGS_NOTE_RUNTIME = 1 << 2,
++ AGS_NOTE_HUMAN_READABLE = 1 << 3,
++ AGS_NOTE_DEFAULT_LENGTH = 1 << 4,
++ AGS_NOTE_IS_SELECTED = 1 << 5,
++ AGS_NOTE_FEED = 1 << 6,
+ }AgsNoteFlags;
+
+ struct _AgsNote
+--- a/ags/audio/ags_pattern.c
++++ b/ags/audio/ags_pattern.c
+@@ -46,6 +46,7 @@
+ GParamSpec *param_spec);
+ void ags_pattern_connect(AgsConnectable *connectable);
+ void ags_pattern_disconnect(AgsConnectable *connectable);
++void ags_pattern_dispose(GObject *gobject);
+ void ags_pattern_finalize(GObject *gobject);
+
+ void ags_pattern_change_bpm(AgsTactable *tactable, gdouble new_bpm, gdouble old_bpm);
+@@ -148,6 +149,7 @@
+ gobject->set_property = ags_pattern_set_property;
+ gobject->get_property = ags_pattern_get_property;
+
++ gobject->dispose = ags_pattern_dispose;
+ gobject->finalize = ags_pattern_finalize;
+
+ /* properties */
+@@ -307,35 +309,29 @@
+
+ pthread_mutex_unlock(application_mutex);
+
+- /* */
++ /* base initialization */
++ pattern->flags = 0;
++
++ /* timestamp */
+ pattern->timestamp = NULL;
+
++ /* dimension and pattern */
+ pattern->dim[0] = 0;
+ pattern->dim[1] = 0;
+ pattern->dim[2] = 0;
+
+ pattern->pattern = NULL;
+
++ /* port */
+ pattern->port = NULL;
+
++ /* indices */
+ pattern->i = 0;
+ pattern->j = 0;
+ pattern->bit = 0;
+ }
+
+ void
+-ags_pattern_connect(AgsConnectable *connectable)
+-{
+- /* empty */
+-}
+-
+-void
+-ags_pattern_disconnect(AgsConnectable *connectable)
+-{
+- /* empty */
+-}
+-
+-void
+ ags_pattern_set_property(GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+@@ -521,23 +517,95 @@
+ }
+
+ void
++ags_pattern_connect(AgsConnectable *connectable)
++{
++ AgsPattern *pattern;
++
++ pattern = AGS_PATTERN(connectable);
++
++ if((AGS_PATTERN_CONNECTED & (pattern->flags)) != 0){
++ return;
++ }
++
++ pattern->flags |= AGS_PATTERN_CONNECTED;
++}
++
++void
++ags_pattern_disconnect(AgsConnectable *connectable)
++{
++ AgsPattern *pattern;
++
++ pattern = AGS_PATTERN(connectable);
++
++ if((AGS_PATTERN_CONNECTED & (pattern->flags)) == 0){
++ return;
++ }
++
++ pattern->flags &= (~AGS_PATTERN_CONNECTED);
++}
++
++void
++ags_pattern_dispose(GObject *gobject)
++{
++ AgsPattern *pattern;
++
++ pattern = AGS_PATTERN(gobject);
++
++ /* timestamp */
++ if(pattern->timestamp != NULL){
++ g_object_run_dispose(G_OBJECT(pattern->timestamp));
++
++ g_object_unref(G_OBJECT(pattern->timestamp));
++ }
++
++ /* port */
++ if(pattern->port != NULL){
++ g_object_unref(G_OBJECT(pattern->port));
++
++ pattern->port = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_pattern_parent_class)->dispose(gobject);
++}
++
++void
+ ags_pattern_finalize(GObject *gobject)
+ {
+ AgsPattern *pattern;
++
+ guint i, j;
+
+ pattern = AGS_PATTERN(gobject);
+
+- for(i = 0; i < pattern->dim[0]; i++){
+- for(j = 0; i < pattern->dim[1]; i++){
+- free(pattern->pattern[i][j]);
+- }
+-
+- free(pattern->pattern[i]);
++ /* timestamp */
++ if(pattern->timestamp != NULL){
++ g_object_unref(G_OBJECT(pattern->timestamp));
+ }
+
+- free(pattern->pattern);
++ /* pattern */
++ if(pattern->pattern != NULL){
++ for(i = 0; i < pattern->dim[0]; i++){
++ if(pattern->pattern[i] != NULL){
++ for(j = 0; j < pattern->dim[1]; j++){
++ if(pattern->pattern[i][j] != NULL){
++ free(pattern->pattern[i][j]);
++ }
++ }
++
++ free(pattern->pattern[i]);
++ }
++ }
+
++ free(pattern->pattern);
++ }
++
++ /* port */
++ if(pattern->port != NULL){
++ g_object_unref(G_OBJECT(pattern->port));
++ }
++
++ /* call parent */
+ G_OBJECT_CLASS(ags_pattern_parent_class)->finalize(gobject);
+ }
+
+@@ -570,9 +638,10 @@
+ GList*
+ ags_pattern_list_safe_properties(AgsPortlet *portlet)
+ {
+- static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ static GList *list = NULL;
+
++ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
++
+ pthread_mutex_lock(&mutex);
+
+ if(list == NULL){
+@@ -668,24 +737,23 @@
+ // shrink
+ if(pattern->dim[0] > dim0){
+ for(i = dim0; i < pattern->dim[0]; i++){
+- for(j = 0; j < pattern->dim[1]; j++)
++ for(j = 0; j < pattern->dim[1]; j++){
+ free(pattern->pattern[i][j]);
++ }
+
+ free(pattern->pattern[i]);
+ }
+
+ if(dim0 == 0){
+ free(pattern->pattern);
+- ags_pattern_init(pattern);
++
++ pattern->pattern = NULL;
++ pattern->dim[0] = 0;
++
+ return;
+ }else{
+- index0 = (guint ***) malloc((int) dim0 * sizeof(guint**));
+-
+- for(i = 0; i < dim0; i++)
+- index0[i] = pattern->pattern[i];
+-
+- free(pattern->pattern);
+- pattern->pattern = index0;
++ pattern->pattern = (guint ***) realloc(pattern->pattern,
++ (int) dim0 * sizeof(guint **));
+
+ pattern->dim[0] = dim0;
+ }
+@@ -697,9 +765,13 @@
+ for(j = dim1; j < pattern->dim[1]; j++){
+ free(pattern->pattern[i][j]);
+ }
++
+ pattern->pattern[i] = NULL;
+ }
+
++ pattern->dim[1] = 0;
++
++ return;
+ }else{
+ for(i = 0; i < pattern->dim[0]; i++){
+ for(j = dim1; j < pattern->dim[1]; j++){
+@@ -708,87 +780,103 @@
+ }
+
+ for(i = 0; pattern->dim[0]; i++){
+- index1 = (guint **) malloc(dim1 * sizeof(guint*));
++ pattern->pattern[i] = (guint **) realloc(pattern->pattern[i],
++ dim1 * sizeof(guint *));
++ }
++
++ pattern->dim[1] = dim1;
++ }
++ }
+
+- for(j = 0; j < dim1; j++){
+- index1[j] = pattern->pattern[i][j];
++ if(pattern->dim[2] > length){
++ if(length == 0){
++ for(i = 0; i < pattern->dim[0]; i++){
++ for(j = 0; j < pattern->dim[1]; j++){
++ free(pattern->pattern[i][j]);
++
++ pattern->pattern[i][j] = NULL;
+ }
++ }
+
+- free(pattern->pattern[i]);
+- pattern->pattern[i] = index1;
++ pattern->dim[2] = 0;
++ }else{
++ for(i = 0; i < pattern->dim[0]; i++){
++ for(j = 0; j < pattern->dim[1]; j++){
++ pattern->pattern[i][j] = (guint *) realloc(pattern->pattern[i][j],
++ (int) ceil((double) length / (double) (sizeof(guint) * 8)) * sizeof(guint));
++ }
+ }
+- }
+
+- pattern->dim[1] = dim1;
++ pattern->dim[2] = length;
++ }
+ }
+
+- if(pattern->dim[2] > length){
+- for(i = 0; i < pattern->dim[0]; i++)
+- for(j = 0; j < pattern->dim[1]; j++){
+- bitmap = (guint *) malloc((int) ceil((double) length / (double) (sizeof(guint) * 8)) * sizeof(guint));
++ // grow
++ bitmap_size = (int) ceil((double) pattern->dim[2] / (double) (sizeof(guint) * 8)) * sizeof(guint);
++
++ if(pattern->dim[0] < dim0){
++ if(pattern->pattern == NULL){
++ pattern->pattern = (guint ***) malloc(dim0 * sizeof(guint **));
++ }else{
++ pattern->pattern = (guint ***) realloc(pattern->pattern,
++ dim0 * sizeof(guint **));
++ }
+
+- for(k = 0; k < (guint) ceil((double) length / (double) (sizeof(guint) * 8)); k++)
+- bitmap[k] = pattern->pattern[i][j][k];
++ for(i = pattern->dim[0]; i < dim0; i++){
++ pattern->pattern[i] = (guint **) malloc(pattern->dim[1] * sizeof(guint *));
+
+- free(pattern->pattern[i][j]);
+- pattern->pattern[i][j] = bitmap;
+- }
+- }else if(pattern->dim[2] < length){ // grow
+- for(i = 0; i < pattern->dim[0]; i++)
+ for(j = 0; j < pattern->dim[1]; j++){
+- bitmap = (guint *) malloc((int) ceil((double) length / (double) (sizeof(guint) * 8)) * sizeof(guint));
+-
+- for(k = 0; k < (guint) ceil((double) pattern->dim[2] / (double) (sizeof(guint) * 8)); k++)
+- bitmap[k] = pattern->pattern[i][j][k];
+-
+- free(pattern->pattern[i][j]);
+- pattern->pattern[i][j] = bitmap;
++ if(bitmap_size == 0){
++ pattern->pattern[i][j] = NULL;
++ }else{
++ pattern->pattern[i][j] = (guint *) malloc(bitmap_size);
++ memset(pattern->pattern[i][j], 0, bitmap_size);
++ }
+ }
+- }
++ }
+
+- pattern->dim[2] = length;
+- bitmap_size = (guint) ceil((double) pattern->dim[2] / (double) (sizeof(guint) * 8)) * sizeof(guint);
++ pattern->dim[0] = dim0;
++ }
+
+- if(pattern->dim[1] < dim1){
++ if(pattern->dim[1] < dim1){
+ for(i = 0; i < pattern->dim[0]; i++){
+- index1 = (guint**) malloc(dim1 * sizeof(guint*));
+-
+- for(j = 0; j < pattern->dim[1]; j++)
+- index1[j] = pattern->pattern[i][j];
+-
+- free(pattern->pattern[i]);
+- pattern->pattern[i] = index1;
++ if(pattern->pattern[i] == NULL){
++ pattern->pattern[i] = (guint **) malloc(dim1 * sizeof(guint *));
++ }else{
++ pattern->pattern[i] = (guint **) realloc(pattern->pattern[i],
++ dim1 * sizeof(guint *));
++ }
+
+ for(j = pattern->dim[1]; j < dim1; j++){
+- pattern->pattern[i][j] = (guint*) malloc(bitmap_size);
+- memset(pattern->pattern[i][j], 0, bitmap_size);
++ if(bitmap_size == 0){
++ pattern->pattern[i][j] = NULL;
++ }else{
++ pattern->pattern[i][j] = (guint *) malloc(bitmap_size);
++ memset(pattern->pattern[i][j], 0, bitmap_size);
++ }
+ }
+ }
+
+ pattern->dim[1] = dim1;
+ }
+
+- if(pattern->dim[0] < dim0){
+- index0 = (guint***) malloc(dim0 * sizeof(guint**));
+-
+- for(i = 0; i < pattern->dim[0]; i++)
+- index0[i] = pattern->pattern[i];
+-
+- if(pattern->pattern != NULL)
+- free(pattern->pattern);
+-
+- pattern->pattern = index0;
+-
+- for(i = pattern->dim[0]; i < dim0; i++){
+- pattern->pattern[i] = (guint**) malloc(pattern->dim[1] * sizeof(guint*));
+-
++ if(pattern->dim[2] < length){
++ guint new_bitmap_size;
++
++ new_bitmap_size = (int) ceil((double) length / (double) (sizeof(guint) * 8)) * sizeof(guint);
++
++ for(i = 0; i < pattern->dim[0]; i++){
+ for(j = 0; j < pattern->dim[1]; j++){
+- pattern->pattern[i][j] = (guint*) malloc(bitmap_size);
+- memset(pattern->pattern[i][j], 0, bitmap_size);
++ if(pattern->pattern[i][j] == NULL){
++ pattern->pattern[i][j] = (guint *) malloc(new_bitmap_size);
++ memset(pattern->pattern[i][j], 0, new_bitmap_size);
++ }else{
++ pattern->pattern[i][j] =(guint *) realloc(pattern->pattern[i][j],
++ new_bitmap_size);
++ memset(pattern->pattern[i][j] + bitmap_size, 0, new_bitmap_size - bitmap_size);
++ }
+ }
+ }
+-
+- pattern->dim[0] = dim0;
+ }
+ }
+
+--- a/ags/audio/ags_pattern.h
++++ b/ags/audio/ags_pattern.h
+@@ -46,10 +46,16 @@
+ typedef struct _AgsPattern AgsPattern;
+ typedef struct _AgsPatternClass AgsPatternClass;
+
++typedef enum{
++ AGS_PATTERN_CONNECTED = 1,
++}AgsPatternFlags;
++
+ struct _AgsPattern
+ {
+- GObject object;
++ GObject gobject;
+
++ guint flags;
++
+ GObject *timestamp;
+
+ guint dim[3];
+@@ -64,7 +70,7 @@
+
+ struct _AgsPatternClass
+ {
+- GObjectClass object;
++ GObjectClass gobject;
+ };
+
+ GType ags_pattern_get_type();
+--- a/ags/audio/ags_playback.c
++++ b/ags/audio/ags_playback.c
+@@ -39,12 +39,28 @@
+ void ags_playback_class_init(AgsPlaybackClass *playback);
+ void ags_playback_connectable_interface_init(AgsConnectableInterface *connectable);
+ void ags_playback_init(AgsPlayback *playback);
++void ags_playback_set_property(GObject *gobject,
++ guint prop_id,
++ const GValue *value,
++ GParamSpec *param_spec);
++void ags_playback_get_property(GObject *gobject,
++ guint prop_id,
++ GValue *value,
++ GParamSpec *param_spec);
+ void ags_playback_disconnect(AgsConnectable *connectable);
+ void ags_playback_connect(AgsConnectable *connectable);
++void ags_playback_dispose(GObject *gobject);
+ void ags_playback_finalize(GObject *gobject);
+
+ static gpointer ags_playback_parent_class = NULL;
+
++enum{
++ PROP_0,
++ PROP_PLAYBACK_DOMAIN,
++ PROP_SOURCE,
++ PROP_AUDIO_CHANNEL,
++};
++
+ GType
+ ags_playback_get_type (void)
+ {
+@@ -93,7 +109,62 @@
+ /* GObjectClass */
+ gobject = (GObjectClass *) playback;
+
++ gobject->set_property = ags_playback_set_property;
++ gobject->get_property = ags_playback_get_property;
++
++ gobject->dispose = ags_playback_dispose;
+ gobject->finalize = ags_playback_finalize;
++
++ /* properties */
++ /**
++ * AgsPlayback:playback-domain:
++ *
++ * The parent playback domain.
++ *
++ * Since: 0.7.122.7
++ */
++ param_spec = g_param_spec_object("playback-domain\0",
++ "parent playback domain\0",
++ "The playback domain it is child of\0",
++ G_TYPE_OBJECT,
++ G_PARAM_READABLE | G_PARAM_WRITABLE);
++ g_object_class_install_property(gobject,
++ PROP_PLAYBACK_DOMAIN,
++ param_spec);
++
++ /**
++ * AgsPlayback:source:
++ *
++ * The assigned source.
++ *
++ * Since: 0.7.122.7
++ */
++ param_spec = g_param_spec_object("source\0",
++ "assigned source\0",
++ "The source it is assigned with\0",
++ G_TYPE_OBJECT,
++ G_PARAM_READABLE | G_PARAM_WRITABLE);
++ g_object_class_install_property(gobject,
++ PROP_SOURCE,
++ param_spec);
++
++ /**
++ * AgsPlayback:audio-channel:
++ *
++ * The assigned audio channel.
++ *
++ * Since: 0.7.122.7
++ */
++ param_spec = g_param_spec_uint("audio-channel\0",
++ "assigned audio channel\0",
++ "The audio channel it is assigned with\0",
++ 0,
++ G_MAXUINT,
++ 0,
++ G_PARAM_READABLE | G_PARAM_WRITABLE);
++ g_object_class_install_property(gobject,
++ PROP_AUDIO_CHANNEL,
++ param_spec);
+ }
+
+ void
+@@ -146,17 +217,295 @@
+ }
+
+ void
++ags_playback_set_property(GObject *gobject,
++ guint prop_id,
++ const GValue *value,
++ GParamSpec *param_spec)
++{
++ AgsPlayback *playback;
++
++ playback = AGS_PLAYBACK(gobject);
++
++ switch(prop_id){
++ case PROP_PLAYBACK_DOMAIN:
++ {
++ GObject *playback_domain;
++
++ playback_domain = (GObject *) g_value_get_object(value);
++
++ if((GObject *) playback->playback_domain == playback_domain){
++ return;
++ }
++
++ if(playback->playback_domain != NULL){
++ g_object_unref(G_OBJECT(playback->playback_domain));
++ }
++
++ if(playback_domain != NULL){
++ g_object_ref(G_OBJECT(playback_domain));
++ }
++
++ playback->playback_domain = (GObject *) playback_domain;
++ }
++ break;
++ case PROP_SOURCE:
++ {
++ GObject *source;
++
++ source = (GObject *) g_value_get_object(value);
++
++ if(source == playback->source){
++ return;
++ }
++
++ if(playback->source != NULL){
++ g_object_unref(G_OBJECT(playback->source));
++ }
++
++ if(source != NULL){
++ g_object_ref(G_OBJECT(source));
++
++ if(AGS_IS_CHANNEL(source) &&
++ ((AGS_PLAYBACK_SUPER_THREADED_CHANNEL & (g_atomic_int_get(&(playback->flags)))) != 0 ||
++ (AGS_PLAYBACK_SUPER_THREADED_RECYCLING & (g_atomic_int_get(&(playback->flags)))) != 0)){
++ gdouble freq;
++
++ /* thread frequency */
++ freq = ceil((gdouble) AGS_CHANNEL(source)->samplerate / (gdouble) AGS_CHANNEL(source)->buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK;
++
++ /* channel thread */
++ g_object_set(playback->channel_thread[0],
++ "frequency\0", freq,
++ "channel\0", source,
++ NULL);
++
++ g_object_set(playback->channel_thread[1],
++ "frequency\0", freq,
++ "channel\0", source,
++ NULL);
++
++ g_object_set(playback->channel_thread[2],
++ "frequency\0", freq,
++ "channel\0", source,
++ NULL);
++
++ if((AGS_PLAYBACK_SUPER_THREADED_RECYCLING & (g_atomic_int_get(&(playback->flags)))) != 0){
++ /* recycling thread */
++ g_object_set(playback->recycling_thread[0],
++ "frequency\0", freq,
++ NULL);
++
++ g_object_set(playback->recycling_thread[1],
++ "frequency\0", freq,
++ NULL);
++
++ g_object_set(playback->recycling_thread[2],
++ "frequency\0", freq,
++ NULL);
++
++ /* iterator thread */
++ g_object_set(playback->iterator_thread[0],
++ "frequency\0", freq,
++ NULL);
++
++ g_object_set(playback->iterator_thread[1],
++ "frequency\0", freq,
++ NULL);
++
++ g_object_set(playback->iterator_thread[2],
++ "frequency\0", freq,
++ NULL);
++ }
++ }
++ }
++
++ playback->source = (GObject *) source;
++ }
++ break;
++ case PROP_AUDIO_CHANNEL:
++ {
++ playback->audio_channel = g_value_get_uint(value);
++ }
++ break;
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
++ break;
++ }
++}
++
++void
++ags_playback_get_property(GObject *gobject,
++ guint prop_id,
++ GValue *value,
++ GParamSpec *param_spec)
++{
++ AgsPlayback *playback;
++
++ playback = AGS_PLAYBACK(gobject);
++
++ switch(prop_id){
++ case PROP_PLAYBACK_DOMAIN:
++ {
++ g_value_set_object(value,
++ playback->playback_domain);
++ }
++ break;
++ case PROP_SOURCE:
++ {
++ g_value_set_object(value,
++ playback->source);
++ }
++ break;
++ case PROP_AUDIO_CHANNEL:
++ {
++ g_value_set_uint(value,
++ playback->audio_channel);
++ }
++ break;
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
++ break;
++ }
++}
++
++void
++ags_playback_dispose(GObject *gobject)
++{
++ AgsPlayback *playback;
++
++ guint i;
++
++ playback = AGS_PLAYBACK(gobject);
++
++ /* playback domain */
++ if(playback->playback_domain != NULL){
++ g_object_unref(playback->playback_domain);
++
++ playback->playback_domain = NULL;
++ }
++
++ /* source */
++ if(playback->source != NULL){
++ g_object_unref(playback->source);
++
++ playback->source = NULL;
++ }
++
++ /* channel thread */
++ if(playback->channel_thread != NULL){
++ for(i = 0; i < 3; i++){
++ if(playback->channel_thread[i] != NULL){
++ g_object_run_dispose(playback->channel_thread[i]);
++ g_object_unref(playback->channel_thread[i]);
++
++ playback->channel_thread[i] = NULL;
++ }
++ }
++ }
++
++ /* recycling thread */
++ if(playback->recycling_thread != NULL){
++ for(i = 0; i < 3; i++){
++ if(playback->recycling_thread[i] != NULL){
++ g_object_run_dispose(playback->recycling_thread[i]);
++ g_object_unref(playback->recycling_thread[i]);
++
++ playback->recycling_thread[i] = NULL;
++ }
++ }
++
++ }
++
++ /* iterator thread */
++ if(playback->iterator_thread != NULL){
++ for(i = 0; i < 3; i++){
++ if(playback->iterator_thread[i] != NULL){
++ g_object_run_dispose(playback->iterator_thread[i]);
++ g_object_unref(playback->iterator_thread[i]);
++
++ playback->iterator_thread[i] = NULL;
++ }
++ }
++
++ }
++
++ /* recall id */
++ if(playback->recall_id != NULL){
++ for(i = 0; i < 3; i++){
++ if(playback->recall_id[i] != NULL){
++ g_object_unref(playback->recall_id[i]);
++
++ playback->recall_id[i] = NULL;
++ }
++ }
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_playback_parent_class)->dispose(gobject);
++}
++
++void
+ ags_playback_finalize(GObject *gobject)
+ {
+ AgsPlayback *playback;
+
++ guint i;
++
+ playback = AGS_PLAYBACK(gobject);
+
+- g_object_unref(G_OBJECT(playback->iterator_thread[0]));
+- g_object_unref(G_OBJECT(playback->iterator_thread[1]));
+- g_object_unref(G_OBJECT(playback->iterator_thread[2]));
++ /* playback domain */
++ if(playback->playback_domain != NULL){
++ g_object_unref(playback->playback_domain);
++ }
+
+- free(playback->iterator_thread);
++ /* source */
++ if(playback->source != NULL){
++ g_object_unref(playback->source);
++ }
++
++ /* channel thread */
++ if(playback->channel_thread != NULL){
++ for(i = 0; i < 3; i++){
++ if(playback->channel_thread[i] != NULL){
++ g_object_unref(playback->channel_thread[i]);
++ }
++ }
++
++ free(playback->channel_thread);
++ }
++
++ /* recycling thread */
++ if(playback->recycling_thread != NULL){
++ for(i = 0; i < 3; i++){
++ if(playback->recycling_thread[i] != NULL){
++ g_object_unref(playback->recycling_thread[i]);
++ }
++ }
++
++ free(playback->recycling_thread);
++ }
++
++ /* iterator thread */
++ if(playback->iterator_thread != NULL){
++ for(i = 0; i < 3; i++){
++ if(playback->iterator_thread[i] != NULL){
++ g_object_unref(playback->iterator_thread[i]);
++ }
++ }
++
++ free(playback->iterator_thread);
++ }
++
++ /* recall id */
++ if(playback->recall_id != NULL){
++ for(i = 0; i < 3; i++){
++ if(playback->recall_id[i] != NULL){
++ g_object_unref(playback->recall_id[i]);
++ }
++ }
++
++ free(playback->recall_id);
++ }
+
+ /* call parent */
+ G_OBJECT_CLASS(ags_playback_parent_class)->finalize(gobject);
+@@ -165,13 +514,250 @@
+ void
+ ags_playback_connect(AgsConnectable *connectable)
+ {
+- //TODO:JK: implement me
++ AgsPlayback *playback;
++
++ playback = AGS_PLAYBACK(connectable);
++
++ if((AGS_PLAYBACK_CONNECTED & (playback->flags)) != 0){
++ return;
++ }
++
++ playback->flags |= AGS_PLAYBACK_CONNECTED;
+ }
+
+ void
+ ags_playback_disconnect(AgsConnectable *connectable)
+ {
+- //TODO:JK: implement me
++ AgsPlayback *playback;
++
++ playback = AGS_PLAYBACK(connectable);
++
++
++ if((AGS_PLAYBACK_CONNECTED & (playback->flags)) == 0){
++ return;
++ }
++
++ playback->flags &= (~AGS_PLAYBACK_CONNECTED);
++}
++
++/**
++ * ags_playback_set_channel_thread:
++ * @playback: the #AgsPlayback
++ * @thread: the #AgsChannelThread
++ * @scope: the scope of the thread to set
++ *
++ * Set channel thread of appropriate scope.
++ *
++ * Since: 0.7.122.7
++ */
++void
++ags_playback_set_channel_thread(AgsPlayback *playback,
++ AgsThread *thread,
++ guint scope)
++{
++ if(playback == NULL ||
++ scope > 2){
++ return;
++ }
++
++ if(playback->channel_thread[scope] != NULL){
++ g_object_unref(playback->channel_thread[scope]);
++ }
++
++ if(thread != NULL){
++ g_object_ref(thread);
++ }
++
++ playback->channel_thread[scope] = thread;
++}
++
++/**
++ * ags_playback_get_channel_thread:
++ * @playback: the #AgsPlayback
++ * @scope: the scope of the thread to get
++ *
++ * Get channel thread of appropriate scope.
++ *
++ * Returns: the matching #AgsThread or %NULL
++ *
++ * Since: 0.7.122.7
++ */
++AgsThread*
++ags_playback_get_channel_thread(AgsPlayback *playback,
++ guint scope)
++{
++ if(playback == NULL ||
++ playback->channel_thread == NULL ||
++ scope > 2){
++ return(NULL);
++ }
++
++ return(playback->channel_thread[scope]);
++}
++
++/**
++ * ags_playback_set_iterator_thread:
++ * @playback: the #AgsPlayback
++ * @thread: the #AgsIteratorThread
++ * @scope: the scope of the thread to set
++ *
++ * Set iterator thread of appropriate scope.
++ *
++ * Since: 0.7.122.7
++ */
++void
++ags_playback_set_iterator_thread(AgsPlayback *playback,
++ AgsThread *thread,
++ guint scope)
++{
++ if(playback == NULL ||
++ scope > 2){
++ return;
++ }
++
++ if(playback->iterator_thread[scope] != NULL){
++ g_object_unref(playback->iterator_thread[scope]);
++ }
++
++ if(thread != NULL){
++ g_object_ref(thread);
++ }
++
++ playback->iterator_thread[scope] = thread;
++}
++
++/**
++ * ags_playback_get_iterator_thread:
++ * @playback: the #AgsPlayback
++ * @scope: the scope of the thread to get
++ *
++ * Get iterator thread of appropriate scope.
++ *
++ * Returns: the matching #AgsThread or %NULL
++ *
++ * Since: 0.7.122.7
++ */
++AgsThread*
++ags_playback_get_iterator_thread(AgsPlayback *playback,
++ guint scope)
++{
++ if(playback == NULL ||
++ playback->iterator_thread == NULL ||
++ scope > 2){
++ return(NULL);
++ }
++
++ return(playback->iterator_thread[scope]);
++}
++
++/**
++ * ags_playback_set_recycling_thread:
++ * @playback: the #AgsPlayback
++ * @thread: the #AgsRecyclingThread
++ * @scope: the scope of the thread to set
++ *
++ * Set recycling thread of appropriate scope.
++ *
++ * Since: 0.7.122.7
++ */
++void
++ags_playback_set_recycling_thread(AgsPlayback *playback,
++ AgsThread *thread,
++ guint scope)
++{
++ if(playback == NULL ||
++ scope > 2){
++ return;
++ }
++
++ if(playback->recycling_thread[scope] != NULL){
++ g_object_unref(playback->recycling_thread[scope]);
++ }
++
++ if(thread != NULL){
++ g_object_ref(thread);
++ }
++
++ playback->recycling_thread[scope] = thread;
++}
++
++/**
++ * ags_playback_get_recycling_thread:
++ * @playback: the #AgsPlayback
++ * @scope: the scope of the thread to get
++ *
++ * Get recycling thread of appropriate scope.
++ *
++ * Returns: the matching #AgsThread or %NULL
++ *
++ * Since: 0.7.122.7
++ */
++AgsThread*
++ags_playback_get_recycling_thread(AgsPlayback *playback,
++ guint scope)
++{
++ if(playback == NULL ||
++ playback->recycling_thread == NULL ||
++ scope > 2){
++ return(NULL);
++ }
++
++ return(playback->recycling_thread[scope]);
++}
++
++/**
++ * ags_playback_set_recall_id:
++ * @playback: the #AgsPlayback
++ * @recall_id: the #AgsRecallID
++ * @scope: the scope of the recall id to set
++ *
++ * Set recall id of appropriate scope.
++ *
++ * Since: 0.7.122.7
++ */
++void
++ags_playback_set_recall_id(AgsPlayback *playback,
++ AgsRecallID *recall_id,
++ guint scope)
++{
++ if(playback == NULL ||
++ scope > 2){
++ return;
++ }
++
++ if(playback->recall_id[scope] != NULL){
++ g_object_unref(playback->recall_id[scope]);
++ }
++
++ if(recall_id != NULL){
++ g_object_ref(recall_id);
++ }
++
++ playback->recall_id[scope] = recall_id;
++}
++
++/**
++ * ags_playback_get_recall_id:
++ * @playback: the #AgsPlayback
++ * @scope: the scope of the recall id to get
++ *
++ * Get recall id of appropriate scope.
++ *
++ * Returns: the matching #AgsRecallID or %NULL
++ *
++ * Since: 0.7.122.7
++ */
++AgsRecallID*
++ags_playback_get_recall_id(AgsPlayback *playback,
++ guint scope)
++{
++ if(playback == NULL ||
++ playback->recall_id == NULL ||
++ scope > 2){
++ return(NULL);
++ }
++
++ return(playback->recall_id[scope]);
+ }
+
+ /**
+--- a/ags/audio/ags_playback.h
++++ b/ags/audio/ags_playback.h
+@@ -31,8 +31,6 @@
+
+ #include <ags/audio/ags_recall_id.h>
+
+-#include <ags/audio/thread/ags_iterator_thread.h>
+-
+ #define AGS_TYPE_PLAYBACK (ags_playback_get_type())
+ #define AGS_PLAYBACK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_PLAYBACK, AgsPlayback))
+ #define AGS_PLAYBACK_CLASS(class) (G_TYPE_CHECK_CLASS_CAST(class, AGS_TYPE_PLAYBACK, AgsPlayback))
+@@ -43,35 +41,43 @@
+ typedef struct _AgsPlayback AgsPlayback;
+ typedef struct _AgsPlaybackClass AgsPlaybackClass;
+
+-typedef enum
+-{
+- AGS_PLAYBACK_DONE = 1,
+- AGS_PLAYBACK_REMOVE = 1 << 1,
+- AGS_PLAYBACK_CHANNEL = 1 << 2,
+- AGS_PLAYBACK_PAD = 1 << 3,
+- AGS_PLAYBACK_AUDIO = 1 << 4,
+- AGS_PLAYBACK_PLAYBACK = 1 << 5,
+- AGS_PLAYBACK_SEQUENCER = 1 << 6,
+- AGS_PLAYBACK_NOTATION = 1 << 7,
+- AGS_PLAYBACK_SINGLE_THREADED = 1 << 8,
+- AGS_PLAYBACK_SUPER_THREADED_CHANNEL = 1 << 9,
+- AGS_PLAYBACK_SUPER_THREADED_RECYCLING = 1 << 10,
++typedef enum{
++ AGS_PLAYBACK_CONNECTED = 1,
++ AGS_PLAYBACK_DONE = 1 << 1,
++ AGS_PLAYBACK_REMOVE = 1 << 2,
++ AGS_PLAYBACK_CHANNEL = 1 << 3,
++ AGS_PLAYBACK_PAD = 1 << 4,
++ AGS_PLAYBACK_AUDIO = 1 << 5,
++ AGS_PLAYBACK_PLAYBACK = 1 << 6,
++ AGS_PLAYBACK_SEQUENCER = 1 << 7,
++ AGS_PLAYBACK_NOTATION = 1 << 8,
++ AGS_PLAYBACK_SINGLE_THREADED = 1 << 9,
++ AGS_PLAYBACK_SUPER_THREADED_CHANNEL = 1 << 10,
++ AGS_PLAYBACK_SUPER_THREADED_RECYCLING = 1 << 11,
+ }AgsPlaybackFlags;
+
++typedef enum{
++ AGS_PLAYBACK_SCOPE_PLAYBACK,
++ AGS_PLAYBACK_SCOPE_SEQUENCER,
++ AGS_PLAYBACK_SCOPE_NOTATION,
++}AgsPlaybackScope;
++
+ struct _AgsPlayback
+ {
+ GObject gobject;
+
+ volatile guint flags;
+
+- AgsThread **channel_thread;
+- AgsIteratorThread **iterator_thread;
+-
+- AgsThread **recycling_thread;
++ GObject *playback_domain;
+
+ GObject *source;
+ guint audio_channel;
+
++ AgsThread **channel_thread;
++ AgsThread **iterator_thread;
++
++ AgsThread **recycling_thread;
++
+ AgsRecallID **recall_id;
+ };
+
+@@ -82,9 +88,36 @@
+
+ GType ags_playback_get_type();
+
++/* get and set */
++void ags_playback_set_channel_thread(AgsPlayback *playback,
++ AgsThread *thread,
++ guint scope);
++AgsThread* ags_playback_get_channel_thread(AgsPlayback *playback,
++ guint scope);
++
++void ags_playback_set_iterator_thread(AgsPlayback *playback,
++ AgsThread *thread,
++ guint scope);
++AgsThread* ags_playback_get_iterator_thread(AgsPlayback *playback,
++ guint scope);
++
++void ags_playback_set_recycling_thread(AgsPlayback *playback,
++ AgsThread *thread,
++ guint scope);
++AgsThread* ags_playback_get_recycling_thread(AgsPlayback *playback,
++ guint scope);
++
++void ags_playback_set_recall_id(AgsPlayback *playback,
++ AgsRecallID *recall_id,
++ guint scope);
++AgsRecallID* ags_playback_get_recall_id(AgsPlayback *playback,
++ guint scope);
++
++/* find */
+ AgsPlayback* ags_playback_find_source(GList *playback,
+ GObject *source);
+
++/* instance */
+ AgsPlayback* ags_playback_new();
+
+ #endif /*__AGS_PLAYBACK_H__*/
+--- a/ags/audio/ags_playback_domain.c
++++ b/ags/audio/ags_playback_domain.c
+@@ -19,7 +19,12 @@
+
+ #include <ags/audio/ags_playback_domain.h>
+
++#include <ags/object/ags_config.h>
+ #include <ags/object/ags_connectable.h>
++#include <ags/object/ags_soundcard.h>
++
++#include <ags/audio/ags_audio.h>
++#include <ags/audio/ags_playback.h>
+
+ #include <ags/audio/thread/ags_audio_thread.h>
+
+@@ -36,12 +41,27 @@
+ void ags_playback_domain_class_init(AgsPlaybackDomainClass *playback_domain);
+ void ags_playback_domain_connectable_interface_init(AgsConnectableInterface *connectable);
+ void ags_playback_domain_init(AgsPlaybackDomain *playback_domain);
++void ags_playback_domain_set_property(GObject *gobject,
++ guint prop_id,
++ const GValue *value,
++ GParamSpec *param_spec);
++void ags_playback_domain_get_property(GObject *gobject,
++ guint prop_id,
++ GValue *value,
++ GParamSpec *param_spec);
+ void ags_playback_domain_disconnect(AgsConnectable *connectable);
+ void ags_playback_domain_connect(AgsConnectable *connectable);
++void ags_playback_domain_dispose(GObject *gobject);
+ void ags_playback_domain_finalize(GObject *gobject);
+
+ static gpointer ags_playback_domain_parent_class = NULL;
+
++enum{
++ PROP_0,
++ PROP_DOMAIN,
++ PROP_PLAYBACK,
++};
++
+ GType
+ ags_playback_domain_get_type (void)
+ {
+@@ -90,7 +110,44 @@
+ /* GObjectClass */
+ gobject = (GObjectClass *) playback_domain;
+
++ gobject->set_property = ags_playback_domain_set_property;
++ gobject->get_property = ags_playback_domain_get_property;
++
++ gobject->dispose = ags_playback_domain_dispose;
+ gobject->finalize = ags_playback_domain_finalize;
++
++ /* properties */
++ /**
++ * AgsPlaybackDomain:domain:
++ *
++ * The assigned domain.
++ *
++ * Since: 0.7.122.7
++ */
++ param_spec = g_param_spec_object("domain\0",
++ "assigned domain\0",
++ "The domain it is assigned with\0",
++ G_TYPE_OBJECT,
++ G_PARAM_READABLE | G_PARAM_WRITABLE);
++ g_object_class_install_property(gobject,
++ PROP_DOMAIN,
++ param_spec);
++
++ /**
++ * AgsPlaybackDomain:playback:
++ *
++ * The assigned playback.
++ *
++ * Since: 0.7.122.7
++ */
++ param_spec = g_param_spec_object("playback\0",
++ "assigned playback\0",
++ "The playback it is assigned with\0",
++ G_TYPE_OBJECT,
++ G_PARAM_READABLE | G_PARAM_WRITABLE);
++ g_object_class_install_property(gobject,
++ PROP_PLAYBACK,
++ param_spec);
+ }
+
+ void
+@@ -105,9 +162,60 @@
+ void
+ ags_playback_domain_init(AgsPlaybackDomain *playback_domain)
+ {
++ AgsConfig *config;
++
++ gchar *str, *str0, *str1;
++
++ gboolean super_threaded_audio;
++
++ /* config */
++ config = ags_config_get_instance();
++
++ /* thread model */
++ str0 = ags_config_get_value(config,
++ AGS_CONFIG_THREAD,
++ "model\0");
++ str1 = ags_config_get_value(config,
++ AGS_CONFIG_THREAD,
++ "super-threaded-scope\0");
++
++ if(str0 != NULL && str1 != NULL){
++ if(!g_ascii_strncasecmp(str0,
++ "super-threaded\0",
++ 15)){
++ if(!g_ascii_strncasecmp(str1,
++ "audio\0",
++ 6) ||
++ !g_ascii_strncasecmp(str1,
++ "channel\0",
++ 8) ||
++ !g_ascii_strncasecmp(str1,
++ "recycling\0",
++ 10)){
++ super_threaded_audio = TRUE;
++ }
++ }
++ }
++
++ if(str0 != NULL){
++ free(str0);
++ }
++
++ if(str1 != NULL){
++ free(str1);
++ }
++
+ /* default flags */
+- g_atomic_int_set(&(playback_domain->flags),
+- AGS_PLAYBACK_DOMAIN_SUPER_THREADED_AUDIO);
++ if(super_threaded_audio){
++ g_atomic_int_set(&(playback_domain->flags),
++ AGS_PLAYBACK_DOMAIN_SUPER_THREADED_AUDIO);
++ }else{
++ g_atomic_int_set(&(playback_domain->flags),
++ 0);
++ }
++
++ /* domain */
++ playback_domain->domain = NULL;
+
+ /* super threaded audio */
+ playback_domain->audio_thread = (AgsThread **) malloc(3 * sizeof(AgsThread *));
+@@ -115,20 +223,248 @@
+ playback_domain->audio_thread[0] = NULL;
+ playback_domain->audio_thread[1] = NULL;
+ playback_domain->audio_thread[2] = NULL;
++
++ if(super_threaded_audio){
++ guint samplerate, buffer_size;
++ gdouble freq;
++
++ samplerate = AGS_SOUNDCARD_DEFAULT_SAMPLERATE;
++ buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
++
++ /* samplerate */
++ str = ags_config_get_value(config,
++ AGS_CONFIG_SOUNDCARD,
++ "samplerate\0");
++
++ if(str == NULL){
++ str = ags_config_get_value(config,
++ AGS_CONFIG_SOUNDCARD_0,
++ "samplerate\0");
++ }
++
++ if(str != NULL){
++ samplerate = g_ascii_strtoull(str,
++ NULL,
++ 10);
++
++ free(str);
++ }
++
++ /* buffer size */
++ str = ags_config_get_value(config,
++ AGS_CONFIG_SOUNDCARD,
++ "buffer-size\0");
++
++ if(str == NULL){
++ str = ags_config_get_value(config,
++ AGS_CONFIG_SOUNDCARD_0,
++ "buffer-size\0");
++ }
++
++ if(str != NULL){
++ buffer_size = g_ascii_strtoull(str,
++ NULL,
++ 10);
++
++ free(str);
++ }
++
++ /* thread frequency */
++ freq = ceil((gdouble) samplerate / (gdouble) buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK;
++
++ /* playback audio thread */
++ playback_domain->audio_thread[0] = (AgsThread *) ags_audio_thread_new(NULL,
++ NULL);
++ g_object_ref(playback_domain->audio_thread[0]);
++ playback_domain->audio_thread[0]->freq = freq;
++
++ /* sequencer audio thread */
++ playback_domain->audio_thread[1] = (AgsThread *) ags_audio_thread_new(NULL,
++ NULL);
++ g_object_ref(playback_domain->audio_thread[1]);
++ playback_domain->audio_thread[1]->freq = freq;
++
++ /* notation audio thread */
++ playback_domain->audio_thread[2] = (AgsThread *) ags_audio_thread_new(NULL,
++ NULL);
++ g_object_ref(playback_domain->audio_thread[2]);
++ playback_domain->audio_thread[2]->freq = freq;
++ }
+
+- playback_domain->domain = NULL;
++ /* playback */
+ playback_domain->playback = NULL;
+ }
+
+ void
++ags_playback_domain_set_property(GObject *gobject,
++ guint prop_id,
++ const GValue *value,
++ GParamSpec *param_spec)
++{
++ AgsPlaybackDomain *playback_domain;
++
++ playback_domain = AGS_PLAYBACK_DOMAIN(gobject);
++
++ switch(prop_id){
++ case PROP_DOMAIN:
++ {
++ GObject *domain;
++
++ domain = (GObject *) g_value_get_object(value);
++
++ if((GObject *) playback_domain->domain == domain){
++ return;
++ }
++
++ if(playback_domain->domain != NULL){
++ g_object_unref(G_OBJECT(playback_domain->domain));
++ }
++
++ if(domain != NULL){
++ g_object_ref(G_OBJECT(domain));
++
++ if(AGS_IS_AUDIO(domain) &&
++ (AGS_PLAYBACK_DOMAIN_SUPER_THREADED_AUDIO & (g_atomic_int_get(&(playback_domain->flags)))) != 0){
++ gdouble freq;
++
++ /* thread frequency */
++ freq = ceil((gdouble) AGS_AUDIO(domain)->samplerate / (gdouble) AGS_AUDIO(domain)->buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK;
++
++ g_object_set(playback_domain->audio_thread[0],
++ "frequency\0", freq,
++ "audio\0", domain,
++ NULL);
++
++ g_object_set(playback_domain->audio_thread[1],
++ "frequency\0", freq,
++ "audio\0", domain,
++ NULL);
++
++ g_object_set(playback_domain->audio_thread[2],
++ "frequency\0", freq,
++ "audio\0", domain,
++ NULL);
++ }
++ }
++
++ playback_domain->domain = (GObject *) domain;
++ }
++ break;
++ case PROP_PLAYBACK:
++ {
++ AgsPlayback *playback;
++
++ playback = (AgsPlayback *) g_value_get_object(value);
++
++ if(playback == NULL ||
++ g_list_find(playback_domain->playback, playback) != NULL){
++ return;
++ }
++
++ ags_playback_domain_add_playback(playback_domain,
++ (GObject *) playback);
++ }
++ break;
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
++ break;
++ }
++}
++
++void
++ags_playback_domain_get_property(GObject *gobject,
++ guint prop_id,
++ GValue *value,
++ GParamSpec *param_spec)
++{
++ AgsPlaybackDomain *playback_domain;
++
++ playback_domain = AGS_PLAYBACK_DOMAIN(gobject);
++
++ switch(prop_id){
++ case PROP_DOMAIN:
++ {
++ g_value_set_object(value,
++ playback_domain->domain);
++ }
++ break;
++ case PROP_PLAYBACK:
++ {
++ g_value_set_pointer(value,
++ g_list_copy(playback_domain->playback));
++ }
++ break;
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
++ break;
++ }
++}
++
++void
++ags_playback_domain_dispose(GObject *gobject)
++{
++ AgsPlaybackDomain *playback_domain;
++
++ guint i;
++
++ playback_domain = AGS_PLAYBACK_DOMAIN(gobject);
++
++ if(playback_domain->audio_thread != NULL){
++ for(i = 0; i < 3; i++){
++ if(playback_domain->audio_thread[i] != NULL){
++ g_object_run_dispose(playback_domain->audio_thread[i]);
++ g_object_unref(playback_domain->audio_thread[i]);
++
++ playback_domain->audio_thread[i] = NULL;
++ }
++ }
++ }
++
++ /* domain */
++ if(playback_domain->domain != NULL){
++ g_object_unref(playback_domain->domain);
++
++ playback_domain->domain = NULL;
++ }
++
++ /* playback */
++ if(playback_domain->playback != NULL){
++ g_list_free_full(playback_domain->playback,
++ g_object_unref);
++
++ playback_domain->playback = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_playback_domain_parent_class)->dispose(gobject);
++}
++
++void
+ ags_playback_domain_finalize(GObject *gobject)
+ {
+ AgsPlaybackDomain *playback_domain;
+
++ guint i;
++
+ playback_domain = AGS_PLAYBACK_DOMAIN(gobject);
+
+- free(playback_domain->audio_thread);
++ /* audio thread */
++ if(playback_domain->audio_thread != NULL){
++ for(i = 0; i < 3; i++){
++ if(playback_domain->audio_thread[i] != NULL){
++ g_object_unref(playback_domain->audio_thread[i]);
++ }
++ }
++
++ free(playback_domain->audio_thread);
++ }
++
++ /* domain */
++ if(playback_domain->domain != NULL){
++ g_object_unref(playback_domain->domain);
++ }
+
++ /* playback */
+ g_list_free_full(playback_domain->playback,
+ g_object_unref);
+
+@@ -139,13 +475,133 @@
+ void
+ ags_playback_domain_connect(AgsConnectable *connectable)
+ {
+- //TODO:JK: implement me
++ AgsPlaybackDomain *playback_domain;
++
++ playback_domain = AGS_PLAYBACK_DOMAIN(connectable);
++
++ if((AGS_PLAYBACK_DOMAIN_CONNECTED & (playback_domain->flags)) != 0){
++ return;
++ }
++
++ playback_domain->flags |= AGS_PLAYBACK_DOMAIN_CONNECTED;
+ }
+
+ void
+ ags_playback_domain_disconnect(AgsConnectable *connectable)
+ {
+- //TODO:JK: implement me
++ AgsPlaybackDomain *playback_domain;
++
++ playback_domain = AGS_PLAYBACK_DOMAIN(connectable);
++
++
++ if((AGS_PLAYBACK_DOMAIN_CONNECTED & (playback_domain->flags)) == 0){
++ return;
++ }
++
++ playback_domain->flags &= (~AGS_PLAYBACK_DOMAIN_CONNECTED);
++}
++
++/**
++ * ags_playback_domain_set_audio_thread:
++ * @playback_domain: the #AgsPlaybackDomain
++ * @thread: the #AgsThread
++ * @scope: the thread's scope
++ *
++ * Set audio thread to specified scope.
++ *
++ * Since: 0.7.122.7
++ */
++void
++ags_playback_domain_set_audio_thread(AgsPlaybackDomain *playback_domain,
++ AgsThread *thread,
++ guint scope)
++{
++ if(playback_domain == NULL ||
++ scope > 2){
++ return;
++ }
++
++ if(playback_domain->audio_thread[scope] != NULL){
++ g_object_unref(playback_domain->audio_thread[scope]);
++ }
++
++ if(thread != NULL){
++ g_object_ref(thread);
++ }
++
++ playback_domain->audio_thread[scope] = thread;
++}
++
++/**
++ * ags_playback_domain_set_audio_thread:
++ * @playback_domain: the #AgsPlaybackDomain
++ * @scope: the thread's scope
++ *
++ * Get audio thread of specified scope.
++ *
++ * Returns: the matching #AgsThread or %NULL
++ *
++ * Since: 0.7.122.7
++ */
++AgsThread*
++ags_playback_domain_get_audio_thread(AgsPlaybackDomain *playback_domain,
++ guint scope)
++{
++ if(playback_domain == NULL ||
++ playback_domain->audio_thread == NULL ||
++ scope > 2){
++ return(NULL);
++ }
++
++ return(playback_domain->audio_thread[scope]);
++}
++
++
++/**
++ * ags_playback_domain_add_playback:
++ * @playback_domain: the #AgsPlaybackDomain
++ * @playback: the #AgsPlayback
++ *
++ * Add @playback to @playback_domain.
++ *
++ * Since: 0.7.122.7
++ */
++void
++ags_playback_domain_add_playback(AgsPlaybackDomain *playback_domain,
++ GObject *playback)
++{
++ if(playback_domain == NULL ||
++ playback == NULL){
++ return;
++ }
++
++ //TODO:JK: rather use prepend but needs refactoring
++ g_object_ref(playback);
++ playback_domain->playback = g_list_append(playback_domain->playback,
++ playback);
++}
++
++/**
++ * ags_playback_domain_remove_playback:
++ * @playback_domain: the #AgsPlaybackDomain
++ * @playback: the #AgsPlayback
++ *
++ * Remove @playback of @playback_domain.
++ *
++ * Since: 0.7.122.7
++ */
++void
++ags_playback_domain_remove_playback(AgsPlaybackDomain *playback_domain,
++ GObject *playback)
++{
++ if(playback_domain == NULL ||
++ playback == NULL){
++ return;
++ }
++
++ playback_domain->playback = g_list_remove(playback_domain->playback,
++ playback);
++ g_object_unref(playback);
+ }
+
+ /**
+--- a/ags/audio/ags_playback_domain.h
++++ b/ags/audio/ags_playback_domain.h
+@@ -40,22 +40,30 @@
+ typedef struct _AgsPlaybackDomainClass AgsPlaybackDomainClass;
+
+ typedef enum{
+- AGS_PLAYBACK_DOMAIN_PLAYBACK = 1,
+- AGS_PLAYBACK_DOMAIN_SEQUENCER = 1 << 1,
+- AGS_PLAYBACK_DOMAIN_NOTATION = 1 << 2,
+- AGS_PLAYBACK_DOMAIN_SINGLE_THREADED = 1 << 3,
+- AGS_PLAYBACK_DOMAIN_SUPER_THREADED_AUDIO = 1 << 4,
++ AGS_PLAYBACK_DOMAIN_CONNECTED = 1,
++ AGS_PLAYBACK_DOMAIN_PLAYBACK = 1 << 1,
++ AGS_PLAYBACK_DOMAIN_SEQUENCER = 1 << 2,
++ AGS_PLAYBACK_DOMAIN_NOTATION = 1 << 3,
++ AGS_PLAYBACK_DOMAIN_SINGLE_THREADED = 1 << 4,
++ AGS_PLAYBACK_DOMAIN_SUPER_THREADED_AUDIO = 1 << 5,
+ }AgsPlaybackDomainFlags;
+
++typedef enum{
++ AGS_PLAYBACK_DOMAIN_SCOPE_PLAYBACK,
++ AGS_PLAYBACK_DOMAIN_SCOPE_SEQUENCER,
++ AGS_PLAYBACK_DOMAIN_SCOPE_NOTATION,
++}AgsPlaybackDomainScope;
++
+ struct _AgsPlaybackDomain
+ {
+ GObject gobject;
+
+ volatile guint flags;
++
++ GObject *domain;
+
+ AgsThread **audio_thread;
+
+- GObject *domain;
+ GList *playback;
+ };
+
+@@ -66,6 +74,20 @@
+
+ GType ags_playback_domain_get_type();
+
++/* get and set */
++void ags_playback_domain_set_audio_thread(AgsPlaybackDomain *playback_domain,
++ AgsThread *thread,
++ guint scope);
++AgsThread* ags_playback_domain_get_audio_thread(AgsPlaybackDomain *playback_domain,
++ guint scope);
++
++/* add and remove */
++void ags_playback_domain_add_playback(AgsPlaybackDomain *playback_domain,
++ GObject *playback);
++void ags_playback_domain_remove_playback(AgsPlaybackDomain *playback_domain,
++ GObject *playback);
++
++/* instance */
+ AgsPlaybackDomain* ags_playback_domain_new();
+
+ #endif /*__AGS_PLAYBACK_DOMAIN_H__*/
+--- a/ags/audio/ags_recall.c
++++ b/ags/audio/ags_recall.c
+@@ -96,7 +96,8 @@
+ GList* ags_recall_get_ports(AgsPlugin *plugin);
+ void ags_recall_read(AgsFile *file, xmlNode *node, AgsPlugin *plugin);
+ xmlNode* ags_recall_write(AgsFile *file, xmlNode *parent, AgsPlugin *plugin);
+-void ags_recall_finalize(GObject *recall);
++void ags_recall_dispose(GObject *gobject);
++void ags_recall_finalize(GObject *gobject);
+
+ void ags_recall_real_load_automation(AgsRecall *recall,
+ GList *automation_port);
+@@ -250,6 +251,7 @@
+ gobject->set_property = ags_recall_set_property;
+ gobject->get_property = ags_recall_get_property;
+
++ gobject->dispose = ags_recall_dispose;
+ gobject->finalize = ags_recall_finalize;
+
+ /* properties */
+@@ -902,18 +904,39 @@
+ case PROP_PARENT:
+ {
+ AgsRecall *parent;
+-
++
+ parent = (AgsRecall *) g_value_get_object(value);
+
+- ags_recall_add_child(parent, recall);
++ if(recall->parent == parent){
++ return;
++ }
++
++ if(recall->parent != NULL){
++ g_object_unref(recall->parent);
++ }
++
++ if(parent != NULL){
++ g_object_ref(parent);
++ }
++
++ recall->parent = parent;
+ }
+ break;
+ case PROP_CHILD:
+ {
+ AgsRecall *child;
+
++ gboolean child_added;
++
+ child = (AgsRecall *) g_value_get_object(value);
+
++ child_added = (g_list_find(recall->children, child) != NULL) ? TRUE: FALSE;
++
++ if(child == NULL ||
++ child_added){
++ return;
++ }
++
+ ags_recall_add_child(recall, child);
+ }
+ break;
+@@ -1297,6 +1320,81 @@
+ }
+
+ void
++ags_recall_dispose(GObject *gobject)
++{
++ AgsRecall *recall;
++
++ GList *list, *list_next;
++
++ recall = AGS_RECALL(gobject);
++
++ /* soundcard */
++ if(recall->soundcard != NULL){
++ g_object_unref(recall->soundcard);
++
++ recall->soundcard = NULL;
++ }
++
++ /* dependency */
++ if(recall->dependencies != NULL){
++ g_list_free_full(recall->dependencies,
++ g_object_unref);
++
++ recall->dependencies = NULL;
++ }
++
++ /* recall id */
++ if(recall->recall_id != NULL){
++ g_object_unref(recall->recall_id);
++
++ recall->recall_id = NULL;
++ }
++
++ /* children */
++ if(recall->children != NULL){
++ list = recall->children;
++
++ while(list != NULL){
++ list_next = list->next;
++
++ g_object_run_dispose(G_OBJECT(list->data));
++
++ list = list_next;
++ }
++
++ g_list_free_full(recall->children,
++ g_object_unref);
++
++ recall->children = NULL;
++ }
++
++ if(recall->container != NULL){
++ ags_packable_unpack(AGS_PACKABLE(recall));
++
++ recall->container = NULL;
++ }
++
++ /* port */
++ if(recall->port != NULL){
++ g_list_free_full(recall->port,
++ g_object_unref);
++
++ recall->port = NULL;
++ }
++
++ /* parent */
++ if(recall->parent != NULL){
++ ags_recall_remove_child(recall->parent,
++ recall);
++
++ recall->parent = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_recall_parent_class)->dispose(gobject);
++}
++
++void
+ ags_recall_finalize(GObject *gobject)
+ {
+ AgsRecall *recall;
+@@ -1324,7 +1422,8 @@
+ }
+
+ g_free(ids);
+-
++
++ /* soundcard */
+ if(recall->soundcard != NULL){
+ g_object_unref(recall->soundcard);
+ }
+@@ -1333,9 +1432,16 @@
+ // g_free(recall->name);
+ // }
+
++ /* dependency */
+ g_list_free_full(recall->dependencies,
+ g_object_unref);
+
++ /* recall id */
++ if(recall->recall_id != NULL){
++ g_object_unref(recall->recall_id);
++ }
++
++ /* children */
+ g_list_free_full(recall->children,
+ g_object_unref);
+
+@@ -1348,9 +1454,11 @@
+ g_free(recall->child_parameters);
+ }
+
++ /* port */
+ g_list_free_full(recall->port,
+ g_object_unref);
+
++ /* parent */
+ if(recall->parent != NULL){
+ ags_recall_remove_child(recall->parent,
+ recall);
+@@ -1890,22 +1998,22 @@
+ ags_recall_real_remove(AgsRecall *recall)
+ {
+ AgsRecall *parent;
+-
+- if(recall == NULL){
+- return;
+- }
+
+ g_object_ref(recall);
+
+ if(recall->parent == NULL){
+- parent = NULL;
++ g_object_run_dispose(recall);
+ g_object_unref(recall);
++
+ return;
+ }else{
+ parent = AGS_RECALL(recall->parent);
+
+ ags_recall_remove_child(parent,
+ recall);
++
++ g_object_run_dispose(recall);
++ g_object_unref(recall);
+ }
+
+ /* propagate done */
+@@ -2227,10 +2335,12 @@
+ ags_recall_add_child(AgsRecall *parent, AgsRecall *child)
+ {
+ guint inheritated_flags_mask;
+-
++
+ if(child == NULL ||
+- child->parent == parent)
++ parent == NULL ||
++ child->parent == parent){
+ return;
++ }
+
+ inheritated_flags_mask = (AGS_RECALL_PLAYBACK |
+ AGS_RECALL_SEQUENCER |
+@@ -2274,6 +2384,10 @@
+ g_signal_connect(G_OBJECT(child), "done\0",
+ G_CALLBACK(ags_recall_child_done), parent);
+ }
++
++ if(child->parent != NULL){
++ g_object_unref(child);
++ }
+
+ child->parent = parent;
+
+--- a/ags/audio/ags_recall_audio.c
++++ b/ags/audio/ags_recall_audio.c
+@@ -44,6 +44,7 @@
+ void ags_recall_audio_disconnect(AgsConnectable *connectable);
+ gboolean ags_recall_audio_pack(AgsPackable *packable, GObject *container);
+ gboolean ags_recall_audio_unpack(AgsPackable *packable);
++void ags_recall_audio_dispose(GObject *gobject);
+ void ags_recall_audio_finalize(GObject *gobject);
+
+ void ags_recall_audio_load_automation(AgsRecall *recall,
+@@ -132,6 +133,7 @@
+ /* GObjectClass */
+ gobject = (GObjectClass *) recall_audio;
+
++ gobject->dispose = ags_recall_audio_dispose;
+ gobject->finalize = ags_recall_audio_finalize;
+
+ gobject->set_property = ags_recall_audio_set_property;
+@@ -337,15 +339,39 @@
+ }
+
+ void
++ags_recall_audio_dispose(GObject *gobject)
++{
++ AgsRecallAudio *recall_audio;
++
++ recall_audio = AGS_RECALL_AUDIO(gobject);
++
++ /* unpack */
++ ags_packable_unpack(AGS_PACKABLE(recall_audio));
++
++ /* audio */
++ if(recall_audio->audio != NULL){
++ g_object_unref(G_OBJECT(recall_audio->audio));
++
++ recall_audio->audio = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_recall_audio_parent_class)->dispose(gobject);
++}
++
++void
+ ags_recall_audio_finalize(GObject *gobject)
+ {
+ AgsRecallAudio *recall_audio;
+
+ recall_audio = AGS_RECALL_AUDIO(gobject);
+
+- if(recall_audio->audio != NULL)
++ /* audio */
++ if(recall_audio->audio != NULL){
+ g_object_unref(G_OBJECT(recall_audio->audio));
++ }
+
++ /* call parent */
+ G_OBJECT_CLASS(ags_recall_audio_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/audio/ags_recall_audio_run.c
++++ b/ags/audio/ags_recall_audio_run.c
+@@ -51,6 +51,7 @@
+ gboolean ags_recall_audio_run_unpack(AgsPackable *packable);
+ void ags_recall_audio_run_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+ void ags_recall_audio_run_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
++void ags_recall_audio_run_dispose(GObject *gobject);
+ void ags_recall_audio_run_finalize(GObject *gobject);
+
+ void ags_recall_audio_run_remove(AgsRecall *recall);
+@@ -71,6 +72,7 @@
+
+ enum{
+ PROP_0,
++ PROP_AUDIO,
+ PROP_RECALL_AUDIO,
+ };
+
+@@ -152,10 +154,27 @@
+ gobject->set_property = ags_recall_audio_run_set_property;
+ gobject->get_property = ags_recall_audio_run_get_property;
+
++ gobject->dispose = ags_recall_audio_run_dispose;
+ gobject->finalize = ags_recall_audio_run_finalize;
+
+ /* properties */
+ /**
++ * AgsRecallAudioRun:audio:
++ *
++ * The assigned audio.
++ *
++ * Since: 0.7.122.7
++ */
++ param_spec = g_param_spec_object("audio\0",
++ "assigned audio\0",
++ "The audio object it is assigned to\0",
++ AGS_TYPE_AUDIO,
++ G_PARAM_READABLE | G_PARAM_WRITABLE);
++ g_object_class_install_property(gobject,
++ PROP_AUDIO,
++ param_spec);
++
++ /**
+ * AgsRecallAudioRun:recall-audio:
+ *
+ * The recall audio belonging to.
+@@ -210,10 +229,10 @@
+ void
+ ags_recall_audio_run_init(AgsRecallAudioRun *recall_audio_run)
+ {
++ recall_audio_run->audio = NULL;
+ recall_audio_run->recall_audio = NULL;
+ }
+
+-
+ void
+ ags_recall_audio_run_set_property(GObject *gobject,
+ guint prop_id,
+@@ -225,14 +244,36 @@
+ recall_audio_run = AGS_RECALL_AUDIO_RUN(gobject);
+
+ switch(prop_id){
++ case PROP_AUDIO:
++ {
++ AgsRecallAudio *audio;
++
++ audio = (AgsRecallAudio *) g_value_get_object(value);
++
++ if(recall_audio_run->audio == audio){
++ return;
++ }
++
++ if(recall_audio_run->audio != NULL){
++ g_object_unref(G_OBJECT(recall_audio_run->audio));
++ }
++
++ if(audio != NULL){
++ g_object_ref(G_OBJECT(audio));
++ }
++
++ recall_audio_run->audio = audio;
++ }
++ break;
+ case PROP_RECALL_AUDIO:
+ {
+ AgsRecallAudio *recall_audio;
+
+ recall_audio = (AgsRecallAudio *) g_value_get_object(value);
+
+- if(recall_audio_run->recall_audio == recall_audio)
++ if(recall_audio_run->recall_audio == recall_audio){
+ return;
++ }
+
+ if(recall_audio_run->recall_audio != NULL){
+ g_object_unref(G_OBJECT(recall_audio_run->recall_audio));
+@@ -262,6 +303,11 @@
+ recall_audio_run = AGS_RECALL_AUDIO_RUN(gobject);
+
+ switch(prop_id){
++ case PROP_AUDIO:
++ {
++ g_value_set_object(value, recall_audio_run->audio);
++ }
++ break;
+ case PROP_RECALL_AUDIO:
+ {
+ g_value_set_object(value, recall_audio_run->recall_audio);
+@@ -274,15 +320,74 @@
+ }
+
+ void
++ags_recall_audio_run_dispose(GObject *gobject)
++{
++ AgsRecallAudioRun *recall_audio_run;
++
++ recall_audio_run = AGS_RECALL_AUDIO_RUN(gobject);
++
++ /* unpack */
++ ags_packable_unpack(AGS_PACKABLE(recall_audio_run));
++
++ if(AGS_RECALL(gobject)->container != NULL){
++ AgsRecallContainer *recall_container;
++
++ recall_container = AGS_RECALL(gobject)->container;
++
++ recall_container->recall_audio_run = g_list_remove(recall_container->recall_audio_run,
++ gobject);
++ g_object_unref(gobject);
++ g_object_unref(AGS_RECALL(gobject)->container);
++
++ AGS_RECALL(gobject)->container = NULL;
++ }
++
++ /* audio */
++ if(recall_audio_run->audio != NULL){
++ g_object_unref(G_OBJECT(recall_audio_run->audio));
++
++ recall_audio_run->audio = NULL;
++ }
++
++ /* recall audio */
++ if(recall_audio_run->recall_audio != NULL){
++ g_object_unref(G_OBJECT(recall_audio_run->recall_audio));
++
++ recall_audio_run->recall_audio = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_recall_audio_run_parent_class)->dispose(gobject);
++}
++
++void
+ ags_recall_audio_run_finalize(GObject *gobject)
+ {
+ AgsRecallAudioRun *recall_audio_run;
+
+ recall_audio_run = AGS_RECALL_AUDIO_RUN(gobject);
+
+- if(recall_audio_run->recall_audio != NULL)
++ if(AGS_RECALL(gobject)->container != NULL){
++ AgsRecallContainer *recall_container;
++
++ recall_container = AGS_RECALL(gobject)->container;
++
++ recall_container->recall_audio_run = g_list_remove(recall_container->recall_audio_run,
++ gobject);
++ g_object_unref(AGS_RECALL(gobject)->container);
++ }
++
++ /* audio */
++ if(recall_audio_run->audio != NULL){
++ g_object_unref(G_OBJECT(recall_audio_run->audio));
++ }
++
++ /* recall audio */
++ if(recall_audio_run->recall_audio != NULL){
+ g_object_unref(G_OBJECT(recall_audio_run->recall_audio));
++ }
+
++ /* call parent */
+ G_OBJECT_CLASS(ags_recall_audio_run_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/audio/ags_recall_audio_signal.c
++++ b/ags/audio/ags_recall_audio_signal.c
+@@ -49,6 +49,7 @@
+ void ags_recall_audio_signal_disconnect(AgsConnectable *connectable);
+ void ags_recall_audio_signal_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+ void ags_recall_audio_signal_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
++void ags_recall_audio_signal_dispose(GObject *gobject);
+ void ags_recall_audio_signal_finalize(GObject *gobject);
+
+ void ags_recall_audio_signal_run_init_pre(AgsRecall *recall);
+@@ -150,6 +151,7 @@
+ gobject->set_property = ags_recall_audio_signal_set_property;
+ gobject->get_property = ags_recall_audio_signal_get_property;
+
++ gobject->dispose = ags_recall_audio_signal_dispose;
+ gobject->finalize = ags_recall_audio_signal_finalize;
+
+ /* for debugging purpose */
+@@ -385,23 +387,48 @@
+ }
+
+ void
+-ags_recall_audio_signal_finalize(GObject *gobject)
++ags_recall_audio_signal_dispose(GObject *gobject)
+ {
+ AgsRecallAudioSignal *recall_audio_signal;
+
+ recall_audio_signal = AGS_RECALL_AUDIO_SIGNAL(gobject);
+-
++
++ /* destination */
+ if(recall_audio_signal->destination != NULL){
+ g_object_unref(recall_audio_signal->destination);
++
+ recall_audio_signal->destination = NULL;
+ }
+
++ /* source */
+ if(recall_audio_signal->source != NULL){
+ g_object_unref(recall_audio_signal->source);
++
+ recall_audio_signal->source = NULL;
+ }
+
+ /* call parent */
++ G_OBJECT_CLASS(ags_recall_audio_signal_parent_class)->dispose(gobject);
++}
++
++void
++ags_recall_audio_signal_finalize(GObject *gobject)
++{
++ AgsRecallAudioSignal *recall_audio_signal;
++
++ recall_audio_signal = AGS_RECALL_AUDIO_SIGNAL(gobject);
++
++ /* destination */
++ if(recall_audio_signal->destination != NULL){
++ g_object_unref(recall_audio_signal->destination);
++ }
++
++ /* source */
++ if(recall_audio_signal->source != NULL){
++ g_object_unref(recall_audio_signal->source);
++ }
++
++ /* call parent */
+ G_OBJECT_CLASS(ags_recall_audio_signal_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/audio/ags_recall_channel.c
++++ b/ags/audio/ags_recall_channel.c
+@@ -49,6 +49,7 @@
+ void ags_recall_channel_disconnect(AgsConnectable *connectable);
+ gboolean ags_recall_channel_pack(AgsPackable *packable, GObject *container);
+ gboolean ags_recall_channel_unpack(AgsPackable *packable);
++void ags_recall_channel_dispose(GObject *gobject);
+ void ags_recall_channel_finalize(GObject *gobject);
+
+ void ags_recall_channel_load_automation(AgsRecall *recall,
+@@ -141,6 +142,7 @@
+ gobject->set_property = ags_recall_channel_set_property;
+ gobject->get_property = ags_recall_channel_get_property;
+
++ gobject->dispose = ags_recall_channel_dispose;
+ gobject->finalize = ags_recall_channel_finalize;
+
+ /* properties */
+@@ -277,10 +279,14 @@
+
+ switch(prop_id){
+ case PROP_DESTINATION:
+- g_value_set_object(value, recall_channel->destination);
++ {
++ g_value_set_object(value, recall_channel->destination);
++ }
+ break;
+ case PROP_SOURCE:
+- g_value_set_object(value, recall_channel->source);
++ {
++ g_value_set_object(value, recall_channel->source);
++ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+@@ -289,18 +295,51 @@
+ }
+
+ void
++ags_recall_channel_dispose(GObject *gobject)
++{
++ AgsRecallChannel *recall_channel;
++
++ recall_channel = AGS_RECALL_CHANNEL(gobject);
++
++ /* unpack */
++ ags_packable_unpack(AGS_PACKABLE(recall_channel));
++
++ /* source */
++ if(recall_channel->source != NULL){
++ g_object_unref(recall_channel->source);
++
++ recall_channel->source = NULL;
++ }
++
++ /* destination */
++ if(recall_channel->destination != NULL){
++ g_object_unref(G_OBJECT(recall_channel->destination));
++
++ recall_channel->destination = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_recall_channel_parent_class)->dispose(gobject);
++}
++
++void
+ ags_recall_channel_finalize(GObject *gobject)
+ {
+ AgsRecallChannel *recall_channel;
+
+ recall_channel = AGS_RECALL_CHANNEL(gobject);
+
+- if(recall_channel->source != NULL)
++ /* source */
++ if(recall_channel->source != NULL){
+ g_object_unref(recall_channel->source);
++ }
+
+- if(recall_channel->destination != NULL)
++ /* destination */
++ if(recall_channel->destination != NULL){
+ g_object_unref(G_OBJECT(recall_channel->destination));
++ }
+
++ /* call parent */
+ G_OBJECT_CLASS(ags_recall_channel_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/audio/ags_recall_channel_run.c
++++ b/ags/audio/ags_recall_channel_run.c
+@@ -63,6 +63,7 @@
+ gboolean ags_recall_channel_run_unpack(AgsPackable *packable);
+ void ags_recall_channel_run_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+ void ags_recall_channel_run_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
++void ags_recall_channel_run_dispose(GObject *gobject);
+ void ags_recall_channel_run_finalize(GObject *gobject);
+
+ void ags_recall_channel_run_remove(AgsRecall *recall);
+@@ -198,6 +199,7 @@
+ gobject->set_property = ags_recall_channel_run_set_property;
+ gobject->get_property = ags_recall_channel_run_get_property;
+
++ gobject->dispose = ags_recall_channel_run_dispose;
+ gobject->finalize = ags_recall_channel_run_finalize;
+
+ /* properties */
+@@ -516,28 +518,98 @@
+ }
+
+ void
+-ags_recall_channel_run_finalize(GObject *gobject)
++ags_recall_channel_run_dispose(GObject *gobject)
+ {
+ AgsRecallChannelRun *recall_channel_run;
+
+ recall_channel_run = AGS_RECALL_CHANNEL_RUN(gobject);
+
++ /* unpack */
++ ags_packable_unpack(AGS_PACKABLE(recall_channel_run));
++
++ if(AGS_RECALL(gobject)->container != NULL){
++ AgsRecallContainer *recall_container;
++
++ recall_container = AGS_RECALL(gobject)->container;
++
++ recall_container->recall_channel_run = g_list_remove(recall_container->recall_channel_run,
++ gobject);
++ g_object_unref(gobject);
++ g_object_unref(AGS_RECALL(gobject)->container);
++
++ AGS_RECALL(gobject)->container = NULL;
++ }
++
++ /* recall audio run */
+ if(recall_channel_run->recall_audio_run != NULL){
+ g_object_unref(G_OBJECT(recall_channel_run->recall_audio_run));
++
++ recall_channel_run->recall_audio_run = NULL;
+ }
+
++ /* recall channel */
+ if(recall_channel_run->recall_channel != NULL){
+ g_object_unref(G_OBJECT(recall_channel_run->recall_channel));
++
++ recall_channel_run->recall_channel = NULL;
+ }
+-
++
++ /* destination */
+ if(recall_channel_run->destination != NULL){
+ g_object_unref(recall_channel_run->destination);
++
++ recall_channel_run->destination = NULL;
+ }
+-
++
++ /* source */
+ if(recall_channel_run->source != NULL){
+ g_object_unref(recall_channel_run->source);
++
++ recall_channel_run->source = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_recall_channel_run_parent_class)->dispose(gobject);
++}
++
++void
++ags_recall_channel_run_finalize(GObject *gobject)
++{
++ AgsRecallChannelRun *recall_channel_run;
++
++ recall_channel_run = AGS_RECALL_CHANNEL_RUN(gobject);
++
++ if(AGS_RECALL(gobject)->container != NULL){
++ AgsRecallContainer *recall_container;
++
++ recall_container = AGS_RECALL(gobject)->container;
++
++ recall_container->recall_channel_run = g_list_remove(recall_container->recall_channel_run,
++ gobject);
++ g_object_unref(AGS_RECALL(gobject)->container);
++ }
++
++ /* recall audio run */
++ if(recall_channel_run->recall_audio_run != NULL){
++ g_object_unref(G_OBJECT(recall_channel_run->recall_audio_run));
+ }
+
++ /* recall channel */
++ if(recall_channel_run->recall_channel != NULL){
++ g_object_unref(G_OBJECT(recall_channel_run->recall_channel));
++ }
++
++ /* destination */
++ if(recall_channel_run->destination != NULL){
++ g_object_unref(recall_channel_run->destination);
++ }
++
++ /* source */
++ if(recall_channel_run->source != NULL){
++ g_object_unref(recall_channel_run->source);
++ }
++
++ /* call parent */
+ G_OBJECT_CLASS(ags_recall_channel_run_parent_class)->finalize(gobject);
+ }
+
+@@ -685,13 +757,15 @@
+
+ recall = AGS_RECALL(packable);
+
+- if(recall == NULL)
++ if(recall == NULL){
+ return(TRUE);
++ }
+
+ recall_container = AGS_RECALL_CONTAINER(recall->container);
+
+- if(recall_container == NULL)
++ if(recall_container == NULL){
+ return(TRUE);
++ }
+
+ /* ref */
+ g_object_ref(recall);
+--- a/ags/audio/ags_recall_container.c
++++ b/ags/audio/ags_recall_container.c
+@@ -324,14 +324,16 @@
+ recall_audio_run = (AgsRecallAudioRun *) g_value_get_object(value);
+
+ if(recall_audio_run == NULL ||
+- g_list_find(recall_container->recall_audio_run, recall_audio_run) != NULL)
++ g_list_find(recall_container->recall_audio_run, recall_audio_run) != NULL){
+ return;
++ }
+
+ if(recall_audio_run != NULL){
+ g_object_ref(G_OBJECT(recall_audio_run));
+ }
+
+- recall_container->recall_audio_run = g_list_prepend(recall_container->recall_audio_run, recall_audio_run);
++ recall_container->recall_audio_run = g_list_prepend(recall_container->recall_audio_run,
++ recall_audio_run);
+ }
+ break;
+ case PROP_RECALL_CHANNEL_TYPE:
+@@ -350,12 +352,14 @@
+ recall_channel = (AgsRecallChannel *) g_value_get_object(value);
+
+ if(recall_channel == NULL ||
+- g_list_find(recall_container->recall_channel, recall_channel) != NULL)
++ g_list_find(recall_container->recall_channel, recall_channel) != NULL){
+ return;
++ }
+
+- g_object_ref(G_OBJECT(recall_channel));
+-
+- recall_container->recall_channel = g_list_prepend(recall_container->recall_channel, recall_channel);
++ g_object_ref(G_OBJECT(recall_channel));
++
++ recall_container->recall_channel = g_list_prepend(recall_container->recall_channel,
++ recall_channel);
+ }
+ break;
+ case PROP_RECALL_CHANNEL_RUN_TYPE:
+@@ -374,12 +378,14 @@
+ recall_channel_run = (AgsRecallChannelRun *) g_value_get_object(value);
+
+ if(recall_channel_run == NULL ||
+- g_list_find(recall_container->recall_channel_run, recall_channel_run) != NULL)
++ g_list_find(recall_container->recall_channel_run, recall_channel_run) != NULL){
+ return;
++ }
+
+ g_object_ref(G_OBJECT(recall_channel_run));
+
+- recall_container->recall_channel_run = g_list_prepend(recall_container->recall_channel_run, recall_channel_run);
++ recall_container->recall_channel_run = g_list_prepend(recall_container->recall_channel_run,
++ recall_channel_run);
+ }
+ break;
+ default:
+--- a/ags/audio/ags_recall_dependency.c
++++ b/ags/audio/ags_recall_dependency.c
+@@ -32,8 +32,17 @@
+ void ags_recall_dependency_class_init(AgsRecallDependencyClass *recall_dependency);
+ void ags_recall_dependency_connectable_interface_init(AgsConnectableInterface *connectable);
+ void ags_recall_dependency_init(AgsRecallDependency *recall_dependency);
++void ags_recall_dependency_set_property(GObject *gobject,
++ guint prop_id,
++ const GValue *value,
++ GParamSpec *param_spec);
++void ags_recall_dependency_get_property(GObject *gobject,
++ guint prop_id,
++ GValue *value,
++ GParamSpec *param_spec);
+ void ags_recall_dependency_connect(AgsConnectable *connectable);
+ void ags_recall_dependency_disconnect(AgsConnectable *connectable);
++void ags_recall_dependency_dispose(GObject *gobject);
+ void ags_recall_dependency_finalize(GObject *gobject);
+
+ /**
+@@ -49,6 +58,11 @@
+
+ static gpointer ags_recall_dependency_parent_class = NULL;
+
++enum{
++ PROP_0,
++ PROP_DEPENDENCY,
++};
++
+ GType
+ ags_recall_dependency_get_type(void)
+ {
+@@ -90,11 +104,34 @@
+ ags_recall_dependency_class_init(AgsRecallDependencyClass *recall_dependency)
+ {
+ GObjectClass *gobject;
+-
++ GParamSpec *param_spec;
++
+ ags_recall_dependency_parent_class = g_type_class_peek_parent(recall_dependency);
+
+ gobject = (GObjectClass *) recall_dependency;
++
++ gobject->set_property = ags_recall_dependency_set_property;
++ gobject->get_property = ags_recall_dependency_get_property;
++
++ gobject->dispose = ags_recall_dependency_dispose;
+ gobject->finalize = ags_recall_dependency_finalize;
++
++ /* properties */
++ /**
++ * AgsRecallDependency:dependency:
++ *
++ * The dependency.
++ *
++ * Since: 0.7.122.7
++ */
++ param_spec = g_param_spec_object("dependency\0",
++ "dependency of recall\0",
++ "A dependency of the recall\0",
++ AGS_TYPE_RECALL,
++ G_PARAM_READABLE | G_PARAM_WRITABLE);
++ g_object_class_install_property(gobject,
++ PROP_DEPENDENCY,
++ param_spec);
+ }
+
+ void
+@@ -107,24 +144,130 @@
+ void
+ ags_recall_dependency_init(AgsRecallDependency *recall_dependency)
+ {
++ recall_dependency->flags = 0;
++
+ recall_dependency->dependency = NULL;
+ }
+
+ void
++ags_recall_dependency_set_property(GObject *gobject,
++ guint prop_id,
++ const GValue *value,
++ GParamSpec *param_spec)
++{
++ AgsRecallDependency *recall_dependency;
++
++ recall_dependency = AGS_RECALL_DEPENDENCY(gobject);
++
++ switch(prop_id){
++ case PROP_DEPENDENCY:
++ {
++ AgsRecall *dependency;
++
++ dependency = (AgsRecall *) g_value_get_object(value);
++
++ if(recall_dependency->dependency == dependency){
++ return;
++ }
++
++ if(recall_dependency->dependency != NULL){
++ g_object_unref(G_OBJECT(recall_dependency->dependency));
++ }
++
++ if(dependency != NULL){
++ g_object_ref(G_OBJECT(dependency));
++ }
++
++ recall_dependency->dependency = dependency;
++ }
++ break;
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
++ break;
++ };
++}
++
++void
++ags_recall_dependency_get_property(GObject *gobject,
++ guint prop_id,
++ GValue *value,
++ GParamSpec *param_spec)
++{
++ AgsRecallDependency *recall_dependency;
++
++ recall_dependency = AGS_RECALL_DEPENDENCY(gobject);
++
++ switch(prop_id){
++ case PROP_DEPENDENCY:
++ {
++ g_value_set_object(value, recall_dependency->dependency);
++ }
++ break;
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
++ break;
++ };
++}
++
++void
+ ags_recall_dependency_connect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsRecallDependency *recall_dependency;
++
++ recall_dependency = AGS_RECALL_DEPENDENCY(connectable);
++
++ if((AGS_RECALL_DEPENDENCY_CONNECTED & (recall_dependency->flags)) != 0){
++ return;
++ }
++
++ recall_dependency->flags |= AGS_RECALL_DEPENDENCY_CONNECTED;
+ }
+
+ void
+ ags_recall_dependency_disconnect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsRecallDependency *recall_dependency;
++
++ recall_dependency = AGS_RECALL_DEPENDENCY(connectable);
++
++ if((AGS_RECALL_DEPENDENCY_CONNECTED & (recall_dependency->flags)) == 0){
++ return;
++ }
++
++ recall_dependency->flags &= (~AGS_RECALL_DEPENDENCY_CONNECTED);
++}
++
++void
++ags_recall_dependency_dispose(GObject *gobject)
++{
++ AgsRecallDependency *recall_dependency;
++
++ recall_dependency = AGS_RECALL_DEPENDENCY(gobject);
++
++ /* dependency */
++ if(recall_dependency->dependency != NULL){
++ g_object_unref(recall_dependency->dependency);
++
++ recall_dependency->dependency = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_recall_dependency_parent_class)->dispose(gobject);
+ }
+
+ void
+ ags_recall_dependency_finalize(GObject *gobject)
+ {
++ AgsRecallDependency *recall_dependency;
++
++ recall_dependency = AGS_RECALL_DEPENDENCY(gobject);
++
++ /* dependency */
++ if(recall_dependency->dependency != NULL){
++ g_object_unref(recall_dependency->dependency);
++ }
++
++ /* call parent */
+ G_OBJECT_CLASS(ags_recall_dependency_parent_class)->finalize(gobject);
+ }
+
+@@ -296,9 +439,8 @@
+ AgsRecallDependency *recall_dependency;
+
+ recall_dependency = (AgsRecallDependency *) g_object_new(AGS_TYPE_RECALL_DEPENDENCY,
++ "dependency\0", dependency,
+ NULL);
+
+- recall_dependency->dependency = dependency;
+-
+ return(recall_dependency);
+ }
+--- a/ags/audio/ags_recall_dependency.h
++++ b/ags/audio/ags_recall_dependency.h
+@@ -35,10 +35,16 @@
+ typedef struct _AgsRecallDependency AgsRecallDependency;
+ typedef struct _AgsRecallDependencyClass AgsRecallDependencyClass;
+
++typedef enum{
++ AGS_RECALL_DEPENDENCY_CONNECTED = 1,
++}AgsRecallDependencyFlags;
++
+ struct _AgsRecallDependency
+ {
+ GObject object;
+
++ guint flags;
++
+ GObject *dependency;
+ };
+
+--- a/ags/audio/ags_recall_dssi.c
++++ b/ags/audio/ags_recall_dssi.c
+@@ -639,6 +639,7 @@
+ "port-value-is-pointer\0", FALSE,
+ "port-value-type\0", G_TYPE_FLOAT,
+ NULL);
++ g_object_ref(current);
+ current->flags |= AGS_PORT_USE_LADSPA_FLOAT;
+
+ current->port_descriptor = port_descriptor->data;
+--- a/ags/audio/ags_recall_id.c
++++ b/ags/audio/ags_recall_id.c
+@@ -37,6 +37,7 @@
+ GParamSpec *param_spec);
+ void ags_recall_id_connect(AgsConnectable *connectable);
+ void ags_recall_id_disconnect(AgsConnectable *connectable);
++void ags_recall_id_dispose(GObject *gobject);
+ void ags_recall_id_finalize(GObject *gobject);
+
+ /**
+@@ -108,6 +109,7 @@
+ gobject->set_property = ags_recall_id_set_property;
+ gobject->get_property = ags_recall_id_get_property;
+
++ gobject->dispose = ags_recall_id_dispose;
+ gobject->finalize = ags_recall_id_finalize;
+
+ /* properties */
+@@ -177,8 +179,9 @@
+
+ recycling = g_value_get_object(value);
+
+- if(recall_id->recycling == (GObject *) recycling)
++ if(recall_id->recycling == (GObject *) recycling){
+ return;
++ }
+
+ if(recall_id->recycling != NULL){
+ g_object_unref(recycling);
+@@ -230,10 +233,14 @@
+
+ switch(prop_id){
+ case PROP_RECYCLING:
+- g_value_set_object(value, recall_id->recycling);
++ {
++ g_value_set_object(value, recall_id->recycling);
++ }
+ break;
+ case PROP_RECYCLING_CONTEXT:
+- g_value_set_object(value, recall_id->recycling_context);
++ {
++ g_value_set_object(value, recall_id->recycling_context);
++ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+@@ -244,18 +251,71 @@
+ void
+ ags_recall_id_connect(AgsConnectable *connectable)
+ {
++ AgsRecallID *recall_id;
++
++ recall_id = AGS_RECALL_ID(connectable);
++
++ if((AGS_RECALL_ID_CONNECTED & (recall_id->flags)) != 0){
++ return;
++ }
++
++ recall_id->flags |= AGS_RECALL_ID_CONNECTED;
+ }
+
+ void
+ ags_recall_id_disconnect(AgsConnectable *connectable)
+ {
++ AgsRecallID *recall_id;
++
++ recall_id = AGS_RECALL_ID(connectable);
++
++
++ if((AGS_RECALL_ID_CONNECTED & (recall_id->flags)) == 0){
++ return;
++ }
++
++ recall_id->flags &= (~AGS_RECALL_ID_CONNECTED);
++}
++
++void
++ags_recall_id_dispose(GObject *gobject)
++{
++ AgsRecallID *recall_id;
++
++ recall_id = AGS_RECALL_ID(gobject);
++
++ if(recall_id->recycling != NULL){
++ g_object_unref(recall_id->recycling);
++
++ recall_id->recycling = NULL;
++ }
++
++ if(recall_id->recycling_context != NULL){
++ g_object_unref(recall_id->recycling_context);
++
++ recall_id->recycling_context = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_recall_id_parent_class)->dispose(gobject);
+ }
+
+ void
+ ags_recall_id_finalize(GObject *gobject)
+ {
+- g_warning("ags_recall_id_finalize\0");
++ AgsRecallID *recall_id;
++
++ recall_id = AGS_RECALL_ID(gobject);
++
++ if(recall_id->recycling != NULL){
++ g_object_unref(recall_id->recycling);
++ }
++
++ if(recall_id->recycling_context != NULL){
++ g_object_unref(recall_id->recycling_context);
++ }
+
++ /* call parent */
+ G_OBJECT_CLASS(ags_recall_id_parent_class)->finalize(gobject);
+ }
+
+@@ -276,18 +336,25 @@
+ {
+ switch(stage){
+ case 0:
+- if((AGS_RECALL_ID_PRE & (id->flags)) == 0)
+- return(TRUE);
+-
++ {
++ if((AGS_RECALL_ID_PRE & (id->flags)) == 0){
++ return(TRUE);
++ }
++ }
+ break;
+ case 1:
+- if((AGS_RECALL_ID_INTER & (id->flags)) == 0)
+- return(TRUE);
+-
++ {
++ if((AGS_RECALL_ID_INTER & (id->flags)) == 0){
++ return(TRUE);
++ }
++ }
+ break;
+ case 2:
+- if((AGS_RECALL_ID_POST & (id->flags)) == 0)
+- return(TRUE);
++ {
++ if((AGS_RECALL_ID_POST & (id->flags)) == 0){
++ return(TRUE);
++ }
++ }
+ break;
+ }
+
+--- a/ags/audio/ags_recall_id.h
++++ b/ags/audio/ags_recall_id.h
+@@ -37,18 +37,19 @@
+ typedef struct _AgsRecallIDClass AgsRecallIDClass;
+
+ typedef enum{
+- AGS_RECALL_ID_PLAYBACK = 1,
+- AGS_RECALL_ID_SEQUENCER = 1 << 1,
+- AGS_RECALL_ID_NOTATION = 1 << 2,
+- AGS_RECALL_ID_DUPLICATE = 1 << 3,
+- AGS_RECALL_ID_RESOLVE = 1 << 4,
+- AGS_RECALL_ID_INIT_PRE = 1 << 5,
+- AGS_RECALL_ID_INIT_INTER = 1 << 6,
+- AGS_RECALL_ID_INIT_POST = 1 << 7,
+- AGS_RECALL_ID_PRE = 1 << 8,
+- AGS_RECALL_ID_INTER = 1 << 9,
+- AGS_RECALL_ID_POST = 1 << 10,
+- AGS_RECALL_ID_CANCEL = 1 << 11,
++ AGS_RECALL_ID_CONNECTED = 1,
++ AGS_RECALL_ID_PLAYBACK = 1 << 1,
++ AGS_RECALL_ID_SEQUENCER = 1 << 2,
++ AGS_RECALL_ID_NOTATION = 1 << 3,
++ AGS_RECALL_ID_DUPLICATE = 1 << 4,
++ AGS_RECALL_ID_RESOLVE = 1 << 5,
++ AGS_RECALL_ID_INIT_PRE = 1 << 6,
++ AGS_RECALL_ID_INIT_INTER = 1 << 7,
++ AGS_RECALL_ID_INIT_POST = 1 << 8,
++ AGS_RECALL_ID_PRE = 1 << 9,
++ AGS_RECALL_ID_INTER = 1 << 10,
++ AGS_RECALL_ID_POST = 1 << 11,
++ AGS_RECALL_ID_CANCEL = 1 << 12,
+ }AgsRecallIDFlags;
+
+ struct _AgsRecallID
+--- a/ags/audio/ags_recall_ladspa.c
++++ b/ags/audio/ags_recall_ladspa.c
+@@ -639,6 +639,7 @@
+ "port-value-is-pointer\0", FALSE,
+ "port-value-type\0", G_TYPE_FLOAT,
+ NULL);
++ g_object_ref(current);
+ current->flags |= AGS_PORT_USE_LADSPA_FLOAT;
+
+ current->port_descriptor = port_descriptor->data;
+--- a/ags/audio/ags_recall_lv2.c
++++ b/ags/audio/ags_recall_lv2.c
+@@ -60,6 +60,7 @@
+ void ags_recall_lv2_connect(AgsConnectable *connectable);
+ void ags_recall_lv2_disconnect(AgsConnectable *connectable);
+ void ags_recall_lv2_set_ports(AgsPlugin *plugin, GList *port);
++void ags_recall_lv2_dispose(GObject *gobject);
+ void ags_recall_lv2_finalize(GObject *gobject);
+
+ void ags_recall_lv2_read(AgsFile *file, xmlNode *node, AgsPlugin *plugin);
+@@ -149,6 +150,7 @@
+ gobject->set_property = ags_recall_lv2_set_property;
+ gobject->get_property = ags_recall_lv2_get_property;
+
++ gobject->dispose = ags_recall_lv2_dispose;
+ gobject->finalize = ags_recall_lv2_finalize;
+
+ /* properties */
+@@ -550,16 +552,36 @@
+ }
+
+ void
++ags_recall_lv2_dispose(GObject *gobject)
++{
++ AgsRecallLv2 *recall_lv2;
++
++ recall_lv2 = AGS_RECALL_LV2(gobject);
++
++ /* turtle */
++ if(recall_lv2->turtle != NULL){
++ g_object_unref(recall_lv2->turtle);
++
++ recall_lv2->turtle = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_recall_lv2_parent_class)->dispose(gobject);
++}
++
++void
+ ags_recall_lv2_finalize(GObject *gobject)
+ {
+ AgsRecallLv2 *recall_lv2;
+
+ recall_lv2 = AGS_RECALL_LV2(gobject);
+
++ /* turtle */
+ if(recall_lv2->turtle != NULL){
+ g_object_unref(recall_lv2->turtle);
+ }
+
++ /* filename, effect and uri */
+ g_free(recall_lv2->filename);
+ g_free(recall_lv2->effect);
+ g_free(recall_lv2->uri);
+@@ -767,6 +789,7 @@
+ "port-value-is-pointer\0", FALSE,
+ "port-value-type\0", G_TYPE_FLOAT,
+ NULL);
++ g_object_ref(current);
+
+ current->port_descriptor = port_descriptor->data;
+ ags_recall_lv2_load_conversion(recall_lv2,
+--- a/ags/audio/ags_recall_recycling.c
++++ b/ags/audio/ags_recall_recycling.c
+@@ -60,6 +60,7 @@
+ void ags_recall_recycling_disconnect(AgsConnectable *connectable);
+ void ags_recall_recycling_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+ void ags_recall_recycling_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
++void ags_recall_recycling_dispose(GObject *gobject);
+ void ags_recall_recycling_finalize(GObject *gobject);
+
+ AgsRecall* ags_recall_recycling_duplicate(AgsRecall *recall,
+@@ -164,6 +165,7 @@
+ gobject->set_property = ags_recall_recycling_set_property;
+ gobject->get_property = ags_recall_recycling_get_property;
+
++ gobject->dispose = ags_recall_recycling_dispose;
+ gobject->finalize = ags_recall_recycling_finalize;
+
+ /* properties */
+@@ -280,7 +282,6 @@
+ void
+ ags_recall_recycling_init(AgsRecallRecycling *recall_recycling)
+ {
+- recall_recycling->flags = 0;
+ recall_recycling->flags = (AGS_RECALL_RECYCLING_MAP_CHILD_DESTINATION |
+ AGS_RECALL_RECYCLING_MAP_CHILD_SOURCE);
+
+@@ -477,24 +478,68 @@
+ }
+
+ void
++ags_recall_recycling_dispose(GObject *gobject)
++{
++ AgsRecallRecycling *recall_recycling;
++
++ recall_recycling = AGS_RECALL_RECYCLING(gobject);
++
++ /* destination */
++ if(recall_recycling->destination != NULL){
++ g_object_unref(G_OBJECT(recall_recycling->destination));
++
++ recall_recycling->destination = NULL;
++ }
++
++ /* source */
++ if(recall_recycling->source != NULL){
++ g_object_unref(G_OBJECT(recall_recycling->source));
++
++ recall_recycling->source = NULL;
++ }
++
++ /* child destination */
++ if(recall_recycling->child_destination != NULL){
++ g_object_unref(G_OBJECT(recall_recycling->child_destination));
++
++ recall_recycling->child_destination = NULL;
++ }
++
++ /* child source */
++ if(recall_recycling->child_source != NULL){
++ g_list_free_full(recall_recycling->child_source,
++ g_object_unref);
++
++ recall_recycling->child_source = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_recall_recycling_parent_class)->dispose(gobject);
++}
++
++void
+ ags_recall_recycling_finalize(GObject *gobject)
+ {
+ AgsRecallRecycling *recall_recycling;
+
+ recall_recycling = AGS_RECALL_RECYCLING(gobject);
+
++ /* destination */
+ if(recall_recycling->destination != NULL){
+ g_object_unref(G_OBJECT(recall_recycling->destination));
+ }
+-
++
++ /* source */
+ if(recall_recycling->source != NULL){
+ g_object_unref(G_OBJECT(recall_recycling->source));
+ }
+-
++
++ /* child destination */
+ if(recall_recycling->child_destination != NULL){
+ g_object_unref(G_OBJECT(recall_recycling->child_destination));
+ }
+-
++
++ /* child source */
+ if(recall_recycling->child_source != NULL){
+ g_list_free_full(recall_recycling->child_source,
+ g_object_unref);
+--- a/ags/audio/ags_recall_recycling.h
++++ b/ags/audio/ags_recall_recycling.h
+@@ -41,9 +41,9 @@
+
+ typedef enum{
+ AGS_RECALL_RECYCLING_GARBAGE_COLLECTOR = 1,
+- AGS_RECALL_RECYCLING_MAP_CHILD_DESTINATION = 1 << 1,
+- AGS_RECALL_RECYCLING_MAP_CHILD_SOURCE = 1 << 2,
+- AGS_RECALL_RECYCLING_CREATE_DESTINATION_ON_MAP_SOURCE = 1 << 3,
++ AGS_RECALL_RECYCLING_MAP_CHILD_DESTINATION = 1 << 1,
++ AGS_RECALL_RECYCLING_MAP_CHILD_SOURCE = 1 << 2,
++ AGS_RECALL_RECYCLING_CREATE_DESTINATION_ON_MAP_SOURCE = 1 << 3,
+ }AgsRecallRecyclingFlags;
+
+ struct _AgsRecallRecycling
+--- a/ags/audio/ags_recycling.c
++++ b/ags/audio/ags_recycling.c
+@@ -49,6 +49,7 @@
+ void ags_recycling_disconnect(AgsConnectable *connectable);
+ pthread_mutex_t* ags_recycling_get_lock(AgsConcurrentTree *concurrent_tree);
+ pthread_mutex_t* ags_recycling_get_parent_lock(AgsConcurrentTree *concurrent_tree);
++void ags_recycling_dispose(GObject *gobject);
+ void ags_recycling_finalize(GObject *gobject);
+
+ void ags_recycling_real_add_audio_signal(AgsRecycling *recycling,
+@@ -147,6 +148,7 @@
+ gobject->set_property = ags_recycling_set_property;
+ gobject->get_property = ags_recycling_get_property;
+
++ gobject->dispose = ags_recycling_dispose;
+ gobject->finalize = ags_recycling_finalize;
+
+ /* properties */
+@@ -481,10 +483,14 @@
+
+ switch(prop_id){
+ case PROP_SOUNDCARD:
+- g_value_set_object(value, recycling->soundcard);
++ {
++ g_value_set_object(value, recycling->soundcard);
++ }
+ break;
+ case PROP_CHANNEL:
+- g_value_set_object(value, recycling->channel);
++ {
++ g_value_set_object(value, recycling->channel);
++ }
+ break;
+ case PROP_PARENT:
+ {
+@@ -515,13 +521,51 @@
+ void
+ ags_recycling_connect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsRecycling *recycling;
++
++ GList *list;
++
++ recycling = AGS_RECYCLING(connectable);
++
++ if((AGS_RECYCLING_CONNECTED & (recycling->flags)) != 0){
++ return;
++ }
++
++ recycling->flags |= AGS_RECYCLING_CONNECTED;
++
++ /* audio signal */
++ list = recycling->audio_signal;
++
++ while(list != NULL){
++ ags_connectable_connect(AGS_CONNECTABLE(list->data));
++
++ list = list->next;
++ }
+ }
+
+ void
+ ags_recycling_disconnect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsRecycling *recycling;
++
++ GList *list;
++
++ recycling = AGS_RECYCLING(connectable);
++
++ if((AGS_RECYCLING_CONNECTED & (recycling->flags)) == 0){
++ return;
++ }
++
++ recycling->flags &= (~AGS_RECYCLING_CONNECTED);
++
++ /* audio signal */
++ list = recycling->audio_signal;
++
++ while(list != NULL){
++ ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
++
++ list = list->next;
++ }
+ }
+
+ pthread_mutex_t*
+@@ -574,14 +618,70 @@
+ }
+
+ void
++ags_recycling_dispose(GObject *gobject)
++{
++ AgsRecycling *recycling;
++
++ GList *list;
++
++ recycling = AGS_RECYCLING(gobject);
++
++ /* channel */
++ if(recycling->channel != NULL){
++ g_object_unref(recycling->channel);
++
++ recycling->channel = NULL;
++ }
++
++ /* soundcard */
++ if(recycling->soundcard != NULL){
++ g_object_unref(recycling->soundcard);
++
++ recycling->soundcard = NULL;
++ }
++
++ /* parent */
++ if(recycling->parent != NULL){
++ g_object_unref(recycling->parent);
++
++ recycling->parent = NULL;
++ }
++
++ /* next and prev */
++ if(recycling->next != NULL){
++ // g_object_unref(recycling->next);
++
++ recycling->next = NULL;
++ }
++
++ if(recycling->prev != NULL){
++ // g_object_unref(recycling->prev);
++
++ recycling->prev = NULL;
++ }
++
++ /* AgsAudioSignal */
++ list = recycling->audio_signal;
++
++ while(list != NULL){
++ g_object_run_dispose(list->data);
++
++ list = list->next;
++ }
++
++ g_list_free_full(recycling->audio_signal,
++ g_object_unref);
++
++ recycling->audio_signal = NULL;
++}
++
++void
+ ags_recycling_finalize(GObject *gobject)
+ {
+ AgsRecycling *recycling;
+
+ AgsMutexManager *mutex_manager;
+
+- GList *list, *list_next;
+-
+ pthread_mutex_t *application_mutex;
+
+ // g_warning("ags_recycling_finalize\0");
+@@ -598,6 +698,30 @@
+
+ recycling = AGS_RECYCLING(gobject);
+
++ /* channel */
++ if(recycling->channel != NULL){
++ g_object_unref(recycling->channel);
++ }
++
++ /* soundcard */
++ if(recycling->soundcard != NULL){
++ g_object_unref(recycling->soundcard);
++ }
++
++ /* parent */
++ if(recycling->parent != NULL){
++ g_object_unref(recycling->parent);
++ }
++
++ /* next and prev */
++ if(recycling->next != NULL){
++ g_object_unref(recycling->next);
++ }
++
++ if(recycling->prev != NULL){
++ g_object_unref(recycling->prev);
++ }
++
+ /* AgsAudioSignal */
+ g_list_free_full(recycling->audio_signal,
+ g_object_unref);
+@@ -619,15 +743,18 @@
+ ags_recycling_set_soundcard(AgsRecycling *recycling, GObject *soundcard)
+ {
+ /* recycling */
+- if(recycling->soundcard == soundcard)
++ if(recycling->soundcard == soundcard){
+ return;
++ }
+
+- if(recycling->soundcard != NULL)
++ if(recycling->soundcard != NULL){
+ g_object_unref(recycling->soundcard);
+-
+- if(soundcard != NULL)
++ }
++
++ if(soundcard != NULL){
+ g_object_ref(soundcard);
+-
++ }
++
+ recycling->soundcard = (GObject *) soundcard;
+ }
+
+@@ -693,21 +820,27 @@
+ ags_recycling_real_add_audio_signal(AgsRecycling *recycling,
+ AgsAudioSignal *audio_signal)
+ {
+- if((AGS_AUDIO_SIGNAL_TEMPLATE & (audio_signal->flags)) != 0){
+- AgsAudioSignal *old_template;
++ if(g_list_find(recycling->audio_signal,
++ audio_signal) == NULL){
++ if((AGS_AUDIO_SIGNAL_TEMPLATE & (audio_signal->flags)) != 0){
++ AgsAudioSignal *old_template;
+
+- /* old template */
+- old_template = ags_audio_signal_get_template(recycling->audio_signal);
++ /* old template */
++ old_template = ags_audio_signal_get_template(recycling->audio_signal);
+
+- /* remove old template */
+- ags_recycling_remove_audio_signal(recycling,
+- old_template);
++ /* remove old template */
++ ags_recycling_remove_audio_signal(recycling,
++ old_template);
++ }
++
++ recycling->audio_signal = g_list_prepend(recycling->audio_signal, (gpointer) audio_signal);
++ g_object_ref(audio_signal);
+ }
+
+- recycling->audio_signal = g_list_prepend(recycling->audio_signal, (gpointer) audio_signal);
+- audio_signal->recycling = (GObject *) recycling;
+- g_object_ref(recycling);
+- g_object_ref(audio_signal);
++ if(audio_signal->recycling != recycling){
++ audio_signal->recycling = (GObject *) recycling;
++ g_object_ref(recycling);
++ }
+ }
+
+ /**
+--- a/ags/audio/ags_recycling.h
++++ b/ags/audio/ags_recycling.h
+@@ -35,7 +35,8 @@
+ typedef struct _AgsRecyclingClass AgsRecyclingClass;
+
+ typedef enum{
+- AGS_RECYCLING_MUTED = 1,
++ AGS_RECYCLING_CONNECTED = 1,
++ AGS_RECYCLING_MUTED = 1 << 1,
+ }AgsRecyclingFlags;
+
+ struct _AgsRecycling
+--- a/ags/audio/ags_recycling_context.c
++++ b/ags/audio/ags_recycling_context.c
+@@ -34,6 +34,7 @@
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec);
++void ags_recycling_context_dispose(GObject *gobject);
+ void ags_recycling_context_finalize(GObject *gobject);
+
+ /**
+@@ -96,6 +97,7 @@
+ gobject->set_property = ags_recycling_context_set_property;
+ gobject->get_property = ags_recycling_context_get_property;
+
++ gobject->dispose = ags_recycling_context_dispose;
+ gobject->finalize = ags_recycling_context_finalize;
+
+ /* properties */
+@@ -270,8 +272,88 @@
+ }
+
+ void
++ags_recycling_context_dispose(GObject *gobject)
++{
++ AgsRecyclingContext *recycling_context;
++
++ GList *list, *list_next;
++
++ guint i;
++
++ recycling_context = AGS_RECYCLING_CONTEXT(gobject);
++
++ /* parent */
++ if(recycling_context->parent != NULL){
++ g_object_unref(recycling_context->parent);
++ }
++
++ /* recall id */
++ if(recycling_context->recall_id != NULL){
++ g_object_unref(recycling_context->recall_id);
++ }
++
++ /* recycling */
++ if(recycling_context->recycling != NULL){
++ for(i = 0; i < recycling_context->length; i++){
++ g_object_unref(recycling_context->recycling[i]);
++ }
++
++ free(recycling_context->recycling);
++
++ recycling_context->recycling = NULL;
++ recycling_context->length = 0;
++ }
++
++ /* children */
++ list = recycling_context->children;
++
++ while(list != NULL){
++ list_next = list->next;
++
++ ags_recycling_context_remove_child(recycling_context,
++ list->data);
++
++ list = list_next;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_recycling_context_parent_class)->dispose(gobject);
++}
++
++void
+ ags_recycling_context_finalize(GObject *gobject)
+ {
++ AgsRecyclingContext *recycling_context;
++
++ GList *list;
++
++ guint i;
++
++ recycling_context = AGS_RECYCLING_CONTEXT(gobject);
++
++ /* parent */
++ if(recycling_context->parent != NULL){
++ g_object_unref(recycling_context->parent);
++ }
++
++ /* recall id */
++ if(recycling_context->recall_id != NULL){
++ g_object_unref(recycling_context->recall_id);
++ }
++
++ /* recycling */
++ if(recycling_context->recycling != NULL){
++ for(i = 0; i < recycling_context->length; i++){
++ g_object_unref(recycling_context->recycling[i]);
++ }
++
++ free(recycling_context->recycling);
++ }
++
++ /* children */
++ g_list_free(recycling_context->children);
++
++ /* call parent */
+ G_OBJECT_CLASS(ags_recycling_context_parent_class)->finalize(gobject);
+ }
+
+@@ -314,8 +396,10 @@
+ AgsRecycling *recycling)
+ {
+ AgsRecyclingContext *new_recycling_context;
+- gint new_length;
+
++ gint new_length;
++ guint i;
++
+ if(recycling_context == NULL){
+ return(NULL);
+ }
+@@ -328,6 +412,11 @@
+ memcpy(new_recycling_context->recycling, recycling_context->recycling, new_length * sizeof(AgsRecycling *));
+ new_recycling_context->recycling[new_length] = recycling;
+
++ /* ref count */
++ for(i = 0; i < new_recycling_context->length; i++){
++ g_object_ref(new_recycling_context->recycling[i]);
++ }
++
+ return(new_recycling_context);
+ }
+
+@@ -347,9 +436,11 @@
+ AgsRecycling *recycling)
+ {
+ AgsRecyclingContext *new_recycling_context;
++
+ gint new_length;
+ gint position;
+-
++ guint i;
++
+ new_recycling_context = (AgsRecyclingContext *) g_object_new(AGS_TYPE_RECYCLING_CONTEXT,
+ NULL);
+
+@@ -362,6 +453,11 @@
+ memcpy(new_recycling_context->recycling, recycling_context->recycling, (new_length - position) * sizeof(AgsRecycling *));
+ memcpy(&(new_recycling_context->recycling[position + 1]), recycling_context->recycling, (-1 * (position - new_length)) * sizeof(AgsRecycling *));
+
++ /* ref count */
++ for(i = 0; i < new_recycling_context->length; i++){
++ g_object_ref(new_recycling_context->recycling[i]);
++ }
++
+ return(new_recycling_context);
+ }
+
+@@ -383,7 +479,9 @@
+ gint position)
+ {
+ AgsRecyclingContext *new_recycling_context;
++
+ gint new_length;
++ guint i;
+
+ new_recycling_context = (AgsRecyclingContext *) g_object_new(AGS_TYPE_RECYCLING_CONTEXT,
+ NULL);
+@@ -395,6 +493,11 @@
+ memcpy(new_recycling_context->recycling, recycling_context->recycling, (new_length - position) * sizeof(AgsRecycling *));
+ new_recycling_context->recycling[position] = recycling;
+ memcpy(&(new_recycling_context->recycling[position + 1]), recycling_context->recycling, (-1 * (position - new_length)) * sizeof(AgsRecycling *));
++
++ /* ref count */
++ for(i = 0; i < new_recycling_context->length; i++){
++ g_object_ref(new_recycling_context->recycling[i]);
++ }
+
+ return(new_recycling_context);
+ }
+@@ -613,6 +716,7 @@
+ {
+ AgsRecyclingContext *new_recycling_context;
+ AgsRecycling *recycling;
++
+ gint new_length;
+ gint first_index, last_index;
+ guint i;
+@@ -726,6 +830,11 @@
+ }
+ }
+
++ /* ref count */
++ for(i = 0; i < new_recycling_context->length; i++){
++ g_object_ref(new_recycling_context->recycling[i]);
++ }
++
+ return(new_recycling_context);
+ }
+
+--- a/ags/audio/ags_recycling_context.h
++++ b/ags/audio/ags_recycling_context.h
+@@ -37,12 +37,13 @@
+ {
+ GObject object;
+
++ AgsRecyclingContext *parent;
++
+ GObject *recall_id;
+
+ AgsRecycling **recycling;
+ guint64 length;
+
+- AgsRecyclingContext *parent;
+ GList *children;
+ };
+
+@@ -53,6 +54,7 @@
+
+ GType ags_recycling_context_get_type();
+
++/* replace, add, remove and insert */
+ void ags_recycling_context_replace(AgsRecyclingContext *recycling_context,
+ AgsRecycling *recycling,
+ gint position);
+@@ -65,6 +67,7 @@
+ AgsRecycling *recycling,
+ gint position);
+
++/* tolevel, find, find child and find parent */
+ AgsRecyclingContext* ags_recycling_context_get_toplevel(AgsRecyclingContext *recycling_context);
+
+ gint ags_recycling_context_find(AgsRecyclingContext *recycling_context,
+@@ -74,17 +77,21 @@
+ gint ags_recycling_context_find_parent(AgsRecyclingContext *recycling_context,
+ AgsRecycling *recycling);
+
++/* add and remove child */
+ void ags_recycling_context_add_child(AgsRecyclingContext *parent,
+ AgsRecyclingContext *child);
+ void ags_recycling_context_remove_child(AgsRecyclingContext *parent,
+ AgsRecyclingContext *child);
+
++/* child recall id */
+ GList* ags_recycling_context_get_child_recall_id(AgsRecyclingContext *recycling_context);
+
++/* instantiate - reset recycling */
+ AgsRecyclingContext* ags_recycling_context_reset_recycling(AgsRecyclingContext *recycling_context,
+ AgsRecycling *old_first_recycling, AgsRecycling *old_last_recycling,
+ AgsRecycling *new_first_recycling, AgsRecycling *new_last_recycling);
+
++/* instantiate */
+ AgsRecyclingContext* ags_recycling_context_new(guint64 length);
+
+ #endif /*__AGS_RECYCLING_CONTEXT_H__*/
+--- a/ags/audio/ags_synth_generator.c
++++ b/ags/audio/ags_synth_generator.c
+@@ -21,7 +21,9 @@
+
+ #include <ags/util/ags_id_generator.h>
+
++#include <ags/object/ags_config.h>
+ #include <ags/object/ags_plugin.h>
++#include <ags/object/ags_soundcard.h>
+
+ #include <ags/thread/ags_timestamp.h>
+
+@@ -310,6 +312,87 @@
+ void
+ ags_synth_generator_init(AgsSynthGenerator *synth_generator)
+ {
++ AgsConfig *config;
++
++ gchar *str;
++
++ /* config */
++ config = ags_config_get_instance();
++
++ /* base init */
++ synth_generator->flags = 0;
++
++ synth_generator->samplerate = AGS_SOUNDCARD_DEFAULT_SAMPLERATE;
++ synth_generator->buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
++ synth_generator->format = AGS_SOUNDCARD_DEFAULT_FORMAT;
++
++ /* samplerate */
++ str = ags_config_get_value(config,
++ AGS_CONFIG_SOUNDCARD,
++ "samplerate\0");
++
++ if(str == NULL){
++ str = ags_config_get_value(config,
++ AGS_CONFIG_SOUNDCARD_0,
++ "samplerate\0");
++ }
++
++ if(str != NULL){
++ synth_generator->samplerate = g_ascii_strtoull(str,
++ NULL,
++ 10);
++
++ free(str);
++ }
++
++ /* buffer size */
++ str = ags_config_get_value(config,
++ AGS_CONFIG_SOUNDCARD,
++ "buffer-size\0");
++
++ if(str == NULL){
++ str = ags_config_get_value(config,
++ AGS_CONFIG_SOUNDCARD_0,
++ "buffer-size\0");
++ }
++
++ if(str != NULL){
++ synth_generator->buffer_size = g_ascii_strtoull(str,
++ NULL,
++ 10);
++
++ free(str);
++ }
++
++ /* format */
++ str = ags_config_get_value(config,
++ AGS_CONFIG_SOUNDCARD,
++ "format\0");
++
++ if(str == NULL){
++ str = ags_config_get_value(config,
++ AGS_CONFIG_SOUNDCARD_0,
++ "format\0");
++ }
++
++ if(str != NULL){
++ synth_generator->format = g_ascii_strtoull(str,
++ NULL,
++ 10);
++
++ free(str);
++ }
++
++ /* more base init */
++ synth_generator->n_frames = 0;
++
++ synth_generator->oscillator = 0;
++
++ synth_generator->frequency = 0.0;
++ synth_generator->phase = 0.0;
++ synth_generator->volume = 1.0;
++
++ /* timestamp */
+ synth_generator->timestamp = NULL;
+ }
+
+--- a/ags/audio/ags_synth_generator.h
++++ b/ags/audio/ags_synth_generator.h
+@@ -45,6 +45,8 @@
+ struct _AgsSynthGenerator
+ {
+ AgsFunction function;
++
++ guint flags;
+
+ guint samplerate;
+ guint buffer_size;
+--- a/ags/audio/jack/ags_jack_port.c
++++ b/ags/audio/jack/ags_jack_port.c
+@@ -49,6 +49,7 @@
+ GParamSpec *param_spec);
+ void ags_jack_port_connect(AgsConnectable *connectable);
+ void ags_jack_port_disconnect(AgsConnectable *connectable);
++void ags_jack_port_dispose(GObject *gobject);
+ void ags_jack_port_finalize(GObject *gobject);
+
+ /**
+@@ -121,6 +122,7 @@
+ gobject->set_property = ags_jack_port_set_property;
+ gobject->get_property = ags_jack_port_get_property;
+
++ gobject->dispose = ags_jack_port_dispose;
+ gobject->finalize = ags_jack_port_finalize;
+
+ /* properties */
+@@ -269,13 +271,50 @@
+ void
+ ags_jack_port_connect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsJackPort *jack_port;
++
++ jack_port = AGS_JACK_PORT(connectable);
++
++ if((AGS_JACK_PORT_CONNECTED & (jack_port->flags)) != 0){
++ return;
++ }
++
++ jack_port->flags |= AGS_JACK_PORT_CONNECTED;
+ }
+
+ void
+ ags_jack_port_disconnect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsJackPort *jack_port;
++
++ jack_port = AGS_JACK_PORT(connectable);
++
++ if((AGS_JACK_PORT_CONNECTED & (jack_port->flags)) == 0){
++ return;
++ }
++
++ jack_port->flags &= (~AGS_JACK_PORT_CONNECTED);
++}
++
++void
++ags_jack_port_dispose(GObject *gobject)
++{
++ AgsJackPort *jack_port;
++
++ jack_port = AGS_JACK_PORT(gobject);
++
++ /* jack client */
++ if(jack_port->jack_client != NULL){
++ g_object_unref(jack_port->jack_client);
++
++ jack_port->jack_client = NULL;
++ }
++
++ /* name */
++ g_free(jack_port->name);
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_jack_port_parent_class)->dispose(gobject);
+ }
+
+ void
+@@ -285,12 +324,15 @@
+
+ jack_port = AGS_JACK_PORT(gobject);
+
++ /* jack client */
+ if(jack_port->jack_client != NULL){
+ g_object_unref(jack_port->jack_client);
+ }
+-
++
++ /* name */
+ g_free(jack_port->name);
+-
++
++ /* call parent */
+ G_OBJECT_CLASS(ags_jack_port_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/audio/jack/ags_jack_server.c
++++ b/ags/audio/jack/ags_jack_server.c
+@@ -48,6 +48,7 @@
+ GParamSpec *param_spec);
+ void ags_jack_server_connect(AgsConnectable *connectable);
+ void ags_jack_server_disconnect(AgsConnectable *connectable);
++void ags_jack_server_dispose(GObject *gobject);
+ void ags_jack_server_finalize(GObject *gobject);
+
+ void ags_jack_server_set_url(AgsDistributedManager *distributed_manager,
+@@ -90,6 +91,9 @@
+ PROP_0,
+ PROP_APPLICATION_CONTEXT,
+ PROP_URL,
++ PROP_DEFAULT_SOUNDCARD,
++ PROP_DEFAULT_JACK_CLIENT,
++ PROP_JACK_CLIENT,
+ };
+
+ static gpointer ags_jack_server_parent_class = NULL;
+@@ -155,6 +159,7 @@
+ gobject->set_property = ags_jack_server_set_property;
+ gobject->get_property = ags_jack_server_get_property;
+
++ gobject->dispose = ags_jack_server_dispose;
+ gobject->finalize = ags_jack_server_finalize;
+
+ /* properties */
+@@ -189,6 +194,54 @@
+ g_object_class_install_property(gobject,
+ PROP_URL,
+ param_spec);
++
++ /**
++ * AgsJackServer:default-soundcard:
++ *
++ * The default soundcard.
++ *
++ * Since: 0.7.122.7
++ */
++ param_spec = g_param_spec_object("default-soundcard\0",
++ "default soundcard\0",
++ "The default soundcard\0",
++ G_TYPE_OBJECT,
++ G_PARAM_READABLE | G_PARAM_WRITABLE);
++ g_object_class_install_property(gobject,
++ PROP_DEFAULT_SOUNDCARD,
++ param_spec);
++
++ /**
++ * AgsJackServer:default-jack-client:
++ *
++ * The default jack client.
++ *
++ * Since: 0.7.122.7
++ */
++ param_spec = g_param_spec_object("default-jack-client\0",
++ "default jack client\0",
++ "The default jack client\0",
++ AGS_TYPE_JACK_CLIENT,
++ G_PARAM_READABLE | G_PARAM_WRITABLE);
++ g_object_class_install_property(gobject,
++ PROP_DEFAULT_JACK_CLIENT,
++ param_spec);
++
++ /**
++ * AgsJackServer:jack-client:
++ *
++ * The jack client list.
++ *
++ * Since: 0.7.122.7
++ */
++ param_spec = g_param_spec_object("jack-client\0",
++ "jack client list\0",
++ "The jack client list\0",
++ AGS_TYPE_JACK_CLIENT,
++ G_PARAM_READABLE | G_PARAM_WRITABLE);
++ g_object_class_install_property(gobject,
++ PROP_JACK_CLIENT,
++ param_spec);
+ }
+
+ void
+@@ -290,6 +343,66 @@
+ jack_server->url = g_strdup(url);
+ }
+ break;
++ case PROP_DEFAULT_SOUNDCARD:
++ {
++ GObject *default_soundcard;
++
++ default_soundcard = (GObject *) g_value_get_object(value);
++
++ if(jack_server->default_soundcard == (GObject *) default_soundcard){
++ return;
++ }
++
++ if(jack_server->default_soundcard != NULL){
++ g_object_unref(G_OBJECT(jack_server->default_soundcard));
++ }
++
++ if(default_soundcard != NULL){
++ g_object_ref(G_OBJECT(default_soundcard));
++ }
++
++ jack_server->default_soundcard = (GObject *) default_soundcard;
++ }
++ break;
++ case PROP_DEFAULT_JACK_CLIENT:
++ {
++ AgsJackClient *default_client;
++
++ default_client = (AgsJackClient *) g_value_get_object(value);
++
++ if(jack_server->default_client == (GObject *) default_client){
++ return;
++ }
++
++ if(jack_server->default_client != NULL){
++ g_object_unref(G_OBJECT(jack_server->default_client));
++ }
++
++ if(default_client != NULL){
++ g_object_ref(G_OBJECT(default_client));
++ }
++
++ jack_server->default_client = (GObject *) default_client;
++ }
++ break;
++ case PROP_JACK_CLIENT:
++ {
++ GObject *client;
++
++ client = (GObject *) g_value_get_object(value);
++
++ if(g_list_find(jack_server->client, client) != NULL){
++ return;
++ }
++
++ if(client != NULL){
++ g_object_ref(G_OBJECT(client));
++
++ jack_server->client = g_list_prepend(jack_server->client,
++ client);
++ }
++ }
++ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+ break;
+@@ -317,6 +430,22 @@
+ g_value_set_string(value, jack_server->url);
+ }
+ break;
++ case PROP_DEFAULT_SOUNDCARD:
++ {
++ g_value_set_object(value, jack_server->default_soundcard);
++ }
++ break;
++ case PROP_DEFAULT_JACK_CLIENT:
++ {
++ g_value_set_object(value, jack_server->default_soundcard);
++ }
++ break;
++ case PROP_JACK_CLIENT:
++ {
++ g_value_set_pointer(value,
++ g_list_copy(jack_server->client));
++ }
++ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+ break;
+@@ -326,28 +455,133 @@
+ void
+ ags_jack_server_connect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsJackServer *jack_server;
++
++ GList *list;
++
++ jack_server = AGS_JACK_SERVER(connectable);
++
++ if((AGS_JACK_SERVER_CONNECTED & (jack_server->flags)) != 0){
++ return;
++ }
++
++ jack_server->flags |= AGS_JACK_SERVER_CONNECTED;
++
++ list = jack_server->client;
++
++ while(list != NULL){
++ ags_connectable_connect(AGS_CONNECTABLE(list->data));
++
++ list = list->next;
++ }
+ }
+
+ void
+ ags_jack_server_disconnect(AgsConnectable *connectable)
+ {
+- /* empty */
++ AgsJackServer *jack_server;
++
++ GList *list;
++
++ jack_server = AGS_JACK_SERVER(connectable);
++
++ if((AGS_JACK_SERVER_CONNECTED & (jack_server->flags)) != 0){
++ return;
++ }
++
++ jack_server->flags |= AGS_JACK_SERVER_CONNECTED;
++
++ list = jack_server->client;
++
++ while(list != NULL){
++ ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
++
++ list = list->next;
++ }
+ }
+
+ void
+-ags_jack_server_finalize(GObject *gobject)
++ags_jack_server_dispose(GObject *gobject)
+ {
+ AgsJackServer *jack_server;
+
++ GList *list;
++
+ jack_server = AGS_JACK_SERVER(gobject);
+
++ /* application context */
+ if(jack_server->application_context != NULL){
++ g_object_unref(G_OBJECT(jack_server->application_context));
++
+ jack_server->application_context = NULL;
+ }
+
++ /* default soundcard */
++ if(jack_server->default_soundcard != NULL){
++ g_object_unref(G_OBJECT(jack_server->default_soundcard));
++
++ jack_server->default_soundcard = NULL;
++ }
++
++ /* default client */
++ if(jack_server->default_client != NULL){
++ g_object_unref(G_OBJECT(jack_server->default_client));
++
++ jack_server->default_client = NULL;
++ }
++
++ /* client */
++ if(jack_server->client != NULL){
++ list = jack_server->client;
++
++ while(list != NULL){
++ g_object_run_dispose(G_OBJECT(list->data));
++
++ list = list->next;
++ }
++
++ g_list_free_full(jack_server->client,
++ g_object_unref);
++
++ jack_server->client = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_jack_server_parent_class)->finalize(gobject);
++}
++
++void
++ags_jack_server_finalize(GObject *gobject)
++{
++ AgsJackServer *jack_server;
++
++ jack_server = AGS_JACK_SERVER(gobject);
++
++ /* application context */
++ if(jack_server->application_context != NULL){
++ g_object_unref(G_OBJECT(jack_server->application_context));
++ }
++
++ /* url */
+ g_free(jack_server->url);
++
++ /* default soundcard */
++ if(jack_server->default_soundcard != NULL){
++ g_object_unref(G_OBJECT(jack_server->default_soundcard));
++ }
++
++ /* default client */
++ if(jack_server->default_client != NULL){
++ g_object_unref(G_OBJECT(jack_server->default_client));
++ }
++
++ /* client */
++ if(jack_server->client != NULL){
++ g_list_free_full(jack_server->client,
++ g_object_unref);
++ }
+
++ /* call parent */
+ G_OBJECT_CLASS(ags_jack_server_parent_class)->finalize(gobject);
+ }
+
+@@ -518,7 +752,9 @@
+
+ /* the default client */
+ if(jack_server->default_client == NULL){
+- jack_server->default_client = ags_jack_client_new((GObject *) jack_server);
++ g_object_set(jack_server,
++ "default-jack-client\0", ags_jack_client_new((GObject *) jack_server),
++ NULL);
+ ags_jack_server_add_client(jack_server,
+ jack_server->default_client);
+
+@@ -543,10 +779,10 @@
+ "device\0", str,
+ NULL);
+ g_free(str);
+- g_object_ref(jack_devout);
+- default_client->device = g_list_prepend(default_client->device,
+- jack_devout);
+-
++ g_object_set(default_client,
++ "device\0", jack_devout,
++ NULL);
++
+ if(initial_set &&
+ default_client->client != NULL){
+ rc = jack_set_buffer_size(default_client->client,
+@@ -562,7 +798,7 @@
+ str = g_strdup_printf("ags-soundcard%d-%04d\0",
+ jack_server->n_soundcards,
+ i);
+-
++
+ #ifdef AGS_DEBUG
+ g_message("%s\0", str);
+ #endif
+@@ -571,8 +807,9 @@
+ ags_jack_client_add_port(default_client,
+ (GObject *) jack_port);
+
+- jack_devout->jack_port = g_list_append(jack_devout->jack_port,
+- jack_port);
++ g_object_set(jack_devout,
++ "jack-port\0", jack_port,
++ NULL);
+
+ if(jack_devout->port_name == NULL){
+ jack_devout->port_name = (gchar **) malloc(2 * sizeof(gchar *));
+@@ -654,7 +891,9 @@
+
+ /* the default client */
+ if(jack_server->default_client == NULL){
+- jack_server->default_client = (GObject *) ags_jack_client_new((GObject *) jack_server);
++ g_object_set(jack_server,
++ "default-jack-client\0", (GObject *) ags_jack_client_new((GObject *) jack_server),
++ NULL);
+ ags_jack_server_add_client(jack_server,
+ jack_server->default_client);
+
+@@ -675,9 +914,9 @@
+ "jack-client\0", default_client,
+ "device\0", str,
+ NULL);
+- g_object_ref(jack_midiin);
+- default_client->device = g_list_prepend(default_client->device,
+- jack_midiin);
++ g_object_set(default_client,
++ "device\0", jack_midiin,
++ NULL);
+
+ /* register sequencer */
+ str = g_strdup_printf("ags-sequencer%d\0",
+@@ -691,8 +930,9 @@
+ ags_jack_client_add_port(default_client,
+ (GObject *) jack_port);
+
+- jack_midiin->jack_port = g_list_append(jack_midiin->jack_port,
+- jack_port);
++ g_object_set(jack_midiin,
++ "jack-port\0", jack_port,
++ NULL);
+
+ ags_jack_port_register(jack_port,
+ str,
+@@ -754,7 +994,9 @@
+
+ /* the default client */
+ if(jack_server->default_client == NULL){
+- jack_server->default_client = (GObject *) ags_jack_client_new((GObject *) jack_server);
++ g_object_set(jack_server,
++ "default-jack-client\0", (GObject *) ags_jack_client_new((GObject *) jack_server),
++ NULL);
+ ags_jack_server_add_client(jack_server,
+ jack_server->default_client);
+
+@@ -776,8 +1018,9 @@
+ "jack-client\0", default_client,
+ "device\0", "ags-default-devout\0",
+ NULL);
+- default_client->device = g_list_prepend(default_client->device,
+- jack_devout);
++ g_object_set(default_client,
++ "device\0", jack_devout,
++ NULL);
+
+ if(default_client->client != NULL){
+ rc = jack_set_buffer_size(default_client->client,
+@@ -801,8 +1044,9 @@
+ ags_jack_client_add_port(default_client,
+ (GObject *) jack_port);
+
+- jack_devout->jack_port = g_list_prepend(jack_devout->jack_port,
+- jack_port);
++ g_object_set(jack_devout,
++ "jack-port\0", jack_port,
++ NULL);
+
+ if(jack_devout->port_name == NULL){
+ jack_devout->port_name = (gchar **) malloc(2 * sizeof(gchar *));
+--- a/ags/audio/recall/ags_buffer_audio_signal.c
++++ b/ags/audio/recall/ags_buffer_audio_signal.c
+@@ -164,10 +164,6 @@
+ void
+ ags_buffer_audio_signal_finalize(GObject *gobject)
+ {
+- if(AGS_RECALL_AUDIO_SIGNAL(gobject)->destination != NULL){
+- g_object_unref(AGS_RECALL_AUDIO_SIGNAL(gobject)->destination);
+- }
+-
+ /* call parent */
+ G_OBJECT_CLASS(ags_buffer_audio_signal_parent_class)->finalize(gobject);
+ }
+--- a/ags/audio/recall/ags_buffer_channel.c
++++ b/ags/audio/recall/ags_buffer_channel.c
+@@ -39,6 +39,7 @@
+ void ags_buffer_channel_connect(AgsConnectable *connectable);
+ void ags_buffer_channel_disconnect(AgsConnectable *connectable);
+ void ags_buffer_channel_set_ports(AgsPlugin *plugin, GList *port);
++void ags_buffer_channel_dispose(GObject *gobject);
+ void ags_buffer_channel_finalize(GObject *gobject);
+
+ void ags_buffer_channel_set_muted(AgsMutable *mutable, gboolean muted);
+@@ -168,9 +169,17 @@
+ gobject->set_property = ags_buffer_channel_set_property;
+ gobject->get_property = ags_buffer_channel_get_property;
+
++ gobject->dispose = ags_buffer_channel_dispose;
+ gobject->finalize = ags_buffer_channel_finalize;
+
+ /* properties */
++ /**
++ * AgsBufferChannel:muted:
++ *
++ * The mute port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("muted\0",
+ "mute channel\0",
+ "Mute the channel\0",
+@@ -202,9 +211,11 @@
+ "port-value-size\0", sizeof(gboolean),
+ "port-value-length\0", 1,
+ NULL);
++ g_object_ref(buffer_channel->muted);
+ buffer_channel->muted->port_value.ags_port_boolean = FALSE;
+
+ port = g_list_prepend(port, buffer_channel->muted);
++ g_object_ref(buffer_channel->muted);
+
+ /* set port */
+ AGS_RECALL(buffer_channel)->port = port;
+@@ -273,6 +284,23 @@
+ }
+
+ void
++ags_buffer_channel_dispose(GObject *gobject)
++{
++ AgsBufferChannel *buffer_channel;
++
++ buffer_channel = AGS_BUFFER_CHANNEL(gobject);
++
++ if(buffer_channel->muted != NULL){
++ g_object_unref(G_OBJECT(buffer_channel->muted));
++
++ buffer_channel->muted = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_buffer_channel_parent_class)->dispose(gobject);
++}
++
++void
+ ags_buffer_channel_finalize(GObject *gobject)
+ {
+ AgsBufferChannel *buffer_channel;
+--- a/ags/audio/recall/ags_copy_channel.c
++++ b/ags/audio/recall/ags_copy_channel.c
+@@ -39,6 +39,7 @@
+ void ags_copy_channel_connect(AgsConnectable *connectable);
+ void ags_copy_channel_disconnect(AgsConnectable *connectable);
+ void ags_copy_channel_set_ports(AgsPlugin *plugin, GList *port);
++void ags_copy_channel_dispose(GObject *gobject);
+ void ags_copy_channel_finalize(GObject *gobject);
+
+ void ags_copy_channel_set_muted(AgsMutable *mutable, gboolean muted);
+@@ -167,9 +168,17 @@
+ gobject->set_property = ags_copy_channel_set_property;
+ gobject->get_property = ags_copy_channel_get_property;
+
++ gobject->dispose = ags_copy_channel_dispose;
+ gobject->finalize = ags_copy_channel_finalize;
+
+ /* properties */
++ /**
++ * AgsCopyChannel:muted:
++ *
++ * The mute port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("muted\0",
+ "mute channel\0",
+ "Mute the channel\0",
+@@ -201,9 +210,12 @@
+ "port-value-size\0", sizeof(gboolean),
+ "port-value-length\0", 1,
+ NULL);
++ g_object_ref(copy_channel->muted);
+ copy_channel->muted->port_value.ags_port_boolean = FALSE;
+
++ /* add to port */
+ port = g_list_prepend(port, copy_channel->muted);
++ g_object_ref(copy_channel->muted);
+
+ /* set port */
+ AGS_RECALL(copy_channel)->port = port;
+@@ -270,6 +282,23 @@
+ }
+
+ void
++ags_copy_channel_dispose(GObject *gobject)
++{
++ AgsCopyChannel *copy_channel;
++
++ copy_channel = AGS_COPY_CHANNEL(gobject);
++
++ if(copy_channel->muted != NULL){
++ g_object_unref(G_OBJECT(copy_channel->muted));
++
++ copy_channel->muted = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_copy_channel_parent_class)->dispose(gobject);
++}
++
++void
+ ags_copy_channel_finalize(GObject *gobject)
+ {
+ AgsCopyChannel *copy_channel;
+--- a/ags/audio/recall/ags_copy_notation_audio.c
++++ b/ags/audio/recall/ags_copy_notation_audio.c
+@@ -29,6 +29,7 @@
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec);
++void ags_copy_notation_audio_dispose(GObject *gobject);
+ void ags_copy_notation_audio_finalize(GObject *gobject);
+
+ /**
+@@ -43,7 +44,6 @@
+
+ enum{
+ PROP_0,
+- PROP_DEVOUT,
+ PROP_NOTATION,
+ PROP_AUDIO_CHANNEL,
+ };
+@@ -94,6 +94,13 @@
+ gobject->finalize = ags_copy_notation_audio_finalize;
+
+ /* properties */
++ /**
++ * AgsCopyNotationAudio:notation:
++ *
++ * The notation.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("notation\0",
+ "the assigned notation\0",
+ "The AgsNotation it is assigned to\0",
+@@ -103,6 +110,13 @@
+ PROP_NOTATION,
+ param_spec);
+
++ /**
++ * AgsCopyNotationAudio:audio-channel:
++ *
++ * The audio channel.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_uint("audio_channel\0",
+ "the audio channel to play\0",
+ "The audio channel to play of audio object\0",
+@@ -136,24 +150,6 @@
+ copy_notation_audio = AGS_COPY_NOTATION_AUDIO(gobject);
+
+ switch(prop_id){
+- case PROP_DEVOUT:
+- {
+- GObject *soundcard;
+-
+- soundcard = (GObject *) g_value_get_object(value);
+-
+- if(copy_notation_audio->soundcard != soundcard)
+- return;
+-
+- if(copy_notation_audio->soundcard != NULL)
+- g_object_unref(copy_notation_audio->soundcard);
+-
+- if(soundcard != NULL)
+- g_object_ref(soundcard);
+-
+- copy_notation_audio->soundcard = soundcard;
+- }
+- break;
+ case PROP_NOTATION:
+ {
+ AgsNotation *notation;
+@@ -197,11 +193,6 @@
+ copy_notation_audio = AGS_COPY_NOTATION_AUDIO(gobject);
+
+ switch(prop_id){
+- case PROP_DEVOUT:
+- {
+- g_value_set_object(value, copy_notation_audio->soundcard);
+- }
+- break;
+ case PROP_NOTATION:
+ {
+ g_value_set_object(value, copy_notation_audio->notation);
+@@ -218,8 +209,35 @@
+ }
+
+ void
++ags_copy_notation_audio_dispose(GObject *gobject)
++{
++ AgsCopyNotationAudio *copy_notation_audio;
++
++ copy_notation_audio = AGS_COPY_NOTATION_AUDIO(gobject);
++
++ /* notation */
++ if(copy_notation_audio->notation != NULL){
++ g_object_unref(copy_notation_audio->notation);
++
++ copy_notation_audio->notation = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_copy_notation_audio_parent_class)->dispose(gobject);
++}
++
++void
+ ags_copy_notation_audio_finalize(GObject *gobject)
+ {
++ AgsCopyNotationAudio *copy_notation_audio;
++
++ copy_notation_audio = AGS_COPY_NOTATION_AUDIO(gobject);
++
++ /* notation */
++ if(copy_notation_audio->notation != NULL){
++ g_object_unref(copy_notation_audio->notation);
++ }
++
+ /* call parent */
+ G_OBJECT_CLASS(ags_copy_notation_audio_parent_class)->finalize(gobject);
+ }
+--- a/ags/audio/recall/ags_copy_notation_audio.h
++++ b/ags/audio/recall/ags_copy_notation_audio.h
+@@ -46,8 +46,6 @@
+
+ guint flags;
+
+- GObject *soundcard;
+-
+ AgsNotation *notation;
+ guint audio_channel;
+ };
+--- a/ags/audio/recall/ags_copy_notation_audio_run.c
++++ b/ags/audio/recall/ags_copy_notation_audio_run.c
+@@ -42,6 +42,7 @@
+ void ags_copy_notation_audio_run_disconnect(AgsConnectable *connectable);
+ void ags_copy_notation_audio_run_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+ void ags_copy_notation_audio_run_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
++void ags_copy_notation_audio_run_dispose(GObject *gobject);
+ void ags_copy_notation_audio_run_finalize(GObject *gobject);
+
+ void ags_copy_notation_audio_run_resolve_dependencies(AgsRecall *recall);
+@@ -135,6 +136,7 @@
+ gobject->set_property = ags_copy_notation_audio_run_set_property;
+ gobject->get_property = ags_copy_notation_audio_run_get_property;
+
++ gobject->dispose = ags_copy_notation_audio_run_dispose;
+ gobject->finalize = ags_copy_notation_audio_run_finalize;
+
+ /* properties */
+@@ -259,15 +261,35 @@
+ }
+
+ void
+-ags_copy_notation_audio_run_finalize(GObject *gobject)
++ags_copy_notation_audio_run_dispose(GObject *gobject)
+ {
+ AgsCopyNotationAudioRun *copy_notation_audio_run;
+
+ copy_notation_audio_run = AGS_COPY_NOTATION_AUDIO_RUN(gobject);
+
+- if(copy_notation_audio_run->count_beats_audio_run != NULL)
++ /* count beats audio run */
++ if(copy_notation_audio_run->count_beats_audio_run != NULL){
+ g_object_unref(copy_notation_audio_run->count_beats_audio_run);
+
++ copy_notation_audio_run->count_beats_audio_run = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_copy_notation_audio_run_parent_class)->dispose(gobject);
++}
++
++void
++ags_copy_notation_audio_run_finalize(GObject *gobject)
++{
++ AgsCopyNotationAudioRun *copy_notation_audio_run;
++
++ copy_notation_audio_run = AGS_COPY_NOTATION_AUDIO_RUN(gobject);
++
++ /* count beats audio run */
++ if(copy_notation_audio_run->count_beats_audio_run != NULL){
++ g_object_unref(copy_notation_audio_run->count_beats_audio_run);
++ }
++
+ /* call parent */
+ G_OBJECT_CLASS(ags_copy_notation_audio_run_parent_class)->finalize(gobject);
+ }
+@@ -434,12 +456,12 @@
+
+ while(recycling != last_recycling->next){
+ if((AGS_COPY_NOTATION_AUDIO_FIT_AUDIO_SIGNAL & (copy_notation_audio->flags)) != 0){
+- audio_signal = ags_audio_signal_new_with_length((GObject *) copy_notation_audio->soundcard,
++ audio_signal = ags_audio_signal_new_with_length((GObject *) AGS_RECALL(copy_notation_audio)->soundcard,
+ (GObject *) recycling,
+ (GObject *) AGS_RECALL(copy_notation_audio_run)->recall_id,
+ length);
+ }else{
+- audio_signal = ags_audio_signal_new((GObject *) copy_notation_audio->soundcard,
++ audio_signal = ags_audio_signal_new((GObject *) AGS_RECALL(copy_notation_audio)->soundcard,
+ (GObject *) recycling,
+ (GObject *) AGS_RECALL(copy_notation_audio_run)->recall_id);
+ }
+--- a/ags/audio/recall/ags_copy_pattern_audio.c
++++ b/ags/audio/recall/ags_copy_pattern_audio.c
+@@ -36,6 +36,7 @@
+ GValue *value,
+ GParamSpec *param_spec);
+ void ags_copy_pattern_audio_set_ports(AgsPlugin *plugin, GList *port);
++void ags_copy_pattern_audio_dispose(GObject *gobject);
+ void ags_copy_pattern_audio_finalize(GObject *gobject);
+
+ /**
+@@ -123,9 +124,17 @@
+ gobject->set_property = ags_copy_pattern_audio_set_property;
+ gobject->get_property = ags_copy_pattern_audio_get_property;
+
++ gobject->dispose = ags_copy_pattern_audio_dispose;
+ gobject->finalize = ags_copy_pattern_audio_finalize;
+
+ /* properties */
++ /**
++ * AgsCopyPatternAudio:bank-index-0:
++ *
++ * The bank index 0 port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("bank-index-0\0",
+ "current bank index 0\0",
+ "The current bank index 0 of the AgsPattern\0",
+@@ -135,6 +144,13 @@
+ PROP_BANK_INDEX_0,
+ param_spec);
+
++ /**
++ * AgsCopyPatternAudio:bank-index-1:
++ *
++ * The bank index 1 port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("bank-index-1\0",
+ "current bank index 1\0",
+ "The current bank index 1 of the AgsPattern\0",
+@@ -157,6 +173,7 @@
+
+ port = NULL;
+
++ /* bank index 0 */
+ copy_pattern_audio->bank_index_0 = g_object_new(AGS_TYPE_PORT,
+ "plugin-name\0", ags_copy_pattern_audio_plugin_name,
+ "specifier\0", ags_copy_pattern_audio_specifier[0],
+@@ -166,10 +183,15 @@
+ "port-value-size\0", sizeof(guint),
+ "port-value-length\0", 1,
+ NULL);
++ g_object_ref(copy_pattern_audio->bank_index_0);
++
+ copy_pattern_audio->bank_index_0->port_value.ags_port_uint = 0;
+
++ /* add to port */
+ port = g_list_prepend(port, copy_pattern_audio->bank_index_0);
++ g_object_ref(copy_pattern_audio->bank_index_0);
+
++ /* bank index 1 */
+ copy_pattern_audio->bank_index_1 = g_object_new(AGS_TYPE_PORT,
+ "plugin-name\0", ags_copy_pattern_audio_plugin_name,
+ "specifier\0", ags_copy_pattern_audio_specifier[1],
+@@ -179,10 +201,15 @@
+ "port-value-size\0", sizeof(guint),
+ "port-value-length\0", 1,
+ NULL);
++ g_object_ref(copy_pattern_audio->bank_index_1);
++
+ copy_pattern_audio->bank_index_1->port_value.ags_port_uint = 0;
+
++ /* add to port */
+ port = g_list_prepend(port, copy_pattern_audio->bank_index_1);
++ g_object_ref(copy_pattern_audio->bank_index_1);
+
++ /* set port */
+ AGS_RECALL(copy_pattern_audio)->port = port;
+ }
+
+@@ -295,6 +322,31 @@
+ }
+
+ void
++ags_copy_pattern_audio_dispose(GObject *gobject)
++{
++ AgsCopyPatternAudio *copy_pattern_audio;
++
++ copy_pattern_audio = AGS_COPY_PATTERN_AUDIO(gobject);
++
++ /* bank index 0 */
++ if(copy_pattern_audio->bank_index_0 != NULL){
++ g_object_unref(copy_pattern_audio->bank_index_0);
++
++ copy_pattern_audio->bank_index_0 = NULL;
++ }
++
++ /* bank index 1 */
++ if(copy_pattern_audio->bank_index_1 != NULL){
++ g_object_unref(copy_pattern_audio->bank_index_1);
++
++ copy_pattern_audio->bank_index_1 = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_copy_pattern_audio_parent_class)->dispose(gobject);
++}
++
++void
+ ags_copy_pattern_audio_finalize(GObject *gobject)
+ {
+ AgsCopyPatternAudio *copy_pattern_audio;
+--- a/ags/audio/recall/ags_copy_pattern_audio_run.c
++++ b/ags/audio/recall/ags_copy_pattern_audio_run.c
+@@ -45,6 +45,7 @@
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec);
++void ags_copy_pattern_audio_run_dispose(GObject *gobject);
+ void ags_copy_pattern_audio_run_finalize(GObject *gobject);
+ void ags_copy_pattern_audio_run_connect(AgsConnectable *connectable);
+ void ags_copy_pattern_audio_run_disconnect(AgsConnectable *connectable);
+@@ -157,9 +158,17 @@
+ gobject->set_property = ags_copy_pattern_audio_run_set_property;
+ gobject->get_property = ags_copy_pattern_audio_run_get_property;
+
++ gobject->dispose = ags_copy_pattern_audio_run_dispose;
+ gobject->finalize = ags_copy_pattern_audio_run_finalize;
+
+ /* properties */
++ /**
++ * AgsCopyPatternAudioRun:delay-audio-run:
++ *
++ * The delay audio run dependency.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("delay-audio-run\0",
+ "assigned AgsDelayAudioRun\0",
+ "the AgsDelayAudioRun which emits alloc signal\0",
+@@ -169,6 +178,13 @@
+ PROP_DELAY_AUDIO_RUN,
+ param_spec);
+
++ /**
++ * AgsCopyPatternAudioRun:count-beats-audio-run:
++ *
++ * The count beats audio run dependency.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("count-beats-audio-run\0",
+ "assigned AgsCountBeatsAudioRun\0",
+ "the AgsCountBeatsAudioRun which emits beat signal\0",
+@@ -285,8 +301,9 @@
+
+ count_beats_audio_run = (AgsCountBeatsAudioRun *) g_value_get_object(value);
+
+- if(copy_pattern_audio_run->count_beats_audio_run == count_beats_audio_run)
++ if(copy_pattern_audio_run->count_beats_audio_run == count_beats_audio_run){
+ return;
++ }
+
+ if(count_beats_audio_run != NULL &&
+ (AGS_RECALL_TEMPLATE & (AGS_RECALL(count_beats_audio_run)->flags)) != 0){
+@@ -350,16 +367,43 @@
+ }
+
+ void
++ags_copy_pattern_audio_run_dispose(GObject *gobject)
++{
++ AgsCopyPatternAudioRun *copy_pattern_audio_run;
++
++ copy_pattern_audio_run = AGS_COPY_PATTERN_AUDIO_RUN(gobject);
++
++ /* delay audio run */
++ if(copy_pattern_audio_run->delay_audio_run != NULL){
++ g_object_unref(copy_pattern_audio_run->delay_audio_run);
++
++ copy_pattern_audio_run->delay_audio_run = NULL;
++ }
++
++ /* count beats audio run */
++ if(copy_pattern_audio_run->count_beats_audio_run != NULL){
++ g_object_unref(copy_pattern_audio_run->count_beats_audio_run);
++
++ copy_pattern_audio_run->count_beats_audio_run = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_copy_pattern_audio_run_parent_class)->dispose(gobject);
++}
++
++void
+ ags_copy_pattern_audio_run_finalize(GObject *gobject)
+ {
+ AgsCopyPatternAudioRun *copy_pattern_audio_run;
+
+ copy_pattern_audio_run = AGS_COPY_PATTERN_AUDIO_RUN(gobject);
+
++ /* delay audio run */
+ if(copy_pattern_audio_run->delay_audio_run != NULL){
+ g_object_unref(copy_pattern_audio_run->delay_audio_run);
+ }
+
++ /* count beats audio run */
+ if(copy_pattern_audio_run->count_beats_audio_run != NULL){
+ g_object_unref(copy_pattern_audio_run->count_beats_audio_run);
+ }
+--- a/ags/audio/recall/ags_copy_pattern_channel.c
++++ b/ags/audio/recall/ags_copy_pattern_channel.c
+@@ -36,6 +36,7 @@
+ GValue *value,
+ GParamSpec *param_spec);
+ void ags_copy_pattern_channel_set_ports(AgsPlugin *plugin, GList *port);
++void ags_copy_pattern_channel_dispose(GObject *gobject);
+ void ags_copy_pattern_channel_finalize(GObject *gobject);
+
+ /**
+@@ -120,9 +121,17 @@
+ gobject->set_property = ags_copy_pattern_channel_set_property;
+ gobject->get_property = ags_copy_pattern_channel_get_property;
+
++ gobject->dispose = ags_copy_pattern_channel_dispose;
+ gobject->finalize = ags_copy_pattern_channel_finalize;
+
+ /* properties */
++ /**
++ * AgsCopyPatternChannel:pattern:
++ *
++ * The pattern port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("pattern\0",
+ "pattern to play\0",
+ "The pattern which has to be played\0",
+@@ -145,6 +154,7 @@
+
+ port = NULL;
+
++ /* pattern */
+ copy_pattern_channel->pattern = g_object_new(AGS_TYPE_PORT,
+ "plugin-name\0", ags_copy_pattern_channel_plugin_name,
+ "specifier\0", ags_copy_pattern_channel_specifier[0],
+@@ -152,11 +162,15 @@
+ "port-value-is-pointer\0", FALSE,
+ "port-value-type\0", G_TYPE_OBJECT,
+ NULL);
+-
++ g_object_ref(copy_pattern_channel->pattern);
++
+ copy_pattern_channel->pattern->port_value.ags_port_object = NULL;
+
++ /* add to port */
+ port = g_list_prepend(port, copy_pattern_channel->pattern);
++ g_object_ref(copy_pattern_channel->pattern);
+
++ /* set port */
+ AGS_RECALL(copy_pattern_channel)->port = port;
+ }
+
+@@ -237,16 +251,36 @@
+ }
+
+ void
++ags_copy_pattern_channel_dispose(GObject *gobject)
++{
++ AgsCopyPatternChannel *copy_pattern_channel;
++
++ copy_pattern_channel = AGS_COPY_PATTERN_CHANNEL(gobject);
++
++ /* pattern */
++ if(copy_pattern_channel->pattern != NULL){
++ g_object_unref(copy_pattern_channel->pattern);
++
++ copy_pattern_channel->pattern = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_copy_pattern_channel_parent_class)->dispose(gobject);
++}
++
++void
+ ags_copy_pattern_channel_finalize(GObject *gobject)
+ {
+ AgsCopyPatternChannel *copy_pattern_channel;
+
+ copy_pattern_channel = AGS_COPY_PATTERN_CHANNEL(gobject);
+
++ /* pattern */
+ if(copy_pattern_channel->pattern != NULL){
+ g_object_unref(copy_pattern_channel->pattern);
+ }
+
++ /* call parent */
+ G_OBJECT_CLASS(ags_copy_pattern_channel_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/audio/recall/ags_count_beats_audio.c
++++ b/ags/audio/recall/ags_count_beats_audio.c
+@@ -39,6 +39,7 @@
+ GValue *value,
+ GParamSpec *param_spec);
+ void ags_count_beats_audio_set_ports(AgsPlugin *plugin, GList *port);
++void ags_count_beats_audio_dispose(GObject *gobject);
+ void ags_count_beats_audio_finalize(GObject *gobject);
+ void ags_count_beats_audio_connect(AgsConnectable *connectable);
+ void ags_count_beats_audio_disconnect(AgsConnectable *connectable);
+@@ -184,6 +185,7 @@
+ gobject->set_property = ags_count_beats_audio_set_property;
+ gobject->get_property = ags_count_beats_audio_get_property;
+
++ gobject->dispose = ags_count_beats_audio_dispose;
+ gobject->finalize = ags_count_beats_audio_finalize;
+
+ /* properties */
+@@ -306,10 +308,13 @@
+ "port-value-size\0", sizeof(gboolean),
+ "port-value-length", 1,
+ NULL);
+-
++ g_object_ref(count_beats_audio->sequencer_loop);
++
+ count_beats_audio->sequencer_loop->port_value.ags_port_boolean = FALSE;
+
++ /* add to port */
+ port = g_list_prepend(port, count_beats_audio->sequencer_loop);
++ g_object_ref(count_beats_audio->sequencer_loop);
+
+ /* notation loop */
+ count_beats_audio->notation_loop = g_object_new(AGS_TYPE_PORT,
+@@ -321,10 +326,13 @@
+ "port-value-size\0", sizeof(gboolean),
+ "port-value-length", 1,
+ NULL);
+-
++ g_object_ref(count_beats_audio->notation_loop);
++
+ count_beats_audio->notation_loop->port_value.ags_port_boolean = FALSE;
+
++ /* add to port */
+ port = g_list_prepend(port, count_beats_audio->notation_loop);
++ g_object_ref(count_beats_audio->notation_loop);
+
+ /* sequencer-loop-start */
+ count_beats_audio->sequencer_loop_start = g_object_new(AGS_TYPE_PORT,
+@@ -336,10 +344,13 @@
+ "port-value-size\0", sizeof(gdouble),
+ "port-value-length", 1,
+ NULL);
+-
++ g_object_ref(count_beats_audio->sequencer_loop_start);
++
+ count_beats_audio->sequencer_loop_start->port_value.ags_port_double = 0.0;
+
++ /* add to port */
+ port = g_list_prepend(port, count_beats_audio->sequencer_loop_start);
++ g_object_ref(count_beats_audio->sequencer_loop_start);
+
+ /* notation-loop-start */
+ count_beats_audio->notation_loop_start = g_object_new(AGS_TYPE_PORT,
+@@ -351,11 +362,14 @@
+ "port-value-size\0", sizeof(gdouble),
+ "port-value-length", 1,
+ NULL);
+-
++ g_object_ref(count_beats_audio->notation_loop_start);
++
+ count_beats_audio->notation_loop_start->port_value.ags_port_double = 0.0;
+
++ /* add to port */
+ port = g_list_prepend(port, count_beats_audio->notation_loop_start);
+-
++ g_object_ref(count_beats_audio->notation_loop_start);
++
+ /* sequencer-loop-end */
+ count_beats_audio->sequencer_loop_end = g_object_new(AGS_TYPE_PORT,
+ "plugin-name\0", ags_count_beats_audio_plugin_name,
+@@ -366,11 +380,14 @@
+ "port-value-size\0", sizeof(gdouble),
+ "port-value-length", 1,
+ NULL);
+-
++ g_object_ref(count_beats_audio->sequencer_loop_end);
++
+ count_beats_audio->sequencer_loop_end->port_value.ags_port_double = 16.0;
+
++ /* add to port */
+ port = g_list_prepend(port, count_beats_audio->sequencer_loop_end);
+-
++ g_object_ref(count_beats_audio->sequencer_loop_end);
++
+ /* notation-loop-end */
+ count_beats_audio->notation_loop_end = g_object_new(AGS_TYPE_PORT,
+ "plugin-name\0", ags_count_beats_audio_plugin_name,
+@@ -381,10 +398,13 @@
+ "port-value-size\0", sizeof(gdouble),
+ "port-value-length", 1,
+ NULL);
+-
++ g_object_ref(count_beats_audio->notation_loop_end);
++
+ count_beats_audio->notation_loop_end->port_value.ags_port_double = 64.0;
+
++ /* add to port */
+ port = g_list_prepend(port, count_beats_audio->notation_loop_end);
++ g_object_ref(count_beats_audio->notation_loop_end);
+
+ /* port */
+ AGS_RECALL(count_beats_audio)->port = port;
+@@ -626,7 +646,54 @@
+ }
+ }
+
+- void
++void
++ags_count_beats_audio_dispose(GObject *gobject)
++{
++ AgsCountBeatsAudio *count_beats_audio;
++
++ count_beats_audio = AGS_COUNT_BEATS_AUDIO(gobject);
++
++ if(count_beats_audio->notation_loop != NULL){
++ g_object_unref(G_OBJECT(count_beats_audio->notation_loop));
++
++ count_beats_audio->notation_loop = NULL;
++ }
++
++ if(count_beats_audio->notation_loop_start != NULL){
++ g_object_unref(G_OBJECT(count_beats_audio->notation_loop_start));
++
++ count_beats_audio->notation_loop_start = NULL;
++ }
++
++ if(count_beats_audio->notation_loop_end != NULL){
++ g_object_unref(G_OBJECT(count_beats_audio->notation_loop_end));
++
++ count_beats_audio->notation_loop_end = NULL;
++ }
++
++ if(count_beats_audio->sequencer_loop != NULL){
++ g_object_unref(G_OBJECT(count_beats_audio->sequencer_loop));
++
++ count_beats_audio->sequencer_loop = NULL;
++ }
++
++ if(count_beats_audio->sequencer_loop_start != NULL){
++ g_object_unref(G_OBJECT(count_beats_audio->sequencer_loop_start));
++
++ count_beats_audio->sequencer_loop_start = NULL;
++ }
++
++ if(count_beats_audio->sequencer_loop_end != NULL){
++ g_object_unref(G_OBJECT(count_beats_audio->sequencer_loop_end));
++
++ count_beats_audio->sequencer_loop_end = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_count_beats_audio_parent_class)->dispose(gobject);
++}
++
++void
+ ags_count_beats_audio_finalize(GObject *gobject)
+ {
+ AgsCountBeatsAudio *count_beats_audio;
+--- a/ags/audio/recall/ags_envelope_channel.c
++++ b/ags/audio/recall/ags_envelope_channel.c
+@@ -37,6 +37,7 @@
+ void ags_envelope_channel_connect(AgsConnectable *connectable);
+ void ags_envelope_channel_disconnect(AgsConnectable *connectable);
+ void ags_envelope_channel_set_ports(AgsPlugin *plugin, GList *port);
++void ags_envelope_channel_dispose(GObject *gobject);
+ void ags_envelope_channel_finalize(GObject *gobject);
+
+ /**
+@@ -137,9 +138,17 @@
+ gobject->set_property = ags_envelope_channel_set_property;
+ gobject->get_property = ags_envelope_channel_get_property;
+
++ gobject->dispose = ags_envelope_channel_dispose;
+ gobject->finalize = ags_envelope_channel_finalize;
+
+ /* properties */
++ /**
++ * AgsEnvelopeChannel:attack:
++ *
++ * The attack of envelope.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("attack\0",
+ "attack channel\0",
+ "Attack of the channel\0",
+@@ -149,6 +158,13 @@
+ PROP_ATTACK,
+ param_spec);
+
++ /**
++ * AgsEnvelopeChannel:decay:
++ *
++ * The decay of envelope.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("decay\0",
+ "decay channel\0",
+ "Decay of the channel\0",
+@@ -158,6 +174,13 @@
+ PROP_DECAY,
+ param_spec);
+
++ /**
++ * AgsEnvelopeChannel:sustain:
++ *
++ * The sustain of envelope.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("sustain\0",
+ "sustain channel\0",
+ "Sustain of the channel\0",
+@@ -167,6 +190,13 @@
+ PROP_SUSTAIN,
+ param_spec);
+
++ /**
++ * AgsEnvelopeChannel:release:
++ *
++ * The release of envelope.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("release\0",
+ "release channel\0",
+ "Release of the channel\0",
+@@ -176,6 +206,13 @@
+ PROP_RELEASE,
+ param_spec);
+
++ /**
++ * AgsEnvelopeChannel:ratio:
++ *
++ * The ratio of envelope.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("ratio\0",
+ "envelope ratio\0",
+ "The ratio of the envelope\0",
+@@ -199,6 +236,7 @@
+ /* ports */
+ port = NULL;
+
++ /* attack */
+ envelope_channel->attack = g_object_new(AGS_TYPE_PORT,
+ "plugin-name\0", g_strdup("ags-envelope\0"),
+ "specifier\0", "./attack[0]\0",
+@@ -208,10 +246,15 @@
+ "port-value-size\0", sizeof(gdouble),
+ "port-value-length\0", 1,
+ NULL);
++ g_object_ref(envelope_channel->attack);
++
+ envelope_channel->attack->port_value.ags_port_double = 1.0;
+
++ /* add to port */
+ port = g_list_prepend(port, envelope_channel->attack);
++ g_object_ref(envelope_channel->attack);
+
++ /* decay */
+ envelope_channel->decay = g_object_new(AGS_TYPE_PORT,
+ "plugin-name\0", g_strdup("ags-envelope\0"),
+ "specifier\0", "./decay[0]\0",
+@@ -221,10 +264,15 @@
+ "port-value-size\0", sizeof(gdouble),
+ "port-value-length\0", 1,
+ NULL);
++ g_object_ref(envelope_channel->decay);
++
+ envelope_channel->decay->port_value.ags_port_double = 1.0;
+
++ /* add to port */
+ port = g_list_prepend(port, envelope_channel->decay);
++ g_object_ref(envelope_channel->decay);
+
++ /* sustain */
+ envelope_channel->sustain = g_object_new(AGS_TYPE_PORT,
+ "plugin-name\0", g_strdup("ags-envelope\0"),
+ "specifier\0", "./sustain[0]\0",
+@@ -234,10 +282,15 @@
+ "port-value-size\0", sizeof(gdouble),
+ "port-value-length\0", 1,
+ NULL);
+- envelope_channel->sustain->port_value.ags_port_double = 1.0;
++ g_object_ref(envelope_channel->sustain);
+
++ envelope_channel->sustain->port_value.ags_port_double = 1.0;
++
++ /* add to port */
+ port = g_list_prepend(port, envelope_channel->sustain);
++ g_object_ref(envelope_channel->sustain);
+
++ /* release */
+ envelope_channel->release = g_object_new(AGS_TYPE_PORT,
+ "plugin-name\0", g_strdup("ags-envelope\0"),
+ "specifier\0", "./release[0]\0",
+@@ -247,10 +300,15 @@
+ "port-value-size\0", sizeof(gdouble),
+ "port-value-length\0", 1,
+ NULL);
++ g_object_ref(envelope_channel->release);
++
+ envelope_channel->release->port_value.ags_port_boolean = 1.0;
+-
++
++ /* add to port */
+ port = g_list_prepend(port, envelope_channel->release);
++ g_object_ref(envelope_channel->release);
+
++ /* ratio */
+ envelope_channel->ratio = g_object_new(AGS_TYPE_PORT,
+ "plugin-name\0", g_strdup("ags-envelope\0"),
+ "specifier\0", "./ratio[0]\0",
+@@ -260,9 +318,13 @@
+ "port-value-size\0", sizeof(gdouble),
+ "port-value-length\0", 1,
+ NULL);
++ g_object_ref(envelope_channel->ratio);
++
+ envelope_channel->ratio->port_value.ags_port_boolean = 1.0;
+
++ /* add to port */
+ port = g_list_prepend(port, envelope_channel->ratio);
++ g_object_ref(envelope_channel->ratio);
+
+ /* set ports */
+ AGS_RECALL(envelope_channel)->port = port;
+@@ -490,6 +552,47 @@
+ }
+
+ void
++ags_envelope_channel_dispose(GObject *gobject)
++{
++ AgsEnvelopeChannel *envelope_channel;
++
++ envelope_channel = AGS_ENVELOPE_CHANNEL(gobject);
++
++ if(envelope_channel->attack != NULL){
++ g_object_unref(G_OBJECT(envelope_channel->attack));
++
++ envelope_channel->attack = NULL;
++ }
++
++ if(envelope_channel->decay != NULL){
++ g_object_unref(G_OBJECT(envelope_channel->decay));
++
++ envelope_channel->decay = NULL;
++ }
++
++ if(envelope_channel->sustain != NULL){
++ g_object_unref(G_OBJECT(envelope_channel->sustain));
++
++ envelope_channel->sustain = NULL;
++ }
++
++ if(envelope_channel->release != NULL){
++ g_object_unref(G_OBJECT(envelope_channel->release));
++
++ envelope_channel->release = NULL;
++ }
++
++ if(envelope_channel->ratio != NULL){
++ g_object_unref(G_OBJECT(envelope_channel->ratio));
++
++ envelope_channel->ratio = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_envelope_channel_parent_class)->dispose(gobject);
++}
++
++void
+ ags_envelope_channel_finalize(GObject *gobject)
+ {
+ AgsEnvelopeChannel *envelope_channel;
+--- a/ags/audio/recall/ags_loop_channel.c
++++ b/ags/audio/recall/ags_loop_channel.c
+@@ -44,6 +44,7 @@
+ GParamSpec *param_spec);
+ void ags_loop_channel_connect(AgsConnectable *connectable);
+ void ags_loop_channel_disconnect(AgsConnectable *connectable);
++void ags_loop_channel_dispose(GObject *gobject);
+ void ags_loop_channel_finalize(GObject *gobject);
+
+ void ags_loop_channel_sequencer_duration_changed_callback(AgsDelayAudio *delay_audio,
+@@ -130,12 +131,20 @@
+ gobject->set_property = ags_loop_channel_set_property;
+ gobject->get_property = ags_loop_channel_get_property;
+
++ gobject->dispose = ags_loop_channel_dispose;
+ gobject->finalize = ags_loop_channel_finalize;
+
+ /* properties */
++ /**
++ * AgsLoopChannel:delay-audio:
++ *
++ * The assigned #AgsDelayAudio.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("delay-audio\0",
+- "assigned delay-audio\0",
+- "The delay-audio it is assigned with\0",
++ "assigned delay audio\0",
++ "The delay audio it is assigned with\0",
+ AGS_TYPE_DELAY_AUDIO,
+ G_PARAM_READABLE | G_PARAM_WRITABLE);
+ g_object_class_install_property(gobject,
+@@ -187,8 +196,9 @@
+
+ delay_audio = (AgsDelayAudio *) g_value_get_object(value);
+
+- if(loop_channel->delay_audio == delay_audio)
++ if(loop_channel->delay_audio == delay_audio){
+ return;
++ }
+
+ if(loop_channel->delay_audio != NULL){
+ g_object_disconnect(G_OBJECT(loop_channel->delay_audio),
+@@ -225,10 +235,12 @@
+ AgsLoopChannel *loop_channel;
+
+ loop_channel = AGS_LOOP_CHANNEL(gobject);
+-
++
+ switch(prop_id){
+ case PROP_DELAY_AUDIO:
+- g_value_set_object(value, loop_channel->delay_audio);
++ {
++ g_value_set_object(value, loop_channel->delay_audio);
++ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+@@ -237,12 +249,31 @@
+ }
+
+ void
++ags_loop_channel_dispose(GObject *gobject)
++{
++ AgsLoopChannel *loop_channel;
++
++ loop_channel = AGS_LOOP_CHANNEL(gobject);
++
++ /* delay audio */
++ if(loop_channel->delay_audio != NULL){
++ g_object_unref(G_OBJECT(loop_channel->delay_audio));
++
++ loop_channel->delay_audio = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_loop_channel_parent_class)->dispose(gobject);
++}
++
++void
+ ags_loop_channel_finalize(GObject *gobject)
+ {
+ AgsLoopChannel *loop_channel;
+
+ loop_channel = AGS_LOOP_CHANNEL(gobject);
+
++ /* delay audio */
+ if(loop_channel->delay_audio != NULL){
+ g_object_unref(G_OBJECT(loop_channel->delay_audio));
+ }
+--- a/ags/audio/recall/ags_loop_channel_run.c
++++ b/ags/audio/recall/ags_loop_channel_run.c
+@@ -52,6 +52,7 @@
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec);
++void ags_loop_channel_run_dispose(GObject *gobject);
+ void ags_loop_channel_run_finalize(GObject *gobject);
+ void ags_loop_channel_run_connect(AgsConnectable *connectable);
+ void ags_loop_channel_run_disconnect(AgsConnectable *connectable);
+@@ -171,9 +172,17 @@
+ gobject->set_property = ags_loop_channel_run_set_property;
+ gobject->get_property = ags_loop_channel_run_get_property;
+
++ gobject->dispose = ags_loop_channel_run_dispose;
+ gobject->finalize = ags_loop_channel_run_finalize;
+
+ /* properties */
++ /**
++ * AgsLoopChannelRun:count-beats-audio-run:
++ *
++ * The count beats audio run dependency.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("count-beats-audio-run\0",
+ "assigned AgsCountBeatsAudioRun\0",
+ "The pointer to a counter object which indicates when looping should happen\0",
+@@ -335,12 +344,31 @@
+ }
+
+ void
++ags_loop_channel_run_dispose(GObject *gobject)
++{
++ AgsLoopChannelRun *loop_channel_run;
++
++ loop_channel_run = AGS_LOOP_CHANNEL_RUN(gobject);
++
++ /* count beats audio run */
++ if(loop_channel_run->count_beats_audio_run != NULL){
++ g_object_unref(G_OBJECT(loop_channel_run->count_beats_audio_run));
++
++ loop_channel_run->count_beats_audio_run = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_loop_channel_run_parent_class)->dispose(gobject);
++}
++
++void
+ ags_loop_channel_run_finalize(GObject *gobject)
+ {
+ AgsLoopChannelRun *loop_channel_run;
+
+ loop_channel_run = AGS_LOOP_CHANNEL_RUN(gobject);
+
++ /* count beats audio run */
+ if(loop_channel_run->count_beats_audio_run != NULL){
+ g_object_unref(G_OBJECT(loop_channel_run->count_beats_audio_run));
+ }
+--- a/ags/audio/recall/ags_mute_audio.c
++++ b/ags/audio/recall/ags_mute_audio.c
+@@ -39,6 +39,7 @@
+ void ags_mute_audio_connect(AgsConnectable *connectable);
+ void ags_mute_audio_disconnect(AgsConnectable *connectable);
+ void ags_mute_audio_set_ports(AgsPlugin *plugin, GList *port);
++void ags_mute_audio_dispose(GObject *gobject);
+ void ags_mute_audio_finalize(GObject *gobject);
+
+ void ags_mute_audio_set_muted(AgsMutable *mutable, gboolean muted);
+@@ -133,9 +134,17 @@
+ gobject->set_property = ags_mute_audio_set_property;
+ gobject->get_property = ags_mute_audio_get_property;
+
++ gobject->dispose = ags_mute_audio_dispose;
+ gobject->finalize = ags_mute_audio_finalize;
+
+ /* properties */
++ /**
++ * AgsMuteAudio:muted:
++ *
++ * The mute port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("muted\0",
+ "mute audio\0",
+ "Mute the audio\0",
+@@ -190,9 +199,11 @@
+ "port-value-size\0", sizeof(gboolean),
+ "port-value-length\0", 1,
+ NULL);
++ g_object_ref(mute_audio->muted);
+ mute_audio->muted->port_value.ags_port_boolean = FALSE;
+
+ port = g_list_prepend(port, mute_audio->muted);
++ g_object_ref(mute_audio->muted);
+
+ /* */
+ AGS_RECALL(mute_audio)->port = port;
+@@ -292,12 +303,31 @@
+ }
+
+ void
++ags_mute_audio_dispose(GObject *gobject)
++{
++ AgsMuteAudio *mute_audio;
++
++ mute_audio = AGS_MUTE_AUDIO(gobject);
++
++ /* muted */
++ if(mute_audio->muted != NULL){
++ g_object_unref(G_OBJECT(mute_audio->muted));
++
++ mute_audio->muted = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_mute_audio_parent_class)->dispose(gobject);
++}
++
++void
+ ags_mute_audio_finalize(GObject *gobject)
+ {
+ AgsMuteAudio *mute_audio;
+
+ mute_audio = AGS_MUTE_AUDIO(gobject);
+
++ /* muted */
+ if(mute_audio->muted != NULL){
+ g_object_unref(G_OBJECT(mute_audio->muted));
+ }
+--- a/ags/audio/recall/ags_mute_channel.c
++++ b/ags/audio/recall/ags_mute_channel.c
+@@ -39,6 +39,7 @@
+ void ags_mute_channel_connect(AgsConnectable *connectable);
+ void ags_mute_channel_disconnect(AgsConnectable *connectable);
+ void ags_mute_channel_set_ports(AgsPlugin *plugin, GList *port);
++void ags_mute_channel_dispose(GObject *gobject);
+ void ags_mute_channel_finalize(GObject *gobject);
+
+ void ags_mute_channel_set_muted(AgsMutable *mutable, gboolean muted);
+@@ -156,9 +157,17 @@
+ gobject->set_property = ags_mute_channel_set_property;
+ gobject->get_property = ags_mute_channel_get_property;
+
++ gobject->dispose = ags_mute_channel_dispose;
+ gobject->finalize = ags_mute_channel_finalize;
+
+ /* properties */
++ /**
++ * AgsMuteChannel:muted:
++ *
++ * The mute port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("muted\0",
+ "mute channel\0",
+ "Mute the channel\0",
+@@ -190,9 +199,11 @@
+ "port-value-size\0", sizeof(gboolean),
+ "port-value-length\0", 1,
+ NULL);
++ g_object_ref(mute_channel->muted);
+ mute_channel->muted->port_value.ags_port_boolean = FALSE;
+
+ port = g_list_prepend(port, mute_channel->muted);
++ g_object_ref(mute_channel->muted);
+
+ AGS_RECALL(mute_channel)->port = port;
+ }
+@@ -290,12 +301,31 @@
+ }
+
+ void
++ags_mute_channel_dispose(GObject *gobject)
++{
++ AgsMuteChannel *mute_channel;
++
++ mute_channel = AGS_MUTE_CHANNEL(gobject);
++
++ /* muted */
++ if(mute_channel->muted != NULL){
++ g_object_unref(G_OBJECT(mute_channel->muted));
++
++ mute_channel->muted = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_mute_channel_parent_class)->dispose(gobject);
++}
++
++void
+ ags_mute_channel_finalize(GObject *gobject)
+ {
+ AgsMuteChannel *mute_channel;
+
+ mute_channel = AGS_MUTE_CHANNEL(gobject);
+
++ /* muted */
+ if(mute_channel->muted != NULL){
+ g_object_unref(G_OBJECT(mute_channel->muted));
+ }
+--- a/ags/audio/recall/ags_peak_channel.c
++++ b/ags/audio/recall/ags_peak_channel.c
+@@ -47,6 +47,7 @@
+ void ags_peak_channel_connect(AgsConnectable *connectable);
+ void ags_peak_channel_disconnect(AgsConnectable *connectable);
+ void ags_peak_channel_set_ports(AgsPlugin *plugin, GList *port);
++void ags_peak_channel_dispose(GObject *gobject);
+ void ags_peak_channel_finalize(GObject *gobject);
+
+ /**
+@@ -154,9 +155,17 @@
+ gobject->set_property = ags_peak_channel_set_property;
+ gobject->get_property = ags_peak_channel_get_property;
+
++ gobject->dispose = ags_peak_channel_dispose;
+ gobject->finalize = ags_peak_channel_finalize;
+
+ /* properties */
++ /**
++ * AgsPeakChannel:peak:
++ *
++ * The peak of the channel.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("peak\0",
+ "peak of channel\0",
+ "The peak of channel\0",
+@@ -191,6 +200,7 @@
+ peak_channel->peak->port_value.ags_port_double = FALSE;
+
+ port = g_list_prepend(port, peak_channel->peak);
++ g_object_ref(peak_channel->peak);
+
+ /* set port */
+ AGS_RECALL(peak_channel)->port = port;
+@@ -257,12 +267,31 @@
+ }
+
+ void
++ags_peak_channel_dispose(GObject *gobject)
++{
++ AgsPeakChannel *peak_channel;
++
++ peak_channel = AGS_PEAK_CHANNEL(gobject);
++
++ /* peak */
++ if(peak_channel->peak != NULL){
++ g_object_unref(G_OBJECT(peak_channel->peak));
++
++ peak_channel->peak = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_peak_channel_parent_class)->dispose(gobject);
++}
++
++void
+ ags_peak_channel_finalize(GObject *gobject)
+ {
+ AgsPeakChannel *peak_channel;
+
+ peak_channel = AGS_PEAK_CHANNEL(gobject);
+
++ /* peak */
+ if(peak_channel->peak != NULL){
+ g_object_unref(G_OBJECT(peak_channel->peak));
+ }
+@@ -329,7 +358,7 @@
+ guint i;
+ guint copy_mode;
+
+- GValue value = {0,};
++ GValue *value;
+
+ if(peak_channel == NULL){
+ return;
+--- a/ags/audio/recall/ags_play_channel.c
++++ b/ags/audio/recall/ags_play_channel.c
+@@ -45,6 +45,7 @@
+ void ags_play_channel_connect(AgsConnectable *connectable);
+ void ags_play_channel_disconnect(AgsConnectable *connectable);
+ void ags_play_channel_set_ports(AgsPlugin *plugin, GList *port);
++void ags_play_channel_dispose(GObject *gobject);
+ void ags_play_channel_finalize(GObject *gobject);
+
+ void ags_play_channel_set_muted(AgsMutable *mutable, gboolean muted);
+@@ -152,9 +153,17 @@
+ gobject->set_property = ags_play_channel_set_property;
+ gobject->get_property = ags_play_channel_get_property;
+
++ gobject->dispose = ags_play_channel_dispose;
+ gobject->finalize = ags_play_channel_finalize;
+
+ /* properties */
++ /**
++ * AgsPlayChannel:audio-channel:
++ *
++ * The audio channel port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("audio-channel\0",
+ "assigned audio channel\0",
+ "The audio channel this recall does output to\0",
+@@ -164,6 +173,13 @@
+ PROP_AUDIO_CHANNEL,
+ param_spec);
+
++ /**
++ * AgsPlayChannel:muted:
++ *
++ * The muted port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("muted\0",
+ "mute channel\0",
+ "Mute the channel\0",
+@@ -211,6 +227,7 @@
+
+ port = NULL;
+
++ /* audio channel */
+ play_channel->audio_channel = g_object_new(AGS_TYPE_PORT,
+ "plugin-name\0", ags_play_channel_plugin_name,
+ "specifier\0", ags_play_channel_specifier[0],
+@@ -220,10 +237,15 @@
+ "port-value-size\0", sizeof(guint64),
+ "port-value-length\0", 1,
+ NULL);
++ g_object_ref(play_channel->audio_channel);
++
+ play_channel->audio_channel->port_value.ags_port_uint = 0;
+
++ /* add to port */
+ port = g_list_prepend(port, play_channel->audio_channel);
++ g_object_ref(play_channel->audio_channel);
+
++ /* muted */
+ play_channel->muted = g_object_new(AGS_TYPE_PORT,
+ "plugin-name\0", ags_play_channel_plugin_name,
+ "specifier\0", ags_play_channel_specifier[1],
+@@ -233,9 +255,13 @@
+ "port-value-size\0", sizeof(gboolean),
+ "port-value-length\0", 1,
+ NULL);
++ g_object_ref(play_channel->muted);
++
+ play_channel->muted->port_value.ags_port_boolean = FALSE;
+
++ /* add to port */
+ port = g_list_prepend(port, play_channel->muted);
++ g_object_ref(play_channel->muted);
+
+ /* set port */
+ AGS_RECALL(play_channel)->port = port;
+@@ -328,16 +354,43 @@
+ }
+
+ void
++ags_play_channel_dispose(GObject *gobject)
++{
++ AgsPlayChannel *play_channel;
++
++ play_channel = AGS_PLAY_CHANNEL(gobject);
++
++ /* audio channel */
++ if(play_channel->audio_channel != NULL){
++ g_object_unref(G_OBJECT(play_channel->audio_channel));
++
++ play_channel->audio_channel = NULL;
++ }
++
++ /* muted */
++ if(play_channel->muted != NULL){
++ g_object_unref(G_OBJECT(play_channel->muted));
++
++ play_channel->muted = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_play_channel_parent_class)->dispose(gobject);
++}
++
++void
+ ags_play_channel_finalize(GObject *gobject)
+ {
+ AgsPlayChannel *play_channel;
+
+ play_channel = AGS_PLAY_CHANNEL(gobject);
+
++ /* audio channel */
+ if(play_channel->audio_channel != NULL){
+ g_object_unref(G_OBJECT(play_channel->audio_channel));
+ }
+
++ /* muted */
+ if(play_channel->muted != NULL){
+ g_object_unref(G_OBJECT(play_channel->muted));
+ }
+--- a/ags/audio/recall/ags_play_channel_run.c
++++ b/ags/audio/recall/ags_play_channel_run.c
+@@ -65,6 +65,7 @@
+ void ags_play_channel_run_disconnect(AgsConnectable *connectable);
+ void ags_play_channel_run_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+ void ags_play_channel_run_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
++void ags_play_channel_run_dispose(GObject *gobject);
+ void ags_play_channel_run_finalize(GObject *gobject);
+
+ void ags_play_channel_run_run_init_inter(AgsRecall *recall);
+@@ -176,9 +177,17 @@
+ gobject->set_property = ags_play_channel_run_set_property;
+ gobject->get_property = ags_play_channel_run_get_property;
+
++ gobject->dispose = ags_play_channel_run_dispose;
+ gobject->finalize = ags_play_channel_run_finalize;
+
+ /* properties */
++ /**
++ * AgsPlayChannelRun:stream-channel-run:
++ *
++ * The stream channel run dependency.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("stream-channel-run\0",
+ "assigned AgsStreamChannelRun\0",
+ "the assigned AgsStreamChannelRun\0",
+@@ -319,12 +328,31 @@
+ }
+
+ void
++ags_play_channel_run_dispose(GObject *gobject)
++{
++ AgsPlayChannelRun *play_channel_run;
++
++ play_channel_run = AGS_PLAY_CHANNEL_RUN(gobject);
++
++ /* stream channel run */
++ if(play_channel_run->stream_channel_run != NULL){
++ g_object_unref(G_OBJECT(play_channel_run->stream_channel_run));
++
++ play_channel_run->stream_channel_run = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_play_channel_run_parent_class)->dispose(gobject);
++}
++
++void
+ ags_play_channel_run_finalize(GObject *gobject)
+ {
+ AgsPlayChannelRun *play_channel_run;
+
+ play_channel_run = AGS_PLAY_CHANNEL_RUN(gobject);
+
++ /* stream channel run */
+ if(play_channel_run->stream_channel_run != NULL){
+ g_object_unref(G_OBJECT(play_channel_run->stream_channel_run));
+ }
+--- a/ags/audio/recall/ags_play_channel_run_master.c
++++ b/ags/audio/recall/ags_play_channel_run_master.c
+@@ -54,6 +54,7 @@
+ void ags_play_channel_run_master_disconnect(AgsConnectable *connectable);
+ void ags_play_channel_run_master_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+ void ags_play_channel_run_master_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
++void ags_play_channel_run_master_dispose(GObject *gobject);
+ void ags_play_channel_run_master_finalize(GObject *gobject);
+
+ void ags_play_channel_run_master_run_init_pre(AgsRecall *recall);
+@@ -173,9 +174,17 @@
+ gobject->set_property = ags_play_channel_run_master_set_property;
+ gobject->get_property = ags_play_channel_run_master_get_property;
+
++ gobject->dispose = ags_play_channel_run_master_dispose;
+ gobject->finalize = ags_play_channel_run_master_finalize;
+
+ /* properties */
++ /**
++ * AgsPlayChannelRunMaster:stream-channel-run:
++ *
++ * The assigned stream channel run.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("stream-channel-run\0",
+ "assigned AgsStreamChannelRun\0",
+ "an assigned AgsStreamChannelRun\0",
+@@ -324,10 +333,37 @@
+ }
+
+ void
++ags_play_channel_run_master_dispose(GObject *gobject)
++{
++ AgsPlayChannelRunMaster *play_channel_run_master;
++
++ play_channel_run_master = AGS_PLAY_CHANNEL_RUN_MASTER(gobject);
++
++ /* streamer */
++ if(play_channel_run_master->streamer != NULL){
++ g_list_free_full(play_channel_run_master->streamer,
++ ags_play_channel_run_master_streamer_free);
++
++ play_channel_run_master->streamer = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_play_channel_run_master_parent_class)->dispose(gobject);
++}
++
++void
+ ags_play_channel_run_master_finalize(GObject *gobject)
+ {
+- /* empty */
++ AgsPlayChannelRunMaster *play_channel_run_master;
+
++ play_channel_run_master = AGS_PLAY_CHANNEL_RUN_MASTER(gobject);
++
++ /* streamer */
++ if(play_channel_run_master->streamer != NULL){
++ g_list_free_full(play_channel_run_master->streamer,
++ ags_play_channel_run_master_streamer_free);
++ }
++
+ /* call parent */
+ G_OBJECT_CLASS(ags_play_channel_run_master_parent_class)->finalize(gobject);
+ }
+@@ -657,6 +693,13 @@
+ void
+ ags_play_channel_run_master_streamer_free(AgsPlayChannelRunMasterStreamer *streamer)
+ {
++ if(streamer == NULL){
++ return;
++ }
++
++ g_object_unref(streamer->play_channel_run_master);
++ g_object_unref(streamer->stream_channel_run);
++
+ free(streamer);
+ }
+
+@@ -666,11 +709,19 @@
+ {
+ AgsPlayChannelRunMasterStreamer *streamer;
+
++ if(play_channel_run_master == NULL ||
++ stream_channel_run == NULL){
++ return;
++ }
++
+ streamer = (AgsPlayChannelRunMasterStreamer *) malloc(sizeof(AgsPlayChannelRunMasterStreamer));
+
+ streamer->play_channel_run_master = play_channel_run_master;
++ g_object_ref(play_channel_run_master);
++
+ streamer->stream_channel_run = stream_channel_run;
+-
++ g_object_ref(stream_channel_run);
++
+ return(streamer);
+ }
+
+--- a/ags/audio/recall/ags_play_notation_audio_run.c
++++ b/ags/audio/recall/ags_play_notation_audio_run.c
+@@ -57,6 +57,7 @@
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec);
++void ags_play_notation_audio_run_dispose(GObject *gobject);
+ void ags_play_notation_audio_run_finalize(GObject *gobject);
+ void ags_play_notation_audio_run_connect(AgsConnectable *connectable);
+ void ags_play_notation_audio_run_disconnect(AgsConnectable *connectable);
+@@ -94,6 +95,7 @@
+ PROP_0,
+ PROP_DELAY_AUDIO_RUN,
+ PROP_COUNT_BEATS_AUDIO_RUN,
++ PROP_NOTATION,
+ };
+
+ static gpointer ags_play_notation_audio_run_parent_class = NULL;
+@@ -173,9 +175,17 @@
+ gobject->set_property = ags_play_notation_audio_run_set_property;
+ gobject->get_property = ags_play_notation_audio_run_get_property;
+
++ gobject->dispose = ags_play_notation_audio_run_dispose;
+ gobject->finalize = ags_play_notation_audio_run_finalize;
+
+ /* properties */
++ /**
++ * AgsPlayNotationAudioRun:delay-audio-run:
++ *
++ * The delay audio run dependency.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("delay-audio-run\0",
+ "assigned AgsDelayAudioRun\0",
+ "the AgsDelayAudioRun which emits notation_alloc_input signal\0",
+@@ -185,6 +195,13 @@
+ PROP_DELAY_AUDIO_RUN,
+ param_spec);
+
++ /**
++ * AgsPlayNotationAudioRun:count-beats-audio-run:
++ *
++ * The count beats audio run dependency.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("count-beats-audio-run\0",
+ "assigned AgsCountBeatsAudioRun\0",
+ "the AgsCountBeatsAudioRun which just counts\0",
+@@ -194,6 +211,22 @@
+ PROP_COUNT_BEATS_AUDIO_RUN,
+ param_spec);
+
++ /**
++ * AgsPlayNotationAudioRun:notation:
++ *
++ * The notation containing the notes.
++ *
++ * Since: 0.7.122.7
++ */
++ param_spec = g_param_spec_object("notation\0",
++ "assigned AgsNotation\0",
++ "The AgsNotation containing notes\0",
++ AGS_TYPE_NOTATION,
++ G_PARAM_READABLE | G_PARAM_WRITABLE);
++ g_object_class_install_property(gobject,
++ PROP_NOTATION,
++ param_spec);
++
+ /* AgsRecallClass */
+ recall = (AgsRecallClass *) play_notation_audio_run;
+
+@@ -346,6 +379,27 @@
+ play_notation_audio_run->count_beats_audio_run = count_beats_audio_run;
+ }
+ break;
++ case PROP_NOTATION:
++ {
++ AgsNotation *notation;
++
++ notation = (AgsNotation *) g_value_get_object(value);
++
++ if(play_notation_audio_run->notation == notation){
++ return;
++ }
++
++ if(play_notation_audio_run->notation != NULL){
++ g_object_unref(play_notation_audio_run->notation);
++ }
++
++ if(notation != NULL){
++ g_object_ref(notation);
++ }
++
++ play_notation_audio_run->notation = notation;
++ }
++ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+ break;
+@@ -373,6 +427,11 @@
+ g_value_set_object(value, G_OBJECT(play_notation_audio_run->count_beats_audio_run));
+ }
+ break;
++ case PROP_NOTATION:
++ {
++ g_value_set_object(value, play_notation_audio_run->notation);
++ }
++ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+ break;
+@@ -380,20 +439,60 @@
+ }
+
+ void
++ags_play_notation_audio_run_dispose(GObject *gobject)
++{
++ AgsPlayNotationAudioRun *play_notation_audio_run;
++
++ play_notation_audio_run = AGS_PLAY_NOTATION_AUDIO_RUN(gobject);
++
++ /* delay audio run */
++ if(play_notation_audio_run->delay_audio_run != NULL){
++ g_object_unref(G_OBJECT(play_notation_audio_run->delay_audio_run));
++
++ play_notation_audio_run->delay_audio_run = NULL;
++ }
++
++ /* count beats audio run */
++ if(play_notation_audio_run->count_beats_audio_run != NULL){
++ g_object_unref(G_OBJECT(play_notation_audio_run->count_beats_audio_run));
++
++ play_notation_audio_run->count_beats_audio_run = NULL;
++ }
++
++ /* notation */
++ if(play_notation_audio_run->notation != NULL){
++ g_object_unref(G_OBJECT(play_notation_audio_run->notation));
++
++ play_notation_audio_run->notation = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_play_notation_audio_run_parent_class)->dispose(gobject);
++}
++
++void
+ ags_play_notation_audio_run_finalize(GObject *gobject)
+ {
+ AgsPlayNotationAudioRun *play_notation_audio_run;
+
+ play_notation_audio_run = AGS_PLAY_NOTATION_AUDIO_RUN(gobject);
+
++ /* delay audio run */
+ if(play_notation_audio_run->delay_audio_run != NULL){
+ g_object_unref(G_OBJECT(play_notation_audio_run->delay_audio_run));
+ }
+
++ /* count beats audio run */
+ if(play_notation_audio_run->count_beats_audio_run != NULL){
+ g_object_unref(G_OBJECT(play_notation_audio_run->count_beats_audio_run));
+ }
+
++ /* notation */
++ if(play_notation_audio_run->notation != NULL){
++ g_object_unref(G_OBJECT(play_notation_audio_run->notation));
++ }
++
++ /* call parent */
+ G_OBJECT_CLASS(ags_play_notation_audio_run_parent_class)->finalize(gobject);
+ }
+
+@@ -911,7 +1010,7 @@
+
+ ags_recycling_add_audio_signal(recycling,
+ audio_signal);
+- g_object_unref(audio_signal);
++ // g_object_unref(audio_signal);
+
+ /* iterate */
+ recycling = recycling->next;
+--- a/ags/audio/recall/ags_record_midi_audio.c
++++ b/ags/audio/recall/ags_record_midi_audio.c
+@@ -32,6 +32,7 @@
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec);
++void ags_record_midi_audio_dispose(GObject *gobject);
+ void ags_record_midi_audio_finalize(GObject *gobject);
+ void ags_record_midi_audio_set_ports(AgsPlugin *plugin, GList *port);
+
+@@ -127,9 +128,17 @@
+ gobject->set_property = ags_record_midi_audio_set_property;
+ gobject->get_property = ags_record_midi_audio_get_property;
+
++ gobject->dispose = ags_record_midi_audio_dispose;
+ gobject->finalize = ags_record_midi_audio_finalize;
+
+ /* properties */
++ /**
++ * AgsRecordMidiAudio:playback:
++ *
++ * The playback port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("playback\0",
+ "if do playback\0",
+ "If playback should be performed\0",
+@@ -139,6 +148,13 @@
+ PROP_PLAYBACK,
+ param_spec);
+
++ /**
++ * AgsRecordMidiAudio:record:
++ *
++ * The record port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("record\0",
+ "if do record\0",
+ "If record data for later use should be done\0",
+@@ -148,6 +164,13 @@
+ PROP_RECORD,
+ param_spec);
+
++ /**
++ * AgsRecordMidiAudio:filename:
++ *
++ * The filename port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("filename\0",
+ "filename of record\0",
+ "The filename of record\0",
+@@ -157,6 +180,13 @@
+ PROP_FILENAME,
+ param_spec);
+
++ /**
++ * AgsRecordMidiAudio:division:
++ *
++ * The division port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("division\0",
+ "division of record\0",
+ "The division of record\0",
+@@ -166,6 +196,13 @@
+ PROP_DIVISION,
+ param_spec);
+
++ /**
++ * AgsRecordMidiAudio:tempo:
++ *
++ * The tempo port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("tempo\0",
+ "tempo of record\0",
+ "The tempo of record\0",
+@@ -175,6 +212,13 @@
+ PROP_TEMPO,
+ param_spec);
+
++ /**
++ * AgsRecordMidiAudio:bpm:
++ *
++ * The bpm port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("bpm\0",
+ "bpm of record\0",
+ "The bpm of record\0",
+@@ -213,11 +257,14 @@
+ "port-value-is-pointer\0", FALSE,
+ "port-value-type\0", G_TYPE_BOOLEAN,
+ NULL);
+-
++ g_object_ref(record_midi_audio->playback);
++
+ record_midi_audio->playback->port_value.ags_port_boolean = TRUE;
+
++ /* add to port */
+ port = g_list_prepend(port, record_midi_audio->playback);
+-
++ g_object_ref(record_midi_audio->playback);
++
+ /* record */
+ record_midi_audio->record = g_object_new(AGS_TYPE_PORT,
+ "plugin-name\0", ags_record_midi_audio_plugin_name,
+@@ -226,10 +273,13 @@
+ "port-value-is-pointer\0", FALSE,
+ "port-value-type\0", G_TYPE_BOOLEAN,
+ NULL);
+-
++ g_object_ref(record_midi_audio->record);
++
+ record_midi_audio->record->port_value.ags_port_boolean = FALSE;
+
++ /* add to port */
+ port = g_list_prepend(port, record_midi_audio->record);
++ g_object_ref(record_midi_audio->record);
+
+ /* filename */
+ record_midi_audio->filename = g_object_new(AGS_TYPE_PORT,
+@@ -239,10 +289,13 @@
+ "port-value-is-pointer\0", FALSE,
+ "port-value-type\0", G_TYPE_BOOLEAN,
+ NULL);
++ g_object_ref(record_midi_audio->filename);
+
+ record_midi_audio->filename->port_value.ags_port_boolean = TRUE;
+
++ /* add to port */
+ port = g_list_prepend(port, record_midi_audio->filename);
++ g_object_ref(record_midi_audio->filename);
+
+ /* division */
+ record_midi_audio->division = g_object_new(AGS_TYPE_PORT,
+@@ -252,10 +305,13 @@
+ "port-value-is-pointer\0", FALSE,
+ "port-value-type\0", G_TYPE_INT64,
+ NULL);
++ g_object_ref(record_midi_audio->division);
+
+ record_midi_audio->division->port_value.ags_port_int = 0;
+
++ /* add to port */
+ port = g_list_prepend(port, record_midi_audio->division);
++ g_object_ref(record_midi_audio->division);
+
+ /* tempo */
+ record_midi_audio->tempo = g_object_new(AGS_TYPE_PORT,
+@@ -265,10 +321,13 @@
+ "port-value-is-pointer\0", FALSE,
+ "port-value-type\0", G_TYPE_INT64,
+ NULL);
++ g_object_ref(record_midi_audio->tempo);
+
+ record_midi_audio->tempo->port_value.ags_port_int = 0;
+
++ /* add to port */
+ port = g_list_prepend(port, record_midi_audio->tempo);
++ g_object_ref(record_midi_audio->tempo);
+
+ /* bpm */
+ record_midi_audio->bpm = g_object_new(AGS_TYPE_PORT,
+@@ -278,10 +337,13 @@
+ "port-value-is-pointer\0", FALSE,
+ "port-value-type\0", G_TYPE_INT64,
+ NULL);
++ g_object_ref(record_midi_audio->bpm);
+
+ record_midi_audio->bpm->port_value.ags_port_int = 120;
+
++ /* add to port */
+ port = g_list_prepend(port, record_midi_audio->bpm);
++ g_object_ref(record_midi_audio->bpm);
+
+ /* set port */
+ AGS_RECALL(record_midi_audio)->port = port;
+@@ -478,12 +540,95 @@
+ }
+
+ void
++ags_record_midi_audio_dispose(GObject *gobject)
++{
++ AgsRecordMidiAudio *record_midi_audio;
++
++ record_midi_audio = AGS_RECORD_MIDI_AUDIO(gobject);
++
++ /* playback */
++ if(record_midi_audio->playback != NULL){
++ g_object_unref(record_midi_audio->playback);
++
++ record_midi_audio->playback = NULL;
++ }
++
++ /* record */
++ if(record_midi_audio->record != NULL){
++ g_object_unref(record_midi_audio->record);
++
++ record_midi_audio->record = NULL;
++ }
++
++ /* filename */
++ if(record_midi_audio->filename != NULL){
++ g_object_unref(record_midi_audio->filename);
++
++ record_midi_audio->filename = NULL;
++ }
++
++ /* division */
++ if(record_midi_audio->division != NULL){
++ g_object_unref(record_midi_audio->division);
++
++ record_midi_audio->division = NULL;
++ }
++
++ /* tempo */
++ if(record_midi_audio->tempo != NULL){
++ g_object_unref(record_midi_audio->tempo);
++
++ record_midi_audio->tempo = NULL;
++ }
++
++ /* bpm */
++ if(record_midi_audio->bpm != NULL){
++ g_object_unref(record_midi_audio->bpm);
++
++ record_midi_audio->bpm = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_record_midi_audio_parent_class)->dispose(gobject);
++}
++
++void
+ ags_record_midi_audio_finalize(GObject *gobject)
+ {
+ AgsRecordMidiAudio *record_midi_audio;
+
+ record_midi_audio = AGS_RECORD_MIDI_AUDIO(gobject);
+
++ /* playback */
++ if(record_midi_audio->playback != NULL){
++ g_object_unref(record_midi_audio->playback);
++ }
++
++ /* record */
++ if(record_midi_audio->record != NULL){
++ g_object_unref(record_midi_audio->record);
++ }
++
++ /* filename */
++ if(record_midi_audio->filename != NULL){
++ g_object_unref(record_midi_audio->filename);
++ }
++
++ /* division */
++ if(record_midi_audio->division != NULL){
++ g_object_unref(record_midi_audio->division);
++ }
++
++ /* tempo */
++ if(record_midi_audio->tempo != NULL){
++ g_object_unref(record_midi_audio->tempo);
++ }
++
++ /* bpm */
++ if(record_midi_audio->bpm != NULL){
++ g_object_unref(record_midi_audio->bpm);
++ }
++
+ /* call parent */
+ G_OBJECT_CLASS(ags_record_midi_audio_parent_class)->finalize(gobject);
+ }
+--- a/ags/audio/recall/ags_route_dssi_audio.c
++++ b/ags/audio/recall/ags_route_dssi_audio.c
+@@ -34,6 +34,7 @@
+ GValue *value,
+ GParamSpec *param_spec);
+ void ags_route_dssi_audio_set_ports(AgsPlugin *plugin, GList *port);
++void ags_route_dssi_audio_dispose(GObject *gobject);
+ void ags_route_dssi_audio_finalize(GObject *gobject);
+
+ /**
+@@ -120,6 +121,7 @@
+ gobject->set_property = ags_route_dssi_audio_set_property;
+ gobject->get_property = ags_route_dssi_audio_get_property;
+
++ gobject->dispose = ags_route_dssi_audio_dispose;
+ gobject->finalize = ags_route_dssi_audio_finalize;
+
+ /* properties */
+@@ -178,10 +180,13 @@
+ "port-value-size\0", sizeof(gboolean),
+ "port-value-length", 1,
+ NULL);
+-
++ g_object_ref(route_dssi_audio->notation_input);
++
+ route_dssi_audio->notation_input->port_value.ags_port_boolean = FALSE;
+
++ /* add to port */
+ port = g_list_prepend(port, route_dssi_audio->notation_input);
++ g_object_ref(route_dssi_audio->notation_input);
+
+ /* sequencer input */
+ route_dssi_audio->sequencer_input = g_object_new(AGS_TYPE_PORT,
+@@ -193,10 +198,13 @@
+ "port-value-size\0", sizeof(gboolean),
+ "port-value-length", 1,
+ NULL);
++ g_object_ref(route_dssi_audio->sequencer_input);
+
+ route_dssi_audio->sequencer_input->port_value.ags_port_boolean = FALSE;
+
++ /* add to port */
+ port = g_list_prepend(port, route_dssi_audio->sequencer_input);
++ g_object_ref(route_dssi_audio->sequencer_input);
+
+ /* port */
+ AGS_RECALL(route_dssi_audio)->port = port;
+@@ -311,6 +319,31 @@
+ }
+
+ void
++ags_route_dssi_audio_dispose(GObject *gobject)
++{
++ AgsRouteDssiAudio *route_dssi_audio;
++
++ route_dssi_audio = AGS_ROUTE_DSSI_AUDIO(gobject);
++
++ /* notation input */
++ if(route_dssi_audio->notation_input != NULL){
++ g_object_unref(G_OBJECT(route_dssi_audio->notation_input));
++
++ route_dssi_audio->notation_input = NULL;
++ }
++
++ /* sequencer input */
++ if(route_dssi_audio->sequencer_input != NULL){
++ g_object_unref(G_OBJECT(route_dssi_audio->sequencer_input));
++
++ route_dssi_audio->sequencer_input = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_route_dssi_audio_parent_class)->dispose(gobject);
++}
++
++void
+ ags_route_dssi_audio_finalize(GObject *gobject)
+ {
+ AgsRouteDssiAudio *route_dssi_audio;
+--- a/ags/audio/recall/ags_route_dssi_audio_run.c
++++ b/ags/audio/recall/ags_route_dssi_audio_run.c
+@@ -63,6 +63,7 @@
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec);
++void ags_route_dssi_audio_run_dispose(GObject *gobject);
+ void ags_route_dssi_audio_run_finalize(GObject *gobject);
+ void ags_route_dssi_audio_run_connect(AgsConnectable *connectable);
+ void ags_route_dssi_audio_run_disconnect(AgsConnectable *connectable);
+@@ -211,9 +212,17 @@
+ gobject->set_property = ags_route_dssi_audio_run_set_property;
+ gobject->get_property = ags_route_dssi_audio_run_get_property;
+
++ gobject->dispose = ags_route_dssi_audio_run_dispose;
+ gobject->finalize = ags_route_dssi_audio_run_finalize;
+
+ /* properties */
++ /**
++ * AgsRouteDssiAudioRun:delay-audio-run:
++ *
++ * The delay audio run dependency.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("delay-audio-run\0",
+ "assigned AgsDelayAudioRun\0",
+ "the AgsDelayAudioRun which emits notation_alloc_input signal\0",
+@@ -223,6 +232,13 @@
+ PROP_DELAY_AUDIO_RUN,
+ param_spec);
+
++ /**
++ * AgsRouteDssiAudioRun:count-beats-audio-run:
++ *
++ * The count beats audio run dependency.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("count-beats-audio-run\0",
+ "assigned AgsCountBeatsAudioRun\0",
+ "the AgsCountBeatsAudioRun which just counts\0",
+@@ -392,20 +408,48 @@
+ }
+
+ void
++ags_route_dssi_audio_run_dispose(GObject *gobject)
++{
++ AgsRouteDssiAudioRun *route_dssi_audio_run;
++
++ route_dssi_audio_run = AGS_ROUTE_DSSI_AUDIO_RUN(gobject);
++
++ /* delay audio run */
++ if(route_dssi_audio_run->delay_audio_run != NULL){
++ g_object_unref(G_OBJECT(route_dssi_audio_run->delay_audio_run));
++
++ route_dssi_audio_run->delay_audio_run = NULL;
++ }
++
++ /* count beats audio run */
++ if(route_dssi_audio_run->count_beats_audio_run != NULL){
++ g_object_unref(G_OBJECT(route_dssi_audio_run->count_beats_audio_run));
++
++ route_dssi_audio_run->count_beats_audio_run = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_route_dssi_audio_run_parent_class)->finalize(gobject);
++}
++
++void
+ ags_route_dssi_audio_run_finalize(GObject *gobject)
+ {
+ AgsRouteDssiAudioRun *route_dssi_audio_run;
+
+ route_dssi_audio_run = AGS_ROUTE_DSSI_AUDIO_RUN(gobject);
+
++ /* delay audio run */
+ if(route_dssi_audio_run->delay_audio_run != NULL){
+ g_object_unref(G_OBJECT(route_dssi_audio_run->delay_audio_run));
+ }
+
++ /* count beats audio run */
+ if(route_dssi_audio_run->count_beats_audio_run != NULL){
+ g_object_unref(G_OBJECT(route_dssi_audio_run->count_beats_audio_run));
+ }
+
++ /* call parent */
+ G_OBJECT_CLASS(ags_route_dssi_audio_run_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/audio/recall/ags_route_lv2_audio.c
++++ b/ags/audio/recall/ags_route_lv2_audio.c
+@@ -34,6 +34,7 @@
+ GValue *value,
+ GParamSpec *param_spec);
+ void ags_route_lv2_audio_set_ports(AgsPlugin *plugin, GList *port);
++void ags_route_lv2_audio_dispose(GObject *gobject);
+ void ags_route_lv2_audio_finalize(GObject *gobject);
+
+ /**
+@@ -120,6 +121,7 @@
+ gobject->set_property = ags_route_lv2_audio_set_property;
+ gobject->get_property = ags_route_lv2_audio_get_property;
+
++ gobject->dispose = ags_route_lv2_audio_dispose;
+ gobject->finalize = ags_route_lv2_audio_finalize;
+
+ /* properties */
+@@ -178,10 +180,13 @@
+ "port-value-size\0", sizeof(gboolean),
+ "port-value-length", 1,
+ NULL);
+-
++ g_object_ref(route_lv2_audio->notation_input);
++
+ route_lv2_audio->notation_input->port_value.ags_port_boolean = FALSE;
+
++ /* add to port */
+ port = g_list_prepend(port, route_lv2_audio->notation_input);
++ g_object_ref(route_lv2_audio->notation_input);
+
+ /* sequencer input */
+ route_lv2_audio->sequencer_input = g_object_new(AGS_TYPE_PORT,
+@@ -193,12 +198,15 @@
+ "port-value-size\0", sizeof(gboolean),
+ "port-value-length", 1,
+ NULL);
++ g_object_ref(route_lv2_audio->sequencer_input);
+
+ route_lv2_audio->sequencer_input->port_value.ags_port_boolean = FALSE;
+
++ /* add to port */
+ port = g_list_prepend(port, route_lv2_audio->sequencer_input);
++ g_object_ref(route_lv2_audio->sequencer_input);
+
+- /* port */
++ /* set port */
+ AGS_RECALL(route_lv2_audio)->port = port;
+ }
+
+@@ -311,16 +319,43 @@
+ }
+
+ void
++ags_route_lv2_audio_dispose(GObject *gobject)
++{
++ AgsRouteLv2Audio *route_lv2_audio;
++
++ route_lv2_audio = AGS_ROUTE_LV2_AUDIO(gobject);
++
++ /* notation input */
++ if(route_lv2_audio->notation_input != NULL){
++ g_object_unref(G_OBJECT(route_lv2_audio->notation_input));
++
++ route_lv2_audio->notation_input = NULL;
++ }
++
++ /* sequencer input */
++ if(route_lv2_audio->sequencer_input != NULL){
++ g_object_unref(G_OBJECT(route_lv2_audio->sequencer_input));
++
++ route_lv2_audio->sequencer_input = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_route_lv2_audio_parent_class)->dispose(gobject);
++}
++
++void
+ ags_route_lv2_audio_finalize(GObject *gobject)
+ {
+ AgsRouteLv2Audio *route_lv2_audio;
+
+ route_lv2_audio = AGS_ROUTE_LV2_AUDIO(gobject);
+
++ /* notation input */
+ if(route_lv2_audio->notation_input != NULL){
+ g_object_unref(G_OBJECT(route_lv2_audio->notation_input));
+ }
+
++ /* sequencer input */
+ if(route_lv2_audio->sequencer_input != NULL){
+ g_object_unref(G_OBJECT(route_lv2_audio->sequencer_input));
+ }
+--- a/ags/audio/recall/ags_stream_audio_signal.c
++++ b/ags/audio/recall/ags_stream_audio_signal.c
+@@ -37,6 +37,7 @@
+ void ags_stream_audio_signal_disconnect(AgsConnectable *connectable);
+ void ags_stream_audio_signal_connect_dynamic(AgsDynamicConnectable *dynamic_connectable);
+ void ags_stream_audio_signal_disconnect_dynamic(AgsDynamicConnectable *dynamic_connectable);
++void ags_stream_audio_signal_dispose(GObject *gobject);
+ void ags_stream_audio_signal_finalize(GObject *gobject);
+
+ void ags_stream_audio_signal_run_init_pre(AgsRecall *recall);
+@@ -118,6 +119,7 @@
+ /* GObjectClass */
+ gobject = (GObjectClass *) stream_audio_signal;
+
++ gobject->dispose = ags_stream_audio_signal_dispose;
+ gobject->finalize = ags_stream_audio_signal_finalize;
+
+ /* AgsRecallClass */
+@@ -156,15 +158,33 @@
+ AGS_RECALL(stream_audio_signal)->port = NULL;
+
+ AGS_RECALL(stream_audio_signal)->child_type = G_TYPE_NONE;
++
++ stream_audio_signal->dispose_source = NULL;
++}
++
++void
++ags_stream_audio_signal_dispose(GObject *gobject)
++{
++ AGS_STREAM_AUDIO_SIGNAL(gobject)->dispose_source = AGS_RECALL_AUDIO_SIGNAL(gobject)->source;
++ /* call parent */
++ G_OBJECT_CLASS(ags_stream_audio_signal_parent_class)->dispose(gobject);
+ }
+
+ void
+ ags_stream_audio_signal_finalize(GObject *gobject)
+ {
+- if(AGS_RECALL_AUDIO_SIGNAL(gobject)->source != NULL &&
+- AGS_RECALL_AUDIO_SIGNAL(gobject)->source->recycling != NULL){
+- ags_recycling_remove_audio_signal((AgsRecycling *) AGS_RECALL_AUDIO_SIGNAL(gobject)->source->recycling,
+- AGS_RECALL_AUDIO_SIGNAL(gobject)->source);
++ if(AGS_STREAM_AUDIO_SIGNAL(gobject)->dispose_source != NULL &&
++ AGS_AUDIO_SIGNAL(AGS_STREAM_AUDIO_SIGNAL(gobject)->dispose_source)->recycling != NULL){
++ AgsRecycling *recycling;
++ AgsAudioSignal *audio_signal;
++
++ recycling = AGS_AUDIO_SIGNAL(AGS_STREAM_AUDIO_SIGNAL(gobject)->dispose_source)->recycling;
++ audio_signal = AGS_STREAM_AUDIO_SIGNAL(gobject)->dispose_source;
++
++ ags_recycling_remove_audio_signal(recycling,
++ audio_signal);
++ g_object_run_dispose(audio_signal);
++ g_object_unref(audio_signal);
+ }
+
+ /* call parent */
+--- a/ags/audio/recall/ags_stream_audio_signal.h
++++ b/ags/audio/recall/ags_stream_audio_signal.h
+@@ -38,6 +38,8 @@
+ struct _AgsStreamAudioSignal
+ {
+ AgsRecallAudioSignal recall_audio_signal;
++
++ GObject *dispose_source;
+ };
+
+ struct _AgsStreamAudioSignalClass
+--- a/ags/audio/recall/ags_stream_channel.c
++++ b/ags/audio/recall/ags_stream_channel.c
+@@ -38,6 +38,7 @@
+ void ags_stream_channel_connect(AgsConnectable *connectable);
+ void ags_stream_channel_disconnect(AgsConnectable *connectable);
+ void ags_stream_channel_set_ports(AgsPlugin *plugin, GList *port);
++void ags_stream_channel_dispose(GObject *gobject);
+ void ags_stream_channel_finalize(GObject *gobject);
+
+ /**
+@@ -129,9 +130,17 @@
+ gobject->set_property = ags_stream_channel_set_property;
+ gobject->get_property = ags_stream_channel_get_property;
+
++ gobject->dispose = ags_stream_channel_dispose;
+ gobject->finalize = ags_stream_channel_finalize;
+
+ /* properties */
++ /**
++ * AgsStreamChannel:auto-sense:
++ *
++ * The auto-sense port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("auto-sense\0",
+ "mute channel\0",
+ "Mute the channel\0",
+@@ -174,8 +183,10 @@
+ AGS_RECALL(stream_channel)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
+ AGS_RECALL(stream_channel)->xml_type = "ags-stream-channel\0";
+
++ /* initialize port */
+ port = NULL;
+
++ /* auto-sense */
+ stream_channel->auto_sense = g_object_new(AGS_TYPE_PORT,
+ "plugin-name\0", ags_stream_channel_plugin_name,
+ "specifier\0", ags_stream_channel_plugin_specifier[0],
+@@ -185,7 +196,8 @@
+ "port-value-size\0", sizeof(gboolean),
+ "port-value-length\0", 1,
+ NULL);
+-
++ g_object_ref(stream_channel->auto_sense);
++
+ config = ags_config_get_instance();
+
+ str = ags_config_get_value(config,
+@@ -194,9 +206,11 @@
+ stream_channel->auto_sense->port_value.ags_port_boolean = ((!g_strcmp0(str, "true\0")
+ ) ? TRUE: FALSE);
+ free(str);
+-
+- port = g_list_prepend(port, stream_channel->auto_sense);
+
++ /* add to port */
++ port = g_list_prepend(port, stream_channel->auto_sense);
++ g_object_ref(stream_channel->auto_sense);
++
+ /* set port */
+ AGS_RECALL(stream_channel)->port = port;
+
+@@ -264,12 +278,31 @@
+ }
+
+ void
++ags_stream_channel_dispose(GObject *gobject)
++{
++ AgsStreamChannel *stream_channel;
++
++ stream_channel = AGS_STREAM_CHANNEL(gobject);
++
++ /* auto-sense */
++ if(stream_channel->auto_sense != NULL){
++ g_object_unref(G_OBJECT(stream_channel->auto_sense));
++
++ stream_channel->auto_sense = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_stream_channel_parent_class)->dispose(gobject);
++}
++
++void
+ ags_stream_channel_finalize(GObject *gobject)
+ {
+ AgsStreamChannel *stream_channel;
+
+ stream_channel = AGS_STREAM_CHANNEL(gobject);
+
++ /* auto-sense */
+ if(stream_channel->auto_sense != NULL){
+ g_object_unref(G_OBJECT(stream_channel->auto_sense));
+ }
+--- a/ags/audio/recall/ags_volume_channel.c
++++ b/ags/audio/recall/ags_volume_channel.c
+@@ -38,6 +38,7 @@
+ void ags_volume_channel_connect(AgsConnectable *connectable);
+ void ags_volume_channel_disconnect(AgsConnectable *connectable);
+ void ags_volume_channel_set_ports(AgsPlugin *plugin, GList *port);
++void ags_volume_channel_dispose(GObject *gobject);
+ void ags_volume_channel_finalize(GObject *gobject);
+
+ /**
+@@ -143,9 +144,17 @@
+ gobject->set_property = ags_volume_channel_set_property;
+ gobject->get_property = ags_volume_channel_get_property;
+
++ gobject->dispose = ags_volume_channel_dispose;
+ gobject->finalize = ags_volume_channel_finalize;
+
+ /* properties */
++ /**
++ * AgsVolumeChannel:volume:
++ *
++ * The volume port.
++ *
++ * Since: 0.7.122.7
++ */
+ param_spec = g_param_spec_object("volume\0",
+ "volume to apply\0",
+ "The volume to apply on the channel\0",
+@@ -166,6 +175,7 @@
+ AGS_RECALL(volume_channel)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
+ AGS_RECALL(volume_channel)->xml_type = "ags-volume-channel\0";
+
++ /* initialize the port */
+ port = NULL;
+
+ /* volume */
+@@ -179,9 +189,11 @@
+ "port-value-length", 1,
+ NULL);
+
++ g_object_ref(volume_channel->volume);
+ volume_channel->volume->port_value.ags_port_double = 1.0;
+
+ port = g_list_prepend(port, volume_channel->volume);
++ g_object_ref(volume_channel->volume);
+
+ AGS_RECALL(volume_channel)->port = port;
+ }
+@@ -279,12 +291,29 @@
+ }
+
+ void
++ags_volume_channel_dispose(GObject *gobject)
++{
++ AgsVolumeChannel *volume_channel;
++
++ volume_channel = AGS_VOLUME_CHANNEL(gobject);
++
++ /* volume */
++ if(volume_channel->volume != NULL){
++ g_object_unref(G_OBJECT(volume_channel->volume));
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_volume_channel_parent_class)->dispose(gobject);
++}
++
++void
+ ags_volume_channel_finalize(GObject *gobject)
+ {
+ AgsVolumeChannel *volume_channel;
+
+ volume_channel = AGS_VOLUME_CHANNEL(gobject);
+
++ /* volume */
+ if(volume_channel->volume != NULL){
+ g_object_unref(G_OBJECT(volume_channel->volume));
+ }
+--- a/ags/audio/task/ags_remove_audio.c
++++ b/ags/audio/task/ags_remove_audio.c
+@@ -314,6 +314,7 @@
+ ags_soundcard_set_audio(AGS_SOUNDCARD(remove_audio->soundcard),
+ list);
+
++ g_object_run_dispose(remove_audio->audio);
+ g_object_unref(remove_audio->audio);
+ }
+
+--- a/ags/audio/thread/ags_audio_thread.c
++++ b/ags/audio/thread/ags_audio_thread.c
+@@ -47,6 +47,7 @@
+ GParamSpec *param_spec);
+ void ags_audio_thread_connect(AgsConnectable *connectable);
+ void ags_audio_thread_disconnect(AgsConnectable *connectable);
++void ags_audio_thread_dispose(GObject *gobject);
+ void ags_audio_thread_finalize(GObject *gobject);
+
+ void ags_audio_thread_start(AgsThread *thread);
+@@ -127,6 +128,7 @@
+ gobject->set_property = ags_audio_thread_set_property;
+ gobject->get_property = ags_audio_thread_get_property;
+
++ gobject->dispose = ags_audio_thread_dispose;
+ gobject->finalize = ags_audio_thread_finalize;
+
+ /* properties */
+@@ -367,11 +369,63 @@
+ }
+
+ void
++ags_audio_thread_dispose(GObject *gobject)
++{
++ AgsAudioThread *audio_thread;
++
++ audio_thread = AGS_AUDIO_THREAD(gobject);
++
++ /* soundcard */
++ if(audio_thread->soundcard != NULL){
++ g_object_unref(audio_thread->soundcard);
++
++ audio_thread->soundcard = NULL;
++ }
++
++ /* audio */
++ if(audio_thread->audio != NULL){
++ g_object_unref(audio_thread->audio);
++
++ audio_thread->audio = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_audio_thread_parent_class)->dispose(gobject);
++}
++
++void
+ ags_audio_thread_finalize(GObject *gobject)
+ {
+- G_OBJECT_CLASS(ags_audio_thread_parent_class)->finalize(gobject);
++ AgsAudioThread *audio_thread;
+
+- /* empty */
++ audio_thread = AGS_AUDIO_THREAD(gobject);
++
++ /* soundcard */
++ if(audio_thread->soundcard != NULL){
++ g_object_unref(audio_thread->soundcard);
++ }
++
++ /* wakeup mutex and cond */
++ pthread_mutex_destroy(audio_thread->wakeup_mutex);
++ free(audio_thread->wakeup_mutex);
++
++ pthread_mutex_destroy(audio_thread->wakeup_cond);
++ free(audio_thread->wakeup_cond);
++
++ /* sync mutex and cond */
++ pthread_mutex_destroy(audio_thread->done_mutex);
++ free(audio_thread->done_mutex);
++
++ pthread_mutex_destroy(audio_thread->done_cond);
++ free(audio_thread->done_cond);
++
++ /* audio */
++ if(audio_thread->audio != NULL){
++ g_object_unref(audio_thread->audio);
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_audio_thread_parent_class)->finalize(gobject);
+ }
+
+ void
+--- a/ags/audio/thread/ags_channel_thread.c
++++ b/ags/audio/thread/ags_channel_thread.c
+@@ -43,6 +43,7 @@
+ GParamSpec *param_spec);
+ void ags_channel_thread_connect(AgsConnectable *connectable);
+ void ags_channel_thread_disconnect(AgsConnectable *connectable);
++void ags_channel_thread_dispose(GObject *gobject);
+ void ags_channel_thread_finalize(GObject *gobject);
+
+ void ags_channel_thread_start(AgsThread *thread);
+@@ -120,6 +121,7 @@
+ gobject->set_property = ags_channel_thread_set_property;
+ gobject->get_property = ags_channel_thread_get_property;
+
++ gobject->dispose = ags_channel_thread_dispose;
+ gobject->finalize = ags_channel_thread_finalize;
+
+ /* properties */
+@@ -360,11 +362,63 @@
+ }
+
+ void
++ags_channel_thread_dispose(GObject *gobject)
++{
++ AgsChannelThread *channel_thread;
++
++ channel_thread = AGS_CHANNEL_THREAD(gobject);
++
++ /* soundcard */
++ if(channel_thread->soundcard != NULL){
++ g_object_unref(channel_thread->soundcard);
++
++ channel_thread->soundcard = NULL;
++ }
++
++ /* channel */
++ if(channel_thread->channel != NULL){
++ g_object_unref(channel_thread->channel);
++
++ channel_thread->channel = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_channel_thread_parent_class)->dispose(gobject);
++}
++
++void
+ ags_channel_thread_finalize(GObject *gobject)
+ {
+- G_OBJECT_CLASS(ags_channel_thread_parent_class)->finalize(gobject);
++ AgsChannelThread *channel_thread;
+
+- /* empty */
++ channel_thread = AGS_CHANNEL_THREAD(gobject);
++
++ /* soundcard */
++ if(channel_thread->soundcard != NULL){
++ g_object_unref(channel_thread->soundcard);
++ }
++
++ /* wakeup mutex and cond */
++ pthread_mutex_destroy(channel_thread->wakeup_mutex);
++ free(channel_thread->wakeup_mutex);
++
++ pthread_mutex_destroy(channel_thread->wakeup_cond);
++ free(channel_thread->wakeup_cond);
++
++ /* sync mutex and cond */
++ pthread_mutex_destroy(channel_thread->done_mutex);
++ free(channel_thread->done_mutex);
++
++ pthread_mutex_destroy(channel_thread->done_cond);
++ free(channel_thread->done_cond);
++
++ /* channel */
++ if(channel_thread->channel != NULL){
++ g_object_unref(channel_thread->channel);
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_channel_thread_parent_class)->finalize(gobject);
+ }
+
+ void
+--- a/ags/audio/thread/ags_sequencer_thread.c
++++ b/ags/audio/thread/ags_sequencer_thread.c
+@@ -47,6 +47,7 @@
+ GParamSpec *param_spec);
+ void ags_sequencer_thread_connect(AgsConnectable *connectable);
+ void ags_sequencer_thread_disconnect(AgsConnectable *connectable);
++void ags_sequencer_thread_dispose(GObject *gobject);
+ void ags_sequencer_thread_finalize(GObject *gobject);
+
+ void ags_sequencer_thread_start(AgsThread *thread);
+@@ -133,6 +134,7 @@
+ gobject->set_property = ags_sequencer_thread_set_property;
+ gobject->get_property = ags_sequencer_thread_get_property;
+
++ gobject->dispose = ags_sequencer_thread_dispose;
+ gobject->finalize = ags_sequencer_thread_finalize;
+
+ /**
+@@ -238,6 +240,7 @@
+
+ sequencer_thread->sequencer = NULL;
+
++ sequencer_thread->timestamp_thread = NULL;
+ // sequencer_thread->timestamp_thread = (AgsThread *) ags_timestamp_thread_new();
+ // ags_thread_add_child(thread, sequencer_thread->timestamp_thread);
+
+@@ -329,11 +332,37 @@
+ }
+
+ void
++ags_sequencer_thread_dispose(GObject *gobject)
++{
++ AgsSequencerThread *sequencer_thread;
++
++ sequencer_thread = AGS_SEQUENCER_THREAD(gobject);
++
++ /* sequencer */
++ if(sequencer_thread->sequencer != NULL){
++ g_object_unref(sequencer_thread->sequencer);
++
++ sequencer_thread->sequencer = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_sequencer_thread_parent_class)->dispose(gobject);
++}
++
++void
+ ags_sequencer_thread_finalize(GObject *gobject)
+ {
+- G_OBJECT_CLASS(ags_sequencer_thread_parent_class)->finalize(gobject);
++ AgsSequencerThread *sequencer_thread;
+
+- /* empty */
++ sequencer_thread = AGS_SEQUENCER_THREAD(gobject);
++
++ /* sequencer */
++ if(sequencer_thread->sequencer != NULL){
++ g_object_unref(sequencer_thread->sequencer);
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_sequencer_thread_parent_class)->finalize(gobject);
+ }
+
+ void
+--- a/ags/audio/thread/ags_soundcard_thread.c
++++ b/ags/audio/thread/ags_soundcard_thread.c
+@@ -48,6 +48,7 @@
+ GParamSpec *param_spec);
+ void ags_soundcard_thread_connect(AgsConnectable *connectable);
+ void ags_soundcard_thread_disconnect(AgsConnectable *connectable);
++void ags_soundcard_thread_dispose(GObject *gobject);
+ void ags_soundcard_thread_finalize(GObject *gobject);
+
+ void ags_soundcard_thread_start(AgsThread *thread);
+@@ -129,6 +130,7 @@
+ gobject->set_property = ags_soundcard_thread_set_property;
+ gobject->get_property = ags_soundcard_thread_get_property;
+
++ gobject->dispose = ags_soundcard_thread_dispose;
+ gobject->finalize = ags_soundcard_thread_finalize;
+
+ /**
+@@ -223,7 +225,8 @@
+ /* */
+ soundcard_thread->soundcard = NULL;
+
+- soundcard_thread->timestamp_thread = (AgsThread *) ags_timestamp_thread_new();
++ soundcard_thread->timestamp_thread = NULL;
++ // soundcard_thread->timestamp_thread = (AgsThread *) ags_timestamp_thread_new();
+ // ags_thread_add_child(thread, soundcard_thread->timestamp_thread);
+
+ soundcard_thread->error = NULL;
+@@ -330,11 +333,37 @@
+ }
+
+ void
++ags_soundcard_thread_dispose(GObject *gobject)
++{
++ AgsSoundcardThread *soundcard_thread;
++
++ soundcard_thread = AGS_SOUNDCARD_THREAD(gobject);
++
++ /* soundcard */
++ if(soundcard_thread->soundcard != NULL){
++ g_object_unref(soundcard_thread->soundcard);
++
++ soundcard_thread->soundcard = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_soundcard_thread_parent_class)->dispose(gobject);
++}
++
++void
+ ags_soundcard_thread_finalize(GObject *gobject)
+ {
+- G_OBJECT_CLASS(ags_soundcard_thread_parent_class)->finalize(gobject);
++ AgsSoundcardThread *soundcard_thread;
+
+- /* empty */
++ soundcard_thread = AGS_SOUNDCARD_THREAD(gobject);
++
++ /* soundcard */
++ if(soundcard_thread->soundcard != NULL){
++ g_object_unref(soundcard_thread->soundcard);
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_soundcard_thread_parent_class)->finalize(gobject);
+ }
+
+ void
+--- a/ags/gsequencer_main.c
++++ b/ags/gsequencer_main.c
+@@ -1271,8 +1271,8 @@
+ // g_thread_init(NULL);
+ gtk_init(&argc, &argv);
+ ipatch_init();
+- // g_log_set_fatal_mask("GLib-GObject\0", //G_LOG_DOMAIN,
+- // G_LOG_LEVEL_CRITICAL);
++ // g_log_set_fatal_mask("GLib-GObject\0", // "Gtk\0" G_LOG_DOMAIN, //
++ // G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
+
+ /* animate */
+ animation_thread = (pthread_t *) malloc(sizeof(pthread_t));
+--- a/ags/lib/ags_conversion.c
++++ b/ags/lib/ags_conversion.c
+@@ -261,6 +261,9 @@
+ if(conversion->description != NULL){
+ g_free(conversion->description);
+ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_conversion_parent_class)->finalize(gobject);
+ }
+
+ gdouble
+--- a/ags/lib/ags_function.c
++++ b/ags/lib/ags_function.c
+@@ -342,6 +342,9 @@
+
+ free(function->pivot_table);
+ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_function_parent_class)->finalize(gobject);
+ }
+
+ /**
+--- a/ags/lib/ags_log.c
++++ b/ags/lib/ags_log.c
+@@ -97,6 +97,7 @@
+ g_list_free_full(g_atomic_pointer_get(&(log->messages)),
+ g_free);
+
++ /* call parent */
+ G_OBJECT_CLASS(ags_log_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/lib/ags_turtle.c
++++ b/ags/lib/ags_turtle.c
+@@ -207,10 +207,14 @@
+
+ switch(prop_id){
+ case PROP_FILENAME:
+- g_value_set_string(value, turtle->filename);
++ {
++ g_value_set_string(value, turtle->filename);
++ }
+ break;
+ case PROP_XML_DOC:
+- g_value_set_pointer(value, turtle->doc);
++ {
++ g_value_set_pointer(value, turtle->doc);
++ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+@@ -225,6 +229,17 @@
+ gchar **str;
+
+ turtle = AGS_TURTLE(gobject);
++
++ if(turtle->filename != NULL){
++ g_free(turtle->filename);
++ }
++
++ if(turtle->doc != NULL){
++ xmlFreeDoc(turtle->doc);
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_turtle_parent_class)->finalize(gobject);
+ }
+
+ /**
+--- a/ags/lib/ags_turtle_manager.c
++++ b/ags/lib/ags_turtle_manager.c
+@@ -22,6 +22,7 @@
+
+ void ags_turtle_manager_class_init(AgsTurtleManagerClass *turtle_manager);
+ void ags_turtle_manager_init (AgsTurtleManager *turtle_manager);
++void ags_turtle_manager_dispose(GObject *gobject);
+ void ags_turtle_manager_finalize(GObject *gobject);
+
+ /**
+@@ -76,6 +77,7 @@
+ /* GObjectClass */
+ gobject = (GObjectClass *) turtle_manager;
+
++ gobject->dispose = ags_turtle_manager_dispose;
+ gobject->finalize = ags_turtle_manager_finalize;
+ }
+
+@@ -86,17 +88,42 @@
+ }
+
+ void
+-ags_turtle_manager_finalize(GObject *gobject)
++ags_turtle_manager_dispose(GObject *gobject)
+ {
+ AgsTurtleManager *turtle_manager;
++
+ GList *turtle;
+
+ turtle_manager = AGS_TURTLE_MANAGER(gobject);
+
+ turtle = turtle_manager->turtle;
+-
++ turtle_manager->turtle = NULL;
++
+ g_list_free_full(turtle,
+ g_object_unref);
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_turtle_manager_parent_class)->dispose(gobject);
++}
++
++void
++ags_turtle_manager_finalize(GObject *gobject)
++{
++ AgsTurtleManager *turtle_manager;
++
++ GList *turtle;
++
++ turtle_manager = AGS_TURTLE_MANAGER(gobject);
++
++ turtle = turtle_manager->turtle;
++
++ if(turtle != NULL){
++ g_list_free_full(turtle,
++ g_object_unref);
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_turtle_manager_parent_class)->finalize(gobject);
+ }
+
+ /**
+--- a/ags/object/ags_application_context.c
++++ b/ags/object/ags_application_context.c
+@@ -43,6 +43,7 @@
+ GParamSpec *param_spec);
+ void ags_application_context_connect(AgsConnectable *connectable);
+ void ags_application_context_disconnect(AgsConnectable *connectable);
++void ags_application_context_dispose(GObject *gobject);
+ void ags_application_context_finalize(GObject *gobject);
+
+ void ags_application_context_real_load_config(AgsApplicationContext *application_context);
+@@ -133,6 +134,7 @@
+ gobject->set_property = ags_application_context_set_property;
+ gobject->get_property = ags_application_context_get_property;
+
++ gobject->dispose = ags_application_context_dispose;
+ gobject->finalize = ags_application_context_finalize;
+
+ /* properties */
+@@ -436,6 +438,75 @@
+ }
+
+ void
++ags_application_context_dispose(GObject *gobject)
++{
++ AgsApplicationContext *application_context;
++
++ application_context = AGS_APPLICATION_CONTEXT(gobject);
++
++ /* log */
++ if(application_context->log != NULL){
++ g_object_unref(application_context->log);
++
++ application_context->log = NULL;
++ }
++
++ /* config */
++ if(application_context->config != NULL){
++ g_object_set(application_context->config,
++ "application-context\0", NULL,
++ NULL);
++
++ g_object_unref(application_context->config);
++
++ application_context->config = NULL;
++ }
++
++ /* main loop */
++ if(application_context->main_loop != NULL){
++ g_object_set(application_context->main_loop,
++ "application-context\0", NULL,
++ NULL);
++
++ g_object_unref(application_context->main_loop);
++
++ application_context->main_loop = NULL;
++ }
++
++ /* autosave thread */
++ if(application_context->autosave_thread != NULL){
++ g_object_set(application_context->autosave_thread,
++ "application-context\0", NULL,
++ NULL);
++
++ g_object_unref(application_context->autosave_thread);
++
++ application_context->autosave_thread = NULL;
++ }
++
++ /* task thread */
++ if(application_context->task_thread != NULL){
++ g_object_unref(application_context->task_thread);
++
++ application_context->task_thread = NULL;
++ }
++
++ /* file */
++ if(application_context->file != NULL){
++ g_object_set(application_context->file,
++ "application-context\0", NULL,
++ NULL);
++
++ g_object_unref(application_context->file);
++
++ application_context->file = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_application_context_parent_class)->dispose(gobject);
++}
++
++void
+ ags_application_context_finalize(GObject *gobject)
+ {
+ AgsApplicationContext *application_context;
+@@ -449,16 +520,43 @@
+ pthread_mutex_destroy(application_context->mutex);
+ free(application_context->mutex);
+
++ /* log */
++ if(application_context->log != NULL){
++ g_object_unref(application_context->log);
++ }
++
+ /* config */
+ if(application_context->config != NULL){
++ g_object_set(application_context->config,
++ "application-context\0", NULL,
++ NULL);
++
+ g_object_unref(application_context->config);
+ }
+
+ /* main loop */
+ if(application_context->main_loop != NULL){
++ g_object_set(application_context->main_loop,
++ "application-context\0", NULL,
++ NULL);
++
+ g_object_unref(application_context->main_loop);
+ }
+-
++
++ /* autosave thread */
++ if(application_context->autosave_thread != NULL){
++ g_object_set(application_context->autosave_thread,
++ "application-context\0", NULL,
++ NULL);
++
++ g_object_unref(application_context->autosave_thread);
++ }
++
++ /* task thread */
++ if(application_context->task_thread != NULL){
++ g_object_unref(application_context->task_thread);
++ }
++
+ /* file */
+ if(application_context->file != NULL){
+ g_object_unref(application_context->file);
+--- a/ags/object/ags_config.c
++++ b/ags/object/ags_config.c
+@@ -52,6 +52,7 @@
+ gboolean ags_config_is_connected(AgsConnectable *connectable);
+ void ags_config_connect(AgsConnectable *connectable);
+ void ags_config_disconnect(AgsConnectable *connectable);
++void ags_config_dispose(GObject *gobject);
+ void ags_config_finalize(GObject *gobject);
+ gchar* ags_config_get_version(AgsConfig *config);
+ void ags_config_set_version(AgsConfig *config, gchar *version);
+@@ -141,6 +142,7 @@
+ gobject->set_property = ags_config_set_property;
+ gobject->get_property = ags_config_get_property;
+
++ gobject->dispose = ags_config_dispose;
+ gobject->finalize = ags_config_finalize;
+
+ /* properties */
+@@ -267,15 +269,18 @@
+
+ application_context = (AgsApplicationContext *) g_value_get_object(value);
+
+- if(application_context == ((AgsApplicationContext *) config->application_context))
++ if(application_context == ((AgsApplicationContext *) config->application_context)){
+ return;
++ }
+
+- if(config->application_context != NULL)
++ if(config->application_context != NULL){
+ g_object_unref(config->application_context);
+-
+- if(application_context != NULL)
++ }
++
++ if(application_context != NULL){
+ g_object_ref(G_OBJECT(application_context));
+-
++ }
++
+ config->application_context = (GObject *) application_context;
+ }
+ break;
+@@ -338,11 +343,38 @@
+ }
+
+ void
++ags_config_dispose(GObject *gobject)
++{
++ AgsConfig *config;
++
++ config = (AgsConfig *) gobject;
++
++ if(config->application_context != NULL){
++ g_object_unref(config->application_context);
++
++ config->application_context = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_config_parent_class)->dispose(gobject);
++}
++
++void
+ ags_config_finalize(GObject *gobject)
+ {
++ AgsConfig *config;
+
+- //TODO:JK: implement me
++ config = (AgsConfig *) gobject;
++
++ if(config->application_context != NULL){
++ g_object_unref(config->application_context);
++ }
++
++ if(config->key_file != NULL){
++ g_key_file_unref(config->key_file);
++ }
+
++ /* call parent */
+ G_OBJECT_CLASS(ags_config_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/object/ags_connection.c
++++ b/ags/object/ags_connection.c
+@@ -29,6 +29,7 @@
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec);
++void ags_connection_dispose(GObject *gobject);
+ void ags_connection_finalize(GObject *gobject);
+
+ /**
+@@ -91,6 +92,7 @@
+ gobject->set_property = ags_connection_set_property;
+ gobject->get_property = ags_connection_get_property;
+
++ gobject->dispose = ags_connection_dispose;
+ gobject->finalize = ags_connection_finalize;
+
+ /* properties */
+@@ -177,6 +179,23 @@
+ }
+
+ void
++ags_connection_dispose(GObject *gobject)
++{
++ AgsConnection *connection;
++
++ connection = AGS_CONNECTION(gobject);
++
++ if(connection->data_object != NULL){
++ g_object_unref(connection->data_object);
++
++ connection->data_object = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_connection_parent_class)->dispose(gobject);
++}
++
++void
+ ags_connection_finalize(GObject *gobject)
+ {
+ AgsConnection *connection;
+@@ -186,6 +205,9 @@
+ if(connection->data_object != NULL){
+ g_object_unref(connection->data_object);
+ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_connection_parent_class)->finalize(gobject);
+ }
+
+ /**
+--- a/ags/object/ags_connection_manager.c
++++ b/ags/object/ags_connection_manager.c
+@@ -21,6 +21,7 @@
+
+ void ags_connection_manager_class_init(AgsConnectionManagerClass *connection_manager);
+ void ags_connection_manager_init (AgsConnectionManager *connection_manager);
++void ags_connection_manager_dispose(GObject *gobject);
+ void ags_connection_manager_finalize(GObject *gobject);
+
+ /**
+@@ -75,6 +76,7 @@
+ /* GObjectClass */
+ gobject = (GObjectClass *) connection_manager;
+
++ gobject->dispose = ags_connection_manager_dispose;
+ gobject->finalize = ags_connection_manager_finalize;
+ }
+
+@@ -85,6 +87,24 @@
+ }
+
+ void
++ags_connection_manager_dispose(GObject *gobject)
++{
++ AgsConnectionManager *connection_manager;
++
++ connection_manager = AGS_CONNECTION_MANAGER(gobject);
++
++ if(connection_manager->connection != NULL){
++ g_list_free_full(connection_manager->connection,
++ g_object_unref);
++
++ connection_manager->connection = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_connection_manager_parent_class)->dispose(gobject);
++}
++
++void
+ ags_connection_manager_finalize(GObject *gobject)
+ {
+ AgsConnectionManager *connection_manager;
+@@ -96,6 +116,7 @@
+ g_object_unref);
+ }
+
++ /* call parent */
+ G_OBJECT_CLASS(ags_connection_manager_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/plugin/ags_base_plugin.c
++++ b/ags/plugin/ags_base_plugin.c
+@@ -33,6 +33,7 @@
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec);
++void ags_base_plugin_dispose(GObject *gobject);
+ void ags_base_plugin_finalize(GObject *gobject);
+
+ /**
+@@ -107,6 +108,7 @@
+ gobject->set_property = ags_base_plugin_set_property;
+ gobject->get_property = ags_base_plugin_get_property;
+
++ gobject->dispose = ags_base_plugin_dispose;
+ gobject->finalize = ags_base_plugin_finalize;
+
+ /* properties */
+@@ -432,6 +434,23 @@
+ }
+
+ void
++ags_base_plugin_dispose(GObject *gobject)
++{
++ AgsBasePlugin *base_plugin;
++
++ base_plugin = AGS_BASE_PLUGIN(gobject);
++
++ if(base_plugin->ui_plugin != NULL){
++ g_object_unref(base_plugin->ui_plugin);
++
++ base_plugin->ui_plugin = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_base_plugin_parent_class)->dispose(gobject);
++}
++
++void
+ ags_base_plugin_finalize(GObject *gobject)
+ {
+ AgsBasePlugin *base_plugin;
+--- a/ags/plugin/ags_dssi_manager.c
++++ b/ags/plugin/ags_dssi_manager.c
+@@ -39,6 +39,7 @@
+
+ void ags_dssi_manager_class_init(AgsDssiManagerClass *dssi_manager);
+ void ags_dssi_manager_init (AgsDssiManager *dssi_manager);
++void ags_dssi_manager_dispose(GObject *gobject);
+ void ags_dssi_manager_finalize(GObject *gobject);
+
+ /**
+@@ -99,6 +100,7 @@
+ /* GObjectClass */
+ gobject = (GObjectClass *) dssi_manager;
+
++ gobject->dispose = ags_dssi_manager_dispose;
+ gobject->finalize = ags_dssi_manager_finalize;
+ }
+
+@@ -117,6 +119,24 @@
+ }
+
+ void
++ags_dssi_manager_dispose(GObject *gobject)
++{
++ AgsDssiManager *dssi_manager;
++
++ dssi_manager = AGS_DSSI_MANAGER(gobject);
++
++ if(dssi_manager->dssi_plugin != NULL){
++ g_list_free_full(dssi_manager->dssi_plugin,
++ (GDestroyNotify) g_object_unref);
++
++ dssi_manager->dssi_plugin = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_dssi_manager_parent_class)->dispose(gobject);
++}
++
++void
+ ags_dssi_manager_finalize(GObject *gobject)
+ {
+ AgsDssiManager *dssi_manager;
+@@ -129,6 +149,9 @@
+
+ g_list_free_full(dssi_plugin,
+ (GDestroyNotify) g_object_unref);
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_dssi_manager_parent_class)->finalize(gobject);
+ }
+
+ /**
+--- a/ags/plugin/ags_ladspa_manager.c
++++ b/ags/plugin/ags_ladspa_manager.c
+@@ -39,6 +39,7 @@
+
+ void ags_ladspa_manager_class_init(AgsLadspaManagerClass *ladspa_manager);
+ void ags_ladspa_manager_init (AgsLadspaManager *ladspa_manager);
++void ags_ladspa_manager_dispose(GObject *gobject);
+ void ags_ladspa_manager_finalize(GObject *gobject);
+
+ /**
+@@ -99,6 +100,7 @@
+ /* GObjectClass */
+ gobject = (GObjectClass *) ladspa_manager;
+
++ gobject->dispose = ags_ladspa_manager_dispose;
+ gobject->finalize = ags_ladspa_manager_finalize;
+ }
+
+@@ -117,9 +119,28 @@
+ }
+
+ void
++ags_ladspa_manager_dispose(GObject *gobject)
++{
++ AgsLadspaManager *ladspa_manager;
++
++ ladspa_manager = AGS_LADSPA_MANAGER(gobject);
++
++ if(ladspa_manager->ladspa_plugin != NULL){
++ g_list_free_full(ladspa_manager->ladspa_plugin,
++ (GDestroyNotify) g_object_unref);
++
++ ladspa_manager->ladspa_plugin = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_ladspa_manager_parent_class)->dispose(gobject);
++}
++
++void
+ ags_ladspa_manager_finalize(GObject *gobject)
+ {
+ AgsLadspaManager *ladspa_manager;
++
+ GList *ladspa_plugin;
+
+ ladspa_manager = AGS_LADSPA_MANAGER(gobject);
+@@ -128,6 +149,9 @@
+
+ g_list_free_full(ladspa_plugin,
+ (GDestroyNotify) g_object_unref);
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_ladspa_manager_parent_class)->finalize(gobject);
+ }
+
+ /**
+--- a/ags/plugin/ags_lv2_event_manager.c
++++ b/ags/plugin/ags_lv2_event_manager.c
+@@ -124,6 +124,9 @@
+ ags_lv2_event_manager_finalize(GObject *gobject)
+ {
+ /* empty */
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_lv2_event_manager_parent_class)->finalize(gobject);
+ }
+
+ uint32_t
+--- a/ags/plugin/ags_lv2_log_manager.c
++++ b/ags/plugin/ags_lv2_log_manager.c
+@@ -122,6 +122,9 @@
+ ags_lv2_log_manager_finalize(GObject *gobject)
+ {
+ /* empty */
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_lv2_log_manager_parent_class)->finalize(gobject);
+ }
+
+ /**
+--- a/ags/plugin/ags_lv2_manager.c
++++ b/ags/plugin/ags_lv2_manager.c
+@@ -48,6 +48,7 @@
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec);
++void ags_lv2_manager_dispose(GObject *gobject);
+ void ags_lv2_manager_finalize(GObject *gobject);
+
+ /**
+@@ -111,6 +112,7 @@
+ gobject->set_property = ags_lv2_manager_set_property;
+ gobject->get_property = ags_lv2_manager_get_property;
+
++ gobject->dispose = ags_lv2_manager_dispose;
+ gobject->finalize = ags_lv2_manager_finalize;
+
+ /* properties */
+@@ -207,9 +209,28 @@
+ }
+
+ void
++ags_lv2_manager_dispose(GObject *gobject)
++{
++ AgsLv2Manager *lv2_manager;
++
++ lv2_manager = AGS_LV2_MANAGER(gobject);
++
++ if(lv2_manager->lv2_plugin != NULL){
++ g_list_free_full(lv2_manager->lv2_plugin,
++ g_object_unref);
++
++ lv2_manager->lv2_plugin = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_lv2_manager_parent_class)->dispose(gobject);
++}
++
++void
+ ags_lv2_manager_finalize(GObject *gobject)
+ {
+ AgsLv2Manager *lv2_manager;
++
+ GList *lv2_plugin;
+
+ lv2_manager = AGS_LV2_MANAGER(gobject);
+@@ -218,6 +239,9 @@
+
+ g_list_free_full(lv2_plugin,
+ g_object_unref);
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_lv2_manager_parent_class)->finalize(gobject);
+ }
+
+ /**
+--- a/ags/plugin/ags_lv2_plugin.c
++++ b/ags/plugin/ags_lv2_plugin.c
+@@ -45,6 +45,7 @@
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec);
++void ags_lv2_plugin_dispose(GObject *gobject);
+ void ags_lv2_plugin_finalize(GObject *gobject);
+
+ gpointer ags_lv2_plugin_instantiate(AgsBasePlugin *base_plugin,
+@@ -125,6 +126,7 @@
+ gobject->set_property = ags_lv2_plugin_set_property;
+ gobject->get_property = ags_lv2_plugin_get_property;
+
++ gobject->dispose = ags_lv2_plugin_dispose;
+ gobject->finalize = ags_lv2_plugin_finalize;
+
+ /* properties */
+@@ -311,6 +313,29 @@
+ }
+
+ void
++ags_lv2_plugin_dispose(GObject *gobject)
++{
++ AgsLv2Plugin *lv2_plugin;
++
++ lv2_plugin = AGS_LV2_PLUGIN(gobject);
++
++ if(lv2_plugin->manifest != NULL){
++ g_object_unref(lv2_plugin->manifest);
++
++ lv2_plugin->manifest = NULL;
++ }
++
++ if(lv2_plugin->turtle != NULL){
++ g_object_unref(lv2_plugin->turtle);
++
++ lv2_plugin->turtle = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_lv2_plugin_parent_class)->dispose(gobject);
++}
++
++void
+ ags_lv2_plugin_finalize(GObject *gobject)
+ {
+ AgsLv2Plugin *lv2_plugin;
+@@ -326,6 +351,9 @@
+ if(lv2_plugin->turtle != NULL){
+ g_object_unref(lv2_plugin->turtle);
+ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_lv2_plugin_parent_class)->finalize(gobject);
+ }
+
+ gpointer
+--- a/ags/plugin/ags_lv2_uri_map_manager.c
++++ b/ags/plugin/ags_lv2_uri_map_manager.c
+@@ -133,6 +133,9 @@
+ lv2_uri_map_manager = AGS_LV2_URI_MAP_MANAGER(gobject);
+
+ g_hash_table_destroy(lv2_uri_map_manager->uri_map);
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_lv2_uri_map_manager_parent_class)->finalize(gobject);
+ }
+
+ void
+--- a/ags/plugin/ags_lv2_urid_manager.c
++++ b/ags/plugin/ags_lv2_urid_manager.c
+@@ -134,6 +134,9 @@
+ lv2_urid_manager = AGS_LV2_URID_MANAGER(gobject);
+
+ g_hash_table_destroy(lv2_urid_manager->urid);
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_lv2_urid_manager_parent_class)->finalize(gobject);
+ }
+
+ void
+--- a/ags/plugin/ags_lv2_worker.c
++++ b/ags/plugin/ags_lv2_worker.c
+@@ -121,21 +121,20 @@
+ ags_lv2_worker_connect(AgsConnectable *connectable)
+ {
+ /* empty */
+-
+- ags_lv2_worker_parent_connectable_interface->connect(connectable);
+ }
+
+ void
+ ags_lv2_worker_disconnect(AgsConnectable *connectable)
+ {
+ /* empty */
+-
+- ags_lv2_worker_parent_connectable_interface->disconnect(connectable);
+ }
+
+ void
+ ags_lv2_worker_finalize(GObject *gobject)
+ {
++ /* empty */
++
++ /* call parent */
+ G_OBJECT_CLASS(ags_lv2_worker_parent_class)->finalize(gobject);
+ }
+
+--- a/ags/plugin/ags_lv2_worker_manager.c
++++ b/ags/plugin/ags_lv2_worker_manager.c
+@@ -130,6 +130,9 @@
+ ags_lv2_worker_manager_finalize(GObject *gobject)
+ {
+ /* empty */
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_lv2_worker_manager_parent_class)->finalize(gobject);
+ }
+
+ GObject*
+--- a/ags/plugin/ags_lv2ui_manager.c
++++ b/ags/plugin/ags_lv2ui_manager.c
+@@ -38,6 +38,7 @@
+
+ void ags_lv2ui_manager_class_init(AgsLv2uiManagerClass *lv2ui_manager);
+ void ags_lv2ui_manager_init (AgsLv2uiManager *lv2ui_manager);
++void ags_lv2ui_manager_dispose(GObject *gobject);
+ void ags_lv2ui_manager_finalize(GObject *gobject);
+
+ /**
+@@ -92,6 +93,7 @@
+ /* GObjectClass */
+ gobject = (GObjectClass *) lv2ui_manager;
+
++ gobject->dispose = ags_lv2ui_manager_dispose;
+ gobject->finalize = ags_lv2ui_manager_finalize;
+ }
+
+@@ -110,9 +112,28 @@
+ }
+
+ void
++ags_lv2ui_manager_dispose(GObject *gobject)
++{
++ AgsLv2uiManager *lv2ui_manager;
++
++ lv2ui_manager = AGS_LV2UI_MANAGER(gobject);
++
++ if(lv2ui_manager->lv2ui_plugin != NULL){
++ g_list_free_full(lv2ui_manager->lv2ui_plugin,
++ g_object_unref);
++
++ lv2ui_manager->lv2ui_plugin = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_lv2ui_manager_parent_class)->dispose(gobject);
++}
++
++void
+ ags_lv2ui_manager_finalize(GObject *gobject)
+ {
+ AgsLv2uiManager *lv2ui_manager;
++
+ GList *lv2ui_plugin;
+
+ lv2ui_manager = AGS_LV2UI_MANAGER(gobject);
+@@ -121,6 +142,9 @@
+
+ g_list_free_full(lv2ui_plugin,
+ g_object_unref);
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_lv2ui_manager_parent_class)->finalize(gobject);
+ }
+
+ /**
+--- a/ags/plugin/ags_lv2ui_plugin.c
++++ b/ags/plugin/ags_lv2ui_plugin.c
+@@ -42,6 +42,7 @@
+ guint prop_id,
+ GValue *value,
+ GParamSpec *param_spec);
++void ags_lv2ui_plugin_dispose(GObject *gobject);
+ void ags_lv2ui_plugin_finalize(GObject *gobject);
+
+ gpointer ags_lv2ui_plugin_instantiate(AgsBasePlugin *base_plugin,
+@@ -124,6 +125,7 @@
+ gobject->set_property = ags_lv2ui_plugin_set_property;
+ gobject->get_property = ags_lv2ui_plugin_get_property;
+
++ gobject->dispose = ags_lv2ui_plugin_dispose;
+ gobject->finalize = ags_lv2ui_plugin_finalize;
+
+ /* properties */
+@@ -385,6 +387,35 @@
+ }
+
+ void
++ags_lv2ui_plugin_dispose(GObject *gobject)
++{
++ AgsLv2uiPlugin *lv2ui_plugin;
++
++ lv2ui_plugin = AGS_LV2UI_PLUGIN(gobject);
++
++ if(lv2ui_plugin->manifest != NULL){
++ g_object_unref(lv2ui_plugin->manifest);
++
++ lv2ui_plugin->manifest = NULL;
++ }
++
++ if(lv2ui_plugin->gui_turtle != NULL){
++ g_object_unref(lv2ui_plugin->gui_turtle);
++
++ lv2ui_plugin->gui_turtle = NULL;
++ }
++
++ if(lv2ui_plugin->lv2_plugin != NULL){
++ g_object_unref(lv2ui_plugin->lv2_plugin);
++
++ lv2ui_plugin->lv2_plugin = NULL;
++ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_lv2ui_plugin_parent_class)->dispose(gobject);
++}
++
++void
+ ags_lv2ui_plugin_finalize(GObject *gobject)
+ {
+ AgsLv2uiPlugin *lv2ui_plugin;
+@@ -404,6 +435,9 @@
+ if(lv2ui_plugin->lv2_plugin != NULL){
+ g_object_unref(lv2ui_plugin->lv2_plugin);
+ }
++
++ /* call parent */
++ G_OBJECT_CLASS(ags_lv2ui_plugin_parent_class)->finalize(gobject);
+ }
+
+ void
diff --git a/debian/patches/series b/debian/patches/series
index 15aca26..8267fa1 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,3 +1,4 @@
+fix-missing-dispose.diff
fix-possible-division-by-zero.diff
fix-matrix-callbacks.patch
fix-matrix.patch
@@ -13,7 +14,6 @@ fix-export-soundcard-callbacks.patch
fix-missing-mutices.diff
fix-soundcard-data-race.diff
fix-thread-posix.patch
-fix-duplicated-flag-definition.diff
fix-null-pointer-dereference.diff
fix-missing-midi-connection-dialog.diff
fix-leak-while-g-timeout-function.diff
--
gsequencer packaging
More information about the pkg-multimedia-commits
mailing list