[SCM] gsequencer/master: Imported Upstream version 0.6.0

jkraehemann-guest at users.alioth.debian.org jkraehemann-guest at users.alioth.debian.org
Sat Sep 12 21:15:30 UTC 2015


The following commit has been merged in the master branch:
commit f521820170e2521d12a2b7b53fb8a9a08bde9f89
Author: Joël Krähemann <jkraehemann-guest at users.alioth.debian.org>
Date:   Sat Sep 12 23:06:36 2015 +0200

    Imported Upstream version 0.6.0

diff --git a/ChangeLog b/ChangeLog
index 3501232..760b183 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+ags (0.6.0)
+
+	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]u
+	* Implemented basic accessibility thus refactored AgsDrum and AgsMatrix. Further enhanced AgsPatternEdit and AgsNoteEdit.
+
 ags (0.5.12)
 
 	[ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
diff --git a/Makefile.am b/Makefile.am
index 5f7313d..e7fa381 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -182,6 +182,7 @@ gsequencerheaders = \
 	src/ags/audio/task/ags_apply_synth.h \
 	src/ags/audio/task/ags_apply_wavetable.h \
 	src/ags/audio/task/ags_audio_set_recycling.h \
+	src/ags/audio/task/ags_blink_cell_pattern_cursor.h \
 	src/ags/audio/task/ags_cancel_audio.h \
 	src/ags/audio/task/ags_cancel_channel.h \
 	src/ags/audio/task/ags_cancel_recall.h \
@@ -376,6 +377,8 @@ gsequencerheaders = \
 	src/ags/X/editor/ags_toolbar_callbacks.h \
 	src/ags/X/editor/ags_toolbar.h \
 	src/ags/X/editor/ags_toolbar_mode_stock.h \
+	src/ags/X/machine/ags_cell_pattern_callbacks.h \
+	src/ags/X/machine/ags_cell_pattern.h \
 	src/ags/X/machine/ags_drum_callbacks.h \
 	src/ags/X/machine/ags_drum.h \
 	src/ags/X/machine/ags_drum_input_line_callbacks.h \
@@ -400,6 +403,8 @@ gsequencerheaders = \
 	src/ags/X/machine/ags_panel.h \
 	src/ags/X/machine/ags_panel_input_line.h \
 	src/ags/X/machine/ags_panel_input_pad.h \
+	src/ags/X/machine/ags_pattern_box_callbacks.h \
+	src/ags/X/machine/ags_pattern_box.h \
 	src/ags/X/machine/ags_synth_callbacks.h \
 	src/ags/X/machine/ags_synth.h \
 	src/ags/X/machine/ags_synth_input_line.h \
@@ -516,6 +521,7 @@ gsequencer_SOURCES = \
 	src/ags/audio/task/ags_apply_synth.c \
 	src/ags/audio/task/ags_apply_wavetable.c \
 	src/ags/audio/task/ags_audio_set_recycling.c \
+	src/ags/audio/task/ags_blink_cell_pattern_cursor.c \
 	src/ags/audio/task/ags_cancel_audio.c \
 	src/ags/audio/task/ags_cancel_channel.c \
 	src/ags/audio/task/ags_cancel_recall.c \
@@ -705,6 +711,8 @@ gsequencer_SOURCES = \
 	src/ags/X/editor/ags_sf2_chooser_callbacks.c \
 	src/ags/X/editor/ags_toolbar.c \
 	src/ags/X/editor/ags_toolbar_callbacks.c \
+	src/ags/X/machine/ags_cell_pattern.c \
+	src/ags/X/machine/ags_cell_pattern_callbacks.c \
 	src/ags/X/machine/ags_drum.c \
 	src/ags/X/machine/ags_drum_callbacks.c \
 	src/ags/X/machine/ags_drum_input_line.c \
@@ -729,6 +737,8 @@ gsequencer_SOURCES = \
 	src/ags/X/machine/ags_panel_callbacks.c \
 	src/ags/X/machine/ags_panel_input_line.c \
 	src/ags/X/machine/ags_panel_input_pad.c \
+	src/ags/X/machine/ags_pattern_box_callbacks.c \
+	src/ags/X/machine/ags_pattern_box.c \
 	src/ags/X/machine/ags_synth.c \
 	src/ags/X/machine/ags_synth_callbacks.c \
 	src/ags/X/machine/ags_synth_input_line.c \
diff --git a/Makefile.in b/Makefile.in
index 8283efe..c7db908 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -213,6 +213,7 @@ am_gsequencer_OBJECTS = $(am__objects_1) \
 	gsequencer-ags_apply_synth.$(OBJEXT) \
 	gsequencer-ags_apply_wavetable.$(OBJEXT) \
 	gsequencer-ags_audio_set_recycling.$(OBJEXT) \
+	gsequencer-ags_blink_cell_pattern_cursor.$(OBJEXT) \
 	gsequencer-ags_cancel_audio.$(OBJEXT) \
 	gsequencer-ags_cancel_channel.$(OBJEXT) \
 	gsequencer-ags_cancel_recall.$(OBJEXT) \
@@ -399,6 +400,8 @@ am_gsequencer_OBJECTS = $(am__objects_1) \
 	gsequencer-ags_sf2_chooser_callbacks.$(OBJEXT) \
 	gsequencer-ags_toolbar.$(OBJEXT) \
 	gsequencer-ags_toolbar_callbacks.$(OBJEXT) \
+	gsequencer-ags_cell_pattern.$(OBJEXT) \
+	gsequencer-ags_cell_pattern_callbacks.$(OBJEXT) \
 	gsequencer-ags_drum.$(OBJEXT) \
 	gsequencer-ags_drum_callbacks.$(OBJEXT) \
 	gsequencer-ags_drum_input_line.$(OBJEXT) \
@@ -423,6 +426,8 @@ am_gsequencer_OBJECTS = $(am__objects_1) \
 	gsequencer-ags_panel_callbacks.$(OBJEXT) \
 	gsequencer-ags_panel_input_line.$(OBJEXT) \
 	gsequencer-ags_panel_input_pad.$(OBJEXT) \
+	gsequencer-ags_pattern_box_callbacks.$(OBJEXT) \
+	gsequencer-ags_pattern_box.$(OBJEXT) \
 	gsequencer-ags_synth.$(OBJEXT) \
 	gsequencer-ags_synth_callbacks.$(OBJEXT) \
 	gsequencer-ags_synth_input_line.$(OBJEXT) \
@@ -658,6 +663,7 @@ pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
+runstatedir = @runstatedir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
@@ -836,6 +842,7 @@ gsequencerheaders = \
 	src/ags/audio/task/ags_apply_synth.h \
 	src/ags/audio/task/ags_apply_wavetable.h \
 	src/ags/audio/task/ags_audio_set_recycling.h \
+	src/ags/audio/task/ags_blink_cell_pattern_cursor.h \
 	src/ags/audio/task/ags_cancel_audio.h \
 	src/ags/audio/task/ags_cancel_channel.h \
 	src/ags/audio/task/ags_cancel_recall.h \
@@ -1030,6 +1037,8 @@ gsequencerheaders = \
 	src/ags/X/editor/ags_toolbar_callbacks.h \
 	src/ags/X/editor/ags_toolbar.h \
 	src/ags/X/editor/ags_toolbar_mode_stock.h \
+	src/ags/X/machine/ags_cell_pattern_callbacks.h \
+	src/ags/X/machine/ags_cell_pattern.h \
 	src/ags/X/machine/ags_drum_callbacks.h \
 	src/ags/X/machine/ags_drum.h \
 	src/ags/X/machine/ags_drum_input_line_callbacks.h \
@@ -1054,6 +1063,8 @@ gsequencerheaders = \
 	src/ags/X/machine/ags_panel.h \
 	src/ags/X/machine/ags_panel_input_line.h \
 	src/ags/X/machine/ags_panel_input_pad.h \
+	src/ags/X/machine/ags_pattern_box_callbacks.h \
+	src/ags/X/machine/ags_pattern_box.h \
 	src/ags/X/machine/ags_synth_callbacks.h \
 	src/ags/X/machine/ags_synth.h \
 	src/ags/X/machine/ags_synth_input_line.h \
@@ -1170,6 +1181,7 @@ gsequencer_SOURCES = \
 	src/ags/audio/task/ags_apply_synth.c \
 	src/ags/audio/task/ags_apply_wavetable.c \
 	src/ags/audio/task/ags_audio_set_recycling.c \
+	src/ags/audio/task/ags_blink_cell_pattern_cursor.c \
 	src/ags/audio/task/ags_cancel_audio.c \
 	src/ags/audio/task/ags_cancel_channel.c \
 	src/ags/audio/task/ags_cancel_recall.c \
@@ -1359,6 +1371,8 @@ gsequencer_SOURCES = \
 	src/ags/X/editor/ags_sf2_chooser_callbacks.c \
 	src/ags/X/editor/ags_toolbar.c \
 	src/ags/X/editor/ags_toolbar_callbacks.c \
+	src/ags/X/machine/ags_cell_pattern.c \
+	src/ags/X/machine/ags_cell_pattern_callbacks.c \
 	src/ags/X/machine/ags_drum.c \
 	src/ags/X/machine/ags_drum_callbacks.c \
 	src/ags/X/machine/ags_drum_input_line.c \
@@ -1383,6 +1397,8 @@ gsequencer_SOURCES = \
 	src/ags/X/machine/ags_panel_callbacks.c \
 	src/ags/X/machine/ags_panel_input_line.c \
 	src/ags/X/machine/ags_panel_input_pad.c \
+	src/ags/X/machine/ags_pattern_box_callbacks.c \
+	src/ags/X/machine/ags_pattern_box.c \
 	src/ags/X/machine/ags_synth.c \
 	src/ags/X/machine/ags_synth_callbacks.c \
 	src/ags/X/machine/ags_synth_input_line.c \
@@ -1534,6 +1550,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_audio_signal.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_audio_thread.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_autosave_thread.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_blink_cell_pattern_cursor.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_buffer_audio_signal.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_buffer_channel.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_buffer_channel_run.Po at am__quote@
@@ -1542,6 +1559,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_cancel_channel.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_cancel_recall.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_cartesian.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_cell_pattern.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_cell_pattern_callbacks.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_change_indicator.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_change_tact.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_channel.Po at am__quote@
@@ -1705,6 +1724,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_panel_input_pad.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_parameter.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_pattern.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_pattern_box.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_pattern_box_callbacks.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_pattern_edit.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_pattern_edit_callbacks.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/gsequencer-ags_peak_audio_signal.Po at am__quote@
@@ -3374,6 +3395,20 @@ gsequencer-ags_audio_set_recycling.obj: src/ags/audio/task/ags_audio_set_recycli
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -c -o gsequencer-ags_audio_set_recycling.obj `if test -f 'src/ags/audio/task/ags_audio_set_recycling.c'; then $(CYGPATH_W) 'src/ags/audio/task/ags_audio_set_recycling.c'; else $(CYGPATH_W) '$(srcdir)/src/ags/audio/task/ags_audio_set_recycling.c'; fi`
 
+gsequencer-ags_blink_cell_pattern_cursor.o: src/ags/audio/task/ags_blink_cell_pattern_cursor.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -MT gsequencer-ags_blink_cell_pattern_cursor.o -MD -MP -MF $(DEPDIR)/gsequencer-ags_blink_cell_pattern_cursor.Tpo -c -o gsequencer-ags_blink_cell_pattern_cursor.o `test -f 'src/ags/audio/task/ags_blink_cell_pattern_cursor.c' || echo '$(srcdir)/'`src/ags/audio/task/ags_blink_cell_pattern_cursor.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/gsequencer-ags_blink_cell_pattern_cursor.Tpo $(DEPDIR)/gsequencer-ags_blink_cell_pattern_cursor.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/ags/audio/task/ags_blink_cell_pattern_cursor.c' object='gsequencer-ags_blink_cell_pattern_cursor.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -c -o gsequencer-ags_blink_cell_pattern_cursor.o `test -f 'src/ags/audio/task/ags_blink_cell_pattern_cursor.c' || echo '$(srcdir)/'`src/ags/audio/task/ags_blink_cell_pattern_cursor.c
+
+gsequencer-ags_blink_cell_pattern_cursor.obj: src/ags/audio/task/ags_blink_cell_pattern_cursor.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -MT gsequencer-ags_blink_cell_pattern_cursor.obj -MD -MP -MF $(DEPDIR)/gsequencer-ags_blink_cell_pattern_cursor.Tpo -c -o gsequencer-ags_blink_cell_pattern_cursor.obj `if test -f 'src/ags/audio/task/ags_blink_cell_pattern_cursor.c'; then $(CYGPATH_W) 'src/ags/audio/task/ags_blink_cell_pattern_cursor.c'; else $(CYGPATH_W) '$(srcdir)/src/ags/audio/task/ags_blink_cell_pattern_cursor.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/gsequencer-ags_blink_cell_pattern_cursor.Tpo $(DEPDIR)/gsequencer-ags_blink_cell_pattern_cursor.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/ags/audio/task/ags_blink_cell_pattern_cursor.c' object='gsequencer-ags_blink_cell_pattern_cursor.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -c -o gsequencer-ags_blink_cell_pattern_cursor.obj `if test -f 'src/ags/audio/task/ags_blink_cell_pattern_cursor.c'; then $(CYGPATH_W) 'src/ags/audio/task/ags_blink_cell_pattern_cursor.c'; else $(CYGPATH_W) '$(srcdir)/src/ags/audio/task/ags_blink_cell_pattern_cursor.c'; fi`
+
 gsequencer-ags_cancel_audio.o: src/ags/audio/task/ags_cancel_audio.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -MT gsequencer-ags_cancel_audio.o -MD -MP -MF $(DEPDIR)/gsequencer-ags_cancel_audio.Tpo -c -o gsequencer-ags_cancel_audio.o `test -f 'src/ags/audio/task/ags_cancel_audio.c' || echo '$(srcdir)/'`src/ags/audio/task/ags_cancel_audio.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/gsequencer-ags_cancel_audio.Tpo $(DEPDIR)/gsequencer-ags_cancel_audio.Po
@@ -6020,6 +6055,34 @@ gsequencer-ags_toolbar_callbacks.obj: src/ags/X/editor/ags_toolbar_callbacks.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -c -o gsequencer-ags_toolbar_callbacks.obj `if test -f 'src/ags/X/editor/ags_toolbar_callbacks.c'; then $(CYGPATH_W) 'src/ags/X/editor/ags_toolbar_callbacks.c'; else $(CYGPATH_W) '$(srcdir)/src/ags/X/editor/ags_toolbar_callbacks.c'; fi`
 
+gsequencer-ags_cell_pattern.o: src/ags/X/machine/ags_cell_pattern.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -MT gsequencer-ags_cell_pattern.o -MD -MP -MF $(DEPDIR)/gsequencer-ags_cell_pattern.Tpo -c -o gsequencer-ags_cell_pattern.o `test -f 'src/ags/X/machine/ags_cell_pattern.c' || echo '$(srcdir)/'`src/ags/X/machine/ags_cell_pattern.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/gsequencer-ags_cell_pattern.Tpo $(DEPDIR)/gsequencer-ags_cell_pattern.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/ags/X/machine/ags_cell_pattern.c' object='gsequencer-ags_cell_pattern.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -c -o gsequencer-ags_cell_pattern.o `test -f 'src/ags/X/machine/ags_cell_pattern.c' || echo '$(srcdir)/'`src/ags/X/machine/ags_cell_pattern.c
+
+gsequencer-ags_cell_pattern.obj: src/ags/X/machine/ags_cell_pattern.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -MT gsequencer-ags_cell_pattern.obj -MD -MP -MF $(DEPDIR)/gsequencer-ags_cell_pattern.Tpo -c -o gsequencer-ags_cell_pattern.obj `if test -f 'src/ags/X/machine/ags_cell_pattern.c'; then $(CYGPATH_W) 'src/ags/X/machine/ags_cell_pattern.c'; else $(CYGPATH_W) '$(srcdir)/src/ags/X/machine/ags_cell_pattern.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/gsequencer-ags_cell_pattern.Tpo $(DEPDIR)/gsequencer-ags_cell_pattern.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/ags/X/machine/ags_cell_pattern.c' object='gsequencer-ags_cell_pattern.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -c -o gsequencer-ags_cell_pattern.obj `if test -f 'src/ags/X/machine/ags_cell_pattern.c'; then $(CYGPATH_W) 'src/ags/X/machine/ags_cell_pattern.c'; else $(CYGPATH_W) '$(srcdir)/src/ags/X/machine/ags_cell_pattern.c'; fi`
+
+gsequencer-ags_cell_pattern_callbacks.o: src/ags/X/machine/ags_cell_pattern_callbacks.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -MT gsequencer-ags_cell_pattern_callbacks.o -MD -MP -MF $(DEPDIR)/gsequencer-ags_cell_pattern_callbacks.Tpo -c -o gsequencer-ags_cell_pattern_callbacks.o `test -f 'src/ags/X/machine/ags_cell_pattern_callbacks.c' || echo '$(srcdir)/'`src/ags/X/machine/ags_cell_pattern_callbacks.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/gsequencer-ags_cell_pattern_callbacks.Tpo $(DEPDIR)/gsequencer-ags_cell_pattern_callbacks.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/ags/X/machine/ags_cell_pattern_callbacks.c' object='gsequencer-ags_cell_pattern_callbacks.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -c -o gsequencer-ags_cell_pattern_callbacks.o `test -f 'src/ags/X/machine/ags_cell_pattern_callbacks.c' || echo '$(srcdir)/'`src/ags/X/machine/ags_cell_pattern_callbacks.c
+
+gsequencer-ags_cell_pattern_callbacks.obj: src/ags/X/machine/ags_cell_pattern_callbacks.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -MT gsequencer-ags_cell_pattern_callbacks.obj -MD -MP -MF $(DEPDIR)/gsequencer-ags_cell_pattern_callbacks.Tpo -c -o gsequencer-ags_cell_pattern_callbacks.obj `if test -f 'src/ags/X/machine/ags_cell_pattern_callbacks.c'; then $(CYGPATH_W) 'src/ags/X/machine/ags_cell_pattern_callbacks.c'; else $(CYGPATH_W) '$(srcdir)/src/ags/X/machine/ags_cell_pattern_callbacks.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/gsequencer-ags_cell_pattern_callbacks.Tpo $(DEPDIR)/gsequencer-ags_cell_pattern_callbacks.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/ags/X/machine/ags_cell_pattern_callbacks.c' object='gsequencer-ags_cell_pattern_callbacks.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -c -o gsequencer-ags_cell_pattern_callbacks.obj `if test -f 'src/ags/X/machine/ags_cell_pattern_callbacks.c'; then $(CYGPATH_W) 'src/ags/X/machine/ags_cell_pattern_callbacks.c'; else $(CYGPATH_W) '$(srcdir)/src/ags/X/machine/ags_cell_pattern_callbacks.c'; fi`
+
 gsequencer-ags_drum.o: src/ags/X/machine/ags_drum.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -MT gsequencer-ags_drum.o -MD -MP -MF $(DEPDIR)/gsequencer-ags_drum.Tpo -c -o gsequencer-ags_drum.o `test -f 'src/ags/X/machine/ags_drum.c' || echo '$(srcdir)/'`src/ags/X/machine/ags_drum.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/gsequencer-ags_drum.Tpo $(DEPDIR)/gsequencer-ags_drum.Po
@@ -6356,6 +6419,34 @@ gsequencer-ags_panel_input_pad.obj: src/ags/X/machine/ags_panel_input_pad.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -c -o gsequencer-ags_panel_input_pad.obj `if test -f 'src/ags/X/machine/ags_panel_input_pad.c'; then $(CYGPATH_W) 'src/ags/X/machine/ags_panel_input_pad.c'; else $(CYGPATH_W) '$(srcdir)/src/ags/X/machine/ags_panel_input_pad.c'; fi`
 
+gsequencer-ags_pattern_box_callbacks.o: src/ags/X/machine/ags_pattern_box_callbacks.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -MT gsequencer-ags_pattern_box_callbacks.o -MD -MP -MF $(DEPDIR)/gsequencer-ags_pattern_box_callbacks.Tpo -c -o gsequencer-ags_pattern_box_callbacks.o `test -f 'src/ags/X/machine/ags_pattern_box_callbacks.c' || echo '$(srcdir)/'`src/ags/X/machine/ags_pattern_box_callbacks.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/gsequencer-ags_pattern_box_callbacks.Tpo $(DEPDIR)/gsequencer-ags_pattern_box_callbacks.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/ags/X/machine/ags_pattern_box_callbacks.c' object='gsequencer-ags_pattern_box_callbacks.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -c -o gsequencer-ags_pattern_box_callbacks.o `test -f 'src/ags/X/machine/ags_pattern_box_callbacks.c' || echo '$(srcdir)/'`src/ags/X/machine/ags_pattern_box_callbacks.c
+
+gsequencer-ags_pattern_box_callbacks.obj: src/ags/X/machine/ags_pattern_box_callbacks.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -MT gsequencer-ags_pattern_box_callbacks.obj -MD -MP -MF $(DEPDIR)/gsequencer-ags_pattern_box_callbacks.Tpo -c -o gsequencer-ags_pattern_box_callbacks.obj `if test -f 'src/ags/X/machine/ags_pattern_box_callbacks.c'; then $(CYGPATH_W) 'src/ags/X/machine/ags_pattern_box_callbacks.c'; else $(CYGPATH_W) '$(srcdir)/src/ags/X/machine/ags_pattern_box_callbacks.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/gsequencer-ags_pattern_box_callbacks.Tpo $(DEPDIR)/gsequencer-ags_pattern_box_callbacks.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/ags/X/machine/ags_pattern_box_callbacks.c' object='gsequencer-ags_pattern_box_callbacks.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -c -o gsequencer-ags_pattern_box_callbacks.obj `if test -f 'src/ags/X/machine/ags_pattern_box_callbacks.c'; then $(CYGPATH_W) 'src/ags/X/machine/ags_pattern_box_callbacks.c'; else $(CYGPATH_W) '$(srcdir)/src/ags/X/machine/ags_pattern_box_callbacks.c'; fi`
+
+gsequencer-ags_pattern_box.o: src/ags/X/machine/ags_pattern_box.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -MT gsequencer-ags_pattern_box.o -MD -MP -MF $(DEPDIR)/gsequencer-ags_pattern_box.Tpo -c -o gsequencer-ags_pattern_box.o `test -f 'src/ags/X/machine/ags_pattern_box.c' || echo '$(srcdir)/'`src/ags/X/machine/ags_pattern_box.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/gsequencer-ags_pattern_box.Tpo $(DEPDIR)/gsequencer-ags_pattern_box.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/ags/X/machine/ags_pattern_box.c' object='gsequencer-ags_pattern_box.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -c -o gsequencer-ags_pattern_box.o `test -f 'src/ags/X/machine/ags_pattern_box.c' || echo '$(srcdir)/'`src/ags/X/machine/ags_pattern_box.c
+
+gsequencer-ags_pattern_box.obj: src/ags/X/machine/ags_pattern_box.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -MT gsequencer-ags_pattern_box.obj -MD -MP -MF $(DEPDIR)/gsequencer-ags_pattern_box.Tpo -c -o gsequencer-ags_pattern_box.obj `if test -f 'src/ags/X/machine/ags_pattern_box.c'; then $(CYGPATH_W) 'src/ags/X/machine/ags_pattern_box.c'; else $(CYGPATH_W) '$(srcdir)/src/ags/X/machine/ags_pattern_box.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/gsequencer-ags_pattern_box.Tpo $(DEPDIR)/gsequencer-ags_pattern_box.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/ags/X/machine/ags_pattern_box.c' object='gsequencer-ags_pattern_box.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -c -o gsequencer-ags_pattern_box.obj `if test -f 'src/ags/X/machine/ags_pattern_box.c'; then $(CYGPATH_W) 'src/ags/X/machine/ags_pattern_box.c'; else $(CYGPATH_W) '$(srcdir)/src/ags/X/machine/ags_pattern_box.c'; fi`
+
 gsequencer-ags_synth.o: src/ags/X/machine/ags_synth.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gsequencer_CFLAGS) $(CFLAGS) -MT gsequencer-ags_synth.o -MD -MP -MF $(DEPDIR)/gsequencer-ags_synth.Tpo -c -o gsequencer-ags_synth.o `test -f 'src/ags/X/machine/ags_synth.c' || echo '$(srcdir)/'`src/ags/X/machine/ags_synth.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/gsequencer-ags_synth.Tpo $(DEPDIR)/gsequencer-ags_synth.Po
diff --git a/configure b/configure
index 7197831..f029626 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for gsequencer 0.5.12.
+# Generated by GNU Autoconf 2.69 for gsequencer 0.6.0.
 #
 # Report bugs to <jkraehemann-guest at users.alioth.debian.org>.
 #
@@ -580,8 +580,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='gsequencer'
 PACKAGE_TARNAME='gsequencer'
-PACKAGE_VERSION='0.5.12'
-PACKAGE_STRING='gsequencer 0.5.12'
+PACKAGE_VERSION='0.6.0'
+PACKAGE_STRING='gsequencer 0.6.0'
 PACKAGE_BUGREPORT='jkraehemann-guest at users.alioth.debian.org'
 PACKAGE_URL=''
 
@@ -720,6 +720,7 @@ infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -819,6 +820,7 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1071,6 +1073,15 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1208,7 +1219,7 @@ fi
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir
+		libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1321,7 +1332,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures gsequencer 0.5.12 to adapt to many kinds of systems.
+\`configure' configures gsequencer 0.6.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1361,6 +1372,7 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -1391,7 +1403,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of gsequencer 0.5.12:";;
+     short | recursive ) echo "Configuration of gsequencer 0.6.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1531,7 +1543,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-gsequencer configure 0.5.12
+gsequencer configure 0.6.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2008,7 +2020,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by gsequencer $as_me 0.5.12, which was
+It was created by gsequencer $as_me 0.6.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2874,7 +2886,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='gsequencer'
- VERSION='0.5.12'
+ VERSION='0.6.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -7263,7 +7275,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by gsequencer $as_me 0.5.12, which was
+This file was extended by gsequencer $as_me 0.6.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -7329,7 +7341,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-gsequencer config.status 0.5.12
+gsequencer config.status 0.6.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index e924fc0..6e3b7f5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ([2.69])
-AC_INIT([gsequencer],[0.5.12],[jkraehemann-guest at users.alioth.debian.org])
+AC_INIT([gsequencer],[0.6.0],[jkraehemann-guest at users.alioth.debian.org])
 AM_INIT_AUTOMAKE([foreign])
 AC_CONFIG_SRCDIR([config.h.in])
 AC_CONFIG_HEADERS([config.h])
diff --git a/src/ags/X/ags_line.c b/src/ags/X/ags_line.c
index c633292..c48bbab 100644
--- a/src/ags/X/ags_line.c
+++ b/src/ags/X/ags_line.c
@@ -294,8 +294,11 @@ ags_line_init(AgsLine *line)
 
   line->channel = NULL;
 
-  line->pad = NULL;
+  //  gtk_widget_set_can_focus(line,
+  //			   TRUE);
 
+  line->pad = NULL;
+  
   line->label = (GtkLabel *) gtk_label_new(NULL);
   gtk_box_pack_start(GTK_BOX(line),
 		     GTK_WIDGET(line->label),
diff --git a/src/ags/X/ags_machine.c b/src/ags/X/ags_machine.c
index 3d1493a..315a4ff 100644
--- a/src/ags/X/ags_machine.c
+++ b/src/ags/X/ags_machine.c
@@ -37,6 +37,7 @@
 
 #include <ags/audio/ags_output.h>
 #include <ags/audio/ags_input.h>
+#include <ags/audio/ags_pattern.h>
 
 #include <ags/audio/file/ags_audio_file.h>
 
@@ -251,7 +252,9 @@ ags_machine_plugin_interface_init(AgsPluginInterface *plugin)
 void
 ags_machine_init(AgsMachine *machine)
 {
+  GtkVBox *vbox;
   GtkFrame *frame;
+  GtkMenuToolButton *menu_tool_button;
 
   machine->flags = 0;
   machine->file_input_flags = 0;
@@ -267,6 +270,8 @@ ags_machine_init(AgsMachine *machine)
 
   machine->bank_0 = 0;
   machine->bank_1 = 0;
+
+  vbox = gtk_vbox_new(FALSE, 0);
   
   frame = (GtkFrame *) gtk_frame_new(NULL);
   gtk_container_add((GtkContainer *) machine, (GtkWidget *) frame);
@@ -285,11 +290,21 @@ ags_machine_init(AgsMachine *machine)
   machine->play = NULL;
 
   machine->output = NULL;
+  machine->selected_output_pad = NULL;
+
   machine->input = NULL;
+  machine->selected_input_pad = NULL;
 
   machine->port = NULL;
 
   machine->popup = ags_machine_popup_new(machine);
+
+  menu_tool_button = g_object_new(GTK_TYPE_MENU_TOOL_BUTTON,
+				  "label\0", "machine\0",
+				  "menu\0", machine->popup,
+				  NULL);
+  gtk_frame_set_label_widget(frame,
+			     menu_tool_button);
   machine->properties = NULL;
   machine->rename = NULL;
 }
@@ -558,8 +573,8 @@ ags_machine_connect(AgsConnectable *connectable)
   }
 
   /* GtkWidget */
-  g_signal_connect(G_OBJECT (machine), "button_press_event\0",
-		   G_CALLBACK(ags_machine_button_press_callback), (gpointer) machine);
+  //  g_signal_connect(G_OBJECT (machine), "button_press_event\0",
+  //		   G_CALLBACK(ags_machine_button_press_callback), (gpointer) machine);
 
   /* AgsPad - input */
   if(machine->input != NULL){
@@ -1196,6 +1211,112 @@ ags_machine_open_files(AgsMachine *machine,
 
 }
 
+void
+ags_machine_copy_pattern(AgsMachine *machine)
+{
+  AgsChannel *channel;
+  
+  xmlDoc *clipboard;
+  xmlNode *audio_node, *notation_node;
+
+  xmlChar *buffer;
+  int size;
+  gint i;
+
+  auto xmlNode* ags_machine_copy_pattern_to_notation(AgsChannel *current);
+
+  xmlNode* ags_machine_copy_pattern_to_notation(AgsChannel *current){
+    AgsPattern *pattern;
+    xmlNode *notation_node, *current_note;
+    guint x_boundary, y_boundary;
+    guint bank_0, bank_1, k;
+    
+    /* create root node */
+    notation_node = xmlNewNode(NULL, BAD_CAST "notation\0");
+
+    xmlNewProp(notation_node, BAD_CAST "program\0", BAD_CAST "ags\0");
+    xmlNewProp(notation_node, BAD_CAST "type\0", BAD_CAST AGS_NOTATION_CLIPBOARD_TYPE);
+    xmlNewProp(notation_node, BAD_CAST "version\0", BAD_CAST AGS_NOTATION_CLIPBOARD_VERSION);
+    xmlNewProp(notation_node, BAD_CAST "format\0", BAD_CAST AGS_NOTATION_CLIPBOARD_FORMAT);
+    xmlNewProp(notation_node, BAD_CAST "base_frequency\0", BAD_CAST g_strdup("0\0"));
+    xmlNewProp(notation_node, BAD_CAST "audio-channel\0", BAD_CAST g_strdup_printf("%u\0", current->audio_channel));
+
+    bank_0 = machine->bank_0;
+    bank_1 = machine->bank_1;
+    
+    x_boundary = G_MAXUINT;
+    y_boundary = G_MAXUINT;
+
+    while(current != NULL){
+      pattern = current->pattern->data;
+
+      for(k = 0; k < pattern->dim[2]; k++){
+	if(ags_pattern_get_bit(pattern, bank_0, bank_1, k)){
+	  current_note = xmlNewChild(notation_node, NULL, BAD_CAST "note\0", NULL);
+	  
+	  xmlNewProp(current_note, BAD_CAST "x\0", BAD_CAST g_strdup_printf("%u\0", k));
+	  xmlNewProp(current_note, BAD_CAST "x1\0", BAD_CAST g_strdup_printf("%u\0", k + 1));
+
+	  if((AGS_MACHINE_REVERSE_NOTATION & (machine->flags)) != 0){
+	    xmlNewProp(current_note, BAD_CAST "y\0", BAD_CAST g_strdup_printf("%u\0", machine->audio->input_pads - current->pad - 1));
+	  }else{
+	    xmlNewProp(current_note, BAD_CAST "y\0", BAD_CAST g_strdup_printf("%u\0", current->pad));
+	  }
+	  
+	  if(x_boundary > k){
+	    x_boundary = k;
+	  }
+      
+	  if((AGS_MACHINE_REVERSE_NOTATION & (machine->flags)) != 0){
+	    guint tmp;
+
+	    tmp = machine->audio->input_pads - current->pad - 1;
+	    
+	    if(y_boundary > tmp){
+	      y_boundary = tmp;
+	    }
+	  }else{
+	    if(y_boundary > current->pad){
+	      y_boundary = current->pad;
+	    }
+	  }
+	}
+      }
+      
+      current = current->next;
+    }
+
+    xmlNewProp(notation_node, BAD_CAST "x_boundary\0", BAD_CAST g_strdup_printf("%u\0", x_boundary));
+    xmlNewProp(notation_node, BAD_CAST "y_boundary\0", BAD_CAST g_strdup_printf("%u\0", y_boundary));
+
+    return(notation_node);
+  }
+  
+  /* create document */
+  clipboard = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
+
+  /* create root node */
+  audio_node = xmlNewNode(NULL, BAD_CAST "audio\0");
+  xmlDocSetRootElement(clipboard, audio_node);
+  
+  channel = machine->audio->input;
+  
+  for(i = 0; i < machine->audio->audio_channels; i++){
+    notation_node = ags_machine_copy_pattern_to_notation(channel);
+    xmlAddChild(audio_node, notation_node);
+
+    channel = channel->next;
+  }
+  
+  /* write to clipboard */
+  xmlDocDumpFormatMemoryEnc(clipboard, &buffer, &size, "UTF-8\0", TRUE);
+  gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
+			 buffer, size);
+  gtk_clipboard_store(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
+  
+  xmlFreeDoc(clipboard);
+}
+
 /**
  * ags_machine_new:
  * @devout: the assigned devout.
diff --git a/src/ags/X/ags_machine.h b/src/ags/X/ags_machine.h
index 9e6d6ab..57d6737 100644
--- a/src/ags/X/ags_machine.h
+++ b/src/ags/X/ags_machine.h
@@ -94,9 +94,13 @@ struct _AgsMachine
   GType output_line_type;
   GtkContainer *output;
 
+  GtkWidget *selected_output_pad;
+  
   GType input_pad_type;
   GType input_line_type;
   GtkContainer *input;
+  
+  GtkWidget *selected_input_pad;
 
   GList *port;
 
@@ -146,6 +150,8 @@ void ags_machine_open_files(AgsMachine *machine,
 			    gboolean overwrite_channels,
 			    gboolean create_channels);
 
+void ags_machine_copy_pattern(AgsMachine *machine);
+
 AgsMachine* ags_machine_new(GObject *devout);
 
 #endif /*__AGS_MACHINE_H__*/
diff --git a/src/ags/X/ags_machine_callbacks.c b/src/ags/X/ags_machine_callbacks.c
index 2893e56..bdcf71c 100644
--- a/src/ags/X/ags_machine_callbacks.c
+++ b/src/ags/X/ags_machine_callbacks.c
@@ -29,7 +29,6 @@
 #include <ags/thread/ags_task_thread.h>
 
 #include <ags/audio/ags_channel.h>
-#include <ags/audio/ags_pattern.h>
 #include <ags/audio/ags_notation.h>
 
 #include <ags/audio/task/ags_start_devout.h>
@@ -246,107 +245,7 @@ ags_machine_popup_properties_destroy_callback(GtkWidget *widget, AgsMachine *mac
 int
 ags_machine_popup_copy_pattern_callback(GtkWidget *widget, AgsMachine *machine)
 {
-  AgsChannel *channel;
-  
-  xmlDoc *clipboard;
-  xmlNode *audio_node, *notation_node;
-
-  xmlChar *buffer;
-  int size;
-  gint i;
-
-  auto xmlNode* ags_machine_popup_copy_pattern_callback_to_notation(AgsChannel *current);
-
-  xmlNode* ags_machine_popup_copy_pattern_callback_to_notation(AgsChannel *current){
-    AgsPattern *pattern;
-    xmlNode *notation_node, *current_note;
-    guint x_boundary, y_boundary;
-    guint bank_0, bank_1, k;
-    
-    /* create root node */
-    notation_node = xmlNewNode(NULL, BAD_CAST "notation\0");
-
-    xmlNewProp(notation_node, BAD_CAST "program\0", BAD_CAST "ags\0");
-    xmlNewProp(notation_node, BAD_CAST "type\0", BAD_CAST AGS_NOTATION_CLIPBOARD_TYPE);
-    xmlNewProp(notation_node, BAD_CAST "version\0", BAD_CAST AGS_NOTATION_CLIPBOARD_VERSION);
-    xmlNewProp(notation_node, BAD_CAST "format\0", BAD_CAST AGS_NOTATION_CLIPBOARD_FORMAT);
-    xmlNewProp(notation_node, BAD_CAST "base_frequency\0", BAD_CAST g_strdup("0\0"));
-    xmlNewProp(notation_node, BAD_CAST "audio-channel\0", BAD_CAST g_strdup_printf("%u\0", current->audio_channel));
-
-    bank_0 = machine->bank_0;
-    bank_1 = machine->bank_1;
-    
-    x_boundary = G_MAXUINT;
-    y_boundary = G_MAXUINT;
-
-    while(current != NULL){
-      pattern = current->pattern->data;
-
-      for(k = 0; k < pattern->dim[2]; k++){
-	if(ags_pattern_get_bit(pattern, bank_0, bank_1, k)){
-	  current_note = xmlNewChild(notation_node, NULL, BAD_CAST "note\0", NULL);
-	  
-	  xmlNewProp(current_note, BAD_CAST "x\0", BAD_CAST g_strdup_printf("%u\0", k));
-	  xmlNewProp(current_note, BAD_CAST "x1\0", BAD_CAST g_strdup_printf("%u\0", k + 1));
-
-	  if((AGS_MACHINE_REVERSE_NOTATION & (machine->flags)) != 0){
-	    xmlNewProp(current_note, BAD_CAST "y\0", BAD_CAST g_strdup_printf("%u\0", machine->audio->input_pads - current->pad - 1));
-	  }else{
-	    xmlNewProp(current_note, BAD_CAST "y\0", BAD_CAST g_strdup_printf("%u\0", current->pad));
-	  }
-	  
-	  if(x_boundary > k){
-	    x_boundary = k;
-	  }
-      
-	  if((AGS_MACHINE_REVERSE_NOTATION & (machine->flags)) != 0){
-	    guint tmp;
-
-	    tmp = machine->audio->input_pads - current->pad - 1;
-	    
-	    if(y_boundary > tmp){
-	      y_boundary = tmp;
-	    }
-	  }else{
-	    if(y_boundary > current->pad){
-	      y_boundary = current->pad;
-	    }
-	  }
-	}
-      }
-      
-      current = current->next;
-    }
-
-    xmlNewProp(notation_node, BAD_CAST "x_boundary\0", BAD_CAST g_strdup_printf("%u\0", x_boundary));
-    xmlNewProp(notation_node, BAD_CAST "y_boundary\0", BAD_CAST g_strdup_printf("%u\0", y_boundary));
-
-    return(notation_node);
-  }
-  
-  /* create document */
-  clipboard = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
-
-  /* create root node */
-  audio_node = xmlNewNode(NULL, BAD_CAST "audio\0");
-  xmlDocSetRootElement(clipboard, audio_node);
-  
-  channel = machine->audio->input;
-  
-  for(i = 0; i < machine->audio->audio_channels; i++){
-    notation_node = ags_machine_popup_copy_pattern_callback_to_notation(channel);
-    xmlAddChild(audio_node, notation_node);
-
-    channel = channel->next;
-  }
-  
-  /* write to clipboard */
-  xmlDocDumpFormatMemoryEnc(clipboard, &buffer, &size, "UTF-8\0", TRUE);
-  gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
-			 buffer, size);
-  gtk_clipboard_store(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
-  
-  xmlFreeDoc(clipboard);
+  ags_machine_copy_pattern(machine);
 
   return(0);
 }
@@ -354,7 +253,8 @@ ags_machine_popup_copy_pattern_callback(GtkWidget *widget, AgsMachine *machine)
 int
 ags_machine_popup_paste_pattern_callback(GtkWidget *widget, AgsMachine *machine)
 {
-
+  //TODO:JK: implement me
+  
   return(0);
 }
 
diff --git a/src/ags/X/ags_navigation.c b/src/ags/X/ags_navigation.c
index 7f52392..f01582e 100644
--- a/src/ags/X/ags_navigation.c
+++ b/src/ags/X/ags_navigation.c
@@ -198,7 +198,7 @@ ags_navigation_init(AgsNavigation *navigation)
 			 G_CALLBACK(ags_navigation_parent_set_callback), NULL);
 
   navigation->start_tact = 0.0;
-  
+
   /* GtkWidget */
   hbox = (GtkHBox *) gtk_hbox_new(FALSE, 0);
   gtk_box_pack_start((GtkBox *) navigation, (GtkWidget *) hbox, FALSE, FALSE, 2);
diff --git a/src/ags/X/ags_pad.c b/src/ags/X/ags_pad.c
index 1938e25..e8766bf 100644
--- a/src/ags/X/ags_pad.c
+++ b/src/ags/X/ags_pad.c
@@ -283,6 +283,7 @@ ags_pad_init(AgsPad *pad)
   pad->build_id = AGS_BUILD_ID;
 
   pad->cols = 2;
+
   pad->expander_set = ags_expander_set_new(1, 1);
   gtk_box_pack_start((GtkBox *) pad, (GtkWidget *) pad->expander_set, TRUE, TRUE, 0);
 
diff --git a/src/ags/X/editor/ags_note_edit.c b/src/ags/X/editor/ags_note_edit.c
index 1cf27e5..2b6f1bb 100644
--- a/src/ags/X/editor/ags_note_edit.c
+++ b/src/ags/X/editor/ags_note_edit.c
@@ -31,11 +31,33 @@
 
 #include <ags/X/editor/ags_note_edit.h>
 
+#include <gdk/gdkkeysyms.h>
+
+#include <atk/atk.h>
+
+static GType ags_accessible_note_edit_get_type(void);
 void ags_note_edit_class_init(AgsNoteEditClass *note_edit);
+void ags_accessible_note_edit_class_init(AtkObject *object);
+void ags_accessible_note_edit_action_interface_init(AtkActionIface *action);
 void ags_note_edit_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_note_edit_init(AgsNoteEdit *note_edit);
 void ags_note_edit_connect(AgsConnectable *connectable);
 void ags_note_edit_disconnect(AgsConnectable *connectable);
+AtkObject* ags_note_edit_get_accessible(GtkWidget *widget);
+
+gboolean ags_accessible_note_edit_do_action(AtkAction *action,
+					    gint i);
+gint ags_accessible_note_edit_get_n_actions(AtkAction *action);
+const gchar* ags_accessible_note_edit_get_description(AtkAction *action,
+						      gint i);
+const gchar* ags_accessible_note_edit_get_name(AtkAction *action,
+					       gint i);
+const gchar* ags_accessible_note_edit_get_keybinding(AtkAction *action,
+						     gint i);
+gboolean ags_accessible_note_edit_set_description(AtkAction *action,
+						  gint i);
+gchar* ags_accessible_note_edit_get_localized_name(AtkAction *action,
+						   gint i);
 
 /**
  * SECTION:ags_note_edit
@@ -51,6 +73,8 @@ GtkStyle *note_edit_style;
 
 extern pthread_mutex_t ags_application_mutex;
 
+static GQuark quark_accessible_object = 0;
+
 GType
 ags_note_edit_get_type(void)
 {
@@ -87,6 +111,42 @@ ags_note_edit_get_type(void)
   return(ags_type_note_edit);
 }
 
+static GType
+ags_accessible_note_edit_get_type(void)
+{
+  static GType ags_type_accessible_note_edit = 0;
+
+  if(!ags_type_accessible_note_edit){
+    const GTypeInfo ags_accesssible_note_edit_info = {
+      sizeof(GtkAccessibleClass),
+      NULL,           /* base_init */
+      NULL,           /* base_finalize */
+      (GClassInitFunc) ags_accessible_note_edit_class_init,
+      NULL,           /* class_finalize */
+      NULL,           /* class_data */
+      sizeof(GtkAccessible),
+      0,             /* n_preallocs */
+      NULL, NULL
+    };
+
+    static const GInterfaceInfo atk_action_interface_info = {
+      (GInterfaceInitFunc) ags_accessible_note_edit_action_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+    
+    ags_type_accessible_note_edit = g_type_register_static(GTK_TYPE_ACCESSIBLE,
+							   "AgsAccessibleNoteEdit\0", &ags_accesssible_note_edit_info,
+							   0);
+
+    g_type_add_interface_static(ags_type_accessible_note_edit,
+				ATK_TYPE_ACTION,
+				&atk_action_interface_info);
+  }
+  
+  return(ags_type_accessible_note_edit);
+}
+
 void
 ags_note_edit_connectable_interface_init(AgsConnectableInterface *connectable)
 {
@@ -99,6 +159,25 @@ ags_note_edit_connectable_interface_init(AgsConnectableInterface *connectable)
 void
 ags_note_edit_class_init(AgsNoteEditClass *note_edit)
 {
+  quark_accessible_object = g_quark_from_static_string("ags-accessible-object\0");
+}
+
+void
+ags_accessible_note_edit_class_init(AtkObject *object)
+{
+  /* empty */
+}
+
+void
+ags_accessible_note_edit_action_interface_init(AtkActionIface *action)
+{
+  action->do_action = ags_accessible_note_edit_do_action;
+  action->get_n_actions = ags_accessible_note_edit_get_n_actions;
+  action->get_description = ags_accessible_note_edit_get_description;
+  action->get_name = ags_accessible_note_edit_get_name;
+  action->get_keybinding = ags_accessible_note_edit_get_keybinding;
+  action->set_description = ags_accessible_note_edit_set_description;
+  action->get_localized_name = ags_accessible_note_edit_get_localized_name;
 }
 
 void
@@ -131,8 +210,7 @@ ags_note_edit_init(AgsNoteEdit *note_edit)
 			| GDK_POINTER_MOTION_HINT_MASK
 			| GDK_CONTROL_MASK
 			| GDK_KEY_PRESS_MASK
-			| GDK_KEY_RELEASE_MASK
-			);
+			| GDK_KEY_RELEASE_MASK);
   gtk_widget_set_can_focus(note_edit->drawing_area,
 			   TRUE);
   
@@ -242,7 +320,7 @@ ags_note_edit_connect(AgsConnectable *connectable)
 		   G_CALLBACK(ags_note_edit_drawing_area_key_press_event), (gpointer) note_edit);
 
   g_signal_connect((GObject *) note_edit->drawing_area, "key_release_event\0",
-		     G_CALLBACK(ags_note_edit_drawing_area_key_release_event), (gpointer) note_edit);
+		   G_CALLBACK(ags_note_edit_drawing_area_key_release_event), (gpointer) note_edit);
 
   g_signal_connect_after((GObject *) note_edit->vscrollbar, "value-changed\0",
 			 G_CALLBACK(ags_note_edit_vscrollbar_value_changed), (gpointer) note_edit);
@@ -257,6 +335,316 @@ ags_note_edit_disconnect(AgsConnectable *connectable)
   //TODO:JK: implement me
 }
 
+AtkObject*
+ags_note_edit_get_accessible(GtkWidget *widget)
+{
+  AtkObject* accessible;
+
+  accessible = g_object_get_qdata(G_OBJECT(widget),
+				    quark_accessible_object);
+  
+  if(!accessible){
+    accessible = g_object_new(ags_accessible_note_edit_get_type(),
+			      NULL);
+    
+    g_object_set_qdata(G_OBJECT(widget),
+		       quark_accessible_object,
+		       accessible);
+    gtk_accessible_set_widget(accessible,
+			      widget);
+  }
+  
+  return(accessible);
+}
+
+gboolean
+ags_accessible_note_edit_do_action(AtkAction *action,
+				   gint i)
+{
+  AgsNoteEdit *note_edit;
+  
+  GdkEventKey *key_press, *key_release;
+  GdkEventKey *modifier_press, *modifier_release;
+  GdkEventKey *second_level_press, *second_level_release;
+  
+  if(!(i >= 0 && i < 13)){
+    return(FALSE);
+  }
+
+  note_edit = gtk_accessible_get_widget(ATK_OBJECT(action));
+  
+  key_press = gdk_event_new(GDK_KEY_PRESS);
+  key_release = gdk_event_new(GDK_KEY_RELEASE);
+
+  /* create modifier */
+  modifier_press = gdk_event_new(GDK_KEY_PRESS);
+  modifier_release = gdk_event_new(GDK_KEY_RELEASE);
+  
+  modifier_press->keyval =
+    modifier_release->keyval = GDK_KEY_Control_R;
+
+  /* create second level */
+  second_level_press = gdk_event_new(GDK_KEY_PRESS);
+  second_level_release = gdk_event_new(GDK_KEY_RELEASE);
+  
+  second_level_press->keyval =
+    second_level_release->keyval = GDK_KEY_Shift_R;
+
+  switch(i){
+  case 0:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Left;
+      
+      /* send event */
+      gtk_widget_event(note_edit->drawing_area, key_press);
+      gtk_widget_event(note_edit->drawing_area, key_release);
+    }
+    break;
+  case 1:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Right;
+      
+      /* send event */
+      gtk_widget_event(note_edit->drawing_area, key_press);
+      gtk_widget_event(note_edit->drawing_area, key_release);
+    }
+    break;
+  case 2:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Up;
+    
+      /* send event */
+      gtk_widget_event(note_edit->drawing_area, key_press);
+      gtk_widget_event(note_edit->drawing_area, key_release);
+    }
+    break;
+  case 3:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Down;
+      
+      /* send event */
+      gtk_widget_event(note_edit->drawing_area, key_press);
+      gtk_widget_event(note_edit->drawing_area, key_release);
+    }
+    break;
+  case 4:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_space;
+      
+      /* send event */
+      gtk_widget_event(note_edit->drawing_area, key_press);
+      gtk_widget_event(note_edit->drawing_area, key_release);
+    }
+    break;
+  case 5:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Left;
+      
+      /* send event */
+      gtk_widget_event(note_edit->drawing_area, second_level_press);
+      gtk_widget_event(note_edit->drawing_area, key_press);
+      gtk_widget_event(note_edit->drawing_area, key_release);
+      gtk_widget_event(note_edit->drawing_area, second_level_release);
+    }
+    break;
+  case 6:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Right;
+      
+      /* send event */
+      gtk_widget_event(note_edit->drawing_area, second_level_press);
+      gtk_widget_event(note_edit->drawing_area, key_press);
+      gtk_widget_event(note_edit->drawing_area, key_release);
+      gtk_widget_event(note_edit->drawing_area, second_level_release);
+    }
+    break;
+  case 7:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Delete;
+      
+      /* send event */
+      gtk_widget_event(note_edit->drawing_area, key_press);
+      gtk_widget_event(note_edit->drawing_area, key_release);
+    }
+    break;
+  case 8:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_c;
+
+      /* send event */
+      gtk_widget_event(note_edit->drawing_area, modifier_press);
+      gtk_widget_event(note_edit->drawing_area, key_press);
+      gtk_widget_event(note_edit->drawing_area, key_release);
+      gtk_widget_event(note_edit->drawing_area, modifier_release);      
+    }    
+    break;
+  case 9:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_x;
+
+      /* send event */
+      gtk_widget_event(note_edit->drawing_area, modifier_press);
+      gtk_widget_event(note_edit->drawing_area, key_press);
+      gtk_widget_event(note_edit->drawing_area, key_release);
+      gtk_widget_event(note_edit->drawing_area, modifier_release);      
+    }
+    break;
+  case 10:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_v;
+
+      /* send event */
+      gtk_widget_event(note_edit->drawing_area, modifier_press);
+      gtk_widget_event(note_edit->drawing_area, key_press);
+      gtk_widget_event(note_edit->drawing_area, key_release);
+      gtk_widget_event(note_edit->drawing_area, modifier_release);      
+    }
+    break;
+  case 11:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_a;
+
+      /* send event */
+      gtk_widget_event(note_edit->drawing_area, modifier_press);
+      gtk_widget_event(note_edit->drawing_area, key_press);
+      gtk_widget_event(note_edit->drawing_area, key_release);
+      gtk_widget_event(note_edit->drawing_area, modifier_release);      
+    }
+    break;
+  case 12:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_i;
+
+      /* send event */
+      gtk_widget_event(note_edit->drawing_area, modifier_press);
+      gtk_widget_event(note_edit->drawing_area, key_press);
+      gtk_widget_event(note_edit->drawing_area, key_release);
+      gtk_widget_event(note_edit->drawing_area, modifier_release);      
+    }
+    break;
+  }
+
+  return(TRUE);
+}
+
+gint
+ags_accessible_note_edit_get_n_actions(AtkAction *action)
+{
+  return(13);
+}
+
+const gchar*
+ags_accessible_note_edit_get_description(AtkAction *action,
+					 gint i)
+{
+  static const gchar **actions = {
+    "move cursor left\0",
+    "move cursor right\0",
+    "move cursor up\0",
+    "move cursor down\0",
+    "add audio note\0",
+    "shrink audio note\0",
+    "grow audio note\0",
+    "remove audio note\0",
+    "copy note to clipboard\0",
+    "cut note to clipbaord\0",
+    "paste note from clipboard\0",
+    "select all note\0",
+    "invert note\0",
+  };
+
+  if(i >= 0 && i < 13){
+    return(actions[i]);
+  }else{
+    return(NULL);
+  }
+}
+
+const gchar*
+ags_accessible_note_edit_get_name(AtkAction *action,
+				  gint i)
+{
+  static const gchar **actions = {
+    "left\0",
+    "right\0",
+    "up\0",
+    "down\0",
+    "add\0",
+    "shrink\0",
+    "grow\0",
+    "remove\0",
+    "copy\0",
+    "cut\0",
+    "paste\0",
+    "select-all\0",
+    "invert\0",
+  };
+  
+  if(i >= 0 && i < 13){
+    return(actions[i]);
+  }else{
+    return(NULL);
+  }
+}
+
+const gchar*
+ags_accessible_note_edit_get_keybinding(AtkAction *action,
+					gint i)
+{
+  static const gchar **actions = {
+    "left\0",
+    "right\0",
+    "up\0",
+    "down\0",
+    "space",
+    "Shft+Left\0",
+    "Shft+Right\0",
+    "Del\0"
+    "Ctrl+c"
+    "Ctrl+x",
+    "Ctrl+v",
+    "Ctrl+a",
+    "Ctrl+i",
+  };
+  
+  if(i >= 0 && i < 13){
+    return(actions[i]);
+  }else{
+    return(NULL);
+  }
+}
+
+gboolean
+ags_accessible_note_edit_set_description(AtkAction *action,
+					 gint i)
+{
+  //TODO:JK: implement me
+
+  return(FALSE);
+}
+
+gchar*
+ags_accessible_note_edit_get_localized_name(AtkAction *action,
+					    gint i)
+{
+  //TODO:JK: implement me
+
+  return(NULL);
+}
+
 /**
  * ags_note_edit_set_map_height:
  * @note_edit: the #AgsNoteEdit
diff --git a/src/ags/X/editor/ags_note_edit.h b/src/ags/X/editor/ags_note_edit.h
index 48a0599..e18e71a 100644
--- a/src/ags/X/editor/ags_note_edit.h
+++ b/src/ags/X/editor/ags_note_edit.h
@@ -62,6 +62,8 @@ typedef enum{
 typedef enum{
   AGS_NOTE_EDIT_KEY_L_CONTROL       = 1,
   AGS_NOTE_EDIT_KEY_R_CONTROL       = 1 <<  1,
+  AGS_NOTE_EDIT_KEY_L_SHIFT         = 1 <<  2,
+  AGS_NOTE_EDIT_KEY_R_SHIFT         = 1 <<  3,
 }AgsNoteEditKeyMask;
 
 struct _AgsNoteEdit
@@ -130,7 +132,7 @@ struct _AgsNoteEdit
 
   guint selected_x;
   guint selected_y;
-  
+
   GtkVScrollbar *vscrollbar;
   GtkHScrollbar *hscrollbar;
 };
diff --git a/src/ags/X/editor/ags_note_edit_callbacks.c b/src/ags/X/editor/ags_note_edit_callbacks.c
index 27009c3..c0f3a79 100644
--- a/src/ags/X/editor/ags_note_edit_callbacks.c
+++ b/src/ags/X/editor/ags_note_edit_callbacks.c
@@ -896,6 +896,10 @@ ags_note_edit_drawing_area_key_press_event(GtkWidget *widget, GdkEventKey *event
 {
   AgsEditor *editor;
 
+  if(event->keyval == GDK_KEY_Tab){
+    return(FALSE);
+  }
+
   editor = (AgsEditor *) gtk_widget_get_ancestor(GTK_WIDGET(note_edit),
 						 AGS_TYPE_EDITOR);
 
@@ -912,6 +916,16 @@ ags_note_edit_drawing_area_key_press_event(GtkWidget *widget, GdkEventKey *event
 	note_edit->key_mask |= AGS_NOTE_EDIT_KEY_R_CONTROL;
       }
       break;
+    case GDK_KEY_Shift_L:
+      {
+	note_edit->key_mask |= AGS_NOTE_EDIT_KEY_L_SHIFT;
+      }
+      break;
+    case GDK_KEY_Shift_R:
+      {
+	note_edit->key_mask |= AGS_NOTE_EDIT_KEY_R_SHIFT;
+      }
+      break;
     case GDK_KEY_a:
       {
 	/* select all notes */
@@ -954,11 +968,22 @@ ags_note_edit_drawing_area_key_press_event(GtkWidget *widget, GdkEventKey *event
       break;
     }
   }
+
+  return(FALSE);
 }
 
 gboolean
 ags_note_edit_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *event, AgsNoteEdit *note_edit)
 {
+  AgsEditor *editor;
+
+  if(event->keyval == GDK_KEY_Tab){
+    return(FALSE);
+  }
+
+  editor = (AgsEditor *) gtk_widget_get_ancestor(GTK_WIDGET(note_edit),
+						 AGS_TYPE_EDITOR);
+
   switch(event->keyval){
   case GDK_KEY_Control_L:
     {
@@ -970,7 +995,242 @@ ags_note_edit_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *eve
       note_edit->key_mask &= (~AGS_NOTE_EDIT_KEY_R_CONTROL);
     }
     break;
+  case GDK_KEY_Shift_L:
+    {
+      note_edit->key_mask &= (~AGS_NOTE_EDIT_KEY_L_SHIFT);
+    }
+    break;
+  case GDK_KEY_Shift_R:
+    {
+      note_edit->key_mask &= (~AGS_NOTE_EDIT_KEY_R_SHIFT);
+    }
+    break;
+  case GDK_KEY_Left:
+  case GDK_KEY_leftarrow:
+    {
+      gdouble tact;
+      guint x0_offset;
+
+      tact = exp2(6.0 - (double) gtk_combo_box_get_active(editor->toolbar->zoom));
+
+      if((AGS_NOTE_EDIT_KEY_L_SHIFT & (note_edit->key_mask)) == 0 &&
+	 (AGS_NOTE_EDIT_KEY_R_SHIFT & (note_edit->key_mask)) == 0){
+	/* position cursor */
+	if(note_edit->selected_x > 0){
+	  if(note_edit->selected_x - (1 * tact) > 0){
+	    note_edit->selected_x -= (1 * tact);
+	  }else{
+	    note_edit->selected_x = 0;
+	  }
+	}
+
+	x0_offset = note_edit->selected_x * note_edit->control_unit.control_width;
+      
+	if(x0_offset < GTK_RANGE(note_edit->hscrollbar)->adjustment->value){
+	  gtk_range_set_value(GTK_RANGE(note_edit->hscrollbar),
+			      x0_offset * GTK_RANGE(note_edit->hscrollbar)->adjustment->step_increment);
+	}
+      }else{
+	AgsMachine *machine;
+	AgsNote *note;
+	GList *list_notation;
+	gint i;
+      
+	/* shrink note */
+	machine = editor->selected_machine;
+
+	i = 0;
+
+	while((i = ags_notebook_next_active_tab(editor->current_notebook,
+						i)) != -1){
+	  list_notation = g_list_nth(machine->audio->notation,
+				     i);
+
+	  if(list_notation == NULL){
+	    i++;
+	
+	    continue;
+	  }
+
+	  note = ags_notation_find_point(AGS_NOTATION(list_notation->data),
+					 note_edit->selected_x, note_edit->selected_y,
+					 FALSE);
+
+	  if(note->x[1] - note->x[0] - tact > tact){
+	    note->x[1] -= tact;
+	  }
+	  
+	  i++;
+	}
+      }
+      
+      gtk_widget_queue_draw(note_edit);
+    }
+    break;
+  case GDK_KEY_Right:
+  case GDK_KEY_rightarrow:
+    {
+      gdouble tact;
+      guint x0_offset;
+
+      tact = exp2(6.0 - (double) gtk_combo_box_get_active(editor->toolbar->zoom));
+      
+      if((AGS_NOTE_EDIT_KEY_L_SHIFT & (note_edit->key_mask)) == 0 &&
+	 (AGS_NOTE_EDIT_KEY_R_SHIFT & (note_edit->key_mask)) == 0){
+	/* position cursor */      
+	if(note_edit->selected_x < 16.0 * AGS_NOTE_EDIT_MAX_CONTROLS){
+	  note_edit->selected_x += (1.0 * tact);
+	}
+
+	x0_offset = note_edit->selected_x * note_edit->control_unit.control_width;
+      
+	if(x0_offset + note_edit->control_current.control_width > GTK_RANGE(note_edit->hscrollbar)->adjustment->value + GTK_WIDGET(note_edit->drawing_area)->allocation.width){
+	  gtk_range_set_value(GTK_RANGE(note_edit->hscrollbar),
+			      x0_offset * GTK_RANGE(note_edit->hscrollbar)->adjustment->step_increment);
+	}
+      }else{
+	AgsMachine *machine;
+	AgsNote *note;
+	GList *list_notation;
+	gint i;
+      
+	/* grow note */
+	machine = editor->selected_machine;
+
+	i = 0;
+
+	while((i = ags_notebook_next_active_tab(editor->current_notebook,
+						i)) != -1){
+	  list_notation = g_list_nth(machine->audio->notation,
+				     i);
+
+	  if(list_notation == NULL){
+	    i++;
+	
+	    continue;
+	  }
+
+	  note = ags_notation_find_point(AGS_NOTATION(list_notation->data),
+					 note_edit->selected_x, note_edit->selected_y,
+					 FALSE);
+	  note->x[1] += tact;
+	
+	  i++;
+	}
+      }
+      
+      gtk_widget_queue_draw(note_edit);
+    }
+    break;
+  case GDK_KEY_Up:
+  case GDK_KEY_uparrow:
+    {
+      gdouble y0_offset;
+      
+      if(note_edit->selected_y > 0){
+	note_edit->selected_y -= 1;
+      }
+
+      y0_offset = note_edit->selected_y * note_edit->control_height;
+      
+      if(y0_offset < GTK_RANGE(note_edit->vscrollbar)->adjustment->value){
+	gtk_range_set_value(GTK_RANGE(note_edit->vscrollbar),
+			    y0_offset * GTK_RANGE(note_edit->vscrollbar)->adjustment->step_increment);
+      }
+
+      gtk_widget_queue_draw(note_edit);
+    }
+    break;
+  case GDK_KEY_Down:
+  case GDK_KEY_downarrow:
+    {
+      gdouble y0_offset;
+      
+      if(note_edit->selected_y * (note_edit->control_height) < note_edit->map_height){
+	note_edit->selected_y += 1;
+      }
+
+      y0_offset = note_edit->selected_y * note_edit->control_height;
+
+      if(y0_offset + note_edit->control_height > GTK_RANGE(note_edit->vscrollbar)->adjustment->value + (GTK_WIDGET(note_edit->drawing_area)->allocation.height)){
+	gtk_range_set_value(GTK_RANGE(note_edit->vscrollbar),
+			    y0_offset * GTK_RANGE(note_edit->vscrollbar)->adjustment->step_increment);
+      }
+
+      gtk_widget_queue_draw(note_edit);
+    }
+    break;
+  case GDK_KEY_space:
+    {
+      AgsMachine *machine;
+      AgsNote *note;
+      GList *list_notation;
+      gint i;
+      
+      machine = editor->selected_machine;
+
+      i = 0;
+
+      while((i = ags_notebook_next_active_tab(editor->current_notebook,
+					      i)) != -1){
+	list_notation = g_list_nth(machine->audio->notation,
+				   i);
+
+	if(list_notation == NULL){
+	  i++;
+	
+	  continue;
+	}
+      
+	note = ags_note_new();
+	note->x[0] = note_edit->selected_x;
+	note->x[1] = note_edit->selected_x + 1;
+	note->y = note_edit->selected_y;
+	
+	ags_notation_add_note(AGS_NOTATION(list_notation->data), note, FALSE);
+
+	i++;
+      }
+
+      gtk_widget_queue_draw(note_edit);
+
+      fprintf(stdout, "x0 = %llu\nx1 = %llu\ny  = %llu\n\n\0", (long long unsigned int) note->x[0], (long long unsigned int) note->x[1], (long long unsigned int) note->y);
+    }
+    break;
+  case GDK_KEY_Delete:
+    {
+      AgsMachine *machine;
+      AgsNote *note;
+      GList *list_notation;
+      gint i;
+      
+      machine = editor->selected_machine;
+
+      i = 0;
+
+      while((i = ags_notebook_next_active_tab(editor->current_notebook,
+					      i)) != -1){
+	list_notation = g_list_nth(machine->audio->notation,
+				   i);
+
+	if(list_notation == NULL){
+	  i++;
+	
+	  continue;
+	}
+
+	ags_notation_remove_note_at_position(AGS_NOTATION(list_notation->data),
+					     note_edit->selected_x, note_edit->selected_y);
+	
+	i++;
+      }
+
+      gtk_widget_queue_draw(note_edit);
+    }
+    break;
   }
+
+  return(TRUE);
 }
 
 void
diff --git a/src/ags/X/editor/ags_note_edit_callbacks.h b/src/ags/X/editor/ags_note_edit_callbacks.h
index 3d1f51f..8d28176 100644
--- a/src/ags/X/editor/ags_note_edit_callbacks.h
+++ b/src/ags/X/editor/ags_note_edit_callbacks.h
@@ -36,6 +36,7 @@ void ags_note_edit_set_pads_callback(AgsAudio *audio,
 
 gboolean ags_note_edit_drawing_area_expose_event(GtkWidget *widget, GdkEventExpose *event, AgsNoteEdit *note_edit);
 gboolean ags_note_edit_drawing_area_configure_event(GtkWidget *widget, GdkEventConfigure *event, AgsNoteEdit *note_edit);
+
 gboolean ags_note_edit_drawing_area_button_press_event(GtkWidget *widget, GdkEventButton *event, AgsNoteEdit *note_edit);
 gboolean ags_note_edit_drawing_area_button_release_event(GtkWidget *widget, GdkEventButton *event, AgsNoteEdit *note_edit);
 gboolean ags_note_edit_drawing_area_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, AgsNoteEdit *note_edit);
diff --git a/src/ags/X/editor/ags_pattern_edit.c b/src/ags/X/editor/ags_pattern_edit.c
index 2a7cedc..6c85ba3 100644
--- a/src/ags/X/editor/ags_pattern_edit.c
+++ b/src/ags/X/editor/ags_pattern_edit.c
@@ -31,11 +31,33 @@
 
 #include <ags/X/editor/ags_pattern_edit.h>
 
+#include <gdk/gdkkeysyms.h>
+
+#include <atk/atk.h>
+
+static GType ags_accessible_pattern_edit_get_type(void);
 void ags_pattern_edit_class_init(AgsPatternEditClass *pattern_edit);
+void ags_accessible_pattern_edit_class_init(AtkObject *object);
+void ags_accessible_pattern_edit_action_interface_init(AtkActionIface *action);
 void ags_pattern_edit_connectable_interface_init(AgsConnectableInterface *connectable);
 void ags_pattern_edit_init(AgsPatternEdit *pattern_edit);
 void ags_pattern_edit_connect(AgsConnectable *connectable);
 void ags_pattern_edit_disconnect(AgsConnectable *connectable);
+AtkObject* ags_pattern_edit_get_accessible(GtkWidget *widget);
+
+gboolean ags_accessible_pattern_edit_do_action(AtkAction *action,
+					       gint i);
+gint ags_accessible_pattern_edit_get_n_actions(AtkAction *action);
+const gchar* ags_accessible_pattern_edit_get_description(AtkAction *action,
+							 gint i);
+const gchar* ags_accessible_pattern_edit_get_name(AtkAction *action,
+						  gint i);
+const gchar* ags_accessible_pattern_edit_get_keybinding(AtkAction *action,
+							gint i);
+gboolean ags_accessible_pattern_edit_set_description(AtkAction *action,
+						     gint i);
+gchar* ags_accessible_pattern_edit_get_localized_name(AtkAction *action,
+						      gint i);
 
 void ags_pattern_edit_paint(AgsPatternEdit *pattern_edit);
 
@@ -53,6 +75,8 @@ GtkStyle *pattern_edit_style;
 
 extern pthread_mutex_t ags_application_mutex;
 
+static GQuark quark_accessible_object = 0;
+
 GType
 ags_pattern_edit_get_type(void)
 {
@@ -89,6 +113,42 @@ ags_pattern_edit_get_type(void)
   return(ags_type_pattern_edit);
 }
 
+static GType
+ags_accessible_pattern_edit_get_type(void)
+{
+  static GType ags_type_accessible_pattern_edit = 0;
+
+  if(!ags_type_accessible_pattern_edit){
+    const GTypeInfo ags_accesssible_pattern_edit_info = {
+      sizeof(GtkAccessibleClass),
+      NULL,           /* base_init */
+      NULL,           /* base_finalize */
+      (GClassInitFunc) ags_accessible_pattern_edit_class_init,
+      NULL,           /* class_finalize */
+      NULL,           /* class_data */
+      sizeof(GtkAccessible),
+      0,             /* n_preallocs */
+      NULL, NULL
+    };
+
+    static const GInterfaceInfo atk_action_interface_info = {
+      (GInterfaceInitFunc) ags_accessible_pattern_edit_action_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+    
+    ags_type_accessible_pattern_edit = g_type_register_static(GTK_TYPE_ACCESSIBLE,
+							      "AgsAccessiblePatternEdit\0", &ags_accesssible_pattern_edit_info,
+							      0);
+
+    g_type_add_interface_static(ags_type_accessible_pattern_edit,
+				ATK_TYPE_ACTION,
+				&atk_action_interface_info);
+  }
+  
+  return(ags_type_accessible_pattern_edit);
+}
+
 void
 ags_pattern_edit_connectable_interface_init(AgsConnectableInterface *connectable)
 {
@@ -101,6 +161,25 @@ ags_pattern_edit_connectable_interface_init(AgsConnectableInterface *connectable
 void
 ags_pattern_edit_class_init(AgsPatternEditClass *pattern_edit)
 {
+  quark_accessible_object = g_quark_from_static_string("ags-accessible-object\0");  
+}
+
+void
+ags_accessible_pattern_edit_class_init(AtkObject *object)
+{
+  /* empty */
+}
+
+void
+ags_accessible_pattern_edit_action_interface_init(AtkActionIface *action)
+{
+  action->do_action = ags_accessible_pattern_edit_do_action;
+  action->get_n_actions = ags_accessible_pattern_edit_get_n_actions;
+  action->get_description = ags_accessible_pattern_edit_get_description;
+  action->get_name = ags_accessible_pattern_edit_get_name;
+  action->get_keybinding = ags_accessible_pattern_edit_get_keybinding;
+  action->set_description = ags_accessible_pattern_edit_set_description;
+  action->get_localized_name = ags_accessible_pattern_edit_get_localized_name;
 }
 
 void
@@ -251,6 +330,278 @@ ags_pattern_edit_disconnect(AgsConnectable *connectable)
   //TODO:JK: implement me
 }
 
+AtkObject*
+ags_pattern_edit_get_accessible(GtkWidget *widget)
+{
+  AtkObject* accessible;
+
+  accessible = g_object_get_qdata(G_OBJECT(widget),
+				    quark_accessible_object);
+  
+  if(!accessible){
+    accessible = g_object_new(ags_accessible_pattern_edit_get_type(),
+			      NULL);
+    
+    g_object_set_qdata(G_OBJECT(widget),
+		       quark_accessible_object,
+		       accessible);
+    gtk_accessible_set_widget(accessible,
+			      widget);
+  }
+  
+  return(accessible);
+}
+
+gboolean
+ags_accessible_pattern_edit_do_action(AtkAction *action,
+				      gint i)
+{
+  AgsPatternEdit *pattern_edit;
+  
+  GdkEventKey *key_press, *key_release;
+  GdkEventKey *modifier_press, *modifier_release;
+  
+  if(!(i >= 0 && i < 11)){
+    return(FALSE);
+  }
+
+  pattern_edit = gtk_accessible_get_widget(ATK_OBJECT(action));
+  
+  key_press = gdk_event_new(GDK_KEY_PRESS);
+  key_release = gdk_event_new(GDK_KEY_RELEASE);
+
+  /* create modifier */
+  modifier_press = gdk_event_new(GDK_KEY_PRESS);
+  modifier_release = gdk_event_new(GDK_KEY_RELEASE);
+  
+  modifier_press->keyval =
+    modifier_release->keyval = GDK_KEY_Control_R;
+
+  switch(i){
+  case 0:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Left;
+      
+      /* send event */
+      gtk_widget_event(pattern_edit->drawing_area, key_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_release);
+    }
+    break;
+  case 1:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Right;
+      
+      /* send event */
+      gtk_widget_event(pattern_edit->drawing_area, key_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_release);
+    }
+    break;
+  case 2:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Up;
+    
+      /* send event */
+      gtk_widget_event(pattern_edit->drawing_area, key_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_release);
+    }
+    break;
+  case 3:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Down;
+      
+      /* send event */
+      gtk_widget_event(pattern_edit->drawing_area, key_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_release);
+    }
+    break;
+  case 4:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_space;
+      
+      /* send event */
+      gtk_widget_event(pattern_edit->drawing_area, key_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_release);
+    }
+    break;
+  case 5:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Delete;
+      
+      /* send event */
+      gtk_widget_event(pattern_edit->drawing_area, key_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_release);
+    }
+    break;
+  case 6:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_c;
+
+      /* send event */
+      gtk_widget_event(pattern_edit->drawing_area, modifier_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_release);
+      gtk_widget_event(pattern_edit->drawing_area, modifier_release);      
+    }    
+    break;
+  case 7:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_x;
+
+      /* send event */
+      gtk_widget_event(pattern_edit->drawing_area, modifier_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_release);
+      gtk_widget_event(pattern_edit->drawing_area, modifier_release);      
+    }
+    break;
+  case 8:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_v;
+
+      /* send event */
+      gtk_widget_event(pattern_edit->drawing_area, modifier_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_release);
+      gtk_widget_event(pattern_edit->drawing_area, modifier_release);      
+    }
+    break;
+  case 9:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_a;
+
+      /* send event */
+      gtk_widget_event(pattern_edit->drawing_area, modifier_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_release);
+      gtk_widget_event(pattern_edit->drawing_area, modifier_release);      
+    }
+    break;
+  case 10:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_i;
+
+      /* send event */
+      gtk_widget_event(pattern_edit->drawing_area, modifier_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_press);
+      gtk_widget_event(pattern_edit->drawing_area, key_release);
+      gtk_widget_event(pattern_edit->drawing_area, modifier_release);      
+    }
+    break;
+  }
+
+  return(TRUE);
+}
+
+gint
+ags_accessible_pattern_edit_get_n_actions(AtkAction *action)
+{
+  return(11);
+}
+
+const gchar*
+ags_accessible_pattern_edit_get_description(AtkAction *action,
+					    gint i)
+{
+  static const gchar **actions = {
+    "move cursor left\0",
+    "move cursor right\0",
+    "move cursor up\0",
+    "move cursor down\0",
+    "add audio pattern\0",
+    "remove audio pattern\0"
+    "copy pattern to clipboard\0",
+    "cut pattern to clipbaord\0",
+    "paste pattern from clipboard\0",
+    "select all pattern\0",
+    "invert pattern\0",
+  };
+
+  if(i >= 0 && i < 11){
+    return(actions[i]);
+  }else{
+    return(NULL);
+  }
+}
+
+const gchar*
+ags_accessible_pattern_edit_get_name(AtkAction *action,
+				     gint i)
+{
+  static const gchar **actions = {
+    "left\0",
+    "right\0",
+    "up\0",
+    "down\0",
+    "add\0",
+    "remove\0",
+    "copy\0",
+    "cut\0",
+    "paste\0",
+    "select-all\0",
+    "invert\0",
+  };
+  
+  if(i >= 0 && i < 11){
+    return(actions[i]);
+  }else{
+    return(NULL);
+  }
+}
+
+const gchar*
+ags_accessible_pattern_edit_get_keybinding(AtkAction *action,
+					   gint i)
+{
+  static const gchar **actions = {
+    "left\0",
+    "right\0",
+    "up\0",
+    "down\0",
+    "space",
+    "Del\0",
+    "Ctrl+c"
+    "Ctrl+x",
+    "Ctrl+v",
+    "Ctrl+a",
+    "Ctrl+i",
+  };
+  
+  if(i >= 0 && i < 11){
+    return(actions[i]);
+  }else{
+    return(NULL);
+  }
+}
+
+gboolean
+ags_accessible_pattern_edit_set_description(AtkAction *action,
+					    gint i)
+{
+  //TODO:JK: implement me
+
+  return(FALSE);
+}
+
+gchar*
+ags_accessible_pattern_edit_get_localized_name(AtkAction *action,
+					       gint i)
+{
+  //TODO:JK: implement me
+
+  return(NULL);
+}
+
 /**
  * ags_pattern_edit_set_map_height:
  * @pattern_edit: the #AgsPatternEdit
diff --git a/src/ags/X/editor/ags_pattern_edit_callbacks.c b/src/ags/X/editor/ags_pattern_edit_callbacks.c
index f723a0f..91ce9ab 100644
--- a/src/ags/X/editor/ags_pattern_edit_callbacks.c
+++ b/src/ags/X/editor/ags_pattern_edit_callbacks.c
@@ -890,11 +890,14 @@ ags_pattern_edit_drawing_area_key_press_event(GtkWidget *widget, GdkEventKey *ev
 {
   AgsEditor *editor;
 
+  if(event->keyval == GDK_KEY_Tab){
+    return(FALSE);
+  }
+
   editor = (AgsEditor *) gtk_widget_get_ancestor(GTK_WIDGET(pattern_edit),
 						 AGS_TYPE_EDITOR);
 
   if(editor->selected_machine != NULL){
-
     switch(event->keyval){
     case GDK_KEY_Control_L:
       {
@@ -948,11 +951,22 @@ ags_pattern_edit_drawing_area_key_press_event(GtkWidget *widget, GdkEventKey *ev
       break;
     }
   }
+
+  return(TRUE);
 }
 
 gboolean
 ags_pattern_edit_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *event, AgsPatternEdit *pattern_edit)
 {
+  AgsEditor *editor;
+  
+  if(event->keyval == GDK_KEY_Tab){
+    return(FALSE);
+  }
+
+  editor = (AgsEditor *) gtk_widget_get_ancestor(GTK_WIDGET(pattern_edit),
+						 AGS_TYPE_EDITOR);
+
   switch(event->keyval){
   case GDK_KEY_Control_L:
     {
@@ -964,7 +978,162 @@ ags_pattern_edit_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *
       pattern_edit->key_mask &= (~AGS_PATTERN_EDIT_KEY_R_CONTROL);
     }
     break;
+  case GDK_KEY_Left:
+  case GDK_KEY_leftarrow:
+    {
+      gdouble tact;
+      guint x0_offset;
+
+      tact = exp2(6.0 - (double) gtk_combo_box_get_active(editor->toolbar->zoom));
+      
+      if(pattern_edit->selected_x > 0){
+	if(pattern_edit->selected_x - (1 * tact) > 0){
+	  pattern_edit->selected_x -= (1 * tact);
+	}else{
+	  pattern_edit->selected_x = 0;
+	}
+      }
+
+      x0_offset = pattern_edit->selected_x * pattern_edit->control_unit.control_width;
+      
+      if(x0_offset < GTK_RANGE(pattern_edit->hscrollbar)->adjustment->value){
+	gtk_range_set_value(GTK_RANGE(pattern_edit->hscrollbar),
+			    x0_offset * GTK_RANGE(pattern_edit->hscrollbar)->adjustment->step_increment);
+      }
+
+      gtk_widget_queue_draw(pattern_edit);
+    }
+    break;
+  case GDK_KEY_Right:
+  case GDK_KEY_rightarrow:
+    {
+      gdouble tact;
+      guint x0_offset;
+
+      tact = exp2(6.0 - (double) gtk_combo_box_get_active(editor->toolbar->zoom));
+      
+      if(pattern_edit->selected_x < 16.0 * AGS_PATTERN_EDIT_MAX_CONTROLS){
+	pattern_edit->selected_x += (1.0 * tact);
+      }
+
+      x0_offset = pattern_edit->selected_x * pattern_edit->control_unit.control_width;
+      
+      if(x0_offset + pattern_edit->control_current.control_width > GTK_RANGE(pattern_edit->hscrollbar)->adjustment->value + GTK_WIDGET(pattern_edit->drawing_area)->allocation.width){
+	gtk_range_set_value(GTK_RANGE(pattern_edit->hscrollbar),
+			    x0_offset * GTK_RANGE(pattern_edit->hscrollbar)->adjustment->step_increment);
+      }
+
+      gtk_widget_queue_draw(pattern_edit);
+    }
+    break;
+  case GDK_KEY_Up:
+  case GDK_KEY_uparrow:
+    {
+      gdouble y0_offset;
+      
+      if(pattern_edit->selected_y > 0){
+	pattern_edit->selected_y -= 1;
+      }
+
+      y0_offset = pattern_edit->selected_y * pattern_edit->control_height;
+      
+      if(y0_offset < GTK_RANGE(pattern_edit->vscrollbar)->adjustment->value){
+	gtk_range_set_value(GTK_RANGE(pattern_edit->vscrollbar),
+			    y0_offset * GTK_RANGE(pattern_edit->vscrollbar)->adjustment->step_increment);
+      }
+
+      gtk_widget_queue_draw(pattern_edit);
+    }
+    break;
+  case GDK_KEY_Down:
+  case GDK_KEY_downarrow:
+    {
+      gdouble y0_offset;
+      
+      if(pattern_edit->selected_y * (pattern_edit->control_height) < pattern_edit->map_height){
+	pattern_edit->selected_y += 1;
+      }
+
+      y0_offset = pattern_edit->selected_y * pattern_edit->control_height;
+
+      if(y0_offset + pattern_edit->control_height > GTK_RANGE(pattern_edit->vscrollbar)->adjustment->value + (GTK_WIDGET(pattern_edit->drawing_area)->allocation.height)){
+	gtk_range_set_value(GTK_RANGE(pattern_edit->vscrollbar),
+			    y0_offset * GTK_RANGE(pattern_edit->vscrollbar)->adjustment->step_increment);
+      }
+
+      gtk_widget_queue_draw(pattern_edit);
+    }
+    break;
+  case GDK_KEY_space:
+    {
+      AgsMachine *machine;
+      AgsNote *note;
+      GList *list_notation;
+      gint i;
+      
+      machine = editor->selected_machine;
+
+      i = 0;
+
+      while((i = ags_notebook_next_active_tab(editor->current_notebook,
+					      i)) != -1){
+	list_notation = g_list_nth(machine->audio->notation,
+				   i);
+
+	if(list_notation == NULL){
+	  i++;
+	
+	  continue;
+	}
+      
+	note = ags_note_new();
+	note->x[0] = pattern_edit->selected_x;
+	note->x[1] = pattern_edit->selected_x + 1;
+	note->y = pattern_edit->selected_y;
+	
+	ags_notation_add_note(AGS_NOTATION(list_notation->data), note, FALSE);
+
+	i++;
+      }
+
+      gtk_widget_queue_draw(pattern_edit);
+
+      fprintf(stdout, "x0 = %llu\nx1 = %llu\ny  = %llu\n\n\0", (long long unsigned int) note->x[0], (long long unsigned int) note->x[1], (long long unsigned int) note->y);
+    }
+    break;
+  case GDK_KEY_Delete:
+    {
+      AgsMachine *machine;
+      GList *list_notation;
+      gint i;
+      
+      machine = editor->selected_machine;
+
+      i = 0;
+
+      while((i = ags_notebook_next_active_tab(editor->current_notebook,
+					      i)) != -1){
+	list_notation = g_list_nth(machine->audio->notation,
+				   i);
+
+	if(list_notation == NULL){
+	  i++;
+	
+	  continue;
+	}
+
+	ags_notation_remove_note_at_position(AGS_NOTATION(list_notation->data),
+					     pattern_edit->selected_x, pattern_edit->selected_y);
+
+	i++;
+      }
+
+      gtk_widget_queue_draw(pattern_edit);
+    }
+    break;
   }
+
+  return(TRUE);
 }
 
 void
diff --git a/src/ags/X/machine/ags_cell_pattern.c b/src/ags/X/machine/ags_cell_pattern.c
new file mode 100644
index 0000000..60e252b
--- /dev/null
+++ b/src/ags/X/machine/ags_cell_pattern.c
@@ -0,0 +1,796 @@
+/* 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/X/machine/ags_cell_pattern.h>
+#include <ags/X/machine/ags_cell_pattern_callbacks.h>
+
+#include <ags/main.h>
+
+#include <ags-lib/object/ags_connectable.h>
+
+#include <ags/thread/ags_mutex_manager.h>
+#include <ags/thread/ags_audio_loop.h>
+#include <ags/thread/ags_task_thread.h>
+
+#include <ags/audio/ags_pattern.h>
+
+#include <ags/audio/task/ags_blink_cell_pattern_cursor.h>
+
+#include <ags/widget/ags_led.h>
+
+#include <ags/X/ags_window.h>
+#include <ags/X/ags_machine.h>
+
+#include <gdk/gdkkeysyms.h>
+
+#include <atk/atk.h>
+
+static GType ags_accessible_cell_pattern_get_type(void);
+void ags_cell_pattern_class_init(AgsCellPatternClass *cell_pattern);
+void ags_accessible_cell_pattern_class_init(AtkObject *object);
+void ags_accessible_cell_pattern_action_interface_init(AtkActionIface *action);
+void ags_cell_pattern_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_cell_pattern_init(AgsCellPattern *cell_pattern);
+void ags_cell_pattern_finalize(GObject *gobject);
+void ags_cell_pattern_connect(AgsConnectable *connectable);
+void ags_cell_pattern_disconnect(AgsConnectable *connectable);
+AtkObject* ags_cell_pattern_get_accessible(GtkWidget *widget);
+void ags_cell_pattern_show(GtkWidget *widget);
+void ags_cell_pattern_show_all(GtkWidget *widget);
+
+gboolean ags_accessible_cell_pattern_do_action(AtkAction *action,
+					       gint i);
+gint ags_accessible_cell_pattern_get_n_actions(AtkAction *action);
+const gchar* ags_accessible_cell_pattern_get_description(AtkAction *action,
+							 gint i);
+const gchar* ags_accessible_cell_pattern_get_name(AtkAction *action,
+						  gint i);
+const gchar* ags_accessible_cell_pattern_get_keybinding(AtkAction *action,
+							gint i);
+gboolean ags_accessible_cell_pattern_set_description(AtkAction *action,
+						     gint i);
+gchar* ags_accessible_cell_pattern_get_localized_name(AtkAction *action,
+						      gint i);
+
+/**
+ * SECTION:ags_cell_pattern
+ * @short_description: cell_pattern sequencer
+ * @title: AgsCellPattern
+ * @section_id:
+ * @include: ags/X/machine/ags_cell_pattern.h
+ *
+ * The #AgsCellPattern is a composite widget to act as cell_pattern sequencer.
+ */
+
+static gpointer ags_cell_pattern_parent_class = NULL;
+static GQuark quark_accessible_object = 0;
+
+extern pthread_mutex_t ags_application_mutex;
+
+GtkStyle *cell_pattern_style;
+
+GType
+ags_cell_pattern_get_type(void)
+{
+  static GType ags_type_cell_pattern = 0;
+
+  if(!ags_type_cell_pattern){
+    static const GTypeInfo ags_cell_pattern_info = {
+      sizeof(AgsCellPatternClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_cell_pattern_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof(AgsCellPattern),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_cell_pattern_init,
+    };
+
+    static const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_cell_pattern_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+    
+    ags_type_cell_pattern = g_type_register_static(GTK_TYPE_TABLE,
+						   "AgsCellPattern\0", &ags_cell_pattern_info,
+						   0);
+    
+    g_type_add_interface_static(ags_type_cell_pattern,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+  }
+
+  return(ags_type_cell_pattern);
+}
+
+static GType
+ags_accessible_cell_pattern_get_type(void)
+{
+  static GType ags_type_accessible_cell_pattern = 0;
+
+  if(!ags_type_accessible_cell_pattern){
+    const GTypeInfo ags_accesssible_cell_pattern_info = {
+      sizeof(GtkAccessibleClass),
+      NULL,           /* base_init */
+      NULL,           /* base_finalize */
+      (GClassInitFunc) ags_accessible_cell_pattern_class_init,
+      NULL,           /* class_finalize */
+      NULL,           /* class_data */
+      sizeof(GtkAccessible),
+      0,             /* n_preallocs */
+      NULL, NULL
+    };
+
+    static const GInterfaceInfo atk_action_interface_info = {
+      (GInterfaceInitFunc) ags_accessible_cell_pattern_action_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+    
+    ags_type_accessible_cell_pattern = g_type_register_static(GTK_TYPE_ACCESSIBLE,
+							      "AgsAccessibleCellPattern\0", &ags_accesssible_cell_pattern_info,
+							      0);
+
+    g_type_add_interface_static(ags_type_accessible_cell_pattern,
+				ATK_TYPE_ACTION,
+				&atk_action_interface_info);
+  }
+  
+  return(ags_type_accessible_cell_pattern);
+}
+
+void
+ags_cell_pattern_class_init(AgsCellPatternClass *cell_pattern)
+{
+  GObjectClass *gobject;
+  GtkWidgetClass *widget;
+
+  ags_cell_pattern_parent_class = g_type_class_peek_parent(cell_pattern);
+
+  quark_accessible_object = g_quark_from_static_string("ags-accessible-object\0");
+
+  /* GObjectClass */
+  gobject = (GObjectClass *) cell_pattern;
+
+  gobject->finalize = ags_cell_pattern_finalize;
+
+  /* GtkWidget */
+  widget = (GtkWidgetClass *) cell_pattern;
+
+  widget->show = ags_cell_pattern_show;
+  widget->show_all = ags_cell_pattern_show_all;
+}
+
+void
+ags_accessible_cell_pattern_class_init(AtkObject *object)
+{
+  /* empty */
+}
+
+void
+ags_accessible_cell_pattern_action_interface_init(AtkActionIface *action)
+{
+  action->do_action = ags_accessible_cell_pattern_do_action;
+  action->get_n_actions = ags_accessible_cell_pattern_get_n_actions;
+  action->get_description = ags_accessible_cell_pattern_get_description;
+  action->get_name = ags_accessible_cell_pattern_get_name;
+  action->get_keybinding = ags_accessible_cell_pattern_get_keybinding;
+  action->set_description = ags_accessible_cell_pattern_set_description;
+  action->get_localized_name = ags_accessible_cell_pattern_get_localized_name;
+}
+
+void
+ags_cell_pattern_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  AgsConnectableInterface *ags_cell_pattern_connectable_parent_interface;
+
+  connectable->connect = ags_cell_pattern_connect;
+  connectable->disconnect = ags_cell_pattern_disconnect;
+}
+
+void
+ags_cell_pattern_init(AgsCellPattern *cell_pattern)
+{
+  GtkAdjustment *adjustment;
+  AgsLed *led;
+
+  guint i;
+
+  g_object_set(cell_pattern,
+	       "can-focus\0", TRUE,
+	       "n-columns\0", 2,
+	       "n-rows", 2,
+	       "homogeneous\0", FALSE,
+	       NULL);
+
+  cell_pattern->flags = 0;
+
+  cell_pattern->key_mask = 0;
+  
+  cell_pattern->cell_width = AGS_CELL_PATTERN_DEFAULT_CELL_WIDTH;
+  cell_pattern->cell_height = AGS_CELL_PATTERN_DEFAULT_CELL_HEIGHT;
+
+  cell_pattern->n_cols = AGS_CELL_PATTERN_DEFAULT_CONTROLS_HORIZONTALLY;
+  cell_pattern->n_rows = AGS_CELL_PATTERN_DEFAULT_CONTROLS_VERTICALLY;
+
+  cell_pattern->cursor_x = 0;
+  cell_pattern->cursor_y = 0;
+  
+  cell_pattern->drawing_area = (GtkDrawingArea *) gtk_drawing_area_new();  
+
+  gtk_widget_set_size_request((GtkWidget *) cell_pattern->drawing_area,
+			      AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_HORIZONTALLY * cell_pattern->cell_width + 1, AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY * cell_pattern->cell_height + 1);
+  gtk_widget_set_style((GtkWidget *) cell_pattern->drawing_area,
+		       cell_pattern_style);
+  gtk_table_attach(cell_pattern,
+		   (GtkWidget *) cell_pattern->drawing_area,
+		   0, 1,
+		   0, 1,
+		   GTK_FILL, GTK_FILL,
+		   0, 0);
+  gtk_widget_set_events((GtkWidget *) cell_pattern->drawing_area,
+			GDK_EXPOSURE_MASK
+			| GDK_LEAVE_NOTIFY_MASK
+			| GDK_BUTTON_PRESS_MASK
+			| GDK_POINTER_MOTION_MASK
+			| GDK_POINTER_MOTION_HINT_MASK
+			| GDK_CONTROL_MASK
+			| GDK_KEY_PRESS_MASK
+			| GDK_KEY_RELEASE_MASK);
+  
+  adjustment = (GtkAdjustment *) gtk_adjustment_new(0.0, 0.0, (double) AGS_CELL_PATTERN_DEFAULT_CONTROLS_VERTICALLY - 1.0, 1.0, 1.0, (gdouble) AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY);
+
+  cell_pattern->vscrollbar = (GtkVScrollbar *) gtk_vscrollbar_new(adjustment);
+  gtk_widget_set_style((GtkWidget *) cell_pattern->vscrollbar,
+		       cell_pattern_style);
+  gtk_table_attach(cell_pattern,
+		   (GtkWidget *) cell_pattern->vscrollbar,
+		   1, 2,
+		   0, 1,
+		   GTK_FILL, GTK_FILL,
+		   0, 0);
+
+  cell_pattern->hscrollbar = NULL;
+  
+  /* led */
+  cell_pattern->active_led = 0;
+
+  cell_pattern->led = (GtkHBox *) gtk_hbox_new(FALSE, 0);
+  gtk_table_attach(cell_pattern,
+		   (GtkWidget *) cell_pattern->led,
+		   0, 1,
+		   2, 3,
+		   GTK_FILL, GTK_FILL,
+		   0, 0);
+  
+  for(i = 0; i < 32; i++){
+    led = ags_led_new();
+    gtk_widget_set_size_request((GtkWidget *) led,
+				cell_pattern->cell_width, cell_pattern->cell_width / 2);
+    gtk_box_pack_start((GtkBox *) cell_pattern->led,
+		       (GtkWidget *) led,
+		       FALSE, FALSE,
+		       0);
+  }
+}
+
+void
+ags_cell_pattern_finalize(GObject *gobject)
+{
+  G_OBJECT_CLASS(ags_cell_pattern_parent_class)->finalize(gobject);
+}
+
+void
+ags_cell_pattern_connect(AgsConnectable *connectable)
+{
+  AgsCellPattern *cell_pattern;
+
+  if((AGS_CELL_PATTERN_CONNECTED & (AGS_CELL_PATTERN(connectable)->flags)) != 0){
+    return;
+  }
+
+  /* AgsCellPattern */
+  cell_pattern = AGS_CELL_PATTERN(connectable);
+
+  cell_pattern->flags |= AGS_CELL_PATTERN_CONNECTED;
+
+  g_signal_connect_after(G_OBJECT(cell_pattern), "focus_in_event\0",
+			 G_CALLBACK(ags_cell_pattern_focus_in_callback), (gpointer) cell_pattern);
+  
+  g_signal_connect(G_OBJECT(cell_pattern), "key_press_event\0",
+		   G_CALLBACK(ags_cell_pattern_drawing_area_key_press_event), (gpointer) cell_pattern);
+
+  g_signal_connect(G_OBJECT(cell_pattern), "key_release_event\0",
+		   G_CALLBACK(ags_cell_pattern_drawing_area_key_release_event), (gpointer) cell_pattern);
+
+  g_signal_connect_after(G_OBJECT(cell_pattern->drawing_area), "configure_event\0",
+			 G_CALLBACK(ags_cell_pattern_drawing_area_configure_callback), (gpointer) cell_pattern);
+
+  g_signal_connect_after(G_OBJECT(cell_pattern->drawing_area), "expose_event\0",
+			 G_CALLBACK(ags_cell_pattern_drawing_area_expose_callback), (gpointer) cell_pattern);
+
+  g_signal_connect(G_OBJECT(cell_pattern->drawing_area), "button_press_event\0",
+		   G_CALLBACK(ags_cell_pattern_drawing_area_button_press_callback), (gpointer) cell_pattern);
+
+  g_signal_connect(G_OBJECT(GTK_RANGE(cell_pattern->vscrollbar)->adjustment), "value_changed\0",
+		   G_CALLBACK(ags_cell_pattern_adjustment_value_changed_callback), (gpointer) cell_pattern);
+}
+
+void
+ags_cell_pattern_disconnect(AgsConnectable *connectable)
+{
+  AgsCellPattern *cell_pattern;
+
+  /* AgsCellPattern */
+  cell_pattern = AGS_CELL_PATTERN(connectable);
+
+  //TODO:JK: implement me
+}
+
+AtkObject*
+ags_cell_pattern_get_accessible(GtkWidget *widget)
+{
+  AtkObject* accessible;
+
+  accessible = g_object_get_qdata(G_OBJECT(widget),
+				  quark_accessible_object);
+  
+  if(!accessible){
+    accessible = g_object_new(ags_accessible_cell_pattern_get_type(),
+			      NULL);
+    
+    g_object_set_qdata(G_OBJECT(widget),
+		       quark_accessible_object,
+		       accessible);
+    gtk_accessible_set_widget(accessible,
+			      widget);
+  }
+  
+  return(accessible);
+}
+
+void
+ags_cell_pattern_show(GtkWidget *widget)
+{
+  GTK_WIDGET_CLASS(ags_cell_pattern_parent_class)->show(widget);
+
+  //  ags_cell_pattern_draw_matrix(AGS_CELL_PATTERN(widget));
+}
+
+void
+ags_cell_pattern_show_all(GtkWidget *widget)
+{
+  GTK_WIDGET_CLASS(ags_cell_pattern_parent_class)->show_all(widget);
+
+  //  ags_cell_pattern_draw_matrix(AGS_CELL_PATTERN(widget));
+}
+
+gboolean
+ags_accessible_cell_pattern_do_action(AtkAction *action,
+				      gint i)
+{
+  AgsCellPattern *cell_pattern;
+  
+  GdkEventKey *key_press, *key_release;
+  GdkEventKey *modifier_press, *modifier_release;
+  
+  if(!(i >= 0 && i < 6)){
+    return(FALSE);
+  }
+
+  cell_pattern = gtk_accessible_get_widget(ATK_OBJECT(action));
+  
+  key_press = gdk_event_new(GDK_KEY_PRESS);
+  key_release = gdk_event_new(GDK_KEY_RELEASE);
+
+  switch(i){
+  case AGS_CELL_PATTERN_MOVE_LEFT:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Left;
+      
+      /* send event */
+      gtk_widget_event(cell_pattern, key_press);
+      gtk_widget_event(cell_pattern, key_release);
+    }
+    break;
+  case AGS_CELL_PATTERN_MOVE_RIGHT:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Right;
+      
+      /* send event */
+      gtk_widget_event(cell_pattern, key_press);
+      gtk_widget_event(cell_pattern, key_release);
+    }
+    break;
+  case AGS_CELL_PATTERN_MOVE_UP:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Up;
+    
+      /* send event */
+      gtk_widget_event(cell_pattern, key_press);
+      gtk_widget_event(cell_pattern, key_release);
+    }
+    break;
+  case AGS_CELL_PATTERN_MOVE_DOWN:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Down;
+      
+      /* send event */
+      gtk_widget_event(cell_pattern, key_press);
+      gtk_widget_event(cell_pattern, key_release);
+    }
+    break;
+  case AGS_CELL_PATTERN_TOGGLE_PAD:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_space;
+      
+      /* send event */
+      gtk_widget_event(cell_pattern, key_press);
+      gtk_widget_event(cell_pattern, key_release);
+    }
+    break;
+  case AGS_CELL_PATTERN_COPY_PATTERN:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_c;
+
+      /* create modifier */
+      modifier_press = gdk_event_new(GDK_KEY_PRESS);
+      modifier_release = gdk_event_new(GDK_KEY_RELEASE);
+
+      modifier_press->keyval =
+	modifier_release->keyval = GDK_KEY_Control_R;
+
+      /* send event */
+      gtk_widget_event(cell_pattern, modifier_press);
+      gtk_widget_event(cell_pattern, key_press);
+      gtk_widget_event(cell_pattern, key_release);
+      gtk_widget_event(cell_pattern, modifier_release);      
+    }    
+    break;
+  }
+
+  return(TRUE);
+}
+
+gint
+ags_accessible_cell_pattern_get_n_actions(AtkAction *action)
+{
+  return(6);
+}
+
+const gchar*
+ags_accessible_cell_pattern_get_description(AtkAction *action,
+					    gint i)
+{
+  static const gchar **actions = {
+    "move cursor left\0",
+    "move cursor right\0",
+    "move cursor up\0",
+    "move cursor down\0",
+    "toggle audio pattern\0"
+    "copy pattern to clipboard\0",
+  };
+
+  if(i >= 0 && i < 6){
+    return(actions[i]);
+  }else{
+    return(NULL);
+  }
+}
+
+const gchar*
+ags_accessible_cell_pattern_get_name(AtkAction *action,
+				     gint i)
+{
+  static const gchar **actions = {
+    "left\0",
+    "right\0",
+    "up\0",
+    "down\0",
+    "toggle\0",
+    "copy\0",
+  };
+  
+  if(i >= 0 && i < 6){
+    return(actions[i]);
+  }else{
+    return(NULL);
+  }
+}
+
+const gchar*
+ags_accessible_cell_pattern_get_keybinding(AtkAction *action,
+					   gint i)
+{
+  static const gchar **actions = {
+    "left\0",
+    "right\0",
+    "up\0",
+    "down\0",
+    "space",
+    "Ctrl+c",
+  };
+  
+  if(i >= 0 && i < 6){
+    return(actions[i]);
+  }else{
+    return(NULL);
+  }
+}
+
+gboolean
+ags_accessible_cell_pattern_set_description(AtkAction *action,
+					    gint i)
+{
+  //TODO:JK: implement me
+
+  return(FALSE);
+}
+
+gchar*
+ags_accessible_cell_pattern_get_localized_name(AtkAction *action,
+					       gint i)
+{
+  //TODO:JK: implement me
+
+  return(NULL);
+}
+
+void
+ags_cell_pattern_paint(AgsCellPattern *cell_pattern)
+{
+  ags_cell_pattern_draw_gutter(cell_pattern);
+  ags_cell_pattern_draw_matrix(cell_pattern);
+
+  ags_cell_pattern_draw_cursor(cell_pattern);
+}
+
+void
+ags_cell_pattern_draw_gutter(AgsCellPattern *cell_pattern)
+{
+  AgsMachine *machine;
+  
+  AgsChannel *channel;
+
+  AgsMutexManager *mutex_manager;
+
+  guint gutter;
+  int i, j;
+
+  pthread_mutex_t *audio_mutex;
+
+  machine = gtk_widget_get_ancestor(cell_pattern,
+				    AGS_TYPE_MACHINE);
+  
+  pthread_mutex_lock(&(ags_application_mutex));
+  
+  mutex_manager = ags_mutex_manager_get_instance();
+
+  audio_mutex = ags_mutex_manager_lookup(mutex_manager,
+					 (GObject *) machine->audio);
+  
+  pthread_mutex_unlock(&(ags_application_mutex));
+
+  pthread_mutex_lock(audio_mutex);
+
+  gdk_draw_rectangle(GTK_WIDGET(cell_pattern->drawing_area)->window,
+		     GTK_WIDGET(cell_pattern->drawing_area)->style->bg_gc[0],
+		     TRUE,
+		     0, 0,
+		     288, 80);
+
+  channel = ags_channel_nth(machine->audio->input, machine->audio->input_lines - ((guint) GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value + AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY) - 1);
+
+  if(machine->audio->input_pads > AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
+    gutter = AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY;
+  }else{
+    gutter = machine->audio->input_pads;
+  }
+
+  for (i = 0; i < gutter; i++){
+    for (j = 0; j < 32; j++){
+      gdk_draw_rectangle(GTK_WIDGET(cell_pattern->drawing_area)->window,
+			 GTK_WIDGET(cell_pattern->drawing_area)->style->fg_gc[0],
+			 FALSE,
+			 j * 12, i * 10,
+			 12, 10);
+
+      ags_cell_pattern_redraw_gutter_point (cell_pattern, channel, j, i);
+    }
+
+    channel = channel->prev;
+  }
+
+  pthread_mutex_unlock(audio_mutex);
+}
+
+void
+ags_cell_pattern_draw_matrix(AgsCellPattern *cell_pattern)
+{
+  AgsMachine *machine;
+
+  AgsChannel *channel;
+
+  AgsMutexManager *mutex_manager;
+
+  guint gutter;
+  int i, j;
+
+  pthread_mutex_t *audio_mutex;
+
+  machine = gtk_widget_get_ancestor(cell_pattern,
+				    AGS_TYPE_MACHINE);
+
+  pthread_mutex_lock(&(ags_application_mutex));
+  
+  mutex_manager = ags_mutex_manager_get_instance();
+
+  audio_mutex = ags_mutex_manager_lookup(mutex_manager,
+					 (GObject *) machine->audio);
+  
+  pthread_mutex_unlock(&(ags_application_mutex));
+
+  pthread_mutex_lock(audio_mutex);
+
+  if(machine->audio->input_pads > AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
+    gutter = AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY;
+  }else{
+    gutter = machine->audio->input_pads;
+  }
+
+  channel = ags_channel_nth(machine->audio->input, machine->audio->input_pads - (guint) GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value - 1);
+
+  if(channel == NULL){
+    pthread_mutex_unlock(audio_mutex);
+    
+    return;
+  }
+
+  for (i = 0; i < gutter; i++){
+    for (j = 0; j < 32; j++)
+      ags_cell_pattern_redraw_gutter_point(cell_pattern, channel, j, i);
+
+    channel = channel->prev;
+  }
+
+  pthread_mutex_unlock(audio_mutex);
+}
+
+void
+ags_cell_pattern_draw_cursor(AgsCellPattern *cell_pattern)
+{
+  guint i, j;
+
+  
+  if(cell_pattern->cursor_y >= GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value &&
+     cell_pattern->cursor_y < GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value + cell_pattern->n_rows){
+    i = cell_pattern->cursor_y - GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value;
+    j = cell_pattern->cursor_x;
+    
+    if((AGS_CELL_PATTERN_CURSOR_ON & (cell_pattern->flags)) != 0){
+      ags_cell_pattern_highlight_gutter_point(cell_pattern, j, i);
+    }else{
+      ags_cell_pattern_unpaint_gutter_point(cell_pattern, j, i);
+    }
+  }
+}
+
+void
+ags_cell_pattern_redraw_gutter_point(AgsCellPattern *cell_pattern, AgsChannel *channel, guint j, guint i)
+{
+  AgsMachine *machine;
+
+  if(channel->pattern == NULL)
+    return;
+
+  machine = gtk_widget_get_ancestor(cell_pattern,
+				    AGS_TYPE_MACHINE);
+
+  if(ags_pattern_get_bit((AgsPattern *) channel->pattern->data, machine->bank_0, machine->bank_1, j)){
+    ags_cell_pattern_highlight_gutter_point(cell_pattern, j, i);
+  }else{
+    ags_cell_pattern_unpaint_gutter_point(cell_pattern, j, i);
+  }
+}
+
+void
+ags_cell_pattern_highlight_gutter_point(AgsCellPattern *cell_pattern, guint j, guint i)
+{
+  gdk_draw_rectangle(GTK_WIDGET (cell_pattern->drawing_area)->window,
+		     GTK_WIDGET (cell_pattern->drawing_area)->style->fg_gc[0],
+		     TRUE,
+		     j * cell_pattern->cell_width + 1, i * cell_pattern->cell_height + 1,
+		     11, 9);
+}
+
+void
+ags_cell_pattern_unpaint_gutter_point(AgsCellPattern *cell_pattern, guint j, guint i)
+{
+  gdk_draw_rectangle(GTK_WIDGET (cell_pattern->drawing_area)->window,
+		     GTK_WIDGET (cell_pattern->drawing_area)->style->bg_gc[0],
+		     TRUE,
+		     j * cell_pattern->cell_width + 1, i * cell_pattern->cell_height +1,
+		     11, 9);
+}
+
+void*
+ags_cell_pattern_blink_worker(void *data)
+{
+  AgsWindow *window;
+  AgsCellPattern *cell_pattern;
+  
+  AgsTaskThread *task_thread;
+  
+  AgsBlinkCellPatternCursor *blink_cell_pattern_cursor;
+  
+  static const guint blink_delay = 1000000; // blink every second
+  
+  cell_pattern = AGS_CELL_PATTERN(data);
+  window = gtk_widget_get_ancestor(cell_pattern,
+				   AGS_TYPE_WINDOW);
+  
+  task_thread = AGS_TASK_THREAD(AGS_AUDIO_LOOP(AGS_MAIN(window->ags_main)->main_loop)->task_thread);
+
+  while(gtk_widget_has_focus(cell_pattern)){
+    /* blink cursor */
+    blink_cell_pattern_cursor = ags_blink_cell_pattern_cursor_new(cell_pattern,
+								  !(AGS_CELL_PATTERN_CURSOR_ON & (cell_pattern->flags)));
+    ags_task_thread_append_task(task_thread,
+				blink_cell_pattern_cursor);
+
+    /* delay */
+    usleep(blink_delay);
+  }
+
+  /* unset cursor */
+  blink_cell_pattern_cursor = ags_blink_cell_pattern_cursor_new(cell_pattern,
+								FALSE);
+  ags_task_thread_append_task(task_thread,
+			      blink_cell_pattern_cursor);
+
+  return(NULL);
+}
+
+/**
+ * ags_cell_pattern_new:
+ *
+ * Creates an #AgsCellPattern
+ *
+ * Returns: a new #AgsCellPattern
+ *
+ * Since: 0.5
+ */
+AgsCellPattern*
+ags_cell_pattern_new()
+{
+  AgsCellPattern *cell_pattern;
+
+  cell_pattern = (AgsCellPattern *) g_object_new(AGS_TYPE_CELL_PATTERN,
+						 NULL);
+
+  return(cell_pattern);
+}
diff --git a/src/ags/X/machine/ags_cell_pattern.h b/src/ags/X/machine/ags_cell_pattern.h
new file mode 100644
index 0000000..361beed
--- /dev/null
+++ b/src/ags/X/machine/ags_cell_pattern.h
@@ -0,0 +1,113 @@
+/* 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_CELL_PATTERN_H__
+#define __AGS_CELL_PATTERN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <ags/audio/ags_channel.h>
+
+#define AGS_TYPE_CELL_PATTERN                (ags_cell_pattern_get_type())
+#define AGS_CELL_PATTERN(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_CELL_PATTERN, AgsCellPattern))
+#define AGS_CELL_PATTERN_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_CELL_PATTERN, AgsCellPatternClass))
+#define AGS_IS_CELL_PATTERN(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), AGS_TYPE_CELL_PATTERN))
+#define AGS_IS_CELL_PATTERN_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_CELL_PATTERN))
+#define AGS_CELL_PATTERN_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_CELL_PATTERN, AgsCellPatternClass))
+
+#define AGS_CELL_PATTERN_DEFAULT_CELL_WIDTH   (12)
+#define AGS_CELL_PATTERN_DEFAULT_CELL_HEIGHT  (10)
+
+#define AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_HORIZONTALLY (32)
+#define AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY (10)
+
+#define AGS_CELL_PATTERN_DEFAULT_CONTROLS_HORIZONTALLY (32)
+#define AGS_CELL_PATTERN_DEFAULT_CONTROLS_VERTICALLY (78)
+
+typedef struct _AgsCellPattern AgsCellPattern;
+typedef struct _AgsCellPatternClass AgsCellPatternClass;
+
+typedef enum{
+  AGS_CELL_PATTERN_CONNECTED    = 1,
+  AGS_CELL_PATTERN_CURSOR_ON    = 1 <<  1,
+}AgsCellPatternFlags;
+
+typedef enum{
+  AGS_CELL_PATTERN_KEY_L_CONTROL       = 1,
+  AGS_CELL_PATTERN_KEY_R_CONTROL       = 1 <<  1,
+}AgsCellPatternKeyMask;
+
+typedef enum{
+  AGS_CELL_PATTERN_MOVE_LEFT,
+  AGS_CELL_PATTERN_MOVE_RIGHT,
+  AGS_CELL_PATTERN_MOVE_UP,
+  AGS_CELL_PATTERN_MOVE_DOWN,
+  AGS_CELL_PATTERN_TOGGLE_PAD,
+  AGS_CELL_PATTERN_COPY_PATTERN,
+}AgsCellPatternAction;
+
+struct _AgsCellPattern
+{
+  GtkTable table;
+
+  guint flags;
+  
+  guint key_mask;
+  
+  guint cell_width;
+  guint cell_height;
+  
+  guint n_cols;
+  guint n_rows;
+
+  guint cursor_x;
+  guint cursor_y;
+  
+  GtkDrawingArea *drawing_area;
+  
+  GtkVScrollbar *vscrollbar;
+  GtkHScrollbar *hscrollbar;
+
+  guint active_led;
+  GtkHBox *led;
+};
+
+struct _AgsCellPatternClass
+{
+  GtkTableClass table;
+};
+
+GType ags_cell_pattern_get_type(void);
+
+void ags_cell_pattern_paint(AgsCellPattern *cell_pattern);
+
+void ags_cell_pattern_draw_gutter(AgsCellPattern *cell_pattern);
+void ags_cell_pattern_draw_matrix(AgsCellPattern *cell_pattern);
+void ags_cell_pattern_draw_cursor(AgsCellPattern *cell_pattern);
+void ags_cell_pattern_redraw_gutter_point(AgsCellPattern *cell_pattern, AgsChannel *channel, guint j, guint i);
+void ags_cell_pattern_highlight_gutter_point(AgsCellPattern *cell_pattern, guint j, guint i);
+void ags_cell_pattern_unpaint_gutter_point(AgsCellPattern *cell_pattern, guint j, guint i);
+
+void* ags_cell_pattern_blink_worker(void *data);
+
+AgsCellPattern* ags_cell_pattern_new();
+
+#endif /*__AGS_CELL_PATTERN_H__*/
diff --git a/src/ags/X/machine/ags_cell_pattern_callbacks.c b/src/ags/X/machine/ags_cell_pattern_callbacks.c
new file mode 100644
index 0000000..9ee1d5f
--- /dev/null
+++ b/src/ags/X/machine/ags_cell_pattern_callbacks.c
@@ -0,0 +1,264 @@
+/* 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/X/machine/ags_cell_pattern_callbacks.h>
+
+#include <ags/main.h>
+
+#include <ags/thread/ags_mutex_manager.h>
+#include <ags/thread/ags_audio_loop.h>
+#include <ags/thread/ags_task_thread.h>
+
+#include <ags/audio/ags_devout.h>
+
+#include <ags/audio/task/ags_toggle_pattern_bit.h>
+
+#include <ags/X/ags_machine.h>
+
+#include <gdk/gdkkeysyms.h>
+
+#include <math.h>
+
+void ags_cell_pattern_refresh_gui_callback(AgsTogglePatternBit *toggle_pattern_bit,
+					   AgsCellPattern *cell_pattern);
+
+gboolean
+ags_cell_pattern_focus_in_callback(GtkWidget *widget, GdkEvent *event, AgsCellPattern *cell_pattern)
+{
+  pthread_t thread;
+  
+  pthread_create(&thread, NULL,
+		 ags_cell_pattern_blink_worker, cell_pattern);
+  
+  return(TRUE);
+}
+
+gboolean
+ags_cell_pattern_drawing_area_configure_callback(GtkWidget *widget, GdkEventConfigure *event, AgsCellPattern *cell_pattern)
+{
+  ags_cell_pattern_paint(cell_pattern);
+  
+  return(FALSE);
+}
+
+gboolean
+ags_cell_pattern_drawing_area_expose_callback(GtkWidget *widget, GdkEventExpose *event, AgsCellPattern *cell_pattern)
+{
+  ags_cell_pattern_paint(cell_pattern);
+
+  return(FALSE);
+}
+
+gboolean
+ags_cell_pattern_drawing_area_button_press_callback(GtkWidget *widget, GdkEventButton *event, AgsCellPattern *cell_pattern)
+{
+  if(event->button == 1){
+    AgsMachine *machine;
+    
+    AgsTogglePatternBit *toggle_pattern_bit;
+    AgsChannel *channel;
+    
+    guint i, j;
+    guint index1;
+
+    machine = gtk_widget_get_ancestor(cell_pattern,
+				      AGS_TYPE_MACHINE);
+        
+    i = (guint) floor((double) event->y / (double) cell_pattern->cell_height);
+    j = (guint) floor((double) event->x / (double) cell_pattern->cell_width);
+
+    index1 = machine->bank_1;
+
+    channel = ags_channel_nth(machine->audio->input, machine->audio->input_lines - ((guint) GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value + i) - 1);
+
+    toggle_pattern_bit = ags_toggle_pattern_bit_new(channel->pattern->data,
+						    channel->line,
+						    0, index1,
+						    j);
+    g_signal_connect(G_OBJECT(toggle_pattern_bit), "refresh-gui\0",
+		     G_CALLBACK(ags_cell_pattern_refresh_gui_callback), cell_pattern);
+
+    ags_task_thread_append_task(AGS_TASK_THREAD(AGS_AUDIO_LOOP(AGS_MAIN(AGS_DEVOUT(machine->audio->devout)->ags_main)->main_loop)->task_thread),
+				AGS_TASK(toggle_pattern_bit));
+  }else if (event->button == 3){
+  }
+
+  return(FALSE);
+}
+
+gboolean
+ags_cell_pattern_drawing_area_key_press_event(GtkWidget *widget, GdkEventKey *event, AgsCellPattern *cell_pattern)
+{
+  if(event->keyval == GDK_KEY_Tab){
+    return(FALSE);
+  }
+
+  switch(event->keyval){
+  case GDK_KEY_Control_L:
+    {
+      cell_pattern->key_mask |= AGS_CELL_PATTERN_KEY_L_CONTROL;
+    }
+    break;
+  case GDK_KEY_Control_R:
+    {
+      cell_pattern->key_mask |= AGS_CELL_PATTERN_KEY_R_CONTROL;
+    }
+    break;
+  case GDK_KEY_c:
+    {
+      /* copy notes */
+      if((AGS_CELL_PATTERN_KEY_L_CONTROL & (cell_pattern->key_mask)) != 0 || (AGS_CELL_PATTERN_KEY_R_CONTROL & (cell_pattern->key_mask)) != 0){
+	AgsMachine *machine;
+
+	machine = gtk_widget_get_ancestor(cell_pattern,
+					  AGS_TYPE_MACHINE);
+	
+	ags_machine_copy_pattern(machine);
+      }
+    }
+    break;
+  }
+  
+  return(TRUE);
+}
+
+gboolean
+ags_cell_pattern_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *event, AgsCellPattern *cell_pattern)
+{
+  if(event->keyval == GDK_KEY_Tab){
+    return(FALSE);
+  }
+  
+  switch(event->keyval){
+  case GDK_KEY_Control_L:
+    {
+      cell_pattern->key_mask &= (~AGS_CELL_PATTERN_KEY_L_CONTROL);
+    }
+    break;
+  case GDK_KEY_Control_R:
+    {
+      cell_pattern->key_mask &= (~AGS_CELL_PATTERN_KEY_R_CONTROL);
+    }
+    break;
+  case GDK_KEY_Left:
+  case GDK_KEY_leftarrow:
+    {
+      if(cell_pattern->cursor_x > 0){
+	cell_pattern->cursor_x -= 1;
+      }
+    }
+    break;
+  case GDK_KEY_Right:
+  case GDK_KEY_rightarrow:
+    {
+      if(cell_pattern->cursor_x < cell_pattern->n_cols){
+	cell_pattern->cursor_x += 1;
+      }
+    }
+    break;
+  case GDK_KEY_Up:
+  case GDK_KEY_uparrow:
+    {
+      if(cell_pattern->cursor_y > 0){
+	cell_pattern->cursor_y -= 1;
+      }
+
+      if(cell_pattern->cursor_y < GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value){
+	gtk_range_set_value(GTK_RANGE(cell_pattern->vscrollbar),
+			    GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value - 1.0);
+      }
+    }
+    break;
+  case GDK_KEY_Down:
+  case GDK_KEY_downarrow:
+    {
+      if(cell_pattern->cursor_y < cell_pattern->n_rows){
+	cell_pattern->cursor_y += 1;
+      }
+
+      if(cell_pattern->cursor_y >= GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value + AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
+	gtk_range_set_value(GTK_RANGE(cell_pattern->vscrollbar),
+			    GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value + 1.0);
+      }
+    }
+    break;
+  case GDK_KEY_space:
+    {
+      AgsMachine *machine;
+      
+      AgsTogglePatternBit *toggle_pattern_bit;
+      AgsChannel *channel;
+      
+      guint i, j;
+      guint index1;
+      
+      machine = gtk_widget_get_ancestor(cell_pattern,
+					AGS_TYPE_MACHINE);
+      
+      i = cell_pattern->cursor_y;
+      j = cell_pattern->cursor_x;
+      
+      index1 = machine->bank_1;
+
+      channel = ags_channel_nth(machine->audio->input, machine->audio->input_lines - i - 1);
+
+      toggle_pattern_bit = ags_toggle_pattern_bit_new(channel->pattern->data,
+						      channel->line,
+						      0, index1,
+						      j);
+      g_signal_connect(G_OBJECT(toggle_pattern_bit), "refresh-gui\0",
+		       G_CALLBACK(ags_cell_pattern_refresh_gui_callback), cell_pattern);
+      
+      ags_task_thread_append_task(AGS_TASK_THREAD(AGS_AUDIO_LOOP(AGS_MAIN(AGS_DEVOUT(machine->audio->devout)->ags_main)->main_loop)->task_thread),
+				  AGS_TASK(toggle_pattern_bit));
+    }
+    break;
+  }
+
+  return(TRUE);
+}
+
+void
+ags_cell_pattern_adjustment_value_changed_callback(GtkWidget *widget, AgsCellPattern *cell_pattern)
+{
+  ags_cell_pattern_draw_matrix(cell_pattern);
+}
+
+void
+ags_cell_pattern_refresh_gui_callback(AgsTogglePatternBit *toggle_pattern_bit,
+				      AgsCellPattern *cell_pattern)
+{
+  AgsMachine *machine;
+  
+  AgsChannel *channel;
+
+  guint line;
+  
+  machine = gtk_widget_get_ancestor(cell_pattern,
+				    AGS_TYPE_MACHINE);
+    
+  channel = ags_channel_nth(machine->audio->input,
+			    toggle_pattern_bit->line);
+  line = machine->audio->input_pads - toggle_pattern_bit->line - (guint) GTK_RANGE(cell_pattern->vscrollbar)->adjustment->value - 1;
+
+  ags_cell_pattern_redraw_gutter_point(cell_pattern,
+				       channel,
+				       toggle_pattern_bit->bit,
+				       line);
+}
diff --git a/src/ags/X/machine/ags_cell_pattern_callbacks.h b/src/ags/X/machine/ags_cell_pattern_callbacks.h
new file mode 100644
index 0000000..2f175dd
--- /dev/null
+++ b/src/ags/X/machine/ags_cell_pattern_callbacks.h
@@ -0,0 +1,41 @@
+/* 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_CELL_PATTERN_CALLBACKS_H__
+#define __AGS_CELL_PATTERN_CALLBACKS_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <ags/X/machine/ags_cell_pattern.h>
+
+/* controls */
+gboolean ags_cell_pattern_focus_in_callback(GtkWidget *widget, GdkEvent *event, AgsCellPattern *cell_pattern);
+
+gboolean ags_cell_pattern_drawing_area_configure_callback(GtkWidget *widget, GdkEventConfigure *event, AgsCellPattern *cell_pattern);
+gboolean ags_cell_pattern_drawing_area_expose_callback(GtkWidget *widget, GdkEventExpose *event, AgsCellPattern *cell_pattern);
+
+gboolean ags_cell_pattern_drawing_area_button_press_callback(GtkWidget *widget, GdkEventButton *event, AgsCellPattern *cell_pattern);
+gboolean ags_cell_pattern_drawing_area_key_press_event(GtkWidget *widget, GdkEventKey *event, AgsCellPattern *cell_pattern);
+gboolean ags_cell_pattern_drawing_area_key_release_event(GtkWidget *widget, GdkEventKey *event, AgsCellPattern *cell_pattern);
+
+void ags_cell_pattern_adjustment_value_changed_callback(GtkWidget *widget, AgsCellPattern *cell_pattern);
+
+#endif /*__AGS_CELL_PATTERN_CALLBACKS_H__*/
diff --git a/src/ags/X/machine/ags_drum.c b/src/ags/X/machine/ags_drum.c
index e9bef92..abc05eb 100644
--- a/src/ags/X/machine/ags_drum.c
+++ b/src/ags/X/machine/ags_drum.c
@@ -302,7 +302,7 @@ ags_drum_init(AgsDrum *drum)
   frame = (GtkFrame *) gtk_frame_new("Pattern\0");
   gtk_box_pack_start((GtkBox *) hbox, (GtkWidget *) frame, FALSE, FALSE, 0);
 
-  table0 = (GtkTable *) gtk_table_new(16, 4, FALSE);
+  table0 = (GtkTable *) gtk_table_new(8, 4, FALSE);
   gtk_container_add((GtkContainer*) frame, (GtkWidget *) table0);
 
   drum->loop_button = (GtkCheckButton *) gtk_check_button_new_with_label("loop\0");
@@ -361,58 +361,13 @@ ags_drum_init(AgsDrum *drum)
   drum->length_spin->adjustment->value = 16.0;
   gtk_box_pack_start((GtkBox*) hbox, (GtkWidget *) drum->length_spin, FALSE, FALSE, 0);
 
-  /* led */
-  drum->active_led = 0;
-
-  drum->led =
-    hbox = (GtkHBox *) gtk_hbox_new(FALSE, 16);
+  /* pattern box */
+  drum->pattern_box = ags_pattern_box_new();
   gtk_table_attach(table0,
-		   (GtkWidget *) hbox,
-		   3, 15,
-		   1, 2,
-		   0, 0,
-		   0, 0);
-
-  for(i = 0; i < 16; i++){
-    toggle_button = (GtkToggleButton *) ags_led_new();
-    gtk_widget_set_size_request((GtkWidget *) toggle_button, 8, 4);
-    gtk_box_pack_start((GtkBox *) hbox, (GtkWidget *) toggle_button, FALSE, FALSE, 0);
-  }
-
-  /* pattern */
-  drum->pattern =
-    hbox = (GtkHBox *) gtk_hbox_new(FALSE, 0);
-  gtk_table_attach(table0,
-		   (GtkWidget *) hbox,
-		   3, 15,
-		   2, 3,
-		   0, 0,
-		   0, 0);
-
-  for(i = 0; i < 16; i++){
-    toggle_button = (GtkToggleButton *) gtk_toggle_button_new();
-    gtk_widget_set_size_request((GtkWidget *) toggle_button, 24, 24);
-    gtk_box_pack_start((GtkBox *) hbox, (GtkWidget *) toggle_button, FALSE, FALSE, 0);
-  }
-
-  /* page / offset */
-  drum->offset = (GtkVBox*) gtk_vbox_new(FALSE, 0);
-  gtk_table_attach_defaults(table0, (GtkWidget *) drum->offset, 15, 16, 0, 3);
-
-  radio_button = (GtkRadioButton *) gtk_radio_button_new_with_label(NULL, "1-16\0");
-  gtk_box_pack_start((GtkBox*) drum->offset, (GtkWidget *) radio_button, FALSE, FALSE, 0);
-
-  gtk_box_pack_start((GtkBox*) drum->offset,
-		     (GtkWidget *) gtk_radio_button_new_with_label(radio_button->group, "17-32\0"),
-		     FALSE, FALSE, 0);
-
-  gtk_box_pack_start((GtkBox*) drum->offset,
-		     (GtkWidget *) gtk_radio_button_new_with_label(radio_button->group, "33-48\0"),
-		     FALSE, FALSE, 0);
-
-  gtk_box_pack_start((GtkBox*) drum->offset,
-		     (GtkWidget *) gtk_radio_button_new_with_label(radio_button->group, "49-64\0"),
-		     FALSE, FALSE, 0);
+		   (GtkWidget *) drum->pattern_box,
+		   7, 8, 0, 3,
+		   GTK_EXPAND, GTK_EXPAND,
+		   0, 0);  
 }
 
 void
@@ -426,9 +381,13 @@ ags_drum_connect(AgsConnectable *connectable)
 {
   AgsWindow *window;
   AgsDrum *drum;
-  AgsDelayAudioRun *play_delay_audio_run;
+
   AgsRecallHandler *recall_handler;
+
+  AgsDelayAudioRun *play_delay_audio_run;
+
   GList *list, *list_start;
+
   int i;
 
   if((AGS_MACHINE_CONNECTED & (AGS_MACHINE(connectable)->flags)) != 0){
@@ -463,31 +422,7 @@ ags_drum_connect(AgsConnectable *connectable)
 		     G_CALLBACK(ags_drum_index0_callback), (gpointer) drum);
   }
 
-  /* connect pattern */
-  list_start = 
-    list = gtk_container_get_children((GtkContainer *) drum->pattern);
-
-  while(list != NULL){
-    g_signal_connect(G_OBJECT(list->data), "clicked\0",
-		     G_CALLBACK(ags_drum_pad_callback), (gpointer) drum);
-
-    list = list->next;
-  }
-
-  g_list_free(list_start);
-
-  /* connect pattern offset range */
-  list_start = 
-    list = gtk_container_get_children((GtkContainer *) drum->offset);
-
-  while(list != NULL){
-    g_signal_connect(G_OBJECT(list->data), "clicked\0",
-		     G_CALLBACK(ags_drum_offset_callback), (gpointer) drum);
-		   
-    list = list->next;
-  }
-
-  g_list_free(list_start);
+  ags_connectable_connect(drum->pattern_box);
 
   /* AgsAudio */
   g_signal_connect_after(G_OBJECT(AGS_MACHINE(drum)->audio), "tact\0",
@@ -517,7 +452,7 @@ ags_drum_show(GtkWidget *widget)
 {
   GTK_WIDGET_CLASS(ags_drum_parent_class)->show(widget);
 
-  ags_drum_set_pattern(AGS_DRUM(widget));
+  ags_pattern_box_set_pattern(AGS_DRUM(widget)->pattern_box);
 }
 
 void
@@ -525,7 +460,7 @@ ags_drum_show_all(GtkWidget *widget)
 {
   GTK_WIDGET_CLASS(ags_drum_parent_class)->show_all(widget);
 
-  ags_drum_set_pattern(AGS_DRUM(widget));
+  ags_pattern_box_set_pattern(AGS_DRUM(widget)->pattern_box);
 }
 
 void
@@ -880,7 +815,9 @@ ags_drum_set_pads(AgsAudio *audio, GType gtype,
       if(pads_old == 0){
 	GtkToggleButton *selected_edit_button;
 
-	drum->selected_pad = AGS_DRUM_INPUT_PAD(gtk_container_get_children((GtkContainer *) drum->input_pad)->data);
+	AGS_MACHINE(drum)->selected_input_pad = 
+	  drum->selected_pad = AGS_DRUM_INPUT_PAD(gtk_container_get_children((GtkContainer *) drum->input_pad)->data);
+	
 	drum->selected_edit_button = drum->selected_pad->edit;
 	gtk_toggle_button_set_active((GtkToggleButton *) drum->selected_edit_button, TRUE);
       }
@@ -893,7 +830,9 @@ ags_drum_set_pads(AgsAudio *audio, GType gtype,
 	drum_input_pad = AGS_DRUM_INPUT_PAD(gtk_widget_get_ancestor(GTK_WIDGET(drum->selected_edit_button), AGS_TYPE_PAD));
 
 	if(drum_input_pad->pad.channel->pad > pads){
-	  drum->selected_pad = AGS_DRUM_INPUT_PAD(gtk_container_get_children((GtkContainer *) drum->input_pad)->data);
+	  AGS_MACHINE(drum)->selected_input_pad = 
+	    drum->selected_pad = AGS_DRUM_INPUT_PAD(gtk_container_get_children((GtkContainer *) drum->input_pad)->data);
+	  
 	  drum->selected_edit_button = drum->selected_pad->edit;
 	  gtk_toggle_button_set_active((GtkToggleButton *) drum->selected_edit_button, TRUE);
 	}
@@ -902,63 +841,6 @@ ags_drum_set_pads(AgsAudio *audio, GType gtype,
   }  
 }
 
-void
-ags_drum_set_pattern(AgsDrum *drum)
-{
-  AgsLine *selected_line;
-  GList *list, *line;
-  guint index0, index1, offset;
-  gboolean set_active;
-  guint i;
-
-  if(drum->selected_pad == NULL){
-    g_message("no selected pad\n\0");
-    return;
-  }
-
-  for(i = 0; i < 4 && drum->selected0 != drum->index0[i]; i++);
-
-  index0 = i;
-
-  for(i = 0; i < 12 && drum->selected1 != drum->index1[i]; i++);
-  
-  index1 = i;
-
-  list = gtk_container_get_children((GtkContainer *) drum->offset);
-
-  for(i = 0; i < 4 && ! GTK_TOGGLE_BUTTON(list->data)->active; i++)
-    list = list->next;
-
-  offset = i * 16;
-
-  list = gtk_container_get_children((GtkContainer *) drum->pattern);
-
-  drum->flags |= AGS_DRUM_BLOCK_PATTERN;
-
-  for(i = 0; i < 16; i++){
-    set_active = TRUE;
-
-    line = gtk_container_get_children(GTK_CONTAINER(AGS_PAD(drum->selected_pad)->expander_set));
-
-    while((line = ags_line_find_next_grouped(line)) != NULL){
-      selected_line = AGS_LINE(line->data);
-
-      if(!ags_pattern_get_bit((AgsPattern *) selected_line->channel->pattern->data, index0, index1, offset + i)){
-	set_active = FALSE;
-	break;
-      }
-
-      line = line->next;
-    }
-
-    gtk_toggle_button_set_active((GtkToggleButton *) list->data, set_active);
-
-    list = list->next;
-  }
-
-  drum->flags &= (~AGS_DRUM_BLOCK_PATTERN);
-}
-
 /**
  * ags_drum_new:
  * @devout: the assigned devout.
diff --git a/src/ags/X/machine/ags_drum.h b/src/ags/X/machine/ags_drum.h
index 426b5f5..d88ee05 100644
--- a/src/ags/X/machine/ags_drum.h
+++ b/src/ags/X/machine/ags_drum.h
@@ -29,6 +29,7 @@
 #include <ags/audio/ags_recall_container.h>
 
 #include <ags/X/machine/ags_drum_input_pad.h>
+#include <ags/X/machine/ags_pattern_box.h>
 
 #define AGS_TYPE_DRUM                (ags_drum_get_type())
 #define AGS_DRUM(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_DRUM, AgsDrum))
@@ -37,21 +38,15 @@
 #define AGS_IS_DRUM_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_DRUM))
 #define AGS_DRUM_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_DRUM, AgsDrumClass))
 
-#define AGS_DRUM_PATTERN_CONTROLS (16)
-
 typedef struct _AgsDrum AgsDrum;
 typedef struct _AgsDrumClass AgsDrumClass;
 
-typedef enum{
-  AGS_DRUM_BLOCK_PATTERN    =  1,
-}AgsDrumFlags;
-
 struct _AgsDrum
 {
   AgsMachine machine;
 
   guint flags;
-
+  
   gchar *name;
   gchar *xml_type;
 
@@ -79,11 +74,7 @@ struct _AgsDrum
   GtkToggleButton *index1[12];
   GtkToggleButton *selected1;
 
-  guint active_led;
-  GtkHBox *led;
-  GtkHBox *pattern;
-
-  GtkVBox *offset;
+  AgsPatternBox *pattern_box;
 };
 
 struct _AgsDrumClass
@@ -93,8 +84,6 @@ struct _AgsDrumClass
 
 GType ags_drum_get_type(void);
 
-void ags_drum_set_pattern(AgsDrum *drum);
-
 AgsDrum* ags_drum_new(GObject *devout);
 
 #endif /*__AGS_DRUM_H__*/
diff --git a/src/ags/X/machine/ags_drum_callbacks.c b/src/ags/X/machine/ags_drum_callbacks.c
index b58f581..152882e 100644
--- a/src/ags/X/machine/ags_drum_callbacks.c
+++ b/src/ags/X/machine/ags_drum_callbacks.c
@@ -309,7 +309,7 @@ ags_drum_index0_callback(GtkWidget *widget, AgsDrum *drum)
       drum->selected0 = (GtkToggleButton*) widget;
     }
 
-    ags_drum_set_pattern(drum);
+    ags_pattern_box_set_pattern(drum->pattern_box);
   }
 
   pthread_mutex_unlock(audio_mutex);
@@ -386,115 +386,13 @@ ags_drum_index1_callback(GtkWidget *widget, AgsDrum *drum)
       drum->selected1 = (GtkToggleButton*) widget;
     }
 
-    ags_drum_set_pattern(drum);
+    ags_pattern_box_set_pattern(drum->pattern_box);
   }
 
   pthread_mutex_unlock(audio_mutex);
 }
 
 void
-ags_drum_pad_callback(GtkWidget *toggle_button, AgsDrum *drum)
-{
-  AgsLine *selected_line;
-
-  AgsPattern *pattern;
-  
-  AgsTogglePatternBit *toggle_pattern_bit;
-
-  AgsMutexManager *mutex_manager;
-
-  GList *list, *list_start;
-  GList *line, *line_start;
-  GList *tasks;
-  guint i, index0, index1, offset;
-
-  pthread_mutex_t *audio_mutex;
-
-  if(drum->selected_pad == NULL){
-    return;
-  }
-
-  if((AGS_DRUM_BLOCK_PATTERN & (drum->flags)) != 0){
-#ifdef AGS_DEBUG
-    g_message("AgsDrum pattern is blocked\n\0");
-#endif
-
-    return;
-  }
-  
-  pthread_mutex_lock(&(ags_application_mutex));
-  
-  mutex_manager = ags_mutex_manager_get_instance();
-
-  audio_mutex = ags_mutex_manager_lookup(mutex_manager,
-					 (GObject *) AGS_MACHINE(drum)->audio);
-  
-  pthread_mutex_unlock(&(ags_application_mutex));
-
-  pthread_mutex_lock(audio_mutex);
-
-  /* calculate offset */
-  list_start = 
-    list = gtk_container_get_children((GtkContainer *) drum->pattern);
-
-  for(i = 0; i < 16 && toggle_button != list->data; i++)
-    list = list->next;
-
-  offset = i;
-  g_list_free(list_start);
-
-  /* calculate index 0 */
-  index0 = ((guint) drum->selected0->button.label_text[0] - 'a');
-  
-  /* calculate index 1 */
-  index1 = ((guint) g_ascii_strtoull(drum->selected1->button.label_text, NULL, 10)) - 1;
-  
-  /* calculate offset / page */
-  list_start = 
-    list = gtk_container_get_children((GtkContainer *) drum->offset);
-
-  for(i = 0; i < 4 && ! GTK_TOGGLE_BUTTON(list->data)->active; i++)
-    list = list->next;
-
-  offset += (i * 16);
-
-  g_list_free(list_start);
-
-  /**/
-  line_start = 
-    line = gtk_container_get_children(GTK_CONTAINER(AGS_PAD(drum->selected_pad)->expander_set));
-  tasks = NULL;
-
-  while((line = ags_line_find_next_grouped(line)) != NULL){
-    selected_line = AGS_LINE(line->data);
-
-    toggle_pattern_bit = ags_toggle_pattern_bit_new(selected_line->channel->pattern->data,
-						    selected_line->channel->line,
-						    index0, index1,
-						    offset);
-
-    tasks = g_list_prepend(tasks,
-			   toggle_pattern_bit);
-
-    line = line->next;
-  }
-
-  g_list_free(line_start);
-
-  /* append AgsTogglePatternBit */
-  ags_task_thread_append_tasks(AGS_TASK_THREAD(AGS_AUDIO_LOOP(AGS_MAIN(AGS_DEVOUT(AGS_MACHINE(drum)->audio->devout)->ags_main)->main_loop)->task_thread),
-			       tasks);
-
-  pthread_mutex_unlock(audio_mutex);
-}
-
-void
-ags_drum_offset_callback(GtkWidget *widget, AgsDrum *drum)
-{
-  ags_drum_set_pattern(drum);
-}
-
-void
 ags_drum_tact_callback(AgsAudio *audio,
 		       AgsRecallID *recall_id,
 		       AgsDrum *drum)
@@ -551,21 +449,21 @@ ags_drum_tact_callback(AgsAudio *audio,
   }
 
   /* set optical feedback */
-  active_led_new = (guint) play_count_beats_audio_run->sequencer_counter % AGS_DRUM_PATTERN_CONTROLS;
-  drum->active_led = (guint) active_led_new;
+  active_led_new = (guint) play_count_beats_audio_run->sequencer_counter % AGS_PATTERN_BOX_N_CONTROLS;
+  drum->pattern_box->active_led = (guint) active_led_new;
 
   if(play_count_beats_audio_run->sequencer_counter == 0){
     g_value_init(&value, G_TYPE_DOUBLE);
     ags_port_safe_read(play_count_beats_audio->sequencer_loop_end,
 		       &value);
     
-    active_led_old = (guint) (g_value_get_double(&value) - 1.0) % AGS_DRUM_PATTERN_CONTROLS;
+    active_led_old = (guint) (g_value_get_double(&value) - 1.0) % AGS_PATTERN_BOX_N_CONTROLS;
     g_value_unset(&value);
   }else{
-    active_led_old = (guint) (drum->active_led - 1.0) % AGS_DRUM_PATTERN_CONTROLS;
+    active_led_old = (guint) (drum->pattern_box->active_led - 1.0) % AGS_PATTERN_BOX_N_CONTROLS;
   }
 
-  toggle_led = ags_toggle_led_new(gtk_container_get_children(GTK_CONTAINER(drum->led)),
+  toggle_led = ags_toggle_led_new(gtk_container_get_children(GTK_CONTAINER(drum->pattern_box->led)),
 				  (guint) active_led_new,
 				  (guint) active_led_old);
 
@@ -602,7 +500,7 @@ ags_drum_done_callback(AgsAudio *audio,
 
     /* unset led */
     list_start = 
-      list = gtk_container_get_children(GTK_CONTAINER(drum->led));
+      list = gtk_container_get_children(GTK_CONTAINER(drum->pattern_box->led));
 
     while(list != NULL){
       ags_led_unset_active(AGS_LED(list->data));
diff --git a/src/ags/X/machine/ags_drum_callbacks.h b/src/ags/X/machine/ags_drum_callbacks.h
index bf0d2c0..1c03d12 100644
--- a/src/ags/X/machine/ags_drum_callbacks.h
+++ b/src/ags/X/machine/ags_drum_callbacks.h
@@ -41,10 +41,6 @@ void ags_drum_length_spin_callback(GtkWidget *spin_button, AgsDrum *drum);
 void ags_drum_index0_callback(GtkWidget *toggle_button, AgsDrum *drum);
 void ags_drum_index1_callback(GtkWidget *toggle_button, AgsDrum *drum);
 
-void ags_drum_pad_callback(GtkWidget *toggle_button, AgsDrum *drum);
-
-void ags_drum_offset_callback(GtkWidget *widget, AgsDrum *drum);
-
 /* audio */
 void ags_drum_tact_callback(AgsAudio *audio,
 			    AgsRecallID *recall_id,
diff --git a/src/ags/X/machine/ags_drum_input_line.c b/src/ags/X/machine/ags_drum_input_line.c
index 4636be3..4ddd09d 100644
--- a/src/ags/X/machine/ags_drum_input_line.c
+++ b/src/ags/X/machine/ags_drum_input_line.c
@@ -390,7 +390,7 @@ ags_drum_input_line_group_changed(AgsLine *line)
   AgsDrum *drum;
 
   drum = (AgsDrum *) gtk_widget_get_ancestor(GTK_WIDGET(line), AGS_TYPE_DRUM);
-  ags_drum_set_pattern(drum);
+  ags_pattern_box_set_pattern(drum->pattern_box);
 }
 
 void
diff --git a/src/ags/X/machine/ags_drum_input_pad_callbacks.c b/src/ags/X/machine/ags_drum_input_pad_callbacks.c
index 418438d..de33b08 100644
--- a/src/ags/X/machine/ags_drum_input_pad_callbacks.c
+++ b/src/ags/X/machine/ags_drum_input_pad_callbacks.c
@@ -627,16 +627,27 @@ ags_drum_input_pad_edit_callback(GtkWidget *toggle_button, AgsDrumInputPad *drum
 
   if(drum->selected_edit_button != NULL){
     if(GTK_TOGGLE_BUTTON(toggle_button) != drum->selected_edit_button){
+      /* unset old */
       toggle = drum->selected_edit_button;
+
       drum->selected_edit_button = NULL;
       gtk_toggle_button_set_active((GtkToggleButton *) toggle, FALSE);
+
+      /* apply new */
       drum->selected_edit_button = (GtkToggleButton *) toggle_button;
       drum->selected_pad = (AgsDrumInputPad *) gtk_widget_get_ancestor((GtkWidget *) toggle_button, AGS_TYPE_DRUM_INPUT_PAD);
-      ags_drum_set_pattern(drum);
+
+      AGS_MACHINE(drum)->selected_input_pad = drum->selected_pad;
+      
+      ags_pattern_box_set_pattern(drum->pattern_box);
     }else{
+      /* chain up */
       toggle = drum->selected_edit_button;
+      
       drum->selected_edit_button = NULL;
       gtk_toggle_button_set_active((GtkToggleButton *) toggle, TRUE);
+
+      /* reset */
       drum->selected_edit_button = toggle;
     }
   }
diff --git a/src/ags/X/machine/ags_matrix.c b/src/ags/X/machine/ags_matrix.c
index 3746d4e..20e4be0 100644
--- a/src/ags/X/machine/ags_matrix.c
+++ b/src/ags/X/machine/ags_matrix.c
@@ -69,8 +69,6 @@
 #include <ags/audio/recall/ags_play_notation_audio.h>
 #include <ags/audio/recall/ags_play_notation_audio_run.h>
 
-#include <ags/widget/ags_led.h>
-
 #include <ags/X/ags_menu_bar.h>
 
 #include <math.h>
@@ -119,8 +117,6 @@ static gpointer ags_matrix_parent_class = NULL;
 
 static AgsConnectableInterface *ags_matrix_parent_connectable_interface;
 
-GtkStyle *matrix_style;
-
 extern const char *AGS_COPY_PATTERN;
 const char *AGS_MATRIX_INDEX = "AgsMatrixIndex\0";
 
@@ -226,8 +222,6 @@ ags_matrix_init(AgsMatrix *matrix)
   GtkFrame *frame;
   GtkTable *table;
   GtkToggleButton *button;
-  GtkVScrollbar *vscrollbar;
-  AgsLed *led;
   GtkVBox *vbox;
   GtkHBox *hbox;
 
@@ -280,7 +274,8 @@ ags_matrix_init(AgsMatrix *matrix)
   frame = (GtkFrame *) (gtk_bin_get_child((GtkBin *) matrix));
 
   matrix->table = (GtkTable *) gtk_table_new(4, 4, FALSE);
-  gtk_container_add((GtkContainer *) frame, (GtkWidget *) matrix->table);
+  gtk_container_add((GtkContainer *) frame,
+		    (GtkWidget *) matrix->table);
 
   AGS_MACHINE(matrix)->play = 
     matrix->run = (GtkToggleButton *) gtk_toggle_button_new_with_label("run\0");
@@ -302,8 +297,10 @@ ags_matrix_init(AgsMatrix *matrix)
       matrix->index[i * 3 + j] =
 	button = (GtkToggleButton *) gtk_toggle_button_new_with_label(g_strdup_printf("%d\0", i * 3 + j +1));
       g_object_set_data((GObject *) button, AGS_MATRIX_INDEX, GUINT_TO_POINTER(i * 3 + j));
-      gtk_table_attach(table, (GtkWidget *) button,
-		       j, j +1, i, i +1,
+      gtk_table_attach(table,
+		       (GtkWidget *) button,
+		       j, j +1,
+		       i, i +1,
 		       GTK_FILL, GTK_FILL,
 		       0, 0);
     }
@@ -313,69 +310,46 @@ ags_matrix_init(AgsMatrix *matrix)
   gtk_toggle_button_set_active(matrix->selected, TRUE);
 
   /* sequencer */
-  table = (GtkTable *) gtk_table_new(2, 2, FALSE);
-  gtk_table_attach(matrix->table, (GtkWidget *) table,
-		   2, 3, 0, 1,
-		   GTK_FILL, GTK_FILL,
-		   0, 0);
-
-  matrix->drawing_area = (GtkDrawingArea *) gtk_drawing_area_new();
-  gtk_widget_set_size_request((GtkWidget *) matrix->drawing_area, 32 * AGS_MATRIX_CELL_WIDTH +1, AGS_MATRIX_OCTAVE * AGS_MATRIX_CELL_HEIGHT +1);
-  gtk_widget_set_style((GtkWidget *) matrix->drawing_area, matrix_style);
-  gtk_table_attach(table, (GtkWidget *) matrix->drawing_area,
-		   0, 1, 0, 1,
-		   GTK_FILL, GTK_FILL,
-		   0, 0);
-  gtk_widget_set_events ((GtkWidget *) matrix->drawing_area,
-                         GDK_EXPOSURE_MASK
-                         | GDK_LEAVE_NOTIFY_MASK
-                         | GDK_BUTTON_PRESS_MASK
-                         | GDK_POINTER_MOTION_MASK
-                         | GDK_POINTER_MOTION_HINT_MASK);
-
-  matrix->adjustment = (GtkAdjustment *) gtk_adjustment_new(0.0, 0.0, 77.0, 1.0, 1.0, (gdouble) AGS_MATRIX_OCTAVE);
-
-  vscrollbar = (GtkVScrollbar *) gtk_vscrollbar_new(matrix->adjustment);
-  gtk_widget_set_style((GtkWidget *) vscrollbar, matrix_style);
-  gtk_table_attach(table, (GtkWidget *) vscrollbar,
-		   1, 2, 0, 1,
+  matrix->cell_pattern = ags_cell_pattern_new();
+  gtk_table_attach(matrix->table,
+		   (GtkWidget *) matrix->cell_pattern,
+		   2, 3,
+		   0, 1,
 		   GTK_FILL, GTK_FILL,
 		   0, 0);
 
-  /* led */
-  matrix->active_led = 0;
-
-  matrix->led =
-    hbox = (GtkHBox *) gtk_hbox_new(FALSE, 0);
-  gtk_table_attach(matrix->table, (GtkWidget *) hbox,
-		   2, 3, 1, 2,
-		   GTK_FILL, GTK_FILL,
-		   0, 0);
-
-  for(i = 0; i < 32; i++){
-    led = ags_led_new();
-    gtk_widget_set_size_request((GtkWidget *) led, AGS_MATRIX_CELL_WIDTH, AGS_MATRIX_CELL_WIDTH / 2);
-    gtk_box_pack_start((GtkBox *) hbox, (GtkWidget *) led, FALSE, FALSE, 0);
-  }
-
-  /*  */
+  /* length and loop */
   vbox = (GtkVBox *) gtk_vbox_new(FALSE, 0);
-  gtk_table_attach(matrix->table, (GtkWidget *) vbox,
-		   3, 4, 0, 1,
+  gtk_table_attach(matrix->table,
+		   (GtkWidget *) vbox,
+		   3, 4,
+		   0, 1,
 		   GTK_FILL, GTK_FILL,
 		   0, 0);
 
   hbox = (GtkHBox *) gtk_hbox_new(FALSE, 0);
-  gtk_box_pack_start((GtkBox *) vbox, (GtkWidget *) hbox, FALSE, FALSE, 0);
+  gtk_box_pack_start((GtkBox *) vbox,
+		     (GtkWidget *) hbox,
+		     FALSE, FALSE,
+		     0);
 
-  gtk_box_pack_start((GtkBox *) hbox, gtk_label_new("length\0"), FALSE, FALSE, 0);
+  gtk_box_pack_start((GtkBox *) hbox,
+		     gtk_label_new("length\0"),
+		     FALSE, FALSE,
+		     0);
 
   matrix->length_spin = (GtkSpinButton *) gtk_spin_button_new_with_range(1.0, 32.0, 1.0);
   matrix->length_spin->adjustment->value = 16.0;
-  gtk_box_pack_start((GtkBox *) hbox, (GtkWidget *) matrix->length_spin, FALSE, FALSE, 0);
+  gtk_box_pack_start((GtkBox *) hbox,
+		     (GtkWidget *) matrix->length_spin,
+		     FALSE, FALSE,
+		     0);
 
   matrix->loop_button = (GtkCheckButton *) gtk_check_button_new_with_label("loop\0");
-  gtk_box_pack_start((GtkBox *) vbox, (GtkWidget *) matrix->loop_button, FALSE, FALSE, 0);
+  gtk_box_pack_start((GtkBox *) vbox,
+		     (GtkWidget *) matrix->loop_button,
+		     FALSE, FALSE,
+		     0);
 }
 
 void
@@ -399,26 +373,16 @@ ags_matrix_connect(AgsConnectable *connectable)
 
   ags_matrix_parent_connectable_interface->connect(connectable);
 
+  /* AgsMatrix */
   matrix = AGS_MATRIX(connectable);
 
-  /* AgsMatrix */
   for(i  = 0; i < 9; i++){
     g_signal_connect (G_OBJECT (matrix->index[i]), "clicked\0",
 		      G_CALLBACK (ags_matrix_index_callback), (gpointer) matrix);
   }
 
-  g_signal_connect_after(G_OBJECT (matrix->drawing_area), "configure_event\0",
-			 G_CALLBACK (ags_matrix_drawing_area_configure_callback), (gpointer) matrix);
-
-  g_signal_connect_after(G_OBJECT (matrix->drawing_area), "expose_event\0",
-			 G_CALLBACK (ags_matrix_drawing_area_expose_callback), (gpointer) matrix);
-
-  g_signal_connect (G_OBJECT (matrix->drawing_area), "button_press_event\0",
-                    G_CALLBACK (ags_matrix_drawing_area_button_press_callback), (gpointer) matrix);
-
-  g_signal_connect (G_OBJECT (matrix->adjustment), "value_changed\0",
-                    G_CALLBACK (ags_matrix_adjustment_value_changed_callback), (gpointer) matrix);
-
+  ags_connectable_connect(AGS_CONNECTABLE(matrix->cell_pattern));
+  
   g_signal_connect_after((GObject *) matrix->length_spin, "value-changed\0",
 			 G_CALLBACK(ags_matrix_length_spin_callback), (gpointer) matrix);
 
@@ -450,16 +414,12 @@ void
 ags_matrix_show(GtkWidget *widget)
 {
   GTK_WIDGET_CLASS(ags_matrix_parent_class)->show(widget);
-
-  ags_matrix_draw_matrix(AGS_MATRIX(widget));
 }
 
 void
 ags_matrix_show_all(GtkWidget *widget)
 {
   GTK_WIDGET_CLASS(ags_matrix_parent_class)->show_all(widget);
-
-  ags_matrix_draw_matrix(AGS_MATRIX(widget));
 }
 
 void
@@ -493,14 +453,14 @@ ags_matrix_set_pads(AgsAudio *audio, GType type,
   machine = AGS_MACHINE(matrix);
 
   if(type == AGS_TYPE_INPUT){
-    if(pads < AGS_MATRIX_OCTAVE){
-      gtk_widget_set_size_request((GtkWidget *) matrix->drawing_area,
-				  32 * AGS_MATRIX_CELL_WIDTH +1,
-				  pads * AGS_MATRIX_CELL_HEIGHT +1);
-    }else if(pads_old < AGS_MATRIX_OCTAVE){
-      gtk_widget_set_size_request((GtkWidget *) matrix->drawing_area,
-				  32 * AGS_MATRIX_CELL_WIDTH +1,
-				  AGS_MATRIX_OCTAVE * AGS_MATRIX_CELL_HEIGHT +1);
+    if(pads < AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
+      gtk_widget_set_size_request((GtkWidget *) matrix->cell_pattern,
+				  -1,
+				  pads * matrix->cell_pattern->cell_height + 1);
+    }else if(pads_old < AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY){
+      gtk_widget_set_size_request((GtkWidget *) matrix->cell_pattern,
+				  -1,
+				  AGS_CELL_PATTERN_MAX_CONTROLS_SHOWN_VERTICALLY * matrix->cell_pattern->cell_height + 1);
     }
   }
 
@@ -854,139 +814,6 @@ ags_matrix_output_map_recall(AgsMatrix *matrix, guint output_pad_start)
   matrix->mapped_output_pad = audio->output_pads;
 }
 
-void
-ags_matrix_draw_gutter(AgsMatrix *matrix)
-{
-  AgsChannel *channel;
-
-  AgsMutexManager *mutex_manager;
-
-  guint gutter;
-  int i, j;
-
-  pthread_mutex_t *audio_mutex;
-  
-  pthread_mutex_lock(&(ags_application_mutex));
-  
-  mutex_manager = ags_mutex_manager_get_instance();
-
-  audio_mutex = ags_mutex_manager_lookup(mutex_manager,
-					 (GObject *) AGS_MACHINE(matrix)->audio);
-  
-  pthread_mutex_unlock(&(ags_application_mutex));
-
-  pthread_mutex_lock(audio_mutex);
-
-  gdk_draw_rectangle (GTK_WIDGET (matrix->drawing_area)->window,
-                      GTK_WIDGET (matrix->drawing_area)->style->bg_gc[0],
-                      TRUE,
-                      0, 0,
-                      288, 80);
-
-  channel = ags_channel_nth(AGS_MACHINE(matrix)->audio->input, AGS_MACHINE(matrix)->audio->input_lines - ((guint) matrix->adjustment->value + AGS_MATRIX_OCTAVE) - 1);
-
-  if(AGS_MACHINE(matrix)->audio->input_pads > AGS_MATRIX_OCTAVE){
-    gutter = AGS_MATRIX_OCTAVE;
-  }else{
-    gutter = AGS_MACHINE(matrix)->audio->input_pads;
-  }
-
-  for (i = 0; i < gutter; i++){
-    for (j = 0; j < 32; j++){
-      gdk_draw_rectangle (GTK_WIDGET (matrix->drawing_area)->window,
-                          GTK_WIDGET (matrix->drawing_area)->style->fg_gc[0],
-                          FALSE,
-                          j * 12, i * 10,
-                          12, 10);
-
-      ags_matrix_redraw_gutter_point (matrix, channel, j, i);
-    }
-
-    channel = channel->prev;
-  }
-
-  pthread_mutex_unlock(audio_mutex);
-}
-
-void
-ags_matrix_draw_matrix(AgsMatrix *matrix)
-{
-  AgsChannel *channel;
-
-  AgsMutexManager *mutex_manager;
-
-  guint gutter;
-  int i, j;
-
-  pthread_mutex_t *audio_mutex;
-
-  pthread_mutex_lock(&(ags_application_mutex));
-  
-  mutex_manager = ags_mutex_manager_get_instance();
-
-  audio_mutex = ags_mutex_manager_lookup(mutex_manager,
-					 (GObject *) AGS_MACHINE(matrix)->audio);
-  
-  pthread_mutex_unlock(&(ags_application_mutex));
-
-  pthread_mutex_lock(audio_mutex);
-
-  if(AGS_MACHINE(matrix)->audio->input_pads > AGS_MATRIX_OCTAVE){
-    gutter = AGS_MATRIX_OCTAVE;
-  }else{
-    gutter = AGS_MACHINE(matrix)->audio->input_pads;
-  }
-
-  channel = ags_channel_nth(AGS_MACHINE(matrix)->audio->input, AGS_MACHINE(matrix)->audio->input_pads - (guint) matrix->adjustment->value - 1);
-
-  if(channel == NULL){
-    pthread_mutex_unlock(audio_mutex);
-    
-    return;
-  }
-
-  for (i = 0; i < gutter; i++){
-    for (j = 0; j < 32; j++)
-      ags_matrix_redraw_gutter_point (matrix, channel, j, i);
-
-    channel = channel->prev;
-  }
-
-  pthread_mutex_unlock(audio_mutex);
-}
-
-void
-ags_matrix_redraw_gutter_point (AgsMatrix *matrix, AgsChannel *channel, guint j, guint i)
-{
-  if(channel->pattern == NULL)
-    return;
-
-  if(ags_pattern_get_bit((AgsPattern *) channel->pattern->data, 0, strtol(matrix->selected->button.label_text, NULL, 10) - 1, j))
-    ags_matrix_highlight_gutter_point(matrix, j, i);
-  else
-    ags_matrix_unpaint_gutter_point(matrix, j, i);
-}
-
-void
-ags_matrix_highlight_gutter_point(AgsMatrix *matrix, guint j, guint i)
-{
-  gdk_draw_rectangle (GTK_WIDGET (matrix->drawing_area)->window,
-		      GTK_WIDGET (matrix->drawing_area)->style->fg_gc[0],
-		      TRUE,
-		      j * AGS_MATRIX_CELL_WIDTH + 1, i * AGS_MATRIX_CELL_HEIGHT + 1,
-		      11, 9);
-}
-
-void
-ags_matrix_unpaint_gutter_point(AgsMatrix *matrix, guint j, guint i)
-{
-  gdk_draw_rectangle (GTK_WIDGET (matrix->drawing_area)->window,
-		      GTK_WIDGET (matrix->drawing_area)->style->bg_gc[0],
-		      TRUE,
-		      j * AGS_MATRIX_CELL_WIDTH + 1, i * AGS_MATRIX_CELL_HEIGHT +1,
-		      11, 9);
-}
-
 gchar*
 ags_matrix_get_name(AgsPlugin *plugin)
 {
diff --git a/src/ags/X/machine/ags_matrix.h b/src/ags/X/machine/ags_matrix.h
index 4a729e6..7637b41 100644
--- a/src/ags/X/machine/ags_matrix.h
+++ b/src/ags/X/machine/ags_matrix.h
@@ -26,6 +26,8 @@
 
 #include <ags/X/ags_machine.h>
 
+#include <ags/X/machine/ags_cell_pattern.h>
+
 #define AGS_TYPE_MATRIX                (ags_matrix_get_type())
 #define AGS_MATRIX(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_MATRIX, AgsMatrix))
 #define AGS_MATRIX_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_MATRIX, AgsMatrixClass))
@@ -33,12 +35,6 @@
 #define AGS_IS_MATRIX_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_MATRIX))
 #define AGS_MATRIX_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_MATRIX, AgsMatrixClass))
 
-#define AGS_MATRIX_PATTERN_CONTROLS (16)
-#define AGS_MATRIX_OCTAVE 10
-
-#define AGS_MATRIX_CELL_WIDTH   12
-#define AGS_MATRIX_CELL_HEIGHT  10
-
 typedef struct _AgsMatrix AgsMatrix;
 typedef struct _AgsMatrixClass AgsMatrixClass;
 
@@ -60,11 +56,7 @@ struct _AgsMatrix
   GtkToggleButton *selected;
   GtkToggleButton *index[9];
 
-  GtkDrawingArea *drawing_area;
-  guint active_led;
-  GtkHBox *led;
-
-  GtkAdjustment *adjustment;
+  AgsCellPattern *cell_pattern;
 
   GtkSpinButton *length_spin;
   GtkCheckButton *loop_button;
@@ -80,12 +72,6 @@ GType ags_matrix_get_type(void);
 void ags_matrix_input_map_recall(AgsMatrix *matrix, guint input_pad_start);
 void ags_matrix_output_map_recall(AgsMatrix *matrix, guint output_pad_start);
 
-void ags_matrix_draw_gutter(AgsMatrix *matrix);
-void ags_matrix_draw_matrix(AgsMatrix *matrix);
-void ags_matrix_redraw_gutter_point(AgsMatrix *matrix, AgsChannel *channel, guint j, guint i);
-void ags_matrix_highlight_gutter_point(AgsMatrix *matrix, guint j, guint i);
-void ags_matrix_unpaint_gutter_point(AgsMatrix *matrix, guint j, guint i);
-
 AgsMatrix* ags_matrix_new(GObject *devout);
 
 #endif /*__AGS_MATRIX_H__*/
diff --git a/src/ags/X/machine/ags_matrix_callbacks.c b/src/ags/X/machine/ags_matrix_callbacks.c
index 66ca5e7..702c3bd 100644
--- a/src/ags/X/machine/ags_matrix_callbacks.c
+++ b/src/ags/X/machine/ags_matrix_callbacks.c
@@ -34,7 +34,6 @@
 #include <ags/audio/ags_recall_container.h>
 
 #include <ags/audio/task/ags_toggle_led.h>
-#include <ags/audio/task/ags_toggle_pattern_bit.h>
 
 #include <ags/audio/task/recall/ags_apply_bpm.h>
 #include <ags/audio/task/recall/ags_apply_sequencer_length.h>
@@ -52,9 +51,6 @@
 
 #include <math.h>
 
-void ags_matrix_refresh_gui_callback(AgsTogglePatternBit *toggle_pattern_bit,
-				     AgsMatrix *matrix);
-
 extern const char *AGS_MATRIX_INDEX;
 extern pthread_mutex_t ags_application_mutex;
 
@@ -98,7 +94,7 @@ ags_matrix_index_callback(GtkWidget *widget, AgsMatrix *matrix)
       gtk_toggle_button_set_active(toggle, FALSE);
 
       matrix->selected = (GtkToggleButton*) widget;
-      ags_matrix_draw_matrix(matrix);
+      gtk_widget_queue_draw(matrix->cell_pattern);
 
       /*  */
       AGS_MACHINE(matrix)->bank_1 = 
@@ -126,60 +122,6 @@ ags_matrix_index_callback(GtkWidget *widget, AgsMatrix *matrix)
   }
 }
 
-gboolean
-ags_matrix_drawing_area_configure_callback(GtkWidget *widget, GdkEventConfigure *event, AgsMatrix *matrix)
-{
-  ags_matrix_draw_matrix(matrix);
-
-  return(FALSE);
-}
-
-gboolean
-ags_matrix_drawing_area_expose_callback(GtkWidget *widget, GdkEventExpose *event, AgsMatrix *matrix)
-{
-  ags_matrix_draw_gutter(matrix);
-  ags_matrix_draw_matrix(matrix);
-
-  return(FALSE);
-}
-
-gboolean
-ags_matrix_drawing_area_button_press_callback(GtkWidget *widget, GdkEventButton *event, AgsMatrix *matrix)
-{
-  if (event->button == 1){
-    AgsTogglePatternBit *toggle_pattern_bit;
-    AgsChannel *channel;
-    guint i, j;
-    guint index1;
-    
-    i = (guint) floor((double) event->y / (double) AGS_MATRIX_CELL_HEIGHT);
-    j = (guint) floor((double) event->x / (double) AGS_MATRIX_CELL_WIDTH);
-
-    index1 = ((guint) g_ascii_strtoull(matrix->selected->button.label_text, NULL, 10)) - 1;
-    
-    channel = ags_channel_nth(AGS_MACHINE(matrix)->audio->input, AGS_MACHINE(matrix)->audio->input_lines - ((guint) matrix->adjustment->value + i) - 1);
-
-    toggle_pattern_bit = ags_toggle_pattern_bit_new(channel->pattern->data,
-						    channel->line,
-						    0, index1,
-						    j);
-    g_signal_connect(G_OBJECT(toggle_pattern_bit), "refresh-gui\0",
-		     G_CALLBACK(ags_matrix_refresh_gui_callback), matrix);
-
-    ags_task_thread_append_task(AGS_TASK_THREAD(AGS_AUDIO_LOOP(AGS_MAIN(AGS_DEVOUT(AGS_MACHINE(matrix)->audio->devout)->ags_main)->main_loop)->task_thread),
-				AGS_TASK(toggle_pattern_bit));
-  }else if (event->button == 3){
-  }
-
-  return(FALSE);
-}
-
-void
-ags_matrix_adjustment_value_changed_callback(GtkWidget *widget, AgsMatrix *matrix)
-{
-  ags_matrix_draw_matrix(matrix);
-}
-
 void
 ags_matrix_length_spin_callback(GtkWidget *spin_button, AgsMatrix *matrix)
 {
@@ -232,19 +174,6 @@ ags_matrix_loop_button_callback(GtkWidget *button, AgsMatrix *matrix)
 }
 
 void
-ags_matrix_refresh_gui_callback(AgsTogglePatternBit *toggle_pattern_bit,
-				AgsMatrix *matrix)
-{
-  AgsChannel *channel;
-  guint line;
-
-  channel = ags_channel_nth(AGS_MACHINE(matrix)->audio->input, toggle_pattern_bit->line);
-  line = AGS_MACHINE(matrix)->audio->input_pads - toggle_pattern_bit->line - (guint) matrix->adjustment->value - 1;
-
-  ags_matrix_redraw_gutter_point(matrix, channel, toggle_pattern_bit->bit, line);
-}
-
-void
 ags_matrix_tact_callback(AgsAudio *audio,
 			 AgsRecallID *recall_id,
 			 AgsMatrix *matrix)
@@ -303,7 +232,7 @@ ags_matrix_tact_callback(AgsAudio *audio,
 
   /* set optical feedback */
   active_led_new = play_count_beats_audio_run->sequencer_counter;
-  matrix->active_led = (guint) active_led_new;
+  matrix->cell_pattern->active_led = (guint) active_led_new;
 
   if(active_led_new == 0){
     g_value_init(&value, G_TYPE_DOUBLE);
@@ -313,11 +242,11 @@ ags_matrix_tact_callback(AgsAudio *audio,
     active_led_old = g_value_get_double(&value) - 1.0;
     g_value_unset(&value);
   }else{
-    active_led_old = (gdouble) matrix->active_led - 1.0;
+    active_led_old = (gdouble) matrix->cell_pattern->active_led - 1.0;
   }
 
   //FIXME:JK: memory leak of GList
-  toggle_led = ags_toggle_led_new(gtk_container_get_children(GTK_CONTAINER(matrix->led)),
+  toggle_led = ags_toggle_led_new(gtk_container_get_children(GTK_CONTAINER(matrix->cell_pattern->led)),
 				  (guint) active_led_new,
 				  (guint) active_led_old);
 
@@ -354,7 +283,7 @@ ags_matrix_done_callback(AgsAudio *audio,
     
     /* unset led */
     list_start = 
-      list = gtk_container_get_children(GTK_CONTAINER(matrix->led));
+      list = gtk_container_get_children(GTK_CONTAINER(matrix->cell_pattern->led));
 
     while(list != NULL){
       ags_led_unset_active(AGS_LED(list->data));
diff --git a/src/ags/X/machine/ags_pattern_box.c b/src/ags/X/machine/ags_pattern_box.c
new file mode 100644
index 0000000..2f529e4
--- /dev/null
+++ b/src/ags/X/machine/ags_pattern_box.c
@@ -0,0 +1,677 @@
+/* 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/X/machine/ags_pattern_box.h>
+#include <ags/X/machine/ags_pattern_box_callbacks.h>
+
+#include <ags/main.h>
+
+#include <ags-lib/object/ags_connectable.h>
+
+#include <ags/thread/ags_mutex_manager.h>
+#include <ags/thread/ags_audio_loop.h>
+#include <ags/thread/ags_task_thread.h>
+
+#include <ags/audio/ags_pattern.h>
+
+#include <ags/widget/ags_led.h>
+
+#include <ags/X/ags_window.h>
+#include <ags/X/ags_machine.h>
+#include <ags/X/ags_pad.h>
+#include <ags/X/ags_line.h>
+
+#include <gdk/gdkkeysyms.h>
+
+#include <atk/atk.h>
+
+static GType ags_accessible_pattern_box_get_type(void);
+void ags_pattern_box_class_init(AgsPatternBoxClass *pattern_box);
+void ags_accessible_pattern_box_class_init(AtkObject *object);
+void ags_accessible_pattern_box_action_interface_init(AtkActionIface *action);
+void ags_pattern_box_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_pattern_box_init(AgsPatternBox *pattern_box);
+void ags_pattern_box_finalize(GObject *gobject);
+void ags_pattern_box_connect(AgsConnectable *connectable);
+void ags_pattern_box_disconnect(AgsConnectable *connectable);
+AtkObject* ags_pattern_box_get_accessible(GtkWidget *widget);
+void ags_pattern_box_show(GtkWidget *widget);
+void ags_pattern_box_show_all(GtkWidget *widget);
+
+gboolean ags_accessible_pattern_box_do_action(AtkAction *action,
+					      gint i);
+gint ags_accessible_pattern_box_get_n_actions(AtkAction *action);
+const gchar* ags_accessible_pattern_box_get_description(AtkAction *action,
+							gint i);
+const gchar* ags_accessible_pattern_box_get_name(AtkAction *action,
+						 gint i);
+const gchar* ags_accessible_pattern_box_get_keybinding(AtkAction *action,
+						       gint i);
+gboolean ags_accessible_pattern_box_set_description(AtkAction *action,
+						    gint i);
+gchar* ags_accessible_pattern_box_get_localized_name(AtkAction *action,
+						     gint i);
+
+/**
+ * SECTION:ags_pattern_box
+ * @short_description: pattern_box sequencer
+ * @title: AgsPatternBox
+ * @section_id:
+ * @include: ags/X/machine/ags_pattern_box.h
+ *
+ * The #AgsPatternBox is a composite widget to act as pattern box sequencer.
+ */
+
+static gpointer ags_pattern_box_parent_class = NULL;
+static GQuark quark_accessible_object = 0;
+
+extern pthread_mutex_t ags_application_mutex;
+
+GtkStyle *pattern_box_style;
+
+GType
+ags_pattern_box_get_type(void)
+{
+  static GType ags_type_pattern_box = 0;
+
+  if(!ags_type_pattern_box){
+    static const GTypeInfo ags_pattern_box_info = {
+      sizeof(AgsPatternBoxClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_pattern_box_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof(AgsPatternBox),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_pattern_box_init,
+    };
+
+    static const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_pattern_box_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+    
+    ags_type_pattern_box = g_type_register_static(GTK_TYPE_TABLE,
+						  "AgsPatternBox\0", &ags_pattern_box_info,
+						  0);
+    
+    g_type_add_interface_static(ags_type_pattern_box,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+  }
+
+  return(ags_type_pattern_box);
+}
+
+static GType
+ags_accessible_pattern_box_get_type(void)
+{
+  static GType ags_type_accessible_pattern_box = 0;
+
+  if(!ags_type_accessible_pattern_box){
+    const GTypeInfo ags_accesssible_pattern_box_info = {
+      sizeof(GtkAccessibleClass),
+      NULL,           /* base_init */
+      NULL,           /* base_finalize */
+      (GClassInitFunc) ags_accessible_pattern_box_class_init,
+      NULL,           /* class_finalize */
+      NULL,           /* class_data */
+      sizeof(GtkAccessible),
+      0,             /* n_preallocs */
+      NULL, NULL
+    };
+
+    static const GInterfaceInfo atk_action_interface_info = {
+      (GInterfaceInitFunc) ags_accessible_pattern_box_action_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+    
+    ags_type_accessible_pattern_box = g_type_register_static(GTK_TYPE_ACCESSIBLE,
+							     "AgsAccessiblePatternBox\0", &ags_accesssible_pattern_box_info,
+							     0);
+
+    g_type_add_interface_static(ags_type_accessible_pattern_box,
+				ATK_TYPE_ACTION,
+				&atk_action_interface_info);
+  }
+  
+  return(ags_type_accessible_pattern_box);
+}
+
+void
+ags_pattern_box_class_init(AgsPatternBoxClass *pattern_box)
+{
+  GObjectClass *gobject;
+  GtkWidgetClass *widget;
+
+  ags_pattern_box_parent_class = g_type_class_peek_parent(pattern_box);
+
+  quark_accessible_object = g_quark_from_static_string("ags-accessible-object\0");
+
+  /* GObjectClass */
+  gobject = (GObjectClass *) pattern_box;
+
+  gobject->finalize = ags_pattern_box_finalize;
+
+  /* GtkWidget */
+  widget = (GtkWidgetClass *) pattern_box;
+
+  widget->show = ags_pattern_box_show;
+  widget->show_all = ags_pattern_box_show_all;
+}
+
+void
+ags_accessible_pattern_box_class_init(AtkObject *object)
+{
+  /* empty */
+}
+
+void
+ags_accessible_pattern_box_action_interface_init(AtkActionIface *action)
+{
+  action->do_action = ags_accessible_pattern_box_do_action;
+  action->get_n_actions = ags_accessible_pattern_box_get_n_actions;
+  action->get_description = ags_accessible_pattern_box_get_description;
+  action->get_name = ags_accessible_pattern_box_get_name;
+  action->get_keybinding = ags_accessible_pattern_box_get_keybinding;
+  action->set_description = ags_accessible_pattern_box_set_description;
+  action->get_localized_name = ags_accessible_pattern_box_get_localized_name;
+}
+
+void
+ags_pattern_box_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  AgsConnectableInterface *ags_pattern_box_connectable_parent_interface;
+
+  connectable->connect = ags_pattern_box_connect;
+  connectable->disconnect = ags_pattern_box_disconnect;
+}
+
+void
+ags_pattern_box_init(AgsPatternBox *pattern_box)
+{
+  AgsLed *led;
+  GtkToggleButton *toggle_button;
+  GtkRadioButton *radio_button;
+  
+  guint i;
+
+  g_object_set(pattern_box,
+	       "can-focus\0", TRUE,
+	       "n-columns\0", 2,
+	       "n-rows", 2,
+	       "homogeneous\0", FALSE,
+	       NULL);
+  gtk_widget_set_events((GtkWidget *) pattern_box,
+			GDK_CONTROL_MASK
+			| GDK_KEY_PRESS_MASK
+			| GDK_KEY_RELEASE_MASK);
+
+  pattern_box->flags = 0;
+
+  pattern_box->key_mask = 0;
+
+  pattern_box->n_controls = AGS_PATTERN_BOX_N_CONTROLS;
+  pattern_box->n_indices = AGS_PATTERN_BOX_N_INDICES;
+  
+  /* led */
+  pattern_box->active_led = 0;
+
+  pattern_box->led = (GtkHBox *) gtk_hbox_new(FALSE, 16);
+  gtk_table_attach(pattern_box,
+		   (GtkWidget *) pattern_box->led,
+		   0, 1,
+		   0, 1,
+		   0, 0,
+		   0, 0);
+
+  for(i = 0; i < pattern_box->n_controls; i++){
+    led = (GtkToggleButton *) ags_led_new();
+    gtk_widget_set_size_request((GtkWidget *) led,
+				AGS_PATTERN_BOX_LED_DEFAULT_WIDTH, AGS_PATTERN_BOX_LED_DEFAULT_HEIGHT);
+    gtk_box_pack_start((GtkBox *) pattern_box->led,
+		       (GtkWidget *) led,
+		       FALSE, FALSE,
+		       0);
+  }
+
+  /* pattern */
+  pattern_box->pattern = (GtkHBox *) gtk_hbox_new(FALSE, 0);
+  gtk_table_attach(pattern_box,
+		   (GtkWidget *) pattern_box->pattern,
+		   0, 1,
+		   1, 2,
+		   0, 0,
+		   0, 0);
+
+  for(i = 0; i < pattern_box->n_controls; i++){
+    toggle_button = (GtkToggleButton *) gtk_toggle_button_new();
+    gtk_widget_set_size_request((GtkWidget *) toggle_button,
+				AGS_PATTERN_BOX_DEFAULT_PAD_WIDTH, AGS_PATTERN_BOX_DEFAULT_PAD_HEIGHT);
+    gtk_box_pack_start((GtkBox *) pattern_box->pattern,
+		       (GtkWidget *) toggle_button,
+		       FALSE, FALSE,
+		       0);
+  }
+
+  /* page / offset */
+  pattern_box->offset = (GtkVBox*) gtk_vbox_new(FALSE, 0);
+  gtk_table_attach_defaults(pattern_box,
+			    (GtkWidget *) pattern_box->offset,
+			    1, 2,
+			    0, 2);
+  radio_button = NULL;
+
+  for(i = 0; i < pattern_box->n_indices; i++){
+    if(radio_button == NULL){
+      radio_button = (GtkRadioButton *) gtk_radio_button_new_with_label(NULL, g_strdup_printf("%d-%d\0",
+											      i * pattern_box->n_controls + 1, (i + 1) * pattern_box->n_controls));
+      gtk_box_pack_start((GtkBox*) pattern_box->offset,
+			 (GtkWidget *) radio_button,
+			 FALSE, FALSE,
+			 0);
+    }else{
+      gtk_box_pack_start((GtkBox*) pattern_box->offset,
+			 (GtkWidget *) gtk_radio_button_new_with_label(radio_button->group, g_strdup_printf("%d-%d\0",
+													    i * pattern_box->n_controls + 1, (i + 1) * pattern_box->n_controls)),
+			 FALSE, FALSE,
+			 0);
+    }
+  }
+}
+
+void
+ags_pattern_box_finalize(GObject *gobject)
+{
+  G_OBJECT_CLASS(ags_pattern_box_parent_class)->finalize(gobject);
+}
+
+void
+ags_pattern_box_connect(AgsConnectable *connectable)
+{
+  AgsPatternBox *pattern_box;
+
+  GList *list, *list_start;
+
+  if((AGS_PATTERN_BOX_CONNECTED & (AGS_PATTERN_BOX(connectable)->flags)) != 0){
+    return;
+  }
+
+  /* AgsPatternBox */
+  pattern_box = AGS_PATTERN_BOX(connectable);
+
+  pattern_box->flags |= AGS_PATTERN_BOX_CONNECTED;
+
+  g_signal_connect_after(G_OBJECT(pattern_box), "focus_in_event\0",
+			 G_CALLBACK(ags_pattern_box_focus_in_callback), (gpointer) pattern_box);
+  
+  g_signal_connect(G_OBJECT(pattern_box), "key_press_event\0",
+		   G_CALLBACK(ags_pattern_box_key_press_event), (gpointer) pattern_box);
+
+  g_signal_connect(G_OBJECT(pattern_box), "key_release_event\0",
+		   G_CALLBACK(ags_pattern_box_key_release_event), (gpointer) pattern_box);
+
+  /* connect pattern */
+  list_start = 
+    list = gtk_container_get_children((GtkContainer *) pattern_box->pattern);
+
+  while(list != NULL){
+    g_signal_connect(G_OBJECT(list->data), "clicked\0",
+		     G_CALLBACK(ags_pattern_box_pad_callback), (gpointer) pattern_box);
+
+    list = list->next;
+  }
+
+  g_list_free(list_start);
+
+  /* connect pattern offset range */
+  list_start = 
+    list = gtk_container_get_children((GtkContainer *) pattern_box->offset);
+
+  while(list != NULL){
+    g_signal_connect(G_OBJECT(list->data), "clicked\0",
+		     G_CALLBACK(ags_pattern_box_offset_callback), (gpointer) pattern_box);
+		   
+    list = list->next;
+  }
+
+  g_list_free(list_start);
+}
+
+void
+ags_pattern_box_disconnect(AgsConnectable *connectable)
+{
+  AgsPatternBox *pattern_box;
+
+  /* AgsPatternBox */
+  pattern_box = AGS_PATTERN_BOX(connectable);
+
+  //TODO:JK: implement me
+}
+
+AtkObject*
+ags_pattern_box_get_accessible(GtkWidget *widget)
+{
+  AtkObject* accessible;
+
+  accessible = g_object_get_qdata(G_OBJECT(widget),
+				  quark_accessible_object);
+  
+  if(!accessible){
+    accessible = g_object_new(ags_accessible_pattern_box_get_type(),
+			      NULL);
+    
+    g_object_set_qdata(G_OBJECT(widget),
+		       quark_accessible_object,
+		       accessible);
+    gtk_accessible_set_widget(accessible,
+			      widget);
+  }
+  
+  return(accessible);
+}
+
+void
+ags_pattern_box_show(GtkWidget *widget)
+{
+  GTK_WIDGET_CLASS(ags_pattern_box_parent_class)->show(widget);
+
+  //  ags_pattern_box_draw_matrix(AGS_PATTERN_BOX(widget));
+}
+
+void
+ags_pattern_box_show_all(GtkWidget *widget)
+{
+  GTK_WIDGET_CLASS(ags_pattern_box_parent_class)->show_all(widget);
+
+  //  ags_pattern_box_draw_matrix(AGS_PATTERN_BOX(widget));
+}
+
+gboolean
+ags_accessible_pattern_box_do_action(AtkAction *action,
+				     gint i)
+{
+  AgsPatternBox *pattern_box;
+  
+  GdkEventKey *key_press, *key_release;
+  GdkEventKey *modifier_press, *modifier_release;
+  
+  if(!(i >= 0 && i < 6)){
+    return(FALSE);
+  }
+
+  pattern_box = gtk_accessible_get_widget(ATK_OBJECT(action));
+  
+  key_press = gdk_event_new(GDK_KEY_PRESS);
+  key_release = gdk_event_new(GDK_KEY_RELEASE);
+
+  switch(i){
+  case AGS_PATTERN_BOX_MOVE_LEFT:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Left;
+      
+      /* send event */
+      gtk_widget_event(pattern_box, key_press);
+      gtk_widget_event(pattern_box, key_release);
+    }
+    break;
+  case AGS_PATTERN_BOX_MOVE_RIGHT:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Right;
+      
+      /* send event */
+      gtk_widget_event(pattern_box, key_press);
+      gtk_widget_event(pattern_box, key_release);
+    }
+    break;
+  case AGS_PATTERN_BOX_INDEX_DECREMENT:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Up;
+    
+      /* send event */
+      gtk_widget_event(pattern_box, key_press);
+      gtk_widget_event(pattern_box, key_release);
+    }
+    break;
+  case AGS_PATTERN_BOX_INDEX_INCREMENT:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_Down;
+      
+      /* send event */
+      gtk_widget_event(pattern_box, key_press);
+      gtk_widget_event(pattern_box, key_release);
+    }
+    break;
+  case AGS_PATTERN_BOX_TOGGLE_PAD:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_space;
+      
+      /* send event */
+      gtk_widget_event(pattern_box, key_press);
+      gtk_widget_event(pattern_box, key_release);
+    }
+    break;
+  case AGS_PATTERN_BOX_COPY_PATTERN:
+    {
+      key_press->keyval =
+	key_release->keyval = GDK_KEY_c;
+
+      /* create modifier */
+      modifier_press = gdk_event_new(GDK_KEY_PRESS);
+      modifier_release = gdk_event_new(GDK_KEY_RELEASE);
+
+      modifier_press->keyval =
+	modifier_release->keyval = GDK_KEY_Control_R;
+
+      /* send event */
+      gtk_widget_event(pattern_box, modifier_press);
+      gtk_widget_event(pattern_box, key_press);
+      gtk_widget_event(pattern_box, key_release);
+      gtk_widget_event(pattern_box, modifier_release);      
+    }    
+    break;
+  }
+
+  return(TRUE);
+}
+
+gint
+ags_accessible_pattern_box_get_n_actions(AtkAction *action)
+{
+  return(6);
+}
+
+const gchar*
+ags_accessible_pattern_box_get_description(AtkAction *action,
+					   gint i)
+{
+  static const gchar **actions = {
+    "move cursor left\0",
+    "move cursor right\0",
+    "decrement pattern index\0",
+    "increment pattern index\0",
+    "toggle audio pattern\0"
+    "copy pattern to clipboard\0",
+  };
+
+  if(i >= 0 && i < 6){
+    return(actions[i]);
+  }else{
+    return(NULL);
+  }
+}
+
+const gchar*
+ags_accessible_pattern_box_get_name(AtkAction *action,
+				    gint i)
+{
+  static const gchar **actions = {
+    "left\0",
+    "right\0",
+    "up\0",
+    "down\0",
+    "toggle\0",
+    "copy\0",
+  };
+  
+  if(i >= 0 && i < 6){
+    return(actions[i]);
+  }else{
+    return(NULL);
+  }
+}
+
+const gchar*
+ags_accessible_pattern_box_get_keybinding(AtkAction *action,
+					  gint i)
+{
+  static const gchar **actions = {
+    "left\0",
+    "right\0",
+    "up\0",
+    "down\0",
+    "space",
+    "Ctrl+c",
+  };
+  
+  if(i >= 0 && i < 6){
+    return(actions[i]);
+  }else{
+    return(NULL);
+  }
+}
+
+gboolean
+ags_accessible_pattern_box_set_description(AtkAction *action,
+					   gint i)
+{
+  //TODO:JK: implement me
+
+  return(FALSE);
+}
+
+gchar*
+ags_accessible_pattern_box_get_localized_name(AtkAction *action,
+					      gint i)
+{
+  //TODO:JK: implement me
+
+  return(NULL);
+}
+
+/**
+ * ags_pattern_box_set_pattern:
+ * @pattern_box: the #AgsPatternBox
+ *
+ * Resets the pattern on @pattern_box.
+ *
+ * since: 0.5.0
+ */
+void
+ags_pattern_box_set_pattern(AgsPatternBox *pattern_box)
+{
+  AgsMachine *machine;
+  AgsLine *selected_line;
+  GList *list, *list_start;
+  GList *line, *line_start;
+  guint index0, index1, offset;
+  gboolean set_active;
+  guint i;
+
+  machine = gtk_widget_get_ancestor(pattern_box,
+				    AGS_TYPE_MACHINE);
+
+  if(machine->selected_input_pad == NULL){
+    return;
+  }
+    
+  index0 = machine->bank_0;
+  index1 = machine->bank_1;
+
+  /* read boundaries */
+  list = gtk_container_get_children((GtkContainer *) pattern_box->offset);
+
+  for(i = 0; i < pattern_box->n_indices && ! GTK_TOGGLE_BUTTON(list->data)->active; i++)
+    list = list->next;
+
+  offset = i * pattern_box->n_controls;
+
+  /* get pads */
+  list_start = 
+    list = gtk_container_get_children((GtkContainer *) pattern_box->pattern);
+
+  /* reset */
+  pattern_box->flags |= AGS_PATTERN_BOX_BLOCK_PATTERN;
+
+  for(i = 0; i < pattern_box->n_controls; i++){
+    set_active = TRUE;
+
+    line_start = 
+      line = gtk_container_get_children(GTK_CONTAINER(AGS_PAD(machine->selected_input_pad)->expander_set));
+
+    while((line = ags_line_find_next_grouped(line)) != NULL){
+      selected_line = AGS_LINE(line->data);
+
+      if(!ags_pattern_get_bit((AgsPattern *) selected_line->channel->pattern->data, index0, index1, offset + i)){
+	set_active = FALSE;
+	break;
+      }
+
+      line = line->next;
+    }
+
+    g_list_free(line_start);
+    
+    gtk_toggle_button_set_active((GtkToggleButton *) list->data, set_active);
+    
+    list = list->next;
+  }
+
+  pattern_box->flags &= (~AGS_PATTERN_BOX_BLOCK_PATTERN);
+
+  g_list_free(list_start);
+}
+
+/**
+ * ags_pattern_box_new:
+ *
+ * Creates an #AgsPatternBox
+ *
+ * Returns: a new #AgsPatternBox
+ *
+ * Since: 0.5
+ */
+AgsPatternBox*
+ags_pattern_box_new()
+{
+  AgsPatternBox *pattern_box;
+
+  pattern_box = (AgsPatternBox *) g_object_new(AGS_TYPE_PATTERN_BOX,
+					       NULL);
+
+  return(pattern_box);
+}
diff --git a/src/ags/X/machine/ags_pattern_box.h b/src/ags/X/machine/ags_pattern_box.h
new file mode 100644
index 0000000..3e7aa50
--- /dev/null
+++ b/src/ags/X/machine/ags_pattern_box.h
@@ -0,0 +1,99 @@
+/* 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_PATTERN_BOX_H__
+#define __AGS_PATTERN_BOX_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#define AGS_TYPE_PATTERN_BOX                (ags_pattern_box_get_type())
+#define AGS_PATTERN_BOX(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_PATTERN_BOX, AgsPatternBox))
+#define AGS_PATTERN_BOX_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_PATTERN_BOX, AgsPatternBoxClass))
+#define AGS_IS_PATTERN_BOX(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), AGS_TYPE_PATTERN_BOX))
+#define AGS_IS_PATTERN_BOX_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_PATTERN_BOX))
+#define AGS_PATTERN_BOX_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_PATTERN_BOX, AgsPatternBoxClass))
+
+#define AGS_PATTERN_BOX_DEFAULT_PAD_WIDTH   (24)
+#define AGS_PATTERN_BOX_DEFAULT_PAD_HEIGHT  (24)
+
+#define AGS_PATTERN_BOX_LED_DEFAULT_WIDTH (8)
+#define AGS_PATTERN_BOX_LED_DEFAULT_HEIGHT (4)
+
+#define AGS_PATTERN_BOX_N_CONTROLS (16)
+#define AGS_PATTERN_BOX_N_INDICES (4)
+
+typedef struct _AgsPatternBox AgsPatternBox;
+typedef struct _AgsPatternBoxClass AgsPatternBoxClass;
+
+typedef enum{
+  AGS_PATTERN_BOX_BLOCK_PATTERN    = 1,
+  AGS_PATTERN_BOX_CONNECTED        = 1 <<  1,
+}AgsPatternBoxFlags;
+
+typedef enum{
+  AGS_PATTERN_BOX_KEY_L_CONTROL       = 1,
+  AGS_PATTERN_BOX_KEY_R_CONTROL       = 1 <<  1,
+}AgsPatternBoxKeyMask;
+
+typedef enum{
+  AGS_PATTERN_BOX_MOVE_LEFT,
+  AGS_PATTERN_BOX_MOVE_RIGHT,
+  AGS_PATTERN_BOX_INDEX_DECREMENT,
+  AGS_PATTERN_BOX_INDEX_INCREMENT,
+  AGS_PATTERN_BOX_TOGGLE_PAD,
+  AGS_PATTERN_BOX_COPY_PATTERN,
+}AgsPatternBoxAction;
+
+struct _AgsPatternBox
+{
+  GtkTable table;
+
+  guint flags;
+  
+  guint key_mask;
+
+  guint n_controls;
+  guint n_indices;
+
+  guint cursor_x;
+  guint cursor_y;
+  
+  guint active_led;
+  
+  GtkHBox *led;
+
+  GtkHBox *pattern;
+
+  GtkVBox *offset;
+};
+
+struct _AgsPatternBoxClass
+{
+  GtkTableClass table;
+};
+
+GType ags_pattern_box_get_type(void);
+
+void ags_pattern_box_set_pattern(AgsPatternBox *pattern_box);
+
+AgsPatternBox* ags_pattern_box_new();
+
+#endif /*__AGS_PATTERN_BOX_H__*/
diff --git a/src/ags/X/machine/ags_pattern_box_callbacks.c b/src/ags/X/machine/ags_pattern_box_callbacks.c
new file mode 100644
index 0000000..18b9fc9
--- /dev/null
+++ b/src/ags/X/machine/ags_pattern_box_callbacks.c
@@ -0,0 +1,334 @@
+/* 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/X/machine/ags_pattern_box_callbacks.h>
+
+#include <ags/main.h>
+
+#include <ags/thread/ags_mutex_manager.h>
+#include <ags/thread/ags_audio_loop.h>
+#include <ags/thread/ags_task_thread.h>
+
+#include <ags/audio/ags_devout.h>
+
+#include <ags/audio/task/ags_toggle_pattern_bit.h>
+
+#include <ags/X/ags_machine.h>
+#include <ags/X/ags_pad.h>
+#include <ags/X/ags_line.h>
+
+#include <gdk/gdkkeysyms.h>
+
+void ags_pattern_box_refresh_gui_callback(AgsTogglePatternBit *toggle_pattern_bit,
+					  AgsPatternBox *pattern_box);
+
+extern pthread_mutex_t ags_application_mutex;
+
+gboolean
+ags_pattern_box_focus_in_callback(GtkWidget *widget, GdkEvent *event, AgsPatternBox *pattern_box)
+{
+  g_message("got focus\0");
+ 
+  return(TRUE);
+}
+
+void
+ags_pattern_box_pad_callback(GtkWidget *toggle_button, AgsPatternBox *pattern_box)
+{
+  AgsMachine *machine;
+  AgsLine *selected_line;
+
+  AgsPattern *pattern;
+  
+  AgsTogglePatternBit *toggle_pattern_bit;
+
+  AgsMutexManager *mutex_manager;
+
+  GList *list, *list_start;
+  GList *line, *line_start;
+  GList *tasks;
+  guint i, index0, index1, offset;
+
+  pthread_mutex_t *audio_mutex;
+
+  machine = gtk_widget_get_ancestor(pattern_box,
+				    AGS_TYPE_MACHINE);
+  
+  if(machine->selected_input_pad == NULL){
+    return;
+  }
+
+  if((AGS_PATTERN_BOX_BLOCK_PATTERN & (pattern_box->flags)) != 0){
+#ifdef AGS_DEBUG
+    g_message("AgsPatternBox pattern is blocked\n\0");
+#endif
+
+    return;
+  }
+  
+  pthread_mutex_lock(&(ags_application_mutex));
+  
+  mutex_manager = ags_mutex_manager_get_instance();
+
+  audio_mutex = ags_mutex_manager_lookup(mutex_manager,
+					 (GObject *) AGS_MACHINE(pattern_box)->audio);
+  
+  pthread_mutex_unlock(&(ags_application_mutex));
+
+  pthread_mutex_lock(audio_mutex);
+
+  /* calculate offset */
+  list_start = 
+    list = gtk_container_get_children((GtkContainer *) pattern_box->pattern);
+
+  for(i = 0; i < 16 && toggle_button != list->data; i++)
+    list = list->next;
+
+  offset = i;
+  g_list_free(list_start);
+
+  /* retrieve indices */
+  index0 = machine->bank_0;
+  index1 = machine->bank_1;
+  
+  /* calculate offset / page */
+  list_start = 
+    list = gtk_container_get_children((GtkContainer *) pattern_box->offset);
+
+  for(i = 0; i < 4 && ! GTK_TOGGLE_BUTTON(list->data)->active; i++)
+    list = list->next;
+
+  offset += (i * 16);
+
+  g_list_free(list_start);
+
+  /**/
+  line_start = 
+    line = gtk_container_get_children(GTK_CONTAINER(AGS_PAD(machine->selected_input_pad)->expander_set));
+  tasks = NULL;
+
+  while((line = ags_line_find_next_grouped(line)) != NULL){
+    selected_line = AGS_LINE(line->data);
+
+    toggle_pattern_bit = ags_toggle_pattern_bit_new(selected_line->channel->pattern->data,
+						    selected_line->channel->line,
+						    index0, index1,
+						    offset);
+
+    tasks = g_list_prepend(tasks,
+			   toggle_pattern_bit);
+
+    line = line->next;
+  }
+
+  g_list_free(line_start);
+
+  /* append AgsTogglePatternBit */
+  ags_task_thread_append_tasks(AGS_TASK_THREAD(AGS_AUDIO_LOOP(AGS_MAIN(AGS_DEVOUT(AGS_MACHINE(pattern_box)->audio->devout)->ags_main)->main_loop)->task_thread),
+			       tasks);
+
+  pthread_mutex_unlock(audio_mutex);
+}
+
+void
+ags_pattern_box_offset_callback(GtkWidget *widget, AgsPatternBox *pattern_box)
+{
+  ags_pattern_box_set_pattern(pattern_box);
+}
+
+gboolean
+ags_pattern_box_key_press_event(GtkWidget *widget, GdkEventKey *event, AgsPatternBox *pattern_box)
+{
+  if(event->keyval == GDK_KEY_Tab){
+    return(FALSE);
+  }
+
+  switch(event->keyval){
+  case GDK_KEY_Control_L:
+    {
+      pattern_box->key_mask |= AGS_PATTERN_BOX_KEY_L_CONTROL;
+    }
+    break;
+  case GDK_KEY_Control_R:
+    {
+      pattern_box->key_mask |= AGS_PATTERN_BOX_KEY_R_CONTROL;
+    }
+    break;
+  case GDK_KEY_c:
+    {
+      /* copy notes */
+      if((AGS_PATTERN_BOX_KEY_L_CONTROL & (pattern_box->key_mask)) != 0 || (AGS_PATTERN_BOX_KEY_R_CONTROL & (pattern_box->key_mask)) != 0){
+	AgsMachine *machine;
+
+	machine = gtk_widget_get_ancestor(pattern_box,
+					  AGS_TYPE_MACHINE);
+	
+	ags_machine_copy_pattern(machine);
+      }
+    }
+    break;
+  }
+  
+  return(TRUE);
+}
+
+gboolean
+ags_pattern_box_key_release_event(GtkWidget *widget, GdkEventKey *event, AgsPatternBox *pattern_box)
+{
+  if(event->keyval == GDK_KEY_Tab){
+    return(FALSE);
+  }
+  
+  switch(event->keyval){
+  case GDK_KEY_Control_L:
+    {
+      pattern_box->key_mask &= (~AGS_PATTERN_BOX_KEY_L_CONTROL);
+    }
+    break;
+  case GDK_KEY_Control_R:
+    {
+      pattern_box->key_mask &= (~AGS_PATTERN_BOX_KEY_R_CONTROL);
+    }
+    break;
+  case GDK_KEY_Left:
+  case GDK_KEY_leftarrow:
+    {
+      if(pattern_box->cursor_x > 0){
+	pattern_box->cursor_x -= 1;
+      }
+    }
+    break;
+  case GDK_KEY_Right:
+  case GDK_KEY_rightarrow:
+    {
+      if(pattern_box->cursor_x < pattern_box->n_controls){
+	pattern_box->cursor_x += 1;
+      }
+    }
+    break;
+  case GDK_KEY_Up:
+  case GDK_KEY_uparrow:
+    {
+      if(pattern_box->cursor_y > 0){
+	GList *list;
+
+	list = gtk_container_get_children(pattern_box->offset);
+	pattern_box->cursor_y -= 1;
+
+      	gtk_button_clicked(g_list_nth_data(pattern_box->offset,
+					   pattern_box->cursor_y));
+
+	free(list);
+      }
+    }
+    break;
+  case GDK_KEY_Down:
+  case GDK_KEY_downarrow:
+    {
+      if(pattern_box->cursor_y < pattern_box->n_indices){
+	GList *list;
+
+	list = gtk_container_get_children(pattern_box->offset);
+	pattern_box->cursor_y += 1;
+
+	gtk_button_clicked(g_list_nth_data(list,
+					   pattern_box->cursor_y));
+
+	g_free(list);
+      }
+    }
+    break;
+  case GDK_KEY_space:
+    {
+      AgsMachine *machine;
+      
+      AgsTogglePatternBit *toggle_pattern_bit;
+      AgsChannel *channel;
+      
+      guint i, j;
+      guint index0, index1;
+      
+      machine = gtk_widget_get_ancestor(pattern_box,
+					AGS_TYPE_MACHINE);
+      
+      i = pattern_box->cursor_y;
+      j = pattern_box->cursor_x;
+      
+      index0 = machine->bank_0;
+      index1 = machine->bank_1;
+
+      channel = ags_channel_nth(machine->audio->input, machine->audio->input_lines - i - 1);
+
+      toggle_pattern_bit = ags_toggle_pattern_bit_new(channel->pattern->data,
+						      channel->line,
+						      index0, index1,
+						      j);
+      g_signal_connect(G_OBJECT(toggle_pattern_bit), "refresh-gui\0",
+		       G_CALLBACK(ags_pattern_box_refresh_gui_callback), pattern_box);
+      
+      ags_task_thread_append_task(AGS_TASK_THREAD(AGS_AUDIO_LOOP(AGS_MAIN(AGS_DEVOUT(machine->audio->devout)->ags_main)->main_loop)->task_thread),
+				  AGS_TASK(toggle_pattern_bit));
+    }
+    break;
+  }
+
+  return(TRUE);
+}
+
+void
+ags_pattern_box_refresh_gui_callback(AgsTogglePatternBit *toggle_pattern_bit,
+				     AgsPatternBox *pattern_box)
+{
+  AgsMachine *machine;
+  
+  AgsChannel *channel;
+
+  GList *radio;
+  
+  machine = gtk_widget_get_ancestor(pattern_box,
+				    AGS_TYPE_MACHINE);
+    
+  channel = ags_channel_nth(machine->audio->input,
+			    toggle_pattern_bit->line);
+
+  if(!gtk_toggle_button_get_active(AGS_LINE(channel->line_widget)->group)){
+    return;
+  }
+  
+  radio = gtk_container_get_children(pattern_box->offset);
+  
+  if(gtk_toggle_button_get_active(g_list_nth_data(radio,
+						  toggle_pattern_bit->bit / pattern_box->n_controls))){
+    GList *list;
+
+    list = gtk_container_get_children(pattern_box->pattern);
+
+    pattern_box->flags |= AGS_PATTERN_BOX_BLOCK_PATTERN;
+    
+    gtk_toggle_button_set_active(g_list_nth_data(list,
+						 toggle_pattern_bit->bit % pattern_box->n_controls),
+				 TRUE);
+    
+    pattern_box->flags &= (~AGS_PATTERN_BOX_BLOCK_PATTERN);
+    
+    g_list_free(list);
+  }
+
+  g_list_free(radio);
+}
diff --git a/src/ags/X/ags_editor_callbacks.h b/src/ags/X/machine/ags_pattern_box_callbacks.h
similarity index 55%
copy from src/ags/X/ags_editor_callbacks.h
copy to src/ags/X/machine/ags_pattern_box_callbacks.h
index 470a0dd..7f30d3a 100644
--- a/src/ags/X/ags_editor_callbacks.h
+++ b/src/ags/X/machine/ags_pattern_box_callbacks.h
@@ -17,24 +17,22 @@
  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __AGS_EDITOR_CALLBACKS_H__
-#define __AGS_EDITOR_CALLBACKS_H__
+#ifndef __AGS_PATTERN_BOX_CALLBACKS_H__
+#define __AGS_PATTERN_BOX_CALLBACKS_H__
 
 #include <glib.h>
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
-#include <ags/X/ags_editor.h>
-#include <ags/X/ags_navigation.h>
-#include <ags/X/ags_machine.h>
+#include <ags/X/machine/ags_pattern_box.h>
 
-void ags_editor_parent_set_callback(GtkWidget  *widget, GtkObject *old_parent,
-				    AgsEditor *editor);
+/* controls */
+gboolean ags_pattern_box_focus_in_callback(GtkWidget *widget, GdkEvent *event, AgsPatternBox *pattern_box);
 
-void ags_editor_tic_callback(AgsDevout *devout,
-			     AgsEditor *editor);
+gboolean ags_pattern_box_key_press_event(GtkWidget *widget, GdkEventKey *event, AgsPatternBox *pattern_box);
+gboolean ags_pattern_box_key_release_event(GtkWidget *widget, GdkEventKey *event, AgsPatternBox *pattern_box);
 
-void ags_editor_machine_changed_callback(AgsMachineSelector *machine_selector, AgsMachine *machine,
-					 AgsEditor *editor);
+void ags_pattern_box_pad_callback(GtkWidget *toggle_button, AgsPatternBox *pattern_box);
+void ags_pattern_box_offset_callback(GtkWidget *widget, AgsPatternBox *pattern_box);
 
-#endif /*__AGS_EDITOR_CALLBACKS_H__*/
+#endif /*__AGS_PATTERN_BOX_CALLBACKS_H__*/
diff --git a/src/ags/audio/task/ags_blink_cell_pattern_cursor.c b/src/ags/audio/task/ags_blink_cell_pattern_cursor.c
new file mode 100644
index 0000000..a96c730
--- /dev/null
+++ b/src/ags/audio/task/ags_blink_cell_pattern_cursor.c
@@ -0,0 +1,183 @@
+/* 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_blink_cell_pattern_cursor.h>
+
+#include <ags-lib/object/ags_connectable.h>
+
+#include <ags/widget/ags_led.h>
+
+void ags_blink_cell_pattern_cursor_class_init(AgsBlinkCellPatternCursorClass *blink_cell_pattern_cursor);
+void ags_blink_cell_pattern_cursor_connectable_interface_init(AgsConnectableInterface *connectable);
+void ags_blink_cell_pattern_cursor_init(AgsBlinkCellPatternCursor *blink_cell_pattern_cursor);
+void ags_blink_cell_pattern_cursor_connect(AgsConnectable *connectable);
+void ags_blink_cell_pattern_cursor_disconnect(AgsConnectable *connectable);
+void ags_blink_cell_pattern_cursor_finalize(GObject *gobject);
+void ags_blink_cell_pattern_cursor_launch(AgsTask *task);
+
+/**
+ * SECTION:ags_blink_cell_pattern_cursor
+ * @short_description: toggle led object
+ * @title: AgsBlinkCellPatternCursor
+ * @section_id:
+ * @include: ags/audio/task/ags_blink_cell_pattern_cursor.h
+ *
+ * The #AgsBlinkCellPatternCursor task blinks the cell pattern cursor.
+ */
+
+static gpointer ags_blink_cell_pattern_cursor_parent_class = NULL;
+static AgsConnectableInterface *ags_blink_cell_pattern_cursor_parent_connectable_interface;
+
+GType
+ags_blink_cell_pattern_cursor_get_type()
+{
+  static GType ags_type_blink_cell_pattern_cursor = 0;
+
+  if(!ags_type_blink_cell_pattern_cursor){
+    static const GTypeInfo ags_blink_cell_pattern_cursor_info = {
+      sizeof (AgsBlinkCellPatternCursorClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_blink_cell_pattern_cursor_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof (AgsBlinkCellPatternCursor),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_blink_cell_pattern_cursor_init,
+    };
+
+    static const GInterfaceInfo ags_connectable_interface_info = {
+      (GInterfaceInitFunc) ags_blink_cell_pattern_cursor_connectable_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+
+    ags_type_blink_cell_pattern_cursor = g_type_register_static(AGS_TYPE_TASK,
+								"AgsBlinkCellPatternCursor\0",
+								&ags_blink_cell_pattern_cursor_info,
+								0);
+
+    g_type_add_interface_static(ags_type_blink_cell_pattern_cursor,
+				AGS_TYPE_CONNECTABLE,
+				&ags_connectable_interface_info);
+  }
+  
+  return (ags_type_blink_cell_pattern_cursor);
+}
+
+void
+ags_blink_cell_pattern_cursor_class_init(AgsBlinkCellPatternCursorClass *blink_cell_pattern_cursor)
+{
+  GObjectClass *gobject;
+  AgsTaskClass *task;
+
+  ags_blink_cell_pattern_cursor_parent_class = g_type_class_peek_parent(blink_cell_pattern_cursor);
+
+  /* GObject */
+  gobject = (GObjectClass *) blink_cell_pattern_cursor;
+
+  gobject->finalize = ags_blink_cell_pattern_cursor_finalize;
+
+  /* AgsTask */
+  task = (AgsTaskClass *) blink_cell_pattern_cursor;
+
+  task->launch = ags_blink_cell_pattern_cursor_launch;
+}
+
+void
+ags_blink_cell_pattern_cursor_connectable_interface_init(AgsConnectableInterface *connectable)
+{
+  ags_blink_cell_pattern_cursor_parent_connectable_interface = g_type_interface_peek_parent(connectable);
+
+  connectable->connect = ags_blink_cell_pattern_cursor_connect;
+  connectable->disconnect = ags_blink_cell_pattern_cursor_disconnect;
+}
+
+void
+ags_blink_cell_pattern_cursor_init(AgsBlinkCellPatternCursor *blink_cell_pattern_cursor)
+{
+  blink_cell_pattern_cursor->cell_pattern = NULL;
+  blink_cell_pattern_cursor->highlight_cursor = FALSE;
+}
+
+void
+ags_blink_cell_pattern_cursor_connect(AgsConnectable *connectable)
+{
+  ags_blink_cell_pattern_cursor_parent_connectable_interface->connect(connectable);
+
+  /* empty */
+}
+
+void
+ags_blink_cell_pattern_cursor_disconnect(AgsConnectable *connectable)
+{
+  ags_blink_cell_pattern_cursor_parent_connectable_interface->disconnect(connectable);
+
+  /* empty */
+}
+
+void
+ags_blink_cell_pattern_cursor_finalize(GObject *gobject)
+{
+  G_OBJECT_CLASS(ags_blink_cell_pattern_cursor_parent_class)->finalize(gobject);
+
+  /* empty */
+}
+
+void
+ags_blink_cell_pattern_cursor_launch(AgsTask *task)
+{
+  AgsBlinkCellPatternCursor *blink_cell_pattern_cursor;
+
+  blink_cell_pattern_cursor = AGS_BLINK_CELL_PATTERN_CURSOR(task);
+  
+  if(blink_cell_pattern_cursor->highlight_cursor){
+    blink_cell_pattern_cursor->cell_pattern->flags |= AGS_CELL_PATTERN_CURSOR_ON;
+  }else{
+    blink_cell_pattern_cursor->cell_pattern->flags &= (~AGS_CELL_PATTERN_CURSOR_ON);
+  }
+
+  gtk_widget_queue_draw(blink_cell_pattern_cursor->cell_pattern);
+}
+
+/**
+ * ags_blink_cell_pattern_cursor_new:
+ * @cell_pattern: the #AgsCellPattern to blink
+ * @highlight_cursor: %TRUE if highlighted
+ *
+ * Creates an #AgsBlinkCellPatternCursor.
+ *
+ * Returns: an new #AgsBlinkCellPatternCursor.
+ *
+ * Since: 0.4
+ */
+AgsBlinkCellPatternCursor*
+ags_blink_cell_pattern_cursor_new(AgsCellPattern *cell_pattern,
+				  gboolean highlight_cursor)
+{
+  AgsBlinkCellPatternCursor *blink_cell_pattern_cursor;
+
+  blink_cell_pattern_cursor = (AgsBlinkCellPatternCursor *) g_object_new(AGS_TYPE_BLINK_CELL_PATTERN_CURSOR,
+									 NULL);
+
+  blink_cell_pattern_cursor->cell_pattern = cell_pattern;
+  blink_cell_pattern_cursor->highlight_cursor = highlight_cursor;
+  
+  return(blink_cell_pattern_cursor);
+}
diff --git a/src/ags/audio/task/ags_blink_cell_pattern_cursor.h b/src/ags/audio/task/ags_blink_cell_pattern_cursor.h
new file mode 100644
index 0000000..e738f65
--- /dev/null
+++ b/src/ags/audio/task/ags_blink_cell_pattern_cursor.h
@@ -0,0 +1,57 @@
+/* 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_BLINK_CELL_PATTERN_CURSOR_H__
+#define __AGS_BLINK_CELL_PATTERN_CURSOR_H__
+
+#include <glib-object.h>
+
+#include <ags/audio/ags_task.h>
+
+#include <ags/X/machine/ags_cell_pattern.h>
+
+#define AGS_TYPE_BLINK_CELL_PATTERN_CURSOR                (ags_blink_cell_pattern_cursor_get_type())
+#define AGS_BLINK_CELL_PATTERN_CURSOR(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_BLINK_CELL_PATTERN_CURSOR, AgsBlinkCellPatternCursor))
+#define AGS_BLINK_CELL_PATTERN_CURSOR_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_BLINK_CELL_PATTERN_CURSOR, AgsBlinkCellPatternCursorClass))
+#define AGS_IS_BLINK_CELL_PATTERN_CURSOR(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), AGS_TYPE_BLINK_CELL_PATTERN_CURSOR))
+#define AGS_IS_BLINK_CELL_PATTERN_CURSOR_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE((class), AGS_TYPE_BLINK_CELL_PATTERN_CURSOR))
+#define AGS_BLINK_CELL_PATTERN_CURSOR_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), AGS_TYPE_BLINK_CELL_PATTERN_CURSOR, AgsBlinkCellPatternCursorClass))
+
+typedef struct _AgsBlinkCellPatternCursor AgsBlinkCellPatternCursor;
+typedef struct _AgsBlinkCellPatternCursorClass AgsBlinkCellPatternCursorClass;
+
+struct _AgsBlinkCellPatternCursor
+{
+  AgsTask task;
+
+  AgsCellPattern *cell_pattern;
+  gboolean highlight_cursor;
+};
+
+struct _AgsBlinkCellPatternCursorClass
+{
+  AgsTaskClass task;
+};
+
+GType ags_blink_cell_pattern_cursor_get_type();
+
+AgsBlinkCellPatternCursor* ags_blink_cell_pattern_cursor_new(AgsCellPattern *cell_pattern,
+							     gboolean highlight_cursor);
+
+#endif /*__AGS_BLINK_CELL_PATTERN_CURSOR_H__*/
diff --git a/src/ags/main.c b/src/ags/main.c
index 182829a..388f973 100644
--- a/src/ags/main.c
+++ b/src/ags/main.c
@@ -85,7 +85,7 @@ extern void ags_thread_suspend_handler(int sig);
 
 extern AgsConfig *config;
 
-extern GtkStyle *matrix_style;
+extern GtkStyle *cell_pattern_style;
 extern GtkStyle *ffplayer_style;
 extern GtkStyle *editor_style;
 extern GtkStyle *notebook_style;
@@ -286,49 +286,49 @@ ags_colors_alloc()
   if(!allocated){
     allocated = TRUE;
 
-    matrix_style = gtk_style_new();
-    matrix_style->fg[0].red = 120 * (65535/255);
-    matrix_style->fg[0].green = 220 * (65535/255);
-    matrix_style->fg[0].blue = 120 * (65535/255);
-    matrix_style->fg[0].pixel = (gulong)(120*65536 + 220*256 + 120);
-
-    matrix_style->light[0].red = 100 * (65535/255);
-    matrix_style->light[0].green = 200 * (65535/255);
-    matrix_style->light[0].blue = 100 * (65535/255);
-    matrix_style->light[0].pixel = (gulong)(100*65536 + 200*256 + 100);
-
-    matrix_style->bg[0].red = 0 * (65535/255);
-    matrix_style->bg[0].green = 80 * (65535/255);
-    matrix_style->bg[0].blue = 0 * (65535/255);
-    matrix_style->bg[0].pixel = (gulong)(0*65536 + 80*256 + 0);
-
-    matrix_style->bg[1].red = 120 * (65535/255);
-    matrix_style->bg[1].green = 220 * (65535/255);
-    matrix_style->bg[1].blue = 120 * (65535/255);
-    matrix_style->bg[1].pixel = (gulong)(120*65536 + 220*256 + 120);
-
-    matrix_style->bg[2].red = 120 * (65535/255);
-    matrix_style->bg[2].green = 220 * (65535/255);
-    matrix_style->bg[2].blue = 120 * (65535/255);
-    matrix_style->bg[2].pixel = (gulong)(120*65536 + 220*256 + 120);
-
-    matrix_style->base[0].red = 120 * (65535/255);
-    matrix_style->base[0].green = 220 * (65535/255);
-    matrix_style->base[0].blue = 120 * (65535/255);
-    matrix_style->base[0].pixel = (gulong)(120*65536 + 220*256 + 120);
-
-
-    /*  matrix_style->fg[1] = matrix_green;
-	matrix_style->fg[2] = matrix_green;
-	matrix_style->fg[3] = matrix_green;
-	matrix_style->fg[4] = matrix_green;
-
-	matrix_style->bg[0] = matrix_led_bg;
-	matrix_style->bg[1] = matrix_led_bg;
-	matrix_style->bg[2] = matrix_led_bg;
-	matrix_style->bg[2] = matrix_led_bg;
-	matrix_style->bg[3] = matrix_led_bg;
-	matrix_style->bg[4] = matrix_led_bg;
+    cell_pattern_style = gtk_style_new();
+    cell_pattern_style->fg[0].red = 120 * (65535/255);
+    cell_pattern_style->fg[0].green = 220 * (65535/255);
+    cell_pattern_style->fg[0].blue = 120 * (65535/255);
+    cell_pattern_style->fg[0].pixel = (gulong)(120*65536 + 220*256 + 120);
+
+    cell_pattern_style->light[0].red = 100 * (65535/255);
+    cell_pattern_style->light[0].green = 200 * (65535/255);
+    cell_pattern_style->light[0].blue = 100 * (65535/255);
+    cell_pattern_style->light[0].pixel = (gulong)(100*65536 + 200*256 + 100);
+
+    cell_pattern_style->bg[0].red = 0 * (65535/255);
+    cell_pattern_style->bg[0].green = 80 * (65535/255);
+    cell_pattern_style->bg[0].blue = 0 * (65535/255);
+    cell_pattern_style->bg[0].pixel = (gulong)(0*65536 + 80*256 + 0);
+
+    cell_pattern_style->bg[1].red = 120 * (65535/255);
+    cell_pattern_style->bg[1].green = 220 * (65535/255);
+    cell_pattern_style->bg[1].blue = 120 * (65535/255);
+    cell_pattern_style->bg[1].pixel = (gulong)(120*65536 + 220*256 + 120);
+
+    cell_pattern_style->bg[2].red = 120 * (65535/255);
+    cell_pattern_style->bg[2].green = 220 * (65535/255);
+    cell_pattern_style->bg[2].blue = 120 * (65535/255);
+    cell_pattern_style->bg[2].pixel = (gulong)(120*65536 + 220*256 + 120);
+
+    cell_pattern_style->base[0].red = 120 * (65535/255);
+    cell_pattern_style->base[0].green = 220 * (65535/255);
+    cell_pattern_style->base[0].blue = 120 * (65535/255);
+    cell_pattern_style->base[0].pixel = (gulong)(120*65536 + 220*256 + 120);
+
+
+    /*  cell_pattern_style->fg[1] = matrix_green;
+	cell_pattern_style->fg[2] = matrix_green;
+	cell_pattern_style->fg[3] = matrix_green;
+	cell_pattern_style->fg[4] = matrix_green;
+
+	cell_pattern_style->bg[0] = matrix_led_bg;
+	cell_pattern_style->bg[1] = matrix_led_bg;
+	cell_pattern_style->bg[2] = matrix_led_bg;
+	cell_pattern_style->bg[2] = matrix_led_bg;
+	cell_pattern_style->bg[3] = matrix_led_bg;
+	cell_pattern_style->bg[4] = matrix_led_bg;
     */
 
     /* ffplayer style */
diff --git a/src/ags/widget/ags_dial.c b/src/ags/widget/ags_dial.c
index cef768e..92a875e 100644
--- a/src/ags/widget/ags_dial.c
+++ b/src/ags/widget/ags_dial.c
@@ -19,10 +19,15 @@
 
 #include "ags_dial.h"
 
+#include <atk/atk.h>
+
 #include <stdlib.h>
 #include <math.h>
 
+static GType ags_accessible_dial_get_type(void);
 void ags_dial_class_init(AgsDialClass *dial);
+void ags_accessible_dial_class_init(AtkObject *object);
+void ags_accessible_dial_value_interface_init(AtkValueIface *value);
 void ags_dial_init(AgsDial *dial);
 void ags_dial_set_property(GObject *gobject,
 			   guint prop_id,
@@ -32,8 +37,17 @@ void ags_dial_get_property(GObject *gobject,
 			   guint prop_id,
 			   GValue *value,
 			   GParamSpec *param_spec);
+AtkObject* ags_dial_get_accessible(GtkWidget *widget);
 void ags_dial_show(GtkWidget *widget);
 
+void ags_accessible_dial_get_value_and_text(AtkValue *value,
+					    gdouble *current_value,
+					    gchar **text);
+AtkRange* ags_accessible_dial_get_range(AtkValue *value);
+gdouble ags_accessible_dial_get_increment(AtkValue *value);
+void ags_accessible_dial_set_value(AtkValue *value,
+				   gdouble new_value);
+
 void ags_dial_map(GtkWidget *widget);
 void ags_dial_realize(GtkWidget *widget);
 void ags_dial_size_request(GtkWidget *widget,
@@ -69,6 +83,8 @@ enum{
 
 static gpointer ags_dial_parent_class = NULL;
 
+static GQuark quark_accessible_object = 0;
+
 GType
 ags_dial_get_type(void)
 {
@@ -95,6 +111,42 @@ ags_dial_get_type(void)
   return(ags_type_dial);
 }
 
+static GType
+ags_accessible_dial_get_type(void)
+{
+  static GType ags_type_accessible_dial = 0;
+
+  if(!ags_type_accessible_dial){
+    const GTypeInfo ags_accesssible_dial_info = {
+      sizeof(GtkAccessibleClass),
+      NULL,           /* base_init */
+      NULL,           /* base_finalize */
+      (GClassInitFunc) ags_accessible_dial_class_init,
+      NULL,           /* class_finalize */
+      NULL,           /* class_data */
+      sizeof(GtkAccessible),
+      0,             /* n_preallocs */
+      NULL, NULL
+    };
+
+    static const GInterfaceInfo atk_value_interface_info = {
+      (GInterfaceInitFunc) ags_accessible_dial_value_interface_init,
+      NULL, /* interface_finalize */
+      NULL, /* interface_data */
+    };
+    
+    ags_type_accessible_dial = g_type_register_static(GTK_TYPE_ACCESSIBLE,
+						      "AgsAccessibleDial\0", &ags_accesssible_dial_info,
+						      0);
+
+    g_type_add_interface_static(ags_type_accessible_dial,
+				ATK_TYPE_VALUE,
+				&atk_value_interface_info);
+  }
+  
+  return(ags_type_accessible_dial);
+}
+
 void
 ags_dial_class_init(AgsDialClass *dial)
 {
@@ -104,6 +156,8 @@ ags_dial_class_init(AgsDialClass *dial)
 
   ags_dial_parent_class = g_type_class_peek_parent(dial);
 
+  quark_accessible_object = g_quark_from_static_string("ags-accessible-object\0");
+  
   /* GObjectClass */
   gobject = (GObjectClass *) dial;
 
@@ -113,6 +167,7 @@ ags_dial_class_init(AgsDialClass *dial)
   /* GtkWidgetClass */
   widget = (GtkWidgetClass *) dial;
 
+  widget->get_accessible = ags_dial_get_accessible;
   //  widget->map = ags_dial_map;
   widget->realize = ags_dial_realize;
   widget->expose_event = ags_dial_expose;
@@ -135,8 +190,42 @@ ags_dial_class_init(AgsDialClass *dial)
 }
 
 void
+ags_accessible_dial_class_init(AtkObject *object)
+{
+  /* empty */
+}
+
+void
+ags_accessible_dial_value_interface_init(AtkValueIface *value)
+{
+  value->get_current_value = NULL;
+  value->get_maximum_value = NULL;
+  value->get_minimum_value = NULL;
+  value->set_current_value = NULL;
+  value->get_minimum_increment = NULL;
+  
+  value->get_value_and_text = ags_accessible_dial_get_value_and_text;
+  value->get_range = ags_accessible_dial_get_range;
+  value->get_increment = ags_accessible_dial_get_increment;
+  value->get_sub_ranges = NULL;
+  value->set_value = ags_accessible_dial_set_value;
+}
+
+void
 ags_dial_init(AgsDial *dial)
 {
+  AtkObject *accessible;
+
+  gtk_widget_set_can_focus(dial,
+			   TRUE);
+
+  accessible = gtk_widget_get_accessible(dial);
+
+  g_object_set(accessible,
+	       "accessible-name\0", "dial\0",
+	       "accessible-description\0", "Adjust a value\0",
+	       NULL);
+  
   g_object_set(G_OBJECT(dial),
   	       "app-paintable\0", TRUE,
   	       NULL);
@@ -222,6 +311,60 @@ ags_dial_get_property(GObject *gobject,
 }
 
 void
+ags_accessible_dial_get_value_and_text(AtkValue *value,
+				       gdouble *current_value,
+				       gchar **text)
+{
+  AgsDial *dial;
+  
+  dial = (AgsDial *) gtk_accessible_get_widget(GTK_ACCESSIBLE(value));
+
+  if(current_value != NULL){
+    *current_value = gtk_adjustment_get_value(dial->adjustment);
+  }
+
+  if(text != NULL){
+    *text = g_strdup_printf("%f\0",
+			    gtk_adjustment_get_value(dial->adjustment));
+  }
+}
+
+AtkRange*
+ags_accessible_dial_get_range(AtkValue *value)
+{
+  AgsDial *dial;
+  AtkRange *range;
+  
+  dial = (AgsDial *) gtk_accessible_get_widget(GTK_ACCESSIBLE(value));
+
+  range = atk_range_new(gtk_adjustment_get_lower(dial->adjustment),
+			gtk_adjustment_get_upper(dial->adjustment),
+			"Valid lower and upper input range of this dial\0");
+}
+
+gdouble
+ags_accessible_dial_get_increment(AtkValue *value)
+{
+  AgsDial *dial;
+
+  dial = (AgsDial *) gtk_accessible_get_widget(GTK_ACCESSIBLE(value));
+
+  return(gtk_adjustment_get_step_increment(dial->adjustment));
+}
+
+void
+ags_accessible_dial_set_value(AtkValue *value,
+			      gdouble new_value)
+{
+  AgsDial *dial;
+
+  dial = (AgsDial *) gtk_accessible_get_widget(GTK_ACCESSIBLE(value));
+  gtk_adjustment_set_value(dial->adjustment,
+			   new_value);
+  gtk_widget_queue_draw(dial);
+}
+
+void
 ags_dial_map(GtkWidget *widget)
 {
   if (gtk_widget_get_realized (widget) && !gtk_widget_get_mapped (widget)) {
@@ -316,6 +459,28 @@ ags_dial_realize(GtkWidget *widget)
   gtk_widget_queue_resize (widget);
 }
 
+AtkObject*
+ags_dial_get_accessible(GtkWidget *widget)
+{
+  AtkObject* accessible;
+
+  accessible = g_object_get_qdata(G_OBJECT(widget),
+				    quark_accessible_object);
+  
+  if(!accessible){
+    accessible = g_object_new(ags_accessible_dial_get_type(),
+			      NULL);
+    
+    g_object_set_qdata(G_OBJECT(widget),
+		       quark_accessible_object,
+		       accessible);
+    gtk_accessible_set_widget(accessible,
+			      widget);
+  }
+  
+  return(accessible);
+}
+
 void
 ags_dial_show(GtkWidget *widget)
 {
@@ -447,6 +612,8 @@ ags_dial_button_release(GtkWidget *widget,
 
   //  GTK_WIDGET_CLASS(ags_dial_parent_class)->button_release_event(widget, event);
 
+  gtk_widget_grab_focus(widget);
+
   dial = AGS_DIAL(widget);
   dial->flags &= (~AGS_DIAL_MOUSE_BUTTON_PRESSED);
 

-- 
gsequencer packaging



More information about the pkg-multimedia-commits mailing list