aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/midi_extractor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/midi_extractor.c')
-rw-r--r--src/plugins/midi_extractor.c187
1 files changed, 187 insertions, 0 deletions
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 */