--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian....@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-gu...@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 <jkraehem...@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 <jkraehem...@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 <jkraehem...@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 <jkraehem...@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 <jkraehem...@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 <jkraehem...@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 <jkraehem...@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 <jkraehem...@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 <jkraehem...@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 <jkraehem...@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 <jkraehem...@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 <jkraehem...@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 <jkraehem...@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 <jkraehem...@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 <jkraehem...@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 ---