[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#853936: marked as done (unblock: gsequencer/0.7.122-2)



Your message dated Thu, 02 Feb 2017 17:43:00 +0000
with message-id <c61c6207-c5e2-d118-4d0b-4ac3f5f3e570@thykier.net>
and subject line Re: Bug#853936: unblock: gsequencer/0.7.122-2
has caused the Debian Bug report #853936,
regarding unblock: gsequencer/0.7.122-2
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
853936: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=853936
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package gsequencer

There are some important bug-fixes available to gsequencer-0.7.122.
The fixes provide improvements to application stability. It might
look like there are many lines in the debdiff but the changes
are rather small und they use proven concepts.

(include/attach the debdiff against the package in testing)

unblock gsequencer/0.7.122-2

-- System Information:
Debian Release: 9.0
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 4.9.0+ (SMP w/24 CPU cores)
Locale: LANG=C.UTF-8, LC_CTYPE=C.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
diff -Nru gsequencer-0.7.122/debian/changelog gsequencer-0.7.122/debian/changelog
--- gsequencer-0.7.122/debian/changelog	2017-01-03 17:02:45.000000000 +0100
+++ gsequencer-0.7.122/debian/changelog	2017-02-01 11:14:14.000000000 +0100
@@ -1,3 +1,13 @@
+gsequencer (0.7.122-2) unstable; urgency=medium
+
+  [ Joël Krähemann ]
+  * Disabled ALSA on non-linux, and enabled OSS4 only on kFreeBSD
+    (Closes: #852985)
+  * Backported patches (from upstream) to fix crasher bugs related to thread
+    safety and memory corruption.
+
+ -- Joël Krähemann <jkraehemann-guest@users.alioth.debian.org>  Wed, 01 Feb 2017 11:14:14 +0100
+
 gsequencer (0.7.122-1) unstable; urgency=medium
 
   * New upstream version 0.7.122
diff -Nru gsequencer-0.7.122/debian/control gsequencer-0.7.122/debian/control
--- gsequencer-0.7.122/debian/control	2017-01-03 17:02:45.000000000 +0100
+++ gsequencer-0.7.122/debian/control	2017-01-31 10:31:42.000000000 +0100
@@ -20,8 +20,9 @@
  dssi-dev,
  lv2-dev,
  libgmp-dev,
- libasound2-dev|liboss4-salsa-dev,
- oss4-dev,
+ libasound2-dev [linux-any],
+ liboss4-salsa-dev [!linux-any],
+ oss4-dev [kfreebsd-any],
  libjack-dev,
  uuid-dev,
  docbook-xsl,
diff -Nru gsequencer-0.7.122/debian/patches/fix-clear-buffer-c.patch gsequencer-0.7.122/debian/patches/fix-clear-buffer-c.patch
--- gsequencer-0.7.122/debian/patches/fix-clear-buffer-c.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-clear-buffer-c.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,391 @@
+Description: AgsClearBuffer fixes data-race causing distorted audio output
+ resulting in useless audio output. Introduced due to low-latency sync
+ strategy for ALSA audio output and alsa MIDI input. Might end in application
+ crash and is required by immediate sync strategy. This patch includes the
+ c-source file of the task clearing soundcard buffers in order you can do
+ additive mixing, during ordinary run context.
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-01-31
+--- /dev/null
++++ b/ags/audio/task/ags_clear_buffer.c
+@@ -0,0 +1,379 @@
++/* GSequencer - Advanced GTK Sequencer
++ * Copyright (C) 2005-2015 Joël Krähemann
++ *
++ * This file is part of GSequencer.
++ *
++ * GSequencer is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation, either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GSequencer is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <ags/audio/task/ags_clear_buffer.h>
++
++#include <ags/object/ags_connectable.h>
++#include <ags/object/ags_soundcard.h>
++
++#include <ags/audio/ags_devout.h>
++#include <ags/audio/ags_midiin.h>
++
++#include <ags/audio/jack/ags_jack_devout.h>
++#include <ags/audio/jack/ags_jack_midiin.h>
++
++void ags_clear_buffer_class_init(AgsClearBufferClass *clear_buffer);
++void ags_clear_buffer_connectable_interface_init(AgsConnectableInterface *connectable);
++void ags_clear_buffer_init(AgsClearBuffer *clear_buffer);
++void ags_clear_buffer_set_property(GObject *gobject,
++					 guint prop_id,
++					 const GValue *value,
++					 GParamSpec *param_spec);
++void ags_clear_buffer_get_property(GObject *gobject,
++					 guint prop_id,
++					 GValue *value,
++					 GParamSpec *param_spec);
++void ags_clear_buffer_connect(AgsConnectable *connectable);
++void ags_clear_buffer_disconnect(AgsConnectable *connectable);
++void ags_clear_buffer_finalize(GObject *gobject);
++
++void ags_clear_buffer_launch(AgsTask *task);
++
++/**
++ * SECTION:ags_clear_buffer
++ * @short_description: switch buffer flag of device
++ * @title: AgsClearBuffer
++ * @section_id:
++ * @include: ags/audio/task/ags_clear_buffer.h
++ *
++ * The #AgsClearBuffer task switches the buffer flag of device.
++ */
++
++static gpointer ags_clear_buffer_parent_class = NULL;
++static AgsConnectableInterface *ags_clear_buffer_parent_connectable_interface;
++
++enum{
++  PROP_0,
++  PROP_DEVICE,
++};
++
++GType
++ags_clear_buffer_get_type()
++{
++  static GType ags_type_clear_buffer = 0;
++
++  if(!ags_type_clear_buffer){
++    static const GTypeInfo ags_clear_buffer_info = {
++      sizeof (AgsClearBufferClass),
++      NULL, /* base_init */
++      NULL, /* base_finalize */
++      (GClassInitFunc) ags_clear_buffer_class_init,
++      NULL, /* class_finalize */
++      NULL, /* class_data */
++      sizeof (AgsClearBuffer),
++      0,    /* n_preallocs */
++      (GInstanceInitFunc) ags_clear_buffer_init,
++    };
++
++    static const GInterfaceInfo ags_connectable_interface_info = {
++      (GInterfaceInitFunc) ags_clear_buffer_connectable_interface_init,
++      NULL, /* interface_finalize */
++      NULL, /* interface_data */
++    };
++
++    ags_type_clear_buffer = g_type_register_static(AGS_TYPE_TASK,
++							 "AgsClearBuffer\0",
++							 &ags_clear_buffer_info,
++							 0);
++
++    g_type_add_interface_static(ags_type_clear_buffer,
++				AGS_TYPE_CONNECTABLE,
++				&ags_connectable_interface_info);
++  }
++  
++  return (ags_type_clear_buffer);
++}
++
++void
++ags_clear_buffer_class_init(AgsClearBufferClass *clear_buffer)
++{
++  GObjectClass *gobject;
++  AgsTaskClass *task;
++  GParamSpec *param_spec;
++
++  ags_clear_buffer_parent_class = g_type_class_peek_parent(clear_buffer);
++
++  /* gobject */
++  gobject = (GObjectClass *) clear_buffer;
++
++  gobject->set_property = ags_clear_buffer_set_property;
++  gobject->get_property = ags_clear_buffer_get_property;
++
++  gobject->finalize = ags_clear_buffer_finalize;
++
++  /* properties */
++  /**
++   * AgsClearBuffer:device:
++   *
++   * The assigned #AgsSoundcard or #AgsSequencer
++   * 
++   * Since: 0.7.124
++   */
++  param_spec = g_param_spec_object("device\0",
++				   "device of change device\0",
++				   "The device of change device task\0",
++				   G_TYPE_OBJECT,
++				   G_PARAM_READABLE | G_PARAM_WRITABLE);
++  g_object_class_install_property(gobject,
++				  PROP_DEVICE,
++				  param_spec);
++
++  /* task */
++  task = (AgsTaskClass *) clear_buffer;
++
++  task->launch = ags_clear_buffer_launch;
++}
++
++void
++ags_clear_buffer_connectable_interface_init(AgsConnectableInterface *connectable)
++{
++  ags_clear_buffer_parent_connectable_interface = g_type_interface_peek_parent(connectable);
++
++  connectable->connect = ags_clear_buffer_connect;
++  connectable->disconnect = ags_clear_buffer_disconnect;
++}
++
++void
++ags_clear_buffer_init(AgsClearBuffer *clear_buffer)
++{
++  clear_buffer->device = NULL;
++}
++
++void
++ags_clear_buffer_set_property(GObject *gobject,
++				    guint prop_id,
++				    const GValue *value,
++				    GParamSpec *param_spec)
++{
++  AgsClearBuffer *clear_buffer;
++
++  clear_buffer = AGS_CLEAR_BUFFER(gobject);
++
++  switch(prop_id){
++  case PROP_DEVICE:
++    {
++      GObject *device;
++
++      device = (GObject *) g_value_get_object(value);
++
++      if(clear_buffer->device == (GObject *) device){
++	return;
++      }
++
++      if(clear_buffer->device != NULL){
++	g_object_unref(clear_buffer->device);
++      }
++
++      if(device != NULL){
++	g_object_ref(device);
++      }
++
++      clear_buffer->device = (GObject *) device;
++    }
++    break;
++  default:
++    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
++    break;
++  }
++}
++
++void
++ags_clear_buffer_get_property(GObject *gobject,
++				    guint prop_id,
++				    GValue *value,
++				    GParamSpec *param_spec)
++{
++  AgsClearBuffer *clear_buffer;
++
++  clear_buffer = AGS_CLEAR_BUFFER(gobject);
++
++  switch(prop_id){
++  case PROP_DEVICE:
++    {
++      g_value_set_object(value, clear_buffer->device);
++    }
++    break;
++  default:
++    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
++    break;
++  }
++}
++
++void
++ags_clear_buffer_connect(AgsConnectable *connectable)
++{
++  ags_clear_buffer_parent_connectable_interface->connect(connectable);
++
++  /* empty */
++}
++
++void
++ags_clear_buffer_disconnect(AgsConnectable *connectable)
++{
++  ags_clear_buffer_parent_connectable_interface->disconnect(connectable);
++
++  /* empty */
++}
++
++void
++ags_clear_buffer_finalize(GObject *gobject)
++{
++  G_OBJECT_CLASS(ags_clear_buffer_parent_class)->finalize(gobject);
++
++  /* empty */
++}
++
++void
++ags_clear_buffer_launch(AgsTask *task)
++{
++  AgsClearBuffer *clear_buffer;
++
++  guint nth_buffer;
++  guint word_size;
++  
++  clear_buffer = AGS_CLEAR_BUFFER(task);
++
++  if(AGS_IS_DEVOUT(clear_buffer->device)){
++    AgsDevout *devout;
++
++    devout = clear_buffer->device;
++
++    /* retrieve word size */
++    switch(devout->format){
++    case AGS_SOUNDCARD_SIGNED_8_BIT:
++      {
++	word_size = sizeof(signed char);
++      }
++      break;
++    case AGS_SOUNDCARD_SIGNED_16_BIT:
++      {
++	word_size = sizeof(signed short);
++      }
++      break;
++    case AGS_SOUNDCARD_SIGNED_24_BIT:
++      {
++	word_size = sizeof(signed long);
++      }
++      break;
++    case AGS_SOUNDCARD_SIGNED_32_BIT:
++      {
++	word_size = sizeof(signed long);
++      }
++      break;
++    case AGS_SOUNDCARD_SIGNED_64_BIT:
++      {
++	word_size = sizeof(signed long long);
++      }
++      break;
++    default:
++      g_warning("ags_clear_buffer_launch(): unsupported word size\0");
++
++      return;
++    }
++
++    
++    if((AGS_DEVOUT_BUFFER0 & (devout->flags)) != 0){
++      nth_buffer = 0;
++    }else if((AGS_DEVOUT_BUFFER1 & (devout->flags)) != 0){
++      nth_buffer = 1;
++    }else if((AGS_DEVOUT_BUFFER2 & (devout->flags)) != 0){
++      nth_buffer = 2;
++    }else if((AGS_DEVOUT_BUFFER3 & devout->flags) != 0){
++      nth_buffer = 3;
++    }
++    
++    memset(devout->buffer[nth_buffer], 0, (size_t) devout->pcm_channels * devout->buffer_size * word_size);
++  }else if(AGS_IS_JACK_DEVOUT(clear_buffer->device)){
++    AgsJackDevout *jack_devout;
++    
++    jack_devout = clear_buffer->device;
++
++    switch(jack_devout->format){
++    case AGS_SOUNDCARD_SIGNED_8_BIT:
++      {
++	word_size = sizeof(signed char);
++      }
++      break;
++    case AGS_SOUNDCARD_SIGNED_16_BIT:
++      {
++	word_size = sizeof(signed short);
++      }
++      break;
++    case AGS_SOUNDCARD_SIGNED_24_BIT:
++      {      
++	//NOTE:JK: The 24-bit linear samples use 32-bit physical space
++	word_size = sizeof(signed long);
++      }
++      break;
++    case AGS_SOUNDCARD_SIGNED_32_BIT:
++      {
++	word_size = sizeof(signed long);
++      }
++      break;
++    case AGS_SOUNDCARD_SIGNED_64_BIT:
++      {
++	word_size = sizeof(signed long long);
++      }
++      break;
++    default:    
++      g_warning("ags_clear_buffer_launch(): unsupported word size\0");
++    
++      return;
++    }
++    
++    if((AGS_JACK_DEVOUT_BUFFER0 & (jack_devout->flags)) != 0){
++      nth_buffer = 3;
++    }else if((AGS_JACK_DEVOUT_BUFFER1 & (jack_devout->flags)) != 0){
++      nth_buffer = 0;
++    }else if((AGS_JACK_DEVOUT_BUFFER2 & (jack_devout->flags)) != 0){
++      nth_buffer = 1;
++    }else if((AGS_JACK_DEVOUT_BUFFER3 & jack_devout->flags) != 0){
++      nth_buffer = 2;
++    }
++      
++    memset(jack_devout->buffer[nth_buffer], 0, (size_t) jack_devout->pcm_channels * jack_devout->buffer_size * word_size);
++  }else if(AGS_IS_MIDIIN(clear_buffer->device)){
++    //TODO:JK: implement me
++  }else if(AGS_IS_JACK_MIDIIN(clear_buffer->device)){
++    //TODO:JK: implement me
++  }
++}
++
++/**
++ * ags_clear_buffer_new:
++ * @device: the #AgsSoundcard or #AgsSequencer
++ *
++ * Creates an #AgsClearBuffer.
++ *
++ * Returns: an new #AgsClearBuffer.
++ *
++ * Since: 0.7.124
++ */
++AgsClearBuffer*
++ags_clear_buffer_new(GObject *device)
++{
++  AgsClearBuffer *clear_buffer;
++
++  clear_buffer = (AgsClearBuffer *) g_object_new(AGS_TYPE_CLEAR_BUFFER,
++							    NULL);
++
++  clear_buffer->device = device;
++
++  return(clear_buffer);
++}
diff -Nru gsequencer-0.7.122/debian/patches/fix-clear-buffer-h.patch gsequencer-0.7.122/debian/patches/fix-clear-buffer-h.patch
--- gsequencer-0.7.122/debian/patches/fix-clear-buffer-h.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-clear-buffer-h.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,66 @@
+Description: AgsClearBuffer fixes data-race causing distorted audio output
+ resulting in useless audio output. Introduced due to low-latency sync
+ strategy for ALSA audio output and alsa MIDI input. Might end in application
+ crash and is required by immediate sync strategy. This patch includes the
+ header file of the task clearing soundcard buffers in order you can do
+ additive mixing, during ordinary run context.
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-01-31
+--- /dev/null
++++ b/ags/audio/task/ags_clear_buffer.h
+@@ -0,0 +1,54 @@
++/* GSequencer - Advanced GTK Sequencer
++ * Copyright (C) 2005-2015 Joël Krähemann
++ *
++ * This file is part of GSequencer.
++ *
++ * GSequencer is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation, either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GSequencer is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __AGS_CLEAR_BUFFER_H__
++#define __AGS_CLEAR_BUFFER_H__
++
++#include <glib.h>
++#include <glib-object.h>
++
++#include <ags/thread/ags_task.h>
++
++#define AGS_TYPE_CLEAR_BUFFER                (ags_clear_buffer_get_type())
++#define AGS_CLEAR_BUFFER(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_CLEAR_BUFFER, AgsClearBuffer))
++#define AGS_CLEAR_BUFFER_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_CLEAR_BUFFER, AgsClearBufferClass))
++#define AGS_IS_CLEAR_BUFFER(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), AGS_TYPE_CLEAR_BUFFER))
++#define AGS_IS_CLEAR_BUFFER_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_CLEAR_BUFFER))
++#define AGS_CLEAR_BUFFER_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_CLEAR_BUFFER, AgsClearBufferClass))
++
++typedef struct _AgsClearBuffer AgsClearBuffer;
++typedef struct _AgsClearBufferClass AgsClearBufferClass;
++
++struct _AgsClearBuffer
++{
++  AgsTask task;
++
++  GObject *device;
++};
++
++struct _AgsClearBufferClass
++{
++  AgsTaskClass task;
++};
++
++GType ags_clear_buffer_get_type();
++
++AgsClearBuffer* ags_clear_buffer_new(GObject *device);
++
++#endif /*__AGS_CLEAR_BUFFER_H__*/
diff -Nru gsequencer-0.7.122/debian/patches/fix-copy-pattern-channel-run.patch gsequencer-0.7.122/debian/patches/fix-copy-pattern-channel-run.patch
--- gsequencer-0.7.122/debian/patches/fix-copy-pattern-channel-run.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-copy-pattern-channel-run.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,108 @@
+Description: This patch includes generic mutex usage improvements. Mutices
+ protect memory and execution stacks of concurrent access. Such data-races
+ occur spurious and may end in crashing the application by SIGINT.
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-01-31
+--- a/ags/audio/recall/ags_copy_pattern_channel_run.c
++++ b/ags/audio/recall/ags_copy_pattern_channel_run.c
+@@ -364,7 +364,7 @@
+ 						      gdouble delay, guint attack,
+ 						      AgsCopyPatternChannelRun *copy_pattern_channel_run)
+ {
+-  AgsChannel *output, *source;
++  AgsChannel *source;
+   AgsPattern *pattern;
+   AgsCopyPatternAudio *copy_pattern_audio;
+   AgsCopyPatternAudioRun *copy_pattern_audio_run;
+@@ -380,7 +380,8 @@
+ 
+   pthread_mutex_t *application_mutex;
+   pthread_mutex_t *pattern_mutex;
+-
++  pthread_mutex_t *source_mutex;
++  
+   if(delay != 0.0){
+     return;
+   }
+@@ -440,34 +441,66 @@
+ 
+   /*  */
+   if(current_bit){
++    AgsChannel *link;
+     AgsRecycling *recycling;
++    AgsRecycling *end_recycling;
+     AgsAudioSignal *audio_signal;
+ 
+     gdouble delay;
+     guint attack;
+   
++    pthread_mutex_t *link_mutex;
++    
+     //    g_message("ags_copy_pattern_channel_run_sequencer_alloc_callback - playing channel: %u; playing pattern: %u\0",
+     //	      AGS_RECALL_CHANNEL(copy_pattern_channel)->source->line,
+     //	      copy_pattern_audio_run->count_beats_audio_run->sequencer_counter);
+ 
+     /* get source */
+     source = AGS_RECALL_CHANNEL(copy_pattern_channel)->source;
++
++    pthread_mutex_lock(application_mutex);
++  
++    source_mutex = ags_mutex_manager_lookup(mutex_manager,
++					    (GObject *) source);
++    
++    pthread_mutex_unlock(application_mutex);
++    
++    /* source fields */
++    pthread_mutex_lock(source_mutex);
++
++    link = source->link;
+     
+-    /* create new audio signals */
+     recycling = source->first_recycling;
++
++    if(recycling != NULL){
++      end_recycling = source->last_recycling->next;
++    }
+     
+-    //TODO:JK: unclear
++    pthread_mutex_unlock(source_mutex);
+ 
++    /* link */
++    if(link != NULL){
++      pthread_mutex_lock(application_mutex);
++      
++      link_mutex = ags_mutex_manager_lookup(mutex_manager,
++					    (GObject *) link);
++      
++      pthread_mutex_unlock(application_mutex);
++    }
++
++    /* create audio signals */
+     if(recycling != NULL){
+       AgsRecallID *child_recall_id;
+ 
+-      while(recycling != source->last_recycling->next){
+-	if(source->link == NULL){
++      while(recycling != end_recycling){
++	if(link == NULL){
+ 	  child_recall_id = AGS_RECALL(copy_pattern_channel_run)->recall_id;
+ 	}else{
+ 	  GList *list;
+ 
+-	  list = source->link->recall_id;
++	  pthread_mutex_lock(link_mutex);
++	  
++	  list = link->recall_id;
+ 
+ 	  while(list != NULL){
+ 	    if(AGS_RECALL_ID(list->data)->recycling_context->parent == AGS_RECALL(copy_pattern_channel_run)->recall_id->recycling_context){
+@@ -481,6 +514,8 @@
+ 	  if(list == NULL){
+ 	    child_recall_id = NULL;
+ 	  }
++
++	  pthread_mutex_unlock(link_mutex);
+ 	}
+ 
+ 	audio_signal = ags_audio_signal_new(AGS_RECALL(copy_pattern_audio)->soundcard,
diff -Nru gsequencer-0.7.122/debian/patches/fix-count-beats-audio-run.patch gsequencer-0.7.122/debian/patches/fix-count-beats-audio-run.patch
--- gsequencer-0.7.122/debian/patches/fix-count-beats-audio-run.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-count-beats-audio-run.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,126 @@
+Description: This patch includes generic mutex usage improvements. Mutices
+ protect memory and execution stacks of concurrent access. Such data-races
+ occur spurious and may end in crashing the application by SIGINT.
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-01-31
+--- a/ags/audio/recall/ags_count_beats_audio_run.c
++++ b/ags/audio/recall/ags_count_beats_audio_run.c
+@@ -1446,38 +1446,87 @@
+   }else{      
+     if(count_beats_audio_run->sequencer_counter >= (guint) loop_end - 1.0){
+       AgsAudio *audio;
++
++      AgsMutexManager *mutex_manager;
++
+       GList *playback;
+ 
++      pthread_mutex_t *application_mutex;
++      pthread_mutex_t *audio_mutex;
++      
++      audio = AGS_RECALL_AUDIO_RUN(count_beats_audio_run)->recall_audio->audio;
++
++      mutex_manager = ags_mutex_manager_get_instance();
++      application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
++  
++      /* lookup audio mutex */
++      pthread_mutex_lock(application_mutex);
++  
++      audio_mutex = ags_mutex_manager_lookup(mutex_manager,
++					     audio);
++  
++      pthread_mutex_unlock(application_mutex);
++
++      /* reset sequencer counter */
+       count_beats_audio_run->sequencer_counter = 0;
+ 
+-      audio = AGS_RECALL_AUDIO_RUN(count_beats_audio_run)->recall_audio->audio;
++      /* get playback */
++      pthread_mutex_lock(audio_mutex);
++      
+       playback = AGS_PLAYBACK_DOMAIN(audio->playback_domain)->playback;
+ 
++      pthread_mutex_unlock(audio_mutex);
++      
+       /* emit stop signals */
+       ags_count_beats_audio_run_sequencer_stop(count_beats_audio_run,
+ 					       FALSE);
+ 
+       /* set done flag in soundcard play */
+       while(playback != NULL){
+-	if(AGS_PLAYBACK(playback->data)->recall_id[1] != NULL &&
+-	   AGS_PLAYBACK(playback->data)->recall_id[1]->recycling_context == AGS_RECALL(count_beats_audio_run)->recall_id->recycling_context){
+-	  AgsChannel *channel;
++	AgsChannel *channel;
++	AgsRecyclingContext *recycling_context;
++	
++	pthread_mutex_lock(audio_mutex);
++
++	channel = audio->output;
++	
++	if(AGS_PLAYBACK(playback->data)->recall_id[1] != NULL){
++	  recycling_context = AGS_PLAYBACK(playback->data)->recall_id[1]->recycling_context;
++	}else{
++	  recycling_context = NULL;
++	}
++
++	pthread_mutex_unlock(audio_mutex);
++
++	if(recycling_context == AGS_RECALL(count_beats_audio_run)->recall_id->recycling_context){
+ 	  AgsStreamChannelRun *stream_channel_run;
++	  
+ 	  GList *list;
+ 	  GList *recall_recycling_list, *recall_audio_signal_list;
++	  
+ 	  gboolean found;
+ 
++	  pthread_mutex_t *channel_mutex;
++
+ 	  //	    AGS_PLAYBACK(playback->data)->flags |= AGS_PLAYBACK_DONE;
+ 
++	  /* lookup channel mutex */
++	  pthread_mutex_lock(application_mutex);
++	  
++	  channel_mutex = ags_mutex_manager_lookup(mutex_manager,
++						   channel);
++	  
++	  pthread_mutex_unlock(application_mutex);
++
+ 	  /* check if to stop audio processing */
+-	  channel = audio->output;
+ 	  found = FALSE;
+ 
++	  pthread_mutex_lock(channel_mutex);
++	  
+ 	  list = channel->play;
+-
+ 	  list = ags_recall_find_type_with_recycling_context(list,
+ 							     AGS_TYPE_STREAM_CHANNEL_RUN,
+-							     (GObject *) AGS_RECALL(count_beats_audio_run)->recall_id->recycling_context);
++							     (GObject *) recycling_context);
+ 
+ 	  if(list != NULL){
+ 	    stream_channel_run = AGS_STREAM_CHANNEL_RUN(list->data);
+@@ -1500,6 +1549,8 @@
+ 	    }
+ 	  }
+ 
++	  pthread_mutex_unlock(channel_mutex);
++
+ 	  /* stop audio processing*/
+ 	  if(!found){
+ 	    ags_count_beats_audio_run_stop(count_beats_audio_run,
+@@ -1509,7 +1560,12 @@
+ 	  break;
+ 	}
+ 
+-	playback = playback->next;
++	/* iterate playback */
++	pthread_mutex_lock(audio_mutex);
++	
++      	playback = playback->next;
++
++	pthread_mutex_unlock(audio_mutex);
+       }
+ 
+       return;
diff -Nru gsequencer-0.7.122/debian/patches/fix-delay-audio-run.patch gsequencer-0.7.122/debian/patches/fix-delay-audio-run.patch
--- gsequencer-0.7.122/debian/patches/fix-delay-audio-run.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-delay-audio-run.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,131 @@
+Description: This patch includes generic mutex usage improvements. Mutices
+ protect memory and execution stacks of concurrent access. Such data-races
+ occur spurious and may end in crashing the application by SIGINT.
+ There are minor code changes included fulfilled during code enhancement.
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-01-31
+--- a/ags/audio/recall/ags_delay_audio_run.c
++++ b/ags/audio/recall/ags_delay_audio_run.c
+@@ -26,6 +26,8 @@
+ #include <ags/object/ags_soundcard.h>
+ #include <ags/object/ags_plugin.h>
+ 
++#include <ags/thread/ags_mutex_manager.h>
++
+ #include <ags/file/ags_file_stock.h>
+ #include <ags/file/ags_file_id_ref.h>
+ #include <ags/file/ags_file_lookup.h>
+@@ -441,16 +443,24 @@
+   AgsDelayAudio *delay_audio;
+   AgsDelayAudioRun *delay_audio_run;
+ 
++  AgsMutexManager *mutex_manager;
++  
+   gdouble notation_delay, sequencer_delay;
++  gdouble delay;
++  guint attack;
+ 
+   GValue value = { 0, };
+ 
++  pthread_mutex_t *application_mutex;
++  pthread_mutex_t *soundcard_mutex;
++  
+   AGS_RECALL_CLASS(ags_delay_audio_run_parent_class)->run_pre(recall);
+ 
+   //  g_message("ags_delay_audio_run_run_pre()\0");
+   
+   delay_audio_run = AGS_DELAY_AUDIO_RUN(recall);
+ 
++  /* check done */  
+   if((AGS_RECALL_PERSISTENT & (recall->flags)) == 0 &&
+      delay_audio_run->dependency_ref == 0){
+     delay_audio_run->notation_counter = 0;
+@@ -463,6 +473,17 @@
+ 
+   delay_audio = AGS_DELAY_AUDIO(AGS_RECALL_AUDIO_RUN(delay_audio_run)->recall_audio);
+ 
++  mutex_manager = ags_mutex_manager_get_instance();
++  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
++  
++  /* lookup soundcard mutex */
++  pthread_mutex_lock(application_mutex);
++  
++  soundcard_mutex = ags_mutex_manager_lookup(mutex_manager,
++					     recall->soundcard);
++  
++  pthread_mutex_unlock(application_mutex);
++
+   /* read notation-delay port */
+   g_value_init(&value, G_TYPE_DOUBLE);
+ 
+@@ -489,22 +510,22 @@
+   }else{
+     delay_audio_run->sequencer_counter += 1;
+   }
++  
++  /* delay and attack */
++  pthread_mutex_lock(soundcard_mutex);
++
++  attack = ags_soundcard_get_attack(AGS_SOUNDCARD(recall->soundcard));
++  
++  pthread_mutex_unlock(soundcard_mutex);
++  
++  delay = 0.0;
+ 
++  /* notation */
+   if(delay_audio_run->notation_counter == 0){    
+     guint run_order;
+-    gdouble delay;
+-    guint attack;
+ 
+     run_order = 0; //NOTE:JK: old hide_ref style
+ 
+-    /* delay and attack */
+-    //TODO:JK: unclear
+-    attack = ags_soundcard_get_attack(AGS_SOUNDCARD(recall->soundcard));
+-      
+-    delay = 0.0; // soundcard->delay[((soundcard->tic_counter + 1 == AGS_NOTATION_TICS_PER_BEAT) ?
+-      //		   0:
+-      //		   soundcard->tic_counter + 1)];
+-
+     //    g_message("ags_delay_audio_run_run_pre@%llu: alloc notation[%u]\0",
+     //	      delay_audio_run,
+     //	      run_order);
+@@ -521,8 +542,6 @@
+ 				       delay, attack);
+   }else{
+     guint run_order;
+-    gdouble delay;
+-    guint attack;
+ 
+     run_order = 0;
+     
+@@ -541,17 +560,9 @@
+ 				       delay, attack);
+   }
+ 
++  /* sequencer */
+   if(delay_audio_run->sequencer_counter == 0){
+     guint run_order;
+-    gdouble delay;
+-    guint attack;
+-
+-    /* delay and attack */
+-    //TODO:JK: unclear
+-    attack = ags_soundcard_get_attack(AGS_SOUNDCARD(recall->soundcard));
+-    delay = 0.0; // soundcard->delay[((soundcard->tic_counter + 1 == AGS_NOTATION_TICS_PER_BEAT) ?
+-      //		   0:
+-      //		   soundcard->tic_counter + 1)];
+ 
+     run_order = 0;
+ 
+@@ -572,8 +583,6 @@
+ 					delay, attack);
+   }else{
+     guint run_order;
+-    gdouble delay;
+-    guint attack;
+ 
+     run_order = 0;
+     
diff -Nru gsequencer-0.7.122/debian/patches/fix-devout.patch gsequencer-0.7.122/debian/patches/fix-devout.patch
--- gsequencer-0.7.122/debian/patches/fix-devout.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-devout.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,79 @@
+Description: AgsClearBuffer fixes data-race causing distorted audio output
+ resulting in useless audio output. Introduced due to low-latency sync
+ strategy for ALSA audio output and alsa MIDI input. Might end in application
+ crash and is required by immediate sync strategy.
+ These changes make use of the task by ags_devout_alsa_play() and
+ ags_devout_oss_play().
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-01-31
+--- a/ags/audio/ags_devout.c
++++ b/ags/audio/ags_devout.c
+@@ -33,6 +33,7 @@
+ #include <ags/thread/ags_poll_fd.h>
+ 
+ #include <ags/audio/task/ags_tic_device.h>
++#include <ags/audio/task/ags_clear_buffer.h>
+ #include <ags/audio/task/ags_switch_buffer_flag.h>
+ #include <ags/audio/task/ags_notify_soundcard.h>
+ 
+@@ -2210,6 +2211,7 @@
+   AgsDevout *devout;
+ 
+   AgsTicDevice *tic_device;
++  AgsClearBuffer *clear_buffer;
+   AgsSwitchBufferFlag *switch_buffer_flag;
+   
+   AgsThread *task_thread;
+@@ -2402,9 +2404,6 @@
+     nth_ring_buffer = 1;
+   }
+ 
+-  /* clear next buffer */
+-  memset(devout->buffer[next_buffer], 0, (size_t) devout->pcm_channels * devout->buffer_size * word_size);
+-
+ #ifdef AGS_WITH_OSS    
+   /* fill ring buffer */
+   ags_devout_oss_play_fill_ring_buffer(devout->buffer[nth_buffer],
+@@ -2434,6 +2433,11 @@
+   tic_device = ags_tic_device_new((GObject *) devout);
+   task = g_list_append(task,
+ 		       tic_device);
++
++  /* reset - clear buffer */
++  clear_buffer = ags_clear_buffer_new((GObject *) devout);
++  task = g_list_append(task,
++		       clear_buffer);
+   
+   /* reset - switch buffer flags */
+   switch_buffer_flag = ags_switch_buffer_flag_new((GObject *) devout);
+@@ -2951,6 +2955,7 @@
+   AgsDevout *devout;
+ 
+   AgsTicDevice *tic_device;
++  AgsClearBuffer *clear_buffer;
+   AgsSwitchBufferFlag *switch_buffer_flag;
+   
+   AgsThread *task_thread;
+@@ -3166,9 +3171,6 @@
+     nth_ring_buffer = 1;
+   }
+ 
+-  /* clear next buffer */
+-  memset(devout->buffer[next_buffer], 0, (size_t) devout->pcm_channels * devout->buffer_size * word_size);
+-
+ #ifdef AGS_WITH_ALSA
+ 
+   /* fill ring buffer */
+@@ -3227,6 +3229,11 @@
+   tic_device = ags_tic_device_new((GObject *) devout);
+   task = g_list_append(task,
+ 		       tic_device);
++
++  /* reset - clear buffer */
++  clear_buffer = ags_clear_buffer_new((GObject *) devout);
++  task = g_list_append(task,
++		       clear_buffer);
+   
+   /* reset - switch buffer flags */
+   switch_buffer_flag = ags_switch_buffer_flag_new((GObject *) devout);
diff -Nru gsequencer-0.7.122/debian/patches/fix-export-soundcard-callbacks.patch gsequencer-0.7.122/debian/patches/fix-export-soundcard-callbacks.patch
--- gsequencer-0.7.122/debian/patches/fix-export-soundcard-callbacks.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-export-soundcard-callbacks.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,45 @@
+Description: This patch fixes a memory corruption causing program instability.
+ It did a cast to a wrong GObject sub-class and ignored possible NULL pointer.
+ Prior appeared during application start warning and critical log messages.
+ Indicating something was wrong, it is fixed now.
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-01-31
+--- a/ags/X/ags_export_soundcard_callbacks.c
++++ b/ags/X/ags_export_soundcard_callbacks.c
+@@ -61,12 +61,16 @@
+   soundcard = NULL;
+ 
+   if(application_context != NULL){
+-    soundcard = ags_sound_provider_get_soundcard(AGS_SOUNDCARD(application_context));
++    soundcard = ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context));
+   }
+ 
+   backend = gtk_combo_box_text_get_active_text(export_soundcard->backend);
+   device = gtk_combo_box_text_get_active_text(export_soundcard->card);
+ 
++  if(device == NULL){
++    return;
++  }
++  
+   found_card = FALSE;
+   
+   while(soundcard != NULL){
+@@ -154,12 +158,16 @@
+   soundcard = NULL;
+     
+   if(application_context != NULL){
+-    soundcard = ags_sound_provider_get_soundcard(AGS_SOUNDCARD(application_context));
++    soundcard = ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context));
+   }
+ 
+   backend = gtk_combo_box_text_get_active_text(export_soundcard->backend);
+   device = gtk_combo_box_text_get_active_text(export_soundcard->card);
+ 
++  if(device == NULL){
++    return;
++  }
++  
+   found_card = FALSE;
+ 
+   while(soundcard != NULL){
diff -Nru gsequencer-0.7.122/debian/patches/fix-jack-client.patch gsequencer-0.7.122/debian/patches/fix-jack-client.patch
--- gsequencer-0.7.122/debian/patches/fix-jack-client.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-jack-client.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,17 @@
+Description: This fix eliminates clearing buffer by memset(). The AgsClearBuffer
+ task is used instead in ags_jack_devout.c. Related to data-race and concurrent
+ access causing possible SIGINT.
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-01-31
+--- a/ags/audio/jack/ags_jack_client.c
++++ b/ags/audio/jack/ags_jack_client.c
+@@ -886,8 +886,6 @@
+       }
+     
+       if(!no_event){
+-	memset(jack_devout->buffer[nth_buffer], 0, (size_t) jack_devout->pcm_channels * jack_devout->buffer_size * word_size);
+-
+ 	/* signal finish */
+ 	pthread_mutex_lock(device_mutex);
+ 
diff -Nru gsequencer-0.7.122/debian/patches/fix-jack-devout.patch gsequencer-0.7.122/debian/patches/fix-jack-devout.patch
--- gsequencer-0.7.122/debian/patches/fix-jack-devout.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-jack-devout.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,108 @@
+Description: AgsClearBuffer fixes data-race causing distorted audio output
+ resulting in useless audio output. Introduced due to low-latency sync
+ strategy for ALSA audio output and alsa MIDI input. Might end in application
+ crash and is required by immediate sync strategy.
+ These changes make use of the task by ags_jack_devout_port_play().
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-01-31
+--- a/ags/audio/jack/ags_jack_devout.c
++++ b/ags/audio/jack/ags_jack_devout.c
+@@ -40,6 +40,7 @@
+ 
+ #include <ags/audio/task/ags_notify_soundcard.h>
+ #include <ags/audio/task/ags_tic_device.h>
++#include <ags/audio/task/ags_clear_buffer.h>
+ #include <ags/audio/task/ags_switch_buffer_flag.h>
+ 
+ #include <ags/audio/thread/ags_audio_loop.h>
+@@ -1609,7 +1610,7 @@
+ {
+   AgsJackClient *jack_client;
+   AgsJackDevout *jack_devout;
+-
++  
+   AgsMutexManager *mutex_manager;
+   AgsTaskThread *task_thread;
+ 
+@@ -1728,6 +1729,7 @@
+ 
+   if(task_thread != NULL){
+     AgsTicDevice *tic_device;
++    AgsClearBuffer *clear_buffer;
+     AgsSwitchBufferFlag *switch_buffer_flag;
+       
+     GList *task;
+@@ -1738,7 +1740,12 @@
+     tic_device = ags_tic_device_new((GObject *) jack_devout);
+     task = g_list_append(task,
+ 			 tic_device);
+-  
++
++    /* reset - clear buffer */
++    clear_buffer = ags_clear_buffer_new((GObject *) jack_devout);
++    task = g_list_append(task,
++			 clear_buffer); 
++    
+     /* reset - switch buffer flags */
+     switch_buffer_flag = ags_switch_buffer_flag_new((GObject *) jack_devout);
+     task = g_list_append(task,
+@@ -1748,9 +1755,57 @@
+     ags_task_thread_append_tasks((AgsTaskThread *) task_thread,
+ 				 task);
+   }else{
++    guint nth_buffer;
++    guint word_size;
++    
+     /* tic */
+     ags_soundcard_tic(AGS_SOUNDCARD(jack_devout));
+-	  
++
++    switch(jack_devout->format){
++    case AGS_SOUNDCARD_SIGNED_8_BIT:
++      {
++	word_size = sizeof(signed char);
++      }
++      break;
++    case AGS_SOUNDCARD_SIGNED_16_BIT:
++      {
++	word_size = sizeof(signed short);
++      }
++      break;
++    case AGS_SOUNDCARD_SIGNED_24_BIT:
++      {
++	//NOTE:JK: The 24-bit linear samples use 32-bit physical space
++	word_size = sizeof(signed long);
++      }
++      break;
++    case AGS_SOUNDCARD_SIGNED_32_BIT:
++      {
++	word_size = sizeof(signed long);
++      }
++      break;
++    case AGS_SOUNDCARD_SIGNED_64_BIT:
++      {
++	word_size = sizeof(signed long long);
++      }
++      break;
++    default:
++      g_warning("ags_jack_devout_port_play(): unsupported word size\0");
++      return;
++    }
++        
++    /* reset - clear buffer */
++    if((AGS_JACK_DEVOUT_BUFFER0 & (jack_devout->flags)) != 0){
++      nth_buffer = 3;
++    }else if((AGS_JACK_DEVOUT_BUFFER1 & (jack_devout->flags)) != 0){
++      nth_buffer = 0;
++    }else if((AGS_JACK_DEVOUT_BUFFER2 & (jack_devout->flags)) != 0){
++      nth_buffer = 1;
++    }else if((AGS_JACK_DEVOUT_BUFFER3 & jack_devout->flags) != 0){
++      nth_buffer = 2;
++    }
++    
++    memset(jack_devout->buffer[nth_buffer], 0, (size_t) jack_devout->pcm_channels * jack_devout->buffer_size * word_size);
++    
+     /* reset - switch buffer flags */
+     ags_jack_devout_switch_buffer_flag(jack_devout);
+   }
diff -Nru gsequencer-0.7.122/debian/patches/fix-line-callbacks.patch gsequencer-0.7.122/debian/patches/fix-line-callbacks.patch
--- gsequencer-0.7.122/debian/patches/fix-line-callbacks.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-line-callbacks.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,74 @@
+Description: Due to spurious crashes while clicking pad's play button there
+ was a need to improve the involved mutices. Expected result better stability.
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-01-31
+--- a/ags/X/ags_line_callbacks.c
++++ b/ags/X/ags_line_callbacks.c
+@@ -423,27 +423,63 @@
+   AgsChannel *channel;
+   AgsPlayback *playback;
+   AgsChannel *next_pad;
++  AgsRecallID *match_recall_id;
++
++  AgsMutexManager *mutex_manager;
+ 
+   gboolean all_done;
+ 
++  pthread_mutex_t *application_mutex;
++  pthread_mutex_t *channel_mutex;
++
++  mutex_manager = ags_mutex_manager_get_instance();
++  application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
++
+   gdk_threads_enter();
+   
++  /* retrieve channel */
+   channel = AGS_PAD(AGS_LINE(line)->pad)->channel;
++
++  /* retrieve channel mutex */
++  pthread_mutex_lock(application_mutex);
++
++  channel_mutex = ags_mutex_manager_lookup(mutex_manager,
++					   (GObject *) channel);
++
++  pthread_mutex_unlock(application_mutex);
++
++  /* get next pad */
++  pthread_mutex_lock(channel_mutex);
++
+   next_pad = channel->next_pad;
+ 
++  pthread_mutex_unlock(channel_mutex);
++
+   all_done = TRUE;
+ 
+   while(channel != next_pad){
++    pthread_mutex_lock(channel_mutex);
++
+     playback = AGS_PLAYBACK(channel->playback);
+-    
+-    if(playback->recall_id[0] != NULL){
++    match_recall_id = playback->recall_id[0];
++		
++    pthread_mutex_unlock(channel_mutex);
++
++    /* check if pending */
++    if(match_recall_id != NULL){
+       all_done = FALSE;
+       break;
+     }
+-    
++
++    /* iterate */
++    pthread_mutex_lock(channel_mutex);
++
+     channel = channel->next;
++
++    pthread_mutex_unlock(channel_mutex);
+   }
+ 
++  /* toggle play button if all playback done */
+   if(all_done){
+     AgsPad *pad;
+ 
diff -Nru gsequencer-0.7.122/debian/patches/fix-machine-selector.patch gsequencer-0.7.122/debian/patches/fix-machine-selector.patch
--- gsequencer-0.7.122/debian/patches/fix-machine-selector.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-machine-selector.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,145 @@
+Description: Since AgsAutomationEditor and AgsEditor have the AgsMachineSelector
+ composite widget as a common component, the migration wasn't done properly.
+ The code to handle automation editor was just missing and caused crashes due
+ to memory corruption.
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-01-31
+--- a/ags/X/editor/ags_machine_selector.c
++++ b/ags/X/editor/ags_machine_selector.c
+@@ -25,6 +25,7 @@
+ #include <ags/audio/ags_notation.h>
+ 
+ #include <ags/X/ags_editor.h>
++#include <ags/X/ags_automation_editor.h>
+ 
+ #include <ags/X/editor/ags_machine_radio_button.h>
+ 
+@@ -225,10 +226,7 @@
+   
+   GList *list, *list_start;
+ 
+-  editor = (AgsEditor *) gtk_widget_get_ancestor((GtkWidget *) machine_selector,
+-						 AGS_TYPE_EDITOR);
+-
+-  /* emit changed */
++  /* get machine radio button */
+   machine_radio_button = NULL;
+ 
+   list_start = 
+@@ -243,28 +241,106 @@
+   }
+   
+   g_list_free(list_start);
++
++  if(machine_radio_button == NULL){
++    return;
++  }
+   
+-  /* destroy edit widgets */
+-  if(machine_radio_button != NULL){
++  /*  */
++  editor = (AgsEditor *) gtk_widget_get_ancestor((GtkWidget *) machine_selector,
++						 AGS_TYPE_EDITOR);
++
++  if(editor != NULL){  
++    /* destroy edit widgets */
+     if(machine_radio_button->machine != NULL){
++      AgsEditorChild *editor_child;
++
++      editor_child = NULL;
++      
+       list = editor->editor_child;
+ 
+       while(list != NULL){
+ 	if(AGS_EDITOR_CHILD(list->data)->machine == machine_radio_button->machine){
+-	  gtk_widget_destroy((GtkWidget *) AGS_EDITOR_CHILD(list->data)->notebook);
+-	  gtk_widget_destroy((GtkWidget *) AGS_EDITOR_CHILD(list->data)->meter);
+-	  gtk_widget_destroy((GtkWidget *) AGS_EDITOR_CHILD(list->data)->edit_widget);
+-	
++	  editor_child = AGS_EDITOR_CHILD(list->data);
++	  
++	  gtk_widget_destroy((GtkWidget *) editor_child->notebook);
++	  gtk_widget_destroy((GtkWidget *) editor_child->meter);
++	  gtk_widget_destroy((GtkWidget *) editor_child->edit_widget);
++
++	  editor->current_notebook = NULL;
++	  editor->current_meter = NULL;
++	  editor->current_edit_widget = NULL;
++	  
+ 	  break;
+ 	}
+     
+ 	list = list->next;
+       }
++
++      if(editor_child != NULL){
++	editor->editor_child = g_list_remove(editor->editor_child,
++					     editor_child);
++	free(editor_child);
++      }
++    }
++  }else{
++    AgsAutomationEditor *automation_editor;
++    
++    automation_editor = (AgsAutomationEditor *) gtk_widget_get_ancestor((GtkWidget *) machine_selector,
++									AGS_TYPE_AUTOMATION_EDITOR);
++
++    if(automation_editor != NULL){
++      /* destroy edit widgets */
++      if(machine_radio_button->machine != NULL){
++	AgsAutomationEditorChild *automation_editor_child;
++
++	automation_editor_child = NULL;
++	
++	list = automation_editor->automation_editor_child;
++
++	while(list != NULL){
++	  if(AGS_AUTOMATION_EDITOR_CHILD(list->data)->machine == machine_radio_button->machine){
++	    automation_editor_child = AGS_AUTOMATION_EDITOR_CHILD(list->data);
++	    
++	    gtk_widget_destroy((GtkWidget *) automation_editor_child->audio_scale);
++	    gtk_widget_destroy((GtkWidget *) automation_editor_child->audio_automation_edit);
++	    
++	    gtk_widget_destroy((GtkWidget *) automation_editor_child->output_scale);
++	    gtk_widget_destroy((GtkWidget *) automation_editor_child->output_notebook);
++	    gtk_widget_destroy((GtkWidget *) automation_editor_child->output_automation_edit);
++
++	    gtk_widget_destroy((GtkWidget *) automation_editor_child->input_scale);
++	    gtk_widget_destroy((GtkWidget *) automation_editor_child->input_notebook);
++	    gtk_widget_destroy((GtkWidget *) automation_editor_child->input_automation_edit);
++
++	    automation_editor->current_audio_scale = NULL;
++	    automation_editor->current_audio_automation_edit = NULL;
++
++	    automation_editor->current_output_notebook = NULL;
++	    automation_editor->current_output_scale = NULL;
++	    automation_editor->current_output_automation_edit = NULL;
++
++	    automation_editor->current_input_notebook = NULL;
++	    automation_editor->current_input_scale = NULL;
++	    automation_editor->current_input_automation_edit = NULL;
++
++	    break;
++	  }
++    
++	  list = list->next;
++	}
++
++	if(automation_editor_child != NULL){
++	  automation_editor->automation_editor_child = g_list_remove(automation_editor->automation_editor_child,
++								     automation_editor_child);
++	  free(automation_editor_child);
++	}
++      }
+     }
+-  
+-    /**/
+-    gtk_widget_destroy(GTK_WIDGET(machine_radio_button));
+   }
++  
++  /**/
++  gtk_widget_destroy(GTK_WIDGET(machine_radio_button));
+ }
+ 
+ void
diff -Nru gsequencer-0.7.122/debian/patches/fix-makefile-am.patch gsequencer-0.7.122/debian/patches/fix-makefile-am.patch
--- gsequencer-0.7.122/debian/patches/fix-makefile-am.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-makefile-am.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,27 @@
+Description: AgsClearBuffer fixes data-race causing distorted audio output
+ resulting in useless audio output. Introduced due to low-latency sync
+ strategy for ALSA audio output and alsa MIDI input. Might end in application
+ crash and is required by immediate sync strategy.
+ This patch includes the Makefile.am fixes to use the new object and its
+ functions.
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-01-31
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -963,6 +963,7 @@
+ 	ags/audio/task/ags_cancel_channel.h \
+ 	ags/audio/task/ags_cancel_recall.h \
+ 	ags/audio/task/ags_change_soundcard.h \
++	ags/audio/task/ags_clear_buffer.h \
+ 	ags/audio/task/ags_export_output.h \
+ 	ags/audio/task/ags_free_selection.h \
+ 	ags/audio/task/ags_init_audio.h \
+@@ -1024,6 +1025,7 @@
+ 	ags/audio/task/ags_cancel_channel.c \
+ 	ags/audio/task/ags_cancel_recall.c \
+ 	ags/audio/task/ags_change_soundcard.c \
++	ags/audio/task/ags_clear_buffer.c \
+ 	ags/audio/task/ags_export_output.c \
+ 	ags/audio/task/ags_free_selection.c \
+ 	ags/audio/task/ags_init_audio.c \
diff -Nru gsequencer-0.7.122/debian/patches/fix-pad-callbacks.patch gsequencer-0.7.122/debian/patches/fix-pad-callbacks.patch
--- gsequencer-0.7.122/debian/patches/fix-pad-callbacks.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-pad-callbacks.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,128 @@
+Description: Due to spurious crashes while clicking pad's play button there
+ was a need to improve the involved mutices. Expected result better stability.
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-01-31
+--- a/ags/X/ags_pad_callbacks.c
++++ b/ags/X/ags_pad_callbacks.c
+@@ -33,6 +33,7 @@
+ #include <ags/audio/ags_playback.h>
+ #include <ags/audio/ags_pattern.h>
+ #include <ags/audio/ags_recall.h>
++#include <ags/audio/ags_recall_id.h>
+ 
+ #include <ags/audio/thread/ags_audio_loop.h>
+ #include <ags/audio/thread/ags_soundcard_thread.h>
+@@ -325,6 +326,7 @@
+ ags_pad_init_channel_launch_callback(AgsTask *task, AgsPad *input_pad)
+ { 
+   AgsSoundcard *soundcard;
++  AgsAudio *audio;
+   AgsChannel *channel, *next_pad;
+   AgsRecycling *recycling, *end_recycling;
+ 
+@@ -338,11 +340,28 @@
+   pthread_mutex_t *application_mutex;
+   pthread_mutex_t *audio_mutex;
+   pthread_mutex_t *channel_mutex;
++  pthread_mutex_t *recycling_mutex;
+  
+   mutex_manager = ags_mutex_manager_get_instance();
+   application_mutex = ags_mutex_manager_get_application_mutex(mutex_manager);
+ 
+-  /* get audio loop and audio mutex */
++  /* get channel and its mutex */
++  channel = input_pad->channel;
++
++  pthread_mutex_lock(application_mutex);
++
++  channel_mutex = ags_mutex_manager_lookup(mutex_manager,
++					   (GObject *) channel);
++
++  pthread_mutex_unlock(application_mutex);
++
++  /* get audio and its audio mutex */
++  pthread_mutex_lock(channel_mutex);
++
++  audio = AGS_AUDIO(channel->audio);
++  
++  pthread_mutex_unlock(channel_mutex);
++
+   pthread_mutex_lock(application_mutex);
+   
+   audio_mutex = ags_mutex_manager_lookup(mutex_manager,
+@@ -353,7 +372,7 @@
+   /* get soundcard */
+   pthread_mutex_lock(audio_mutex);
+   
+-  soundcard = AGS_SOUNDCARD(AGS_AUDIO(input_pad->channel->audio)->soundcard);
++  soundcard = AGS_SOUNDCARD(audio->soundcard);
+   
+   pthread_mutex_unlock(audio_mutex);
+ 
+@@ -361,16 +380,6 @@
+   list_start = 
+     list = gtk_container_get_children((GtkContainer *) input_pad->expander_set);
+ 
+-  /* get channel and its mutex */
+-  channel = input_pad->channel;
+-
+-  pthread_mutex_lock(application_mutex);
+-
+-  channel_mutex = ags_mutex_manager_lookup(mutex_manager,
+-					   (GObject *) channel);
+-
+-  pthread_mutex_unlock(application_mutex);
+-
+   /* get next pad */
+   pthread_mutex_lock(channel_mutex);
+   
+@@ -407,6 +416,7 @@
+     
+     if(recall != NULL){
+       AgsAudioSignal *audio_signal;
++      AgsRecallID *current_recall_id;
+       
+       g_signal_connect_after(channel, "done\0",
+ 			     G_CALLBACK(ags_line_channel_done_callback), AGS_LINE(list->data));
+@@ -416,13 +426,25 @@
+       
+       recycling = channel->first_recycling;
+       end_recycling = channel->last_recycling->next;
++
++      current_recall_id = AGS_RECALL(recall->data)->recall_id;
+       
+       pthread_mutex_unlock(channel_mutex);
+ 
+       while(recycling != end_recycling){
++	/* get recycling mutex */
++	pthread_mutex_lock(application_mutex);
++  
++	recycling_mutex = ags_mutex_manager_lookup(mutex_manager,
++						   (GObject *) recycling);
++	
++	pthread_mutex_unlock(application_mutex);
++
++	/* instantiate audio signal */
+ 	audio_signal = ags_audio_signal_new((GObject *) soundcard,
+ 					    (GObject *) recycling,
+-					    (GObject *) AGS_RECALL(recall->data)->recall_id);
++					    (GObject *) current_recall_id);
++	
+ 	/* add audio signal */
+ 	ags_recycling_create_audio_signal_with_defaults(recycling,
+ 							audio_signal,
+@@ -436,7 +458,13 @@
+ 	ags_recycling_add_audio_signal(recycling,
+ 				       audio_signal);
+ 
++
++	/* iterate recycling */
++	pthread_mutex_lock(recycling_mutex);
++
+ 	recycling = recycling->next;
++
++	pthread_mutex_unlock(recycling_mutex);
+       }    
+     }
+ 
diff -Nru gsequencer-0.7.122/debian/patches/fix-thread-posix.patch gsequencer-0.7.122/debian/patches/fix-thread-posix.patch
--- gsequencer-0.7.122/debian/patches/fix-thread-posix.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-thread-posix.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,35 @@
+Description: This patch is considered critical since it fixes the beginning
+ of the data-race. It has a strong relation with soundcard output. Since
+ the start of threads has some uncertainity about when it is ready. It
+ has a need for 2 tics to be ready and not only 1.
+ Note this is a work-around, better would be add 1 tic to tic_delay field as
+ it's in sync. But it's not evident when it happens.
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-01-31
+--- a/ags/thread/ags_thread-posix.c
++++ b/ags/thread/ags_thread-posix.c
+@@ -2288,6 +2288,7 @@
+ 	
+ 	chaos_tree = ags_thread_chaos_tree(thread);
+ 
++	//FIXME:JK: it works but I think its wrong
+ 	/* set tic delay */
+ 	if((AGS_THREAD_INTERMEDIATE_PRE_SYNC & (g_atomic_int_get(&(thread->flags)))) != 0){
+ 	  /* intermediate pre sync */
+@@ -2298,10 +2299,12 @@
+ 	  }
+ 	}else if((AGS_THREAD_INTERMEDIATE_POST_SYNC & (g_atomic_int_get(&(thread->flags)))) != 0){
+ 	  /* intermediate post sync */
+-	  if(chaos_tree->tic_delay < thread->delay){
+-	    thread->tic_delay = chaos_tree->tic_delay + 1;
+-	  }else{
++	  if(chaos_tree->tic_delay + 1 < thread->delay){
++	    thread->tic_delay = chaos_tree->tic_delay + 2;
++	  }else if(chaos_tree->tic_delay + 1 == thread->delay){
+ 	    thread->tic_delay = 0;
++	  }else{
++	    thread->tic_delay = 1;
+ 	  }
+ 	}else{
+ 	  /* ordinary sync */
diff -Nru gsequencer-0.7.122/debian/patches/fix-xorg-application-context.patch gsequencer-0.7.122/debian/patches/fix-xorg-application-context.patch
--- gsequencer-0.7.122/debian/patches/fix-xorg-application-context.patch	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/fix-xorg-application-context.patch	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,45 @@
+Description: This patch is believed to be important. Since the was some critical
+ messages about not finding the type, we call it's appropriate get_type() function.
+Author: Joël Krähmann <jkraehemann@gmail.com>
+Applied-Upstream: 0.7.122.x, http://git.savannah.gnu.org/cgit/gsequencer.git
+Last-Update: 2017-02-01
+--- a/ags/X/ags_xorg_application_context.c
++++ b/ags/X/ags_xorg_application_context.c
+@@ -63,6 +63,9 @@
+ #include <ags/audio/jack/ags_jack_port.h>
+ #include <ags/audio/jack/ags_jack_devout.h>
+ 
++#include <ags/audio/task/ags_cancel_audio.h>
++#include <ags/audio/task/ags_cancel_channel.h>
++
+ #include <ags/audio/recall/ags_play_audio.h>
+ #include <ags/audio/recall/ags_play_channel.h>
+ #include <ags/audio/recall/ags_play_channel_run.h>
+@@ -634,10 +637,10 @@
+   */
+     
+   /* AgsWindow */
+-  window = ags_window_new((GObject *) xorg_application_context);
+-  g_object_set(window,
+-	       "soundcard\0", soundcard,
+-	       NULL);
++  window = g_object_new(AGS_TYPE_WINDOW,
++			"soundcard\0", soundcard,
++			"application-context\0", xorg_application_context,
++			NULL);
+   AGS_XORG_APPLICATION_CONTEXT(xorg_application_context)->window = window;
+   g_object_ref(G_OBJECT(window));
+ 
+@@ -982,6 +985,12 @@
+   /*  */
+   ags_audio_file_get_type();
+   ags_audio_file_link_get_type();
++
++  /* register tasks */
++  ags_cancel_audio_get_type();
++  ags_cancel_channel_get_type();
++  
++  //TODO:JK: extend me
+   
+   /* register recalls */
+   ags_recall_channel_run_dummy_get_type();
diff -Nru gsequencer-0.7.122/debian/patches/series gsequencer-0.7.122/debian/patches/series
--- gsequencer-0.7.122/debian/patches/series	1970-01-01 01:00:00.000000000 +0100
+++ gsequencer-0.7.122/debian/patches/series	2017-02-01 10:25:06.000000000 +0100
@@ -0,0 +1,15 @@
+fix-xorg-application-context.patch
+fix-thread-posix.patch
+fix-makefile-am.patch
+fix-machine-selector.patch
+fix-pad-callbacks.patch
+fix-line-callbacks.patch
+fix-export-soundcard-callbacks.patch
+fix-jack-devout.patch
+fix-jack-client.patch
+fix-delay-audio-run.patch
+fix-count-beats-audio-run.patch
+fix-copy-pattern-channel-run.patch
+fix-clear-buffer-h.patch
+fix-clear-buffer-c.patch
+fix-devout.patch
diff -Nru gsequencer-0.7.122/debian/rules gsequencer-0.7.122/debian/rules
--- gsequencer-0.7.122/debian/rules	2017-01-03 17:02:45.000000000 +0100
+++ gsequencer-0.7.122/debian/rules	2017-01-31 10:31:42.000000000 +0100
@@ -11,7 +11,13 @@
 else
   archconfflags += --disable-alsa
 endif
-archconfflags += --enable-oss
+
+
+ifeq ($(DEB_HOST_ARCH_OS),kfreebsd)
+  archconfflags += --enable-oss
+else
+  archconfflags += --disable-oss
+endif
 
 archconfflags += --enable-gtk-doc --enable-gtk-doc-html
 

--- End Message ---
--- Begin Message ---
Joël Krähemann:
> Package: release.debian.org
> Severity: normal
> User: release.debian.org@packages.debian.org
> Usertags: unblock
> 
> Please unblock package gsequencer
> 
> There are some important bug-fixes available to gsequencer-0.7.122.
> The fixes provide improvements to application stability. It might
> look like there are many lines in the debdiff but the changes
> are rather small und they use proven concepts.
> 
> (include/attach the debdiff against the package in testing)
> 
> unblock gsequencer/0.7.122-2
> 
> [...]

Unblocked, thanks.

~Niels

--- End Message ---

Reply to: