[SCM] gsequencer/master: undelete directory

jkraehemann-guest at users.alioth.debian.org jkraehemann-guest at users.alioth.debian.org
Fri Jun 19 16:24:39 UTC 2015


The following commit has been merged in the master branch:
commit dc8632a3837be056dc98c7e0d9ac571e8e17442e
Author: Joël Krähemann <jkraehemann at gmail.com>
Date:   Fri Jun 19 17:52:30 2015 +0200

    undelete directory

diff --git a/debian/changelog b/debian/changelog
index 356a9cd..fbc997a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,7 +1,9 @@
-ags (0.4.2-67-1) unstable; urgency=low
+ags (0.4.2-68-1) unstable; urgency=low
 
   [ Joël Krähemann (Maintainer of Advanced Gtk+ Sequencer) ]
-  * fixed extended LADSPA support XML IO
+  * fixed itp-bug (Closes: #788590)
+  * fixed audio preferences
+  * added midi2xml
 
   [ Joël Krähemann ]
 
diff --git a/src/midi2ags/main.c b/src/midi2ags/main.c
new file mode 100644
index 0000000..2f97aa9
--- /dev/null
+++ b/src/midi2ags/main.c
@@ -0,0 +1,60 @@
+#include <glib.h>
+#include <glib-object.h>
+
+#include <midi2ags/midi/ags_midi_parser.h>
+
+#include <stdio.h>
+
+#include <libxml/tree.h>
+
+int
+main(int argc, char **argv)
+{
+  AgsMidiParser *midi_parser;
+
+  FILE *out;
+  FILE *file;
+  
+  xmlChar *buffer;
+  gchar *filename;
+  size_t length;
+
+  if(argc == 2){
+
+    if(!strncmp(argv[1], "--help\0", 7)){
+      printf("midi2xml converts MIDI to XML\n\n\0");
+
+      printf("Usage:\n\t%s\n\t%s\n\t%s\n\t%s\n\n",
+	     "Report bugs to <jkraehemann at gmail.com>\n\0",
+	     "--help              display this help and exit\0",
+	     "--version           output version information and exit\0",
+	     "<file>              the file to be processed\0");
+      
+      exit(0);
+    }else if(!strncmp(argv[1], "--version\0", 10)){
+      printf("midi2xml 1.0.0\n\n\0");
+      
+      printf("%s\n%s\n%s\n\n\0",
+	     "Copyright (C) 2015 Joël Krähemann\0",
+	     "This is free software; see the source for copying conditions.  There is NO\0",
+	     "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\0");
+      
+      printf("Written by Joël Krähemann\n\0");
+      exit(0);
+    }else{
+      filename = argv[1];
+    }
+  }else{
+    return(-1);
+  }
+
+  file = fopen(filename, "r\0");
+  fseek(file, 0, SEEK_SET);
+  midi_parser = ags_midi_parser_new(file);
+
+  ags_midi_parser_parse_full(midi_parser);
+
+  xmlSaveFormatFileEnc("-", midi_parser->doc, "UTF-8", 1);
+  
+  return(0);
+}
diff --git a/src/midi2ags/midi/ags_midi_parser.c b/src/midi2ags/midi/ags_midi_parser.c
new file mode 100644
index 0000000..e855704
--- /dev/null
+++ b/src/midi2ags/midi/ags_midi_parser.c
@@ -0,0 +1,2276 @@
+/* AGS - Advanced GTK Sequencer
+ * Copyright (C) 2015 Joël Krähemann
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <midi2ags/midi/ags_midi_parser.h>
+#include <midi2ags/object/ags_marshal.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+
+void ags_midi_parser_class_init(AgsMidiParserClass *midi_parser);
+void ags_midi_parser_init(AgsMidiParser *midi_parser);
+void ags_midi_parser_set_property(GObject *gobject,
+				  guint prop_id,
+				  const GValue *value,
+				  GParamSpec *param_spec);
+void ags_midi_parser_get_property(GObject *gobject,
+				  guint prop_id,
+				  GValue *value,
+				  GParamSpec *param_spec);
+void ags_midi_parser_finalize(GObject *gobject);
+
+int ags_midi_parser_real_midi_getc(AgsMidiParser *midi_parser);
+void ags_midi_parser_real_on_error(AgsMidiParser *midi_parser,
+				   GError **error);
+
+xmlDoc* ags_midi_parser_real_parse_full(AgsMidiParser *midi_parser);
+xmlNode* ags_midi_parser_real_parse_header(AgsMidiParser *midi_parser);
+xmlNode* ags_midi_parser_real_parse_track(AgsMidiParser *midi_parser);
+
+xmlNode* ags_midi_parser_real_key_on(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_real_key_off(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_real_key_pressure(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_real_change_parameter(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_real_change_pitch_bend(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_real_change_program(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_real_change_channel_pressure(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_real_not_defined(AgsMidiParser *midi_parser, guint status);
+
+xmlNode* ags_midi_parser_real_sysex(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_real_system_common(AgsMidiParser *midi_parser, guint status);
+
+xmlNode* ags_midi_parser_real_meta_event(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_real_sequence_number(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_real_end_of_track(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_real_smpte(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_real_tempo(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_real_time_signature(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_real_key_signature(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_real_sequencer_meta_event(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_real_text_event(AgsMidiParser *midi_parser, guint meta_type);
+
+#define AGS_MIDI_PARSER_MAX_TEXT_LENGTH (4096)
+
+#define AGS_MIDI_EVENT "event\0"
+
+/**
+ * SECTION:ags_midi_parser
+ * @short_description: the menu bar.
+ * @title: AgsMidiParser
+ * @section_id:
+ * @include: ags/X/ags_midi_parser.h
+ *
+ * #AgsMidiParser reads your midi parsers.
+ */
+
+enum{
+  PROP_0,
+  PROP_FILE,
+};
+
+enum{
+  MIDI_GETC,
+  ON_ERROR,
+  PARSE_FULL,
+  PARSE_HEADER,
+  PARSE_TRACK,
+  KEY_ON,
+  KEY_OFF,
+  KEY_PRESSURE,
+  CHANGE_PARAMETER,
+  CHANGE_PITCH_BEND,
+  CHANGE_PROGRAM,
+  CHANGE_CHANNEL_PRESSURE,
+  NOT_DEFINED,
+  SYSEX,
+  SYSTEM_COMMON,
+  META_EVENT,
+  SEQUENCE_NUMBER,
+  END_OF_TRACK,
+  SMPTE,
+  TEMPO,
+  TIME_SIGNATURE,
+  KEY_SIGNATURE,
+  SEQUENCER_META_EVENT,
+  TEXT_EVENT,
+  LAST_SIGNAL,
+};
+
+static gpointer ags_midi_parser_parent_class = NULL;
+static guint midi_parser_signals[LAST_SIGNAL];
+
+GType
+ags_midi_parser_get_type(void)
+{
+  static GType ags_type_midi_parser = 0;
+
+  if(!ags_type_midi_parser){
+    static const GTypeInfo ags_midi_parser_info = {
+      sizeof (AgsMidiParserClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc) ags_midi_parser_class_init,
+      NULL, /* class_finalize */
+      NULL, /* class_data */
+      sizeof (AgsMidiParser),
+      0,    /* n_preallocs */
+      (GInstanceInitFunc) ags_midi_parser_init,
+    };
+
+    ags_type_midi_parser = g_type_register_static(G_TYPE_OBJECT,
+						  "AgsMidiParser\0", &ags_midi_parser_info,
+						  0);
+  }
+
+  return(ags_type_midi_parser);
+}
+
+void
+ags_midi_parser_class_init(AgsMidiParserClass *midi_parser)
+{
+  GObjectClass *gobject;
+  GParamSpec *param_spec;
+  
+  ags_midi_parser_parent_class = g_type_class_peek_parent(midi_parser);
+
+  /* GObjectClass */
+  gobject = (GObjectClass *) midi_parser;
+
+  gobject->set_property = ags_midi_parser_set_property;
+  gobject->get_property = ags_midi_parser_get_property;
+  
+  gobject->finalize = ags_midi_parser_finalize;
+
+  /**
+   * AgsMidiParser:dsp-channels:
+   *
+   * The dsp channel count
+   * 
+   * Since: 0.4.2
+   */
+  param_spec = g_param_spec_pointer("file\0",
+				    "the file stream\0",
+				    "The file stream to parse\0",
+				    G_PARAM_READABLE | G_PARAM_WRITABLE);
+  g_object_class_install_property(gobject,
+				  PROP_FILE,
+				  param_spec);
+
+  /* AgsMidiParser */
+  midi_parser->midi_getc = ags_midi_parser_real_midi_getc;
+  midi_parser->on_error = ags_midi_parser_real_on_error;
+
+  midi_parser->parse_header = ags_midi_parser_real_parse_header;
+  midi_parser->parse_track = ags_midi_parser_real_parse_track;
+
+  midi_parser->key_on = ags_midi_parser_real_key_on;
+  midi_parser->key_off = ags_midi_parser_real_key_off;
+  midi_parser->key_pressure = ags_midi_parser_real_key_pressure;
+  midi_parser->change_parameter = ags_midi_parser_real_change_parameter;
+  midi_parser->change_pitch_bend = ags_midi_parser_real_change_pitch_bend;
+  midi_parser->change_program = ags_midi_parser_real_change_program;
+  midi_parser->change_channel_pressure = ags_midi_parser_real_change_channel_pressure;
+  midi_parser->not_defined = ags_midi_parser_real_not_defined;
+
+  midi_parser->sysex = ags_midi_parser_real_sysex;
+  midi_parser->system_common = ags_midi_parser_real_system_common;
+
+  midi_parser->meta_event = ags_midi_parser_real_meta_event;
+  midi_parser->sequence_number = ags_midi_parser_real_sequence_number;
+  midi_parser->end_of_track = ags_midi_parser_real_end_of_track;
+  midi_parser->smpte = ags_midi_parser_real_smpte;
+  midi_parser->tempo = ags_midi_parser_real_tempo;
+  midi_parser->time_signature = ags_midi_parser_real_time_signature;
+  midi_parser->key_signature = ags_midi_parser_real_key_signature;
+  midi_parser->sequencer_meta_event = ags_midi_parser_real_sequencer_meta_event;
+  midi_parser->text_event = ags_midi_parser_real_text_event;
+
+  midi_parser->parse_full = ags_midi_parser_real_parse_full;
+  
+  /* signals */
+  /**
+   * AgsMidiParser::midi-getc:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::midi-getc signal is emited during parsing of event.
+   */
+  midi_parser_signals[MIDI_GETC] =
+    g_signal_new("midi-getc\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, midi_getc),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_INT__VOID,
+		 G_TYPE_INT, 0);
+
+  /**
+   * AgsMidiParser::on-error:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::on-error signal is emited during parsing of event.
+   */
+  midi_parser_signals[ON_ERROR] =
+    g_signal_new("on-error\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, on_error),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__VOID,
+		 G_TYPE_POINTER, 0);
+
+
+  /**
+   * AgsMidiParser::parse-header:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the header
+   *
+   * The ::parse-header signal is emited during parsing of header.
+   */
+  midi_parser_signals[PARSE_HEADER] =
+    g_signal_new("parse-header\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, parse_header),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__VOID,
+		 G_TYPE_POINTER, 0);
+
+  /**
+   * AgsMidiParser::parse-track:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the track
+   *
+   * The ::parse-track signal is emited during parsing of track.
+   */
+  midi_parser_signals[PARSE_TRACK] =
+    g_signal_new("parse-track\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, parse_track),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__VOID,
+		 G_TYPE_POINTER, 0);
+
+  /**
+   * AgsMidiParser::key-on:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::key-on signal is emited during parsing of event.
+   */
+  midi_parser_signals[KEY_ON] =
+    g_signal_new("key-on\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, key_on),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::key-off:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::key-off signal is emited during parsing of event.
+   */
+  midi_parser_signals[KEY_OFF] =
+    g_signal_new("key-off\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, key_off),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::key-pressure:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::key-pressure signal is emited during parsing of event.
+   */
+  midi_parser_signals[KEY_PRESSURE] =
+    g_signal_new("key-pressure\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, key_pressure),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::change-parameter:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::change-parameter signal is emited during parsing of event.
+   */
+  midi_parser_signals[CHANGE_PARAMETER] =
+    g_signal_new("change-parameter\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, change_parameter),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::change-pitch-bend:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::change-pitch-bend signal is emited during parsing of event.
+   */
+  midi_parser_signals[CHANGE_PITCH_BEND] =
+    g_signal_new("change-pitch-bend\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, change_pitch_bend),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::change-program:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::change-program signal is emited during parsing of event.
+   */
+  midi_parser_signals[CHANGE_PROGRAM] =
+    g_signal_new("change-program\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, change_program),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::change-channel-pressure:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::change-channel-pressure signal is emited during parsing of event.
+   */
+  midi_parser_signals[CHANGE_CHANNEL_PRESSURE] =
+    g_signal_new("change-channel-pressure\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, change_channel_pressure),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::not-defined:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::not-defined signal is emited during parsing of event.
+   */
+  midi_parser_signals[NOT_DEFINED] =
+    g_signal_new("not-defined\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, not_defined),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::sysex:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::sysex signal is emited during parsing of event.
+   */
+  midi_parser_signals[SYSEX] =
+    g_signal_new("sysex\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, sysex),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::system-common:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::system-common signal is emited during parsing of event.
+   */
+  midi_parser_signals[SYSTEM_COMMON] =
+    g_signal_new("system-common\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, system_common),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::meta-event:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::meta-event signal is emited during parsing of event.
+   */
+  midi_parser_signals[META_EVENT] =
+    g_signal_new("meta-event\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, meta_event),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::sequence-number:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::sequence-number signal is emited during parsing of event.
+   */
+  midi_parser_signals[SEQUENCE_NUMBER] =
+    g_signal_new("sequence-number\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, sequence_number),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::end-of-track:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::end-of-track signal is emited during parsing of event.
+   */
+  midi_parser_signals[END_OF_TRACK] =
+    g_signal_new("end-of-track\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, end_of_track),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::smpte:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::smpte signal is emited during parsing of event.
+   */
+  midi_parser_signals[SMPTE] =
+    g_signal_new("smpte\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, smpte),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::tempo:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::tempo signal is emited during parsing of event.
+   */
+  midi_parser_signals[TEMPO] =
+    g_signal_new("tempo\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, tempo),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::time-signature:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::time-signature signal is emited during parsing of event.
+   */
+  midi_parser_signals[TIME_SIGNATURE] =
+    g_signal_new("time-signature\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, time_signature),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::key-signature:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::key-signature signal is emited during parsing of event.
+   */
+  midi_parser_signals[KEY_SIGNATURE] =
+    g_signal_new("key-signature\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, key_signature),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::sequencer-meta-event:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::sequencer-meta-event signal is emited during parsing of event.
+   */
+  midi_parser_signals[SEQUENCER_META_EVENT] =
+    g_signal_new("sequencer-meta-event\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, sequencer_meta_event),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::text-event:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::text-event signal is emited during parsing of event.
+   */
+  midi_parser_signals[TEXT_EVENT] =
+    g_signal_new("text-event\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, text_event),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__UINT,
+		 G_TYPE_POINTER, 1,
+		 G_TYPE_UINT);
+
+  /**
+   * AgsMidiParser::parse-full:
+   * @midi_parser: the parser
+   *
+   * Returns: The XML node representing the event
+   *
+   * The ::parse-full signal is emited during parsing of midi file.
+   */
+  midi_parser_signals[PARSE_FULL] =
+    g_signal_new("parse-full\0",
+		 G_TYPE_FROM_CLASS(midi_parser),
+		 G_SIGNAL_RUN_LAST,
+		 G_STRUCT_OFFSET(AgsMidiParserClass, parse_full),
+		 NULL, NULL,
+		 g_cclosure_user_marshal_POINTER__VOID,
+		 G_TYPE_POINTER, 0);
+}
+
+void
+ags_midi_parser_init(AgsMidiParser *midi_parser)
+{
+  midi_parser->flags = 0;
+  
+  midi_parser->file = NULL;
+  midi_parser->nth_chunk = 0;
+
+  midi_parser->file_length = 0;
+  midi_parser->offset = 0;
+
+  midi_parser->current_time = 0;
+
+  midi_parser->doc = NULL;
+}
+
+void
+ags_midi_parser_set_property(GObject *gobject,
+			     guint prop_id,
+			     const GValue *value,
+			     GParamSpec *param_spec)
+{
+  AgsMidiParser *midi_parser;
+
+  midi_parser = AGS_MIDI_PARSER(gobject);
+  
+  switch(prop_id){
+  case PROP_FILE:
+    {
+      midi_parser->file = g_value_get_pointer(value);
+    }
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  }
+}
+
+void
+ags_midi_parser_get_property(GObject *gobject,
+			     guint prop_id,
+			     GValue *value,
+			     GParamSpec *param_spec)
+{
+  AgsMidiParser *midi_parser;
+
+  midi_parser = AGS_MIDI_PARSER(gobject);
+  
+  switch(prop_id){
+  case PROP_FILE:
+    {
+      g_value_set_pointer(value,
+			  midi_parser->file);
+    }
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
+    break;
+  }
+}
+
+void
+ags_midi_parser_finalize(GObject *gobject)
+{
+  G_OBJECT_CLASS(ags_midi_parser_parent_class)->finalize(gobject);
+}
+
+gint16
+ags_midi_parser_read_gint16(AgsMidiParser *midi_parser)
+{
+  char str[2];
+  gint16 value = 0;
+
+  str[0] = (char) 0xff & ags_midi_parser_midi_getc(midi_parser);
+  str[1] = (char) 0xff & ags_midi_parser_midi_getc(midi_parser);
+
+  value = (str[0] & 0xff);
+  value = (value<<8) + (str[1] & 0xff);
+  
+  return(value);
+}
+
+gint32
+ags_midi_parser_read_gint24(AgsMidiParser *midi_parser)
+{
+  char str[4];
+  gint32 value = 0;
+  
+  str[0] = (char) 0x00;
+  str[1] = (char) 0xff & ags_midi_parser_midi_getc(midi_parser);
+  str[2] = (char) 0xff & ags_midi_parser_midi_getc(midi_parser);
+  str[3] = (char) 0xff & ags_midi_parser_midi_getc(midi_parser);
+
+  value = (value<<8) + (str[1] & 0xff);
+  value = (value<<8) + (str[2] & 0xff);
+  value = (value<<8) + (str[3] & 0xff);
+  
+  return(value);
+}
+
+gint32
+ags_midi_parser_read_gint32(AgsMidiParser *midi_parser)
+{
+  char str[4];
+  gint32 value;
+  
+  str[0] = (char) 0xff & ags_midi_parser_midi_getc(midi_parser);
+  str[1] = (char) 0xff & ags_midi_parser_midi_getc(midi_parser);
+  str[2] = (char) 0xff & ags_midi_parser_midi_getc(midi_parser);
+  str[3] = (char) 0xff & ags_midi_parser_midi_getc(midi_parser);
+
+  value = (str[0] & 0xff);
+  value = (value<<8) + (str[1] & 0xff);
+  value = (value<<8) + (str[2] & 0xff);
+  value = (value<<8) + (str[3] & 0xff);
+  
+  return(value);
+}
+
+long
+ags_midi_parser_read_varlength(AgsMidiParser *midi_parser)
+{
+  long value;
+  guint i;
+  char c;
+  
+  c = ags_midi_parser_midi_getc(midi_parser);
+  value = c;
+  i = 1;
+  
+  if(c & 0x80){
+    value &= 0x7F;
+   
+    do{
+      value = (value << 7) + ((c = ags_midi_parser_midi_getc(midi_parser)) & 0x7F);
+      i++;
+    }while(c & 0x80);
+  }
+  
+  return(value);
+}
+
+gchar*
+ags_midi_parser_read_text(AgsMidiParser *midi_parser,
+			  gint length)
+{
+  gchar text[AGS_MIDI_PARSER_MAX_TEXT_LENGTH];
+  gchar c;
+  guint i;
+
+  memset(text, 0, AGS_MIDI_PARSER_MAX_TEXT_LENGTH * sizeof(char));
+  i = 0;
+  
+  while((length <= 0 ||
+	 i < length) && (c = (char) 0xff & ags_midi_parser_midi_getc(midi_parser)) != EOF){
+    if(c == '\0' || !(g_ascii_isalnum(c) ||
+		      g_ascii_ispunct(c) ||
+		      c == ' ')){
+      break;
+    }
+
+    text[i] = c;
+    i++;
+  }
+
+  text[i] = '\0';
+    
+  return(g_strdup(text));
+}
+
+gdouble
+ags_midi_parser_ticks_to_sec(AgsMidiParser *midi_parser,
+			     guint ticks, gint division, guint tempo)
+{
+  gdouble retval;
+  
+  if(division > 0){
+    retval = ((gdouble) ticks * tempo) /
+	      (gdouble) (division * 1000000.0);
+    return(retval);
+  }else{
+    gdouble smpte_format, smpte_resolution;
+
+    smpte_format = (gdouble) ((0xff00 & division) >> 8);
+    smpte_resolution = (gdouble) (0xff & division);
+
+    retval = (((gdouble) ticks) /
+	      (gdouble) (smpte_format * smpte_resolution * 1000000.0));
+    
+    return(retval);
+  }
+}
+
+int
+ags_midi_parser_midi_getc(AgsMidiParser *midi_parser)
+{
+  int c;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), '\0');
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[MIDI_GETC], 0,
+		&c);
+  g_object_unref((GObject *) midi_parser);
+
+  return(c);
+}
+
+int
+ags_midi_parser_real_midi_getc(AgsMidiParser *midi_parser)
+{
+  int c;
+
+  c = fgetc(midi_parser->file);
+  
+  if(c == EOF){
+    g_warning("reached end of file\0");
+    midi_parser->flags |= AGS_MIDI_PARSER_EOF;
+  }
+
+  return(c);
+}
+
+void
+ags_midi_parser_on_error(AgsMidiParser *midi_parser,
+			 GError **error)
+{
+  g_return_if_fail(AGS_IS_MIDI_PARSER(midi_parser));
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[ON_ERROR], 0,
+		error);
+  g_object_unref((GObject *) midi_parser);
+}
+
+void
+ags_midi_parser_real_on_error(AgsMidiParser *midi_parser,
+			      GError **error)
+{
+}
+
+xmlDoc*  
+ags_midi_parser_parse_full(AgsMidiParser *midi_parser)
+{
+  xmlDoc *doc;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[PARSE_FULL], 0,
+		&doc);
+  g_object_unref((GObject *) midi_parser);
+
+  return(doc);
+}
+
+xmlDoc*
+ags_midi_parser_real_parse_full(AgsMidiParser *midi_parser)
+{
+  xmlDoc *doc;
+  xmlNode *root_node;
+  xmlNode *tracks_node;
+  xmlNode *current;
+
+  GError *error;
+
+  midi_parser->doc = 
+    doc = xmlNewDoc("1.0\0");
+  root_node = xmlNewNode(NULL, "midi\0");
+  xmlDocSetRootElement(doc, root_node);
+
+  tracks_node = xmlNewNode(NULL, "midi-tracks\0");
+
+  error = NULL;
+
+  current = ags_midi_parser_parse_header(midi_parser);
+  xmlAddChild(root_node,
+	      current);
+#ifdef DEBUG
+  g_message("parsed header\0");
+#endif
+  
+  xmlAddChild(root_node,
+	      tracks_node);
+  
+  while(((AGS_MIDI_PARSER_EOF & (midi_parser->flags))) == 0){
+    current = ags_midi_parser_parse_track(midi_parser);
+    
+    if(current != NULL){
+      xmlAddChild(tracks_node,
+		  current);
+#ifdef DEBUG
+      g_message("parsed track\0");
+#endif
+    }else{
+      g_warning("skipped input\0");
+    }
+  }
+
+  return(doc);
+}
+
+xmlNode*  
+ags_midi_parser_parse_header(AgsMidiParser *midi_parser)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[PARSE_HEADER], 0,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*
+ags_midi_parser_real_parse_header(AgsMidiParser *midi_parser)
+{
+  xmlNode *node;
+
+  static gchar header[] = "MThd";
+  guint format;
+  guint count;
+  guint division;
+  guint offset;
+  guint times;
+  guint beat, clicks;
+  guint n;
+  gchar c;
+  
+  n = 0;
+  
+  while(n < 4 &&
+	(AGS_MIDI_PARSER_EOF & (midi_parser->flags)) == 0){
+    c = ags_midi_parser_midi_getc(midi_parser);
+    
+    if(c == header[n]){
+      n++;
+    }else{
+      n = 0;
+    }
+  }
+  
+  node = xmlNewNode(NULL,
+		    "midi-header\0");
+
+  offset = (guint) ags_midi_parser_read_gint32(midi_parser);
+  format = (guint) ags_midi_parser_read_gint16(midi_parser);
+  count = (guint) ags_midi_parser_read_gint16(midi_parser);
+  division = (guint) ags_midi_parser_read_gint16(midi_parser);
+
+  xmlNewProp(node,
+	     "format\0",
+	     g_strdup_printf("%d\0", format));
+
+  if(division & 0x8000){
+    /* SMPTE */
+    times = 0; /* Can't do beats */
+
+    xmlNewProp(node,
+	       "division\0",
+	       g_strdup_printf("%d %d\0", -((-(division>>8))&0xff), division&0xff));
+  }else{
+    xmlNewProp(node,
+	       "division\0",
+	       g_strdup_printf("%d\0", division));
+  }
+  
+  if(format > 2){
+    fprintf(stderr, "Can't deal with format %d files\n", format);
+    exit(-1);
+  }
+  
+  beat =
+    clicks = division;
+
+  xmlNewProp(node,
+	     "beat\0",
+	     g_strdup_printf("%d\0", beat));
+
+  xmlNewProp(node,
+	     "track-count\0",
+	     g_strdup_printf("%d\0", count));
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_parse_track(AgsMidiParser *midi_parser)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[PARSE_TRACK], 0,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*
+ags_midi_parser_real_parse_track(AgsMidiParser *midi_parser)
+{
+  xmlNode *node, *current;
+  static gchar track[] = "MTrk";
+  gint offset, start_offset;
+  long delta_time;
+  guint status;
+  guint n;
+  gchar c;
+
+  n = 0;
+  
+  while(n < 4 &&
+	(AGS_MIDI_PARSER_EOF & (midi_parser->flags)) == 0){
+    c = ags_midi_parser_midi_getc(midi_parser);
+    
+    if(c == track[n]){
+      n++;
+    }else{
+      n = 0;
+    }
+  }
+
+  if((AGS_MIDI_PARSER_EOF & (midi_parser->flags)) != 0){
+    return(NULL);
+  }
+
+  node = xmlNewNode(NULL, "midi-track\0");
+
+  offset = ags_midi_parser_read_gint32(midi_parser);
+
+#ifdef DEBUG
+  g_message("n = %d\noffset = %d\0", n, offset);
+#endif
+  
+  start_offset = ftell(midi_parser->file);
+
+  if(offset < 0){
+    return(NULL);
+  }
+
+  midi_parser->current_time = 0;
+  
+  for(; ftell(midi_parser->file) < start_offset + offset; ){
+    delta_time = ags_midi_parser_read_varlength(midi_parser);
+    midi_parser->current_time += delta_time;
+    
+    status = ags_midi_parser_midi_getc(midi_parser);
+    
+    if((0xf0 & (0xf0 & status)) != 0xf0){
+      current = ags_midi_parser_channel_message(midi_parser,
+						status);
+
+      if(current != NULL){
+	xmlNewProp(current,
+		   "delta-time\0",
+		   g_strdup_printf("%d\0", midi_parser->current_time));
+	
+	xmlAddChild(node,
+		    current);
+      }
+      
+#ifdef DEBUG
+      g_message("channel message");
+#endif
+    }else{
+#ifdef DEBUG
+      g_message("status message");
+#endif
+      
+      switch(status){
+      case 0xf0:
+	{
+	  /* start of system exclusive */
+	  ags_midi_parser_sysex(midi_parser,
+				status);
+
+	}
+      case 0xf1:
+      case 0xf2:
+      case 0xf3:
+      case 0xf4:
+      case 0xf5:
+      case 0xf6:
+	{
+	  ags_midi_parser_system_common(midi_parser,
+					status);
+	}
+	break;
+      case 0xf7:
+	{
+	  /* sysex continuation or arbitrary stuff */
+#ifdef DEBUG
+	  g_message("sysex end\0");
+#endif
+	}
+	break;
+      case 0xff:
+	{
+	  /* meta event */
+	  current = ags_midi_parser_meta_event(midi_parser,
+					       status);
+
+	  if(current != NULL){
+	    xmlNewProp(current,
+		       "delta-time\0",
+		       g_strdup_printf("%d\0", midi_parser->current_time));
+	    
+	    xmlAddChild(node,
+			current);
+	  }
+	}
+	break;
+      default:
+	g_warning("bad byte\0");
+	break;
+      }
+    }
+  }
+  
+  return(node);
+}
+
+xmlNode*
+ags_midi_parser_channel_message(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+
+  node = NULL;
+  
+  switch(status & 0xf0){
+  case 0x80:
+    {
+      node = ags_midi_parser_key_off(midi_parser, status);
+    }
+    break;
+  case 0x90:
+    {
+      node = ags_midi_parser_key_on(midi_parser, status);
+    }
+    break;
+  case 0xa0:
+    {
+      node = ags_midi_parser_key_pressure(midi_parser, status);
+    }
+    break;
+  case 0xb0:
+    {
+      node = ags_midi_parser_change_parameter(midi_parser, status);
+    }
+    break;
+  case 0xc0:
+    {
+      node = ags_midi_parser_change_program(midi_parser, status);
+    }
+    break;
+  case 0xd0:
+    {
+      node = ags_midi_parser_change_channel_pressure(midi_parser, status);
+    }
+    break;
+  case 0xe0:
+    {
+      node = ags_midi_parser_change_pitch_bend(midi_parser, status);
+    }
+    break;
+  }
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_key_on(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  int channel, note, velocity;
+
+  channel = 0xf & status;
+  note = (0x7f) & ags_midi_parser_midi_getc(midi_parser);
+  velocity = (0x7f) & ags_midi_parser_midi_getc(midi_parser);
+
+  node = xmlNewNode(NULL,
+		    "midi-message\0");
+
+  xmlNewProp(node,
+	     AGS_MIDI_EVENT,
+	     "note-on\0");
+
+  xmlNewProp(node,
+	     "key\0",
+	     g_strdup_printf("%d\0", channel));
+
+  xmlNewProp(node,
+	     "note\0",
+	     g_strdup_printf("%d\0", note));
+
+  xmlNewProp(node,
+	     "velocity\0",
+	     g_strdup_printf("%d\0", velocity));
+  
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_key_on(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[KEY_ON], 0,
+		status,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_key_off(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  int channel, note, velocity;
+
+  channel = 0xf & status;
+  note = (0x7f) & ags_midi_parser_midi_getc(midi_parser);
+  velocity = (0x7f) & ags_midi_parser_midi_getc(midi_parser);
+
+  node = xmlNewNode(NULL,
+		    "midi-message\0");
+  
+  xmlNewProp(node,
+	     AGS_MIDI_EVENT,
+	     "note-off\0");
+
+
+  xmlNewProp(node,
+	     "key\0",
+	     g_strdup_printf("%d\0", channel));
+
+  xmlNewProp(node,
+	     "note\0",
+	     g_strdup_printf("%d\0", note));
+
+  xmlNewProp(node,
+	     "velocity\0",
+	     g_strdup_printf("%d\0", velocity));
+  
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_key_off(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[KEY_OFF], 0,
+		status,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_key_pressure(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  int channel, note, pressure;
+
+  channel = 0xf & status;
+  note = 0x7f & ags_midi_parser_midi_getc(midi_parser);
+  pressure = 0x7f & ags_midi_parser_midi_getc(midi_parser);
+  
+  node = xmlNewNode(NULL,
+		    "midi-message\0");
+
+  xmlNewProp(node,
+	     AGS_MIDI_EVENT,
+	     "polyphonic\0");
+	
+  xmlNewProp(node,
+	     "key\0",
+	     g_strdup_printf("%d\0", channel));
+  
+  xmlNewProp(node,
+	     "note\0",
+	     g_strdup_printf("%d\0", note));
+
+  xmlNewProp(node,
+	     "pressure\0",
+	     g_strdup_printf("%d\0", pressure));
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_key_pressure(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[KEY_PRESSURE], 0,
+		status,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_change_parameter(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  int channel, control, value;
+
+  channel = 0xf & status;
+  control = 0x7f & ags_midi_parser_midi_getc(midi_parser);
+  value = 0x7f & ags_midi_parser_midi_getc(midi_parser);
+
+  node = xmlNewNode(NULL,
+		    "midi-message\0");
+
+  if(control < 120){
+    xmlNewProp(node,
+	       AGS_MIDI_EVENT,
+	       "change-parameter\0");
+
+    xmlNewProp(node,
+	       "channel\0",
+	       g_strdup_printf("%d\0", channel));
+
+    xmlNewProp(node,
+	       "control\0",
+	       g_strdup_printf("%d\0", control));
+
+    xmlNewProp(node,
+	       "value\0",
+	       g_strdup_printf("%d\0", value));
+  }else{
+    xmlNewProp(node,
+	       AGS_MIDI_EVENT,
+	       "change-mode\0");
+
+    xmlNewProp(node,
+	       "channel\0",
+	       g_strdup_printf("%d\0", channel));
+
+    switch(control){
+    case 120:
+      {
+	xmlNewProp(node,
+		   "mode\0",
+		   "all-sound-off\0");
+      }
+      break;
+    case 121:
+      {
+	xmlNewProp(node,
+		   "mode\0",
+		   "reset-control-all\0");
+	    
+	xmlNewProp(node,
+		   "value\0",
+		   g_strdup_printf("%d\0", value));
+      }
+      break;
+    case 122:
+      {
+	if(value == 0){
+	  xmlNewProp(node,
+		     "mode\0",
+		     "local-control-off\0");
+	}else{
+	  xmlNewProp(node,
+		     "mode\0",
+		     "local-control-on\0");
+	}
+      }
+      break;
+    case 123:
+      {
+	xmlNewProp(node,
+		   "mode\0",
+		   "all-notes-off");
+      }
+      break;
+    case 124:
+      {
+	xmlNewProp(node,
+		   "mode\0",
+		   "omni-mode-on");
+      }
+      break;
+    case 125:
+      {
+	xmlNewProp(node,
+		   "mode\0",
+		   "omni-mode-off\0");
+      }
+      break;
+    case 126:
+      {
+	xmlNewProp(node,
+		   "mode\0",
+		   "mono-mode-on\0");
+
+	xmlNewProp(node,
+		   "omni-off-channels\0",
+		   g_strdup_printf("%d\0", value));
+      }
+      break;
+    case 127:
+      {
+	xmlNewProp(node,
+		   "mode\0",
+		   "poly-mode-on\0");
+      }
+      break;
+    }
+  }
+  
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_change_parameter(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[CHANGE_PARAMETER], 0,
+		status,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_change_pitch_bend(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  int channel, pitch, transmitter;
+
+  channel = 0xf & status;
+  pitch = 0x7f & ags_midi_parser_midi_getc(midi_parser);
+  transmitter = 0x7f & ags_midi_parser_midi_getc(midi_parser);
+  
+  node = xmlNewNode(NULL,
+		    "midi-message\0");
+
+  xmlNewProp(node,
+	     "channel\0",
+	     g_strdup_printf("%d\0", channel));
+
+  xmlNewProp(node,
+	     AGS_MIDI_EVENT,
+	     "pitch-bend\0");
+
+  xmlNewProp(node,
+	     "pitch\0",
+	     g_strdup_printf("%d\0", pitch));	  
+
+  xmlNewProp(node,
+	     "transmitter\0",
+	     g_strdup_printf("%d\0", transmitter));	  
+  
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_change_pitch_bend(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[CHANGE_PITCH_BEND], 0,
+		status,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_change_program(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  int channel, program;
+
+  channel = 0xf & status;
+  program = 0x7f & ags_midi_parser_midi_getc(midi_parser);
+  
+  node = xmlNewNode(NULL,
+		    "midi-message\0");
+
+  xmlNewProp(node,
+	     AGS_MIDI_EVENT,
+	     "program-change\0");
+
+  xmlNewProp(node,
+	     "channel\0",
+	     g_strdup_printf("%d\0", channel));
+
+  xmlNewProp(node,
+	     "program\0",
+	     g_strdup_printf("%d\0", program));
+  
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_change_program(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[CHANGE_PROGRAM], 0,
+		status,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_change_channel_pressure(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  int channel, pressure;
+
+  channel = 0xf & status;
+  pressure = 0x7f & ags_midi_parser_midi_getc(midi_parser);
+  
+  node = xmlNewNode(NULL,
+		    "midi-message\0");
+
+  xmlNewProp(node,
+	     AGS_MIDI_EVENT,
+	     "channel-pressure\0");
+
+  xmlNewProp(node,
+	     "channel\0",
+	     g_strdup_printf("%d\0", channel));
+
+  xmlNewProp(node,
+	     "pressure\0",
+	     g_strdup_printf("%d\0", pressure));
+  
+  
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_change_channel_pressure(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[CHANGE_CHANNEL_PRESSURE], 0,
+		status,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_not_defined(AgsMidiParser *midi_parser, guint status)
+{
+  return(NULL);
+}
+
+xmlNode*  
+ags_midi_parser_not_defined(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[NOT_DEFINED], 0,
+		status,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*
+ags_midi_parser_real_sysex(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  gchar c;
+  
+  while((c = ags_midi_parser_midi_getc(midi_parser)) != 0xf7 &&
+	c != EOF);
+
+#ifdef DEBUG
+  g_message("discarded sysex\0");
+#endif
+}
+
+xmlNode*
+ags_midi_parser_sysex(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[SYSEX], 0,
+		status,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*
+ags_midi_parser_real_system_common(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  int c;
+
+  node = NULL;
+  
+  switch(status){
+  case 0xf1:
+    {
+      guint quarter_frame;
+      
+      quarter_frame = 0xff & (ags_midi_parser_midi_getc(midi_parser));
+    }
+    break;
+  case 0xf2:
+    {
+      guint song_position;
+      
+      song_position = 0x7f & (ags_midi_parser_midi_getc(midi_parser)) << 7;
+      song_position = 0x7f & (ags_midi_parser_midi_getc(midi_parser));
+    }
+    break;
+  case 0xf3:
+    {
+      guint song_select;
+      
+      song_select = 0x7f & (ags_midi_parser_midi_getc(midi_parser));
+    }
+    break;
+  case 0xf4:
+    {
+#ifdef DEBUG
+      g_message("undefined\0");
+#endif
+    }
+    break;
+  case 0xf5:
+    {
+#ifdef DEBUG
+      g_message("undefined\0");
+#endif
+    }
+    break;
+  case 0xf6:
+    {
+#ifdef DEBUG
+      g_message("tune request\0");
+#endif
+    }
+    break;
+  }
+
+  return(node);
+}
+
+xmlNode*
+ags_midi_parser_system_common(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[SYSTEM_COMMON], 0,
+		status,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_meta_event(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  char chunk_meta_length[4];
+  guint meta_type;
+  
+  meta_type = 0xff & (ags_midi_parser_midi_getc(midi_parser));
+  midi_parser->offset += 1;
+
+  node = NULL;
+  
+  switch(meta_type){
+  case 0x00:
+    {
+      int c;
+
+      c = ags_midi_parser_midi_getc(midi_parser);
+
+      if(c == 0x02){
+	node = ags_midi_parser_sequence_number(midi_parser, meta_type);
+      }
+    }
+    break;
+  case 0x01:      /* Text event */
+  case 0x02:      /* Copyright notice */
+  case 0x03:      /* Sequence/Track name */
+  case 0x04:      /* Instrument name */
+  case 0x05:      /* Lyric */
+  case 0x06:      /* Marker */
+  case 0x07:      /* Cue point */
+  case 0x08:
+  case 0x09:
+  case 0x0a:
+  case 0x0b:
+  case 0x0c:
+  case 0x0d:
+  case 0x0e:
+  case 0x0f:
+    {
+      /* These are all text events */
+      node = ags_midi_parser_text_event(midi_parser, meta_type);
+    }
+    break;
+  case 0x2f:
+    {
+      int c;
+
+      c = ags_midi_parser_midi_getc(midi_parser);
+
+      if(c == 0x0){
+	/* End of Track */
+	node = ags_midi_parser_end_of_track(midi_parser, meta_type);
+      }
+    }
+    break;
+  case 0x51:
+    {
+      int c;
+
+      c = ags_midi_parser_midi_getc(midi_parser);
+
+      if(c == 0x03){
+	/* Set tempo */
+	node = ags_midi_parser_tempo(midi_parser, meta_type);
+      }
+    }
+    break;
+  case 0x54:
+    {
+      int c;
+
+      c = ags_midi_parser_midi_getc(midi_parser);
+
+      if(c == 0x05){
+	node = ags_midi_parser_smpte(midi_parser, meta_type);
+      }
+    }
+    break;
+  case 0x58:
+    {
+      int c;
+
+      c = ags_midi_parser_midi_getc(midi_parser);
+      
+      if(c == 0x04){
+	node = ags_midi_parser_time_signature(midi_parser, meta_type);
+      }
+    }
+    break;
+  case 0x59:
+    {
+      int c;
+
+      c = ags_midi_parser_midi_getc(midi_parser);
+
+      if(c == 0x02){
+	node = ags_midi_parser_key_signature(midi_parser, meta_type);
+      }
+    }
+    break;
+  case 0x7f:
+    {
+      node = ags_midi_parser_sequencer_meta_event(midi_parser, meta_type);
+    }
+    break;
+  default:
+    {
+      node = xmlNewNode(NULL,
+			"midi-message\0");
+      xmlNewProp(node,
+		 AGS_MIDI_EVENT,
+		 "misc\0");
+    }
+  }
+	
+#ifdef DEBUG
+  g_message("meta type 0x%x\0", meta_type);
+#endif
+  
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_meta_event(AgsMidiParser *midi_parser, guint status)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[META_EVENT], 0,
+		status,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_sequence_number(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  guint sequence;
+  
+  node = xmlNewNode(NULL,
+		    "midi-message\0");
+
+  sequence = (guint) ags_midi_parser_read_gint16(midi_parser);
+  
+  xmlNewProp(node,
+	     AGS_MIDI_EVENT,
+	     "sequence-number\0");
+  
+  xmlNewProp(node,
+	     "sequence\0",
+	     g_strdup_printf("%d\0", sequence));
+    
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_sequence_number(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[SEQUENCE_NUMBER], 0,
+		meta_type,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_end_of_track(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+
+  node = xmlNewNode(NULL,
+		    "midi-message\0");
+
+  xmlNewProp(node,
+	     AGS_MIDI_EVENT,
+	     "end-of-track\0");
+  
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_end_of_track(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[END_OF_TRACK], 0,
+		meta_type,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_smpte(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  int hr, mn, se, fr, ff;
+  
+  node = xmlNewNode(NULL,
+		    "midi-message\0");
+
+  hr = ags_midi_parser_midi_getc(midi_parser);
+  mn = ags_midi_parser_midi_getc(midi_parser);
+  se = ags_midi_parser_midi_getc(midi_parser);
+  fr = ags_midi_parser_midi_getc(midi_parser);
+  ff = ags_midi_parser_midi_getc(midi_parser);
+  
+  xmlNewProp(node,
+	     AGS_MIDI_EVENT,
+	     "smpte\0");
+  
+  xmlNewProp(node,
+	     "timestamp\0",
+	     g_strdup_printf("%d %d %d %d %d\0", hr, mn, se, fr, ff));
+  
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_smpte(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[SMPTE], 0,
+		meta_type,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_tempo(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  gint tempo;
+  
+  node = xmlNewNode(NULL,
+		    "midi-message\0");
+
+  tempo = ags_midi_parser_read_gint24(midi_parser);
+  
+  xmlNewProp(node,
+	     AGS_MIDI_EVENT,
+	     "tempo-number\0");
+  
+  xmlNewProp(node,
+	     "tempo\0",
+	     g_strdup_printf("%ld\0", tempo));
+  
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_tempo(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[TEMPO], 0,
+		meta_type,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_time_signature(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  int nn, dd, cc, bb;
+  int denom = 1;
+  
+  node = xmlNewNode(NULL,
+		    "midi-message\0");
+
+  nn = ags_midi_parser_midi_getc(midi_parser);
+  dd = ags_midi_parser_midi_getc(midi_parser);
+  cc = ags_midi_parser_midi_getc(midi_parser);
+  bb = ags_midi_parser_midi_getc(midi_parser);
+
+  while(dd-- > 0){
+    denom *= 2;
+  }
+
+  xmlNewProp(node,
+	     AGS_MIDI_EVENT,
+	     "time-signature\0");
+
+  xmlNewProp(node,
+	     "timesig\0",
+	     g_strdup_printf("%d/%d %d %d\0", nn, denom, cc, bb));
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_time_signature(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[TIME_SIGNATURE], 0,
+		meta_type,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_key_signature(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  int sf, mi;
+  
+  node = xmlNewNode(NULL,
+		    "midi-message\0");
+
+  xmlNewProp(node,
+	     AGS_MIDI_EVENT,
+	     "key-signature\0");
+  
+  sf = ags_midi_parser_midi_getc(midi_parser);
+  mi = ags_midi_parser_midi_getc(midi_parser);
+
+  xmlNewProp(node,
+	     "keysig\0",
+	     g_strdup_printf("%d %s\0", (sf>127?sf-256:sf), (mi?"minor":"major")));
+  
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_key_signature(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[KEY_SIGNATURE], 0,
+		meta_type,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_sequencer_meta_event(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  guint len, id, data;
+
+  node = NULL;
+
+  len = ags_midi_parser_midi_getc(midi_parser);
+  id = ags_midi_parser_midi_getc(midi_parser);
+  data = ags_midi_parser_midi_getc(midi_parser);
+  
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_sequencer_meta_event(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[META_EVENT], 0,
+		meta_type,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_real_text_event(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  gchar *text;
+  guint text_length;
+
+  node = xmlNewNode(NULL,
+		    "midi-message\0");
+
+  text_length = ags_midi_parser_read_varlength(midi_parser);
+  text = ags_midi_parser_read_text(midi_parser,
+				   text_length);
+  
+  switch(0x0f & meta_type){
+  case 0x01:      /* Text event */
+    break;
+  case 0x02:
+    {
+      /* Copyright notice */
+      xmlNewProp(node,
+		 "copyright\0",
+		 text);
+    }
+    break;
+  case 0x03:
+    {
+      /* Sequence/Track name */
+      xmlNewProp(node,
+		 "sequence-name\0",
+		 text);
+    }
+    break;
+  case 0x04:
+    {
+      /* Instrument name */
+      xmlNewProp(node,
+		 "instrument-name\0",
+		 text);
+    }
+    break;
+  case 0x05:      /* Lyric */
+    break;
+  case 0x06:      /* Marker */
+    break;
+  case 0x07:      /* Cue point */
+    break;
+  case 0x08:
+    break;
+  case 0x09:
+    break;
+  case 0x0a:
+    break;
+  case 0x0b:
+    break;
+  case 0x0c:
+    break;
+  case 0x0d:
+    break;
+  case 0x0e:
+    break;
+  case 0x0f:
+    break;
+  default:
+    g_warning("unknown text event\0");
+  }
+    
+  return(node);
+}
+
+xmlNode*  
+ags_midi_parser_text_event(AgsMidiParser *midi_parser, guint meta_type)
+{
+  xmlNode *node;
+  
+  g_return_val_if_fail(AGS_IS_MIDI_PARSER(midi_parser), NULL);
+  
+  g_object_ref((GObject *) midi_parser);
+  g_signal_emit(G_OBJECT(midi_parser),
+		midi_parser_signals[TEXT_EVENT], 0,
+		meta_type,
+		&node);
+  g_object_unref((GObject *) midi_parser);
+
+  return(node);
+}
+
+AgsMidiParser*
+ags_midi_parser_new(FILE *file)
+{
+  AgsMidiParser *midi_parser;
+  struct stat sb;
+  
+  midi_parser = (AgsMidiParser *) g_object_new(AGS_TYPE_MIDI_PARSER,
+					       "file\0", file,
+					       NULL);
+
+  
+  return(midi_parser);
+}
+
diff --git a/src/midi2ags/midi/ags_midi_parser.h b/src/midi2ags/midi/ags_midi_parser.h
new file mode 100644
index 0000000..ed13452
--- /dev/null
+++ b/src/midi2ags/midi/ags_midi_parser.h
@@ -0,0 +1,152 @@
+/* AGS - Advanced GTK Sequencer
+ * Copyright (C) 2015 Joël Krähemann
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __AGS_MIDI_PARSER_H__
+#define __AGS_MIDI_PARSER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <libxml/tree.h>
+
+#define AGS_TYPE_MIDI_PARSER                (ags_midi_parser_get_type ())
+#define AGS_MIDI_PARSER(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_MIDI_PARSER, AgsMidiParser))
+#define AGS_MIDI_PARSER_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST((class), AGS_TYPE_MIDI_PARSER, AgsMidiParserClass))
+#define AGS_IS_MIDI_PARSER(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_MIDI_PARSER))
+#define AGS_IS_MIDI_PARSER_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_MIDI_PARSER))
+#define AGS_MIDI_PARSER_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), AGS_TYPE_MIDI_PARSER, AgsMidiParserClass))
+
+#define AGS_MIDI_PARSER_MTHD "MThd\0"
+#define AGS_MIDI_PARSER_MTCK "MTrk\0"
+
+typedef struct _AgsMidiParser AgsMidiParser;
+typedef struct _AgsMidiParserClass AgsMidiParserClass;
+
+typedef enum{
+  AGS_MIDI_PARSER_EOF  = 1,
+  AGS_MIDI_PARSER_EOT  = 1 << 1,
+}AgsMidiParserFlags;
+
+typedef enum{
+  AGS_MIDI_CHUNK_HEADER   = 1,
+  AGS_MIDI_CHUNK_TRACK    = 1 << 1,
+  AGS_MIDI_CHUNK_UNKNOWN  = 1 << 2,
+}AgsMidiChunkFlags;
+
+struct _AgsMidiParser
+{
+  GObject gobject;
+
+  guint flags;
+
+  FILE *file;
+  guint nth_chunk;
+
+  size_t file_length;
+  size_t offset;
+
+  guint current_time;
+
+  xmlDoc *doc;
+};
+
+struct _AgsMidiParserClass
+{
+  GObjectClass gobject;
+
+  int (*midi_getc)(AgsMidiParser *midi_parser);
+  void (*on_error)(AgsMidiParser *midi_parser,
+		   GError **error);
+  
+  xmlNode* (*parse_header)(AgsMidiParser *midi_parser);
+  xmlNode* (*parse_track)(AgsMidiParser *midi_parser);
+
+  xmlNode* (*key_on)(AgsMidiParser *midi_parser, guint status);
+  xmlNode* (*key_off)(AgsMidiParser *midi_parser, guint status);
+  xmlNode* (*key_pressure)(AgsMidiParser *midi_parser, guint status);
+
+  xmlNode* (*change_parameter)(AgsMidiParser *midi_parser, guint status);
+  xmlNode* (*change_pitch_bend)(AgsMidiParser *midi_parser, guint status);
+  xmlNode* (*change_program)(AgsMidiParser *midi_parser, guint status);
+  xmlNode* (*change_channel_pressure)(AgsMidiParser *midi_parser, guint status);
+  xmlNode* (*not_defined)(AgsMidiParser *midi_parser, guint status);
+
+  xmlNode* (*sysex)(AgsMidiParser *midi_parser, guint status);
+  xmlNode* (*system_common)(AgsMidiParser *midi_parser, guint status);
+
+  xmlNode* (*meta_event)(AgsMidiParser *midi_parser, guint status);
+  xmlNode* (*sequence_number)(AgsMidiParser *midi_parser, guint meta_type);
+  xmlNode* (*end_of_track)(AgsMidiParser *midi_parser, guint meta_type);
+  xmlNode* (*smpte)(AgsMidiParser *midi_parser, guint meta_type);
+  xmlNode* (*tempo)(AgsMidiParser *midi_parser, guint meta_type);
+  xmlNode* (*time_signature)(AgsMidiParser *midi_parser, guint meta_type);
+  xmlNode* (*key_signature)(AgsMidiParser *midi_parser, guint meta_type);
+  xmlNode* (*sequencer_meta_event)(AgsMidiParser *midi_parser, guint meta_type);
+  xmlNode* (*text_event)(AgsMidiParser *midi_parser, guint meta_type);
+  
+  xmlDoc* (*parse_full)(AgsMidiParser *midi_parser);
+};
+
+GType ags_midi_parser_get_type(void);
+
+gint16 ags_midi_parser_read_gint16(AgsMidiParser *midi_parser);
+gint32 ags_midi_parser_read_gint24(AgsMidiParser *midi_parser);
+gint32 ags_midi_parser_read_gint32(AgsMidiParser *midi_parser);
+long ags_midi_parser_read_varlength(AgsMidiParser *midi_parser);
+gchar* ags_midi_parser_read_text(AgsMidiParser *midi_parser,
+				 gint length);
+
+gdouble ags_midi_parser_ticks_to_sec(AgsMidiParser *midi_parser,
+				     guint ticks, gint division, guint tempo);
+
+int ags_midi_parser_midi_getc(AgsMidiParser *midi_parser);
+void ags_midi_parser_on_error(AgsMidiParser *midi_parser,
+			      GError **error);
+
+xmlDoc* ags_midi_parser_parse_full(AgsMidiParser *midi_parser);
+
+xmlNode* ags_midi_parser_parse_header(AgsMidiParser *midi_parser);
+xmlNode* ags_midi_parser_parse_track(AgsMidiParser *midi_parser);
+
+xmlNode* ags_midi_parser_channel_message(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_key_on(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_key_off(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_key_pressure(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_change_parameter(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_change_pitch_bend(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_change_program(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_change_channel_pressure(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_not_defined(AgsMidiParser *midi_parser, guint status);
+
+xmlNode* ags_midi_parser_sysex(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_system_common(AgsMidiParser *midi_parser, guint status);
+
+xmlNode* ags_midi_parser_meta_event(AgsMidiParser *midi_parser, guint status);
+xmlNode* ags_midi_parser_sequence_number(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_end_of_track(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_smpte(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_tempo(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_time_signature(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_key_signature(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_sequencer_meta_event(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_meta_misc(AgsMidiParser *midi_parser, guint meta_type);
+xmlNode* ags_midi_parser_text_event(AgsMidiParser *midi_parser, guint meta_type);
+
+AgsMidiParser* ags_midi_parser_new(FILE *file);
+
+#endif /*__AGS_MIDI_PARSER_H__*/
diff --git a/src/midi2ags/object/ags_marshal.c b/src/midi2ags/object/ags_marshal.c
new file mode 100644
index 0000000..ab8534a
--- /dev/null
+++ b/src/midi2ags/object/ags_marshal.c
@@ -0,0 +1,164 @@
+
+#include	<glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v)     g_value_get_schar (v)
+#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v)      g_value_get_int (v)
+#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#define g_marshal_value_peek_variant(v)  g_value_get_variant (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_variant(v)  (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* INT:VOID (ags_marshallers.list:1) */
+void
+g_cclosure_user_marshal_INT__VOID (GClosure     *closure,
+                                   GValue       *return_value G_GNUC_UNUSED,
+                                   guint         n_param_values,
+                                   const GValue *param_values,
+                                   gpointer      invocation_hint G_GNUC_UNUSED,
+                                   gpointer      marshal_data)
+{
+  typedef gint (*GMarshalFunc_INT__VOID) (gpointer     data1,
+                                          gpointer     data2);
+  register GMarshalFunc_INT__VOID callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gint v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 1);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_INT__VOID) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       data2);
+
+  g_value_set_int (return_value, v_return);
+}
+
+/* POINTER:VOID (ags_marshallers.list:2) */
+void
+g_cclosure_user_marshal_POINTER__VOID (GClosure     *closure,
+                                       GValue       *return_value G_GNUC_UNUSED,
+                                       guint         n_param_values,
+                                       const GValue *param_values,
+                                       gpointer      invocation_hint G_GNUC_UNUSED,
+                                       gpointer      marshal_data)
+{
+  typedef gpointer (*GMarshalFunc_POINTER__VOID) (gpointer     data1,
+                                                  gpointer     data2);
+  register GMarshalFunc_POINTER__VOID callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gpointer v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 1);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_POINTER__VOID) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       data2);
+
+  g_value_set_pointer (return_value, v_return);
+}
+
+/* POINTER:UINT (ags_marshallers.list:3) */
+void
+g_cclosure_user_marshal_POINTER__UINT (GClosure     *closure,
+                                       GValue       *return_value G_GNUC_UNUSED,
+                                       guint         n_param_values,
+                                       const GValue *param_values,
+                                       gpointer      invocation_hint G_GNUC_UNUSED,
+                                       gpointer      marshal_data)
+{
+  typedef gpointer (*GMarshalFunc_POINTER__UINT) (gpointer     data1,
+                                                  guint        arg_1,
+                                                  gpointer     data2);
+  register GMarshalFunc_POINTER__UINT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gpointer v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 2);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_POINTER__UINT) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_uint (param_values + 1),
+                       data2);
+
+  g_value_set_pointer (return_value, v_return);
+}
+
diff --git a/src/midi2ags/object/ags_marshal.h b/src/midi2ags/object/ags_marshal.h
new file mode 100644
index 0000000..0043dbc
--- /dev/null
+++ b/src/midi2ags/object/ags_marshal.h
@@ -0,0 +1,36 @@
+
+#ifndef __g_cclosure_user_marshal_MARSHAL_H__
+#define __g_cclosure_user_marshal_MARSHAL_H__
+
+#include	<glib-object.h>
+
+G_BEGIN_DECLS
+
+/* INT:VOID (ags_marshallers.list:1) */
+extern void g_cclosure_user_marshal_INT__VOID (GClosure     *closure,
+                                               GValue       *return_value,
+                                               guint         n_param_values,
+                                               const GValue *param_values,
+                                               gpointer      invocation_hint,
+                                               gpointer      marshal_data);
+
+/* POINTER:VOID (ags_marshallers.list:2) */
+extern void g_cclosure_user_marshal_POINTER__VOID (GClosure     *closure,
+                                                   GValue       *return_value,
+                                                   guint         n_param_values,
+                                                   const GValue *param_values,
+                                                   gpointer      invocation_hint,
+                                                   gpointer      marshal_data);
+
+/* POINTER:UINT (ags_marshallers.list:3) */
+extern void g_cclosure_user_marshal_POINTER__UINT (GClosure     *closure,
+                                                   GValue       *return_value,
+                                                   guint         n_param_values,
+                                                   const GValue *param_values,
+                                                   gpointer      invocation_hint,
+                                                   gpointer      marshal_data);
+
+G_END_DECLS
+
+#endif /* __g_cclosure_user_marshal_MARSHAL_H__ */
+

-- 
gsequencer packaging



More information about the pkg-multimedia-commits mailing list