aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-08-22 19:18:55 +0000
committerChristian Grothoff <christian@grothoff.org>2012-08-22 19:18:55 +0000
commit33c16e297af5aad1bd7ee22741c4c2fc347eee5c (patch)
treefbfe88a16c3b27c4a1af4a99371c386c4072ea5e
parent072eeeccc8bc85170b90b36ec9a4fce9cb328f00 (diff)
downloadlibextractor-33c16e297af5aad1bd7ee22741c4c2fc347eee5c.tar.gz
libextractor-33c16e297af5aad1bd7ee22741c4c2fc347eee5c.zip
adding support for MIDI
-rw-r--r--configure.ac19
-rw-r--r--src/plugins/Makefile.am23
-rw-r--r--src/plugins/midi_extractor.c187
-rw-r--r--src/plugins/test_midi.c92
-rw-r--r--src/plugins/testdata/midi_dth.midbin0 -> 97507 bytes
5 files changed, 320 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index 1a6cd7b..13303be 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,6 +22,7 @@ AM_INIT_AUTOMAKE([silent-rules])
22AC_USE_SYSTEM_EXTENSIONS 22AC_USE_SYSTEM_EXTENSIONS
23AC_PROG_AWK 23AC_PROG_AWK
24AC_PROG_CC 24AC_PROG_CC
25AM_PROG_CC_C_O
25AC_PROG_CPP 26AC_PROG_CPP
26AC_PROG_CXX 27AC_PROG_CXX
27AC_CHECK_PROG(HAVE_CXX, $CXX, yes, no) 28AC_CHECK_PROG(HAVE_CXX, $CXX, yes, no)
@@ -423,7 +424,18 @@ else
423 AM_CONDITIONAL(HAVE_GLIB,false) 424 AM_CONDITIONAL(HAVE_GLIB,false)
424 AC_DEFINE(HAVE_GLIB, 0, [Have glib]) 425 AC_DEFINE(HAVE_GLIB, 0, [Have glib])
425fi 426fi
426 427
428# smf requires glib.h
429CFLAGS_OLD=$CFLAGS
430export CFLAGS="$CFLAGS $GLIB_CFLAGS"
431
432AC_CHECK_LIB(smf, smf_load_from_memory,
433 [AC_CHECK_HEADERS([smf.h],
434 AM_CONDITIONAL(HAVE_SMF, true)
435 AC_DEFINE(HAVE_MPEG2,1,[Have libsmf]),
436 AM_CONDITIONAL(HAVE_SMF, false))],
437 AM_CONDITIONAL(HAVE_SMF, false))
438export CFLAGS=$CFLAGS_OLD
427 439
428# check for gtk >= 2.6.0 440# check for gtk >= 2.6.0
429AC_MSG_CHECKING(for gtk) 441AC_MSG_CHECKING(for gtk)
@@ -645,6 +657,11 @@ then
645 AC_MSG_NOTICE([NOTICE: libflac not found, flac support disabled]) 657 AC_MSG_NOTICE([NOTICE: libflac not found, flac support disabled])
646fi 658fi
647 659
660if test "x$HAVE_SMF_TRUE" = "x#"
661then
662 AC_MSG_NOTICE([NOTICE: libsmf not found, midi support disabled])
663fi
664
648if test "x$HAVE_MPEG2_TRUE" = "x#" 665if test "x$HAVE_MPEG2_TRUE" = "x#"
649then 666then
650 AC_MSG_NOTICE([NOTICE: libmpeg2 not found, mpeg2 support disabled]) 667 AC_MSG_NOTICE([NOTICE: libmpeg2 not found, mpeg2 support disabled])
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 77a3614..5be4a22 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -25,6 +25,7 @@ EXTRA_DIST = \
25 testdata/it_dawn.it \ 25 testdata/it_dawn.it \
26 testdata/jpeg_image.jpg \ 26 testdata/jpeg_image.jpg \
27 testdata/man_extract.1 \ 27 testdata/man_extract.1 \
28 testdata/midi_dth.mid \
28 testdata/mpeg_alien.mpg \ 29 testdata/mpeg_alien.mpg \
29 testdata/mpeg_melt.mpg \ 30 testdata/mpeg_melt.mpg \
30 testdata/nsf_arkanoid.nsf \ 31 testdata/nsf_arkanoid.nsf \
@@ -118,6 +119,11 @@ PLUGIN_RPM=libextractor_rpm.la
118TEST_RPM=test_rpm 119TEST_RPM=test_rpm
119endif 120endif
120 121
122if HAVE_SMF
123PLUGIN_MIDI=libextractor_midi.la
124TEST_MIDI=test_midi
125endif
126
121if HAVE_TIFF 127if HAVE_TIFF
122PLUGIN_TIFF=libextractor_tiff.la 128PLUGIN_TIFF=libextractor_tiff.la
123TEST_TIFF=test_tiff 129TEST_TIFF=test_tiff
@@ -159,6 +165,7 @@ plugin_LTLIBRARIES = \
159 $(PLUGIN_GTK) \ 165 $(PLUGIN_GTK) \
160 $(PLUGIN_HTML) \ 166 $(PLUGIN_HTML) \
161 $(PLUGIN_JPEG) \ 167 $(PLUGIN_JPEG) \
168 $(PLUGIN_MIDI) \
162 $(PLUGIN_MIME) \ 169 $(PLUGIN_MIME) \
163 $(PLUGIN_MPEG) \ 170 $(PLUGIN_MPEG) \
164 $(PLUGIN_OGG) \ 171 $(PLUGIN_OGG) \
@@ -195,6 +202,7 @@ check_PROGRAMS = \
195 $(TEST_GTK) \ 202 $(TEST_GTK) \
196 $(TEST_HTML) \ 203 $(TEST_HTML) \
197 $(TEST_JPEG) \ 204 $(TEST_JPEG) \
205 $(TEST_MIDI) \
198 $(TEST_MIME) \ 206 $(TEST_MIME) \
199 $(TEST_MPEG) \ 207 $(TEST_MPEG) \
200 $(TEST_OGG) \ 208 $(TEST_OGG) \
@@ -343,6 +351,21 @@ test_man_LDADD = \
343 $(top_builddir)/src/plugins/libtest.la 351 $(top_builddir)/src/plugins/libtest.la
344 352
345 353
354libextractor_midi_la_SOURCES = \
355 midi_extractor.c
356libextractor_midi_la_CFLAGS = \
357 $(GLIB_CFLAGS)
358libextractor_midi_la_LDFLAGS = \
359 $(PLUGINFLAGS)
360libextractor_midi_la_LIBADD = \
361 -lsmf
362
363test_midi_SOURCES = \
364 test_midi.c
365test_midi_LDADD = \
366 $(top_builddir)/src/plugins/libtest.la
367
368
346libextractor_mime_la_SOURCES = \ 369libextractor_mime_la_SOURCES = \
347 mime_extractor.c 370 mime_extractor.c
348libextractor_mime_la_LDFLAGS = \ 371libextractor_mime_la_LDFLAGS = \
diff --git a/src/plugins/midi_extractor.c b/src/plugins/midi_extractor.c
new file mode 100644
index 0000000..d35b435
--- /dev/null
+++ b/src/plugins/midi_extractor.c
@@ -0,0 +1,187 @@
1/*
2 This file is part of libextractor.
3 (C) 2012 Christian Grothoff
4
5 libextractor is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 libextractor is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with libextractor; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20/**
21 * @file plugins/midi_extractor.c
22 * @brief plugin to support MIDI files
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "extractor.h"
27#include <smf.h>
28
29
30/**
31 * Types of events in MIDI.
32 */
33enum EventType
34 {
35 ET_SEQUENCE_NUMBER = 0,
36 ET_TEXT_EVENT = 1,
37 ET_COPYRIGHT_NOTICE = 2,
38 ET_TRACK_NAME = 3,
39 ET_INSTRUMENT_NAME = 4,
40 ET_LYRIC_TEXT = 5,
41 ET_MARKER_TEXT = 6,
42 ET_CUE_POINT = 7,
43 ET_CHANNEL_PREFIX_ASSIGNMENT = 0x20,
44 ET_END_OF_TRACK = 0x2F,
45 ET_TEMPO_SETTING = 0x51,
46 ET_SMPTE_OFFSET = 0x54,
47 ET_TIME_SIGNATURE = 0x58,
48 ET_KEY_SIGNATURE = 0x59,
49 ET_SEQUENCE_SPECIRFIC_EVENT = 0x7F
50 };
51
52
53/**
54 * Main entry method for the 'audio/midi' extraction plugin.
55 *
56 * @param ec extraction context provided to the plugin
57 */
58void
59EXTRACTOR_midi_extract_method (struct EXTRACTOR_ExtractContext *ec)
60{
61 void *buf;
62 unsigned char *data;
63 uint64_t size;
64 uint64_t off;
65 ssize_t iret;
66 smf_t *m = NULL;
67 smf_event_t *event;
68 uint8_t len;
69
70 if (4 >= (iret = ec->read (ec->cls, &buf, 1024)))
71 return;
72 data = buf;
73 if ( (data[0] != 0x4D) || (data[1] != 0x54) ||
74 (data[2] != 0x68) || (data[3] != 0x64) )
75 return; /* cannot be MIDI */
76 size = ec->get_size (ec->cls);
77 if (size > 16 * 1024 * 1024)
78 return; /* too large */
79 if (NULL == (data = malloc ((size_t) size)))
80 return; /* out of memory */
81 memcpy (data, buf, iret);
82 off = iret;
83 while (off < size)
84 {
85 if (0 >= (iret = ec->read (ec->cls, &buf, 16 * 1024)))
86 {
87 free (data);
88 return;
89 }
90 memcpy (&data[off], buf, iret);
91 off += iret;
92 }
93 if (0 != ec->proc (ec->cls,
94 "midi",
95 EXTRACTOR_METATYPE_MIMETYPE,
96 EXTRACTOR_METAFORMAT_UTF8,
97 "text/plain",
98 "audio/midi",
99 strlen ("audio/midi") + 1))
100 goto CLEANUP;
101 if (NULL == (m = smf_load_from_memory (data, size)))
102 goto CLEANUP;
103 while (NULL != (event = smf_get_next_event (m)))
104 {
105 if (! smf_event_is_metadata (event))
106 break;
107 len = event->midi_buffer[2];
108 if ( (len > 0) &&
109 isspace (event->midi_buffer[2 + len]))
110 len--;
111#if 0
112 fprintf (stderr,
113 "type: %d, len: %d value: %.*s\n",
114 event->midi_buffer[1],
115 event->midi_buffer[2],
116 (int) event->midi_buffer_length - 3,
117 (char *) &event->midi_buffer[3]);
118#endif
119 if (1 != event->track_number)
120 continue; /* heuristic to not get instruments */
121 if (0 == len)
122 continue;
123 switch (event->midi_buffer[1])
124 {
125 case ET_TEXT_EVENT:
126 if (0 != ec->proc (ec->cls,
127 "midi",
128 EXTRACTOR_METATYPE_COMMENT,
129 EXTRACTOR_METAFORMAT_UTF8,
130 "text/plain",
131 (void*) &event->midi_buffer[3],
132 len))
133 goto CLEANUP;
134 break;
135 case ET_COPYRIGHT_NOTICE:
136 if (0 != ec->proc (ec->cls,
137 "midi",
138 EXTRACTOR_METATYPE_COPYRIGHT,
139 EXTRACTOR_METAFORMAT_UTF8,
140 "text/plain",
141 (void*) &event->midi_buffer[3],
142 len))
143 goto CLEANUP;
144 break;
145 case ET_TRACK_NAME:
146 if (0 != ec->proc (ec->cls,
147 "midi",
148 EXTRACTOR_METATYPE_TITLE,
149 EXTRACTOR_METAFORMAT_UTF8,
150 "text/plain",
151 (void*) &event->midi_buffer[3],
152 len))
153 goto CLEANUP;
154 break;
155 case ET_INSTRUMENT_NAME:
156 if (0 != ec->proc (ec->cls,
157 "midi",
158 EXTRACTOR_METATYPE_SOURCE_DEVICE,
159 EXTRACTOR_METAFORMAT_UTF8,
160 "text/plain",
161 (void*) &event->midi_buffer[3],
162 len))
163 goto CLEANUP;
164 break;
165 case ET_LYRIC_TEXT:
166 if (0 != ec->proc (ec->cls,
167 "midi",
168 EXTRACTOR_METATYPE_LYRICS,
169 EXTRACTOR_METAFORMAT_UTF8,
170 "text/plain",
171 (void*) &event->midi_buffer[3],
172 len))
173 goto CLEANUP;
174 break;
175 default:
176 break;
177 }
178 }
179
180 CLEANUP:
181 if (NULL != m)
182 smf_delete (m);
183 free (data);
184}
185
186
187/* end of midi_extractor.c */
diff --git a/src/plugins/test_midi.c b/src/plugins/test_midi.c
new file mode 100644
index 0000000..ffe9ebf
--- /dev/null
+++ b/src/plugins/test_midi.c
@@ -0,0 +1,92 @@
1/*
2 This file is part of libextractor.
3 (C) 2012 Vidyut Samanta and Christian Grothoff
4
5 libextractor is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 libextractor is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with libextractor; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file plugins/test_midi.c
22 * @brief testcase for midi plugin
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "test_lib.h"
27
28
29/**
30 * Main function for the MIDI testcase.
31 *
32 * @param argc number of arguments (ignored)
33 * @param argv arguments (ignored)
34 * @return 0 on success
35 */
36int
37main (int argc, char *argv[])
38{
39 struct SolutionData midi_dth_sol[] =
40 {
41 {
42 EXTRACTOR_METATYPE_MIMETYPE,
43 EXTRACTOR_METAFORMAT_UTF8,
44 "text/plain",
45 "audio/midi",
46 strlen ("audio/midi") + 1,
47 0
48 },
49 {
50 EXTRACTOR_METATYPE_COPYRIGHT,
51 EXTRACTOR_METAFORMAT_UTF8,
52 "text/plain",
53 "(c) 2012 d-o-o",
54 strlen ("(c) 2012 d-o-o"),
55 0
56 },
57 {
58 EXTRACTOR_METATYPE_TITLE,
59 EXTRACTOR_METAFORMAT_UTF8,
60 "text/plain",
61 "Tage wie diese T2",
62 strlen ("Tage wie diese T2"),
63 0
64 },
65 {
66 EXTRACTOR_METATYPE_COMMENT,
67 EXTRACTOR_METAFORMAT_UTF8,
68 "text/plain",
69 "XFhd:::Rock:8 Beat:1:m1:-:-:-:-:DD",
70 strlen ("XFhd:::Rock:8 Beat:1:m1:-:-:-:-:DD"),
71 0
72 },
73 {
74 EXTRACTOR_METATYPE_COMMENT,
75 EXTRACTOR_METAFORMAT_UTF8,
76 "text/plain",
77 "XFln:L1:Tage wie diese:von Holst:von Holst:-:Toten Hosen:DD",
78 strlen ("XFln:L1:Tage wie diese:von Holst:von Holst:-:Toten Hosen:DD"),
79 0
80 },
81 { 0, 0, NULL, NULL, 0, -1 }
82 };
83 struct ProblemSet ps[] =
84 {
85 { "testdata/midi_dth.mid",
86 midi_dth_sol },
87 { NULL, NULL }
88 };
89 return ET_main ("midi", ps);
90}
91
92/* end of test_midi.c */
diff --git a/src/plugins/testdata/midi_dth.mid b/src/plugins/testdata/midi_dth.mid
new file mode 100644
index 0000000..c1da1db
--- /dev/null
+++ b/src/plugins/testdata/midi_dth.mid
Binary files differ