44 files changed, 2696 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..204d437 --- a/dev/null +++ b/.gitignore | |||
@@ -0,0 +1,22 @@ | |||
1 | configure | ||
2 | Makefile.in | ||
3 | Doxyfile | ||
4 | config.log | ||
5 | depcomp | ||
6 | config.guess | ||
7 | config.h | ||
8 | ltmain.sh | ||
9 | config.sub | ||
10 | INSTALL | ||
11 | NEWS | ||
12 | Makefile | ||
13 | config.status | ||
14 | midillo.pc | ||
15 | stamp-h1 | ||
16 | config.h.in | ||
17 | libtool | ||
18 | autom4te.cache | ||
19 | missing | ||
20 | aclocal.m4 | ||
21 | install-sh | ||
22 | doxydox | ||
@@ -0,0 +1,3 @@ | |||
1 | Klever dissected: | ||
2 | Michael 'hacker' Krelin <hacker@klever.net> | ||
3 | Leonid Ivanov <kamel@klever.net> | ||
@@ -0,0 +1,19 @@ | |||
1 | Copyright (c) 2006 Klever Group (http://www.klever.net/) | ||
2 | |||
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
4 | this software and associated documentation files (the "Software"), to deal in | ||
5 | the Software without restriction, including without limitation the rights to | ||
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | ||
7 | of the Software, and to permit persons to whom the Software is furnished to do | ||
8 | so, subject to the following conditions: | ||
9 | |||
10 | The above copyright notice and this permission notice shall be included in all | ||
11 | copies or substantial portions of the Software. | ||
12 | |||
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
19 | SOFTWARE. | ||
diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 --- a/dev/null +++ b/ChangeLog | |||
diff --git a/Doxyfile.in b/Doxyfile.in new file mode 100644 index 0000000..95552d7 --- a/dev/null +++ b/Doxyfile.in | |||
@@ -0,0 +1,247 @@ | |||
1 | # Doxyfile 1.3.9.1 | ||
2 | |||
3 | #--------------------------------------------------------------------------- | ||
4 | # Project related configuration options | ||
5 | #--------------------------------------------------------------------------- | ||
6 | PROJECT_NAME = @PACKAGE@ | ||
7 | PROJECT_NUMBER = @VERSION@ | ||
8 | OUTPUT_DIRECTORY = @builddir@/doxydox | ||
9 | CREATE_SUBDIRS = NO | ||
10 | OUTPUT_LANGUAGE = English | ||
11 | USE_WINDOWS_ENCODING = NO | ||
12 | BRIEF_MEMBER_DESC = YES | ||
13 | REPEAT_BRIEF = YES | ||
14 | ABBREVIATE_BRIEF = | ||
15 | ALWAYS_DETAILED_SEC = NO | ||
16 | INLINE_INHERITED_MEMB = NO | ||
17 | FULL_PATH_NAMES = YES | ||
18 | STRIP_FROM_PATH = include | ||
19 | STRIP_FROM_INC_PATH = include | ||
20 | SHORT_NAMES = NO | ||
21 | JAVADOC_AUTOBRIEF = NO | ||
22 | MULTILINE_CPP_IS_BRIEF = NO | ||
23 | DETAILS_AT_TOP = NO | ||
24 | INHERIT_DOCS = YES | ||
25 | DISTRIBUTE_GROUP_DOC = NO | ||
26 | TAB_SIZE = 8 | ||
27 | ALIASES = | ||
28 | OPTIMIZE_OUTPUT_FOR_C = NO | ||
29 | OPTIMIZE_OUTPUT_JAVA = NO | ||
30 | SUBGROUPING = YES | ||
31 | |||
32 | #--------------------------------------------------------------------------- | ||
33 | # Build related configuration options | ||
34 | #--------------------------------------------------------------------------- | ||
35 | |||
36 | EXTRACT_ALL = NO | ||
37 | EXTRACT_PRIVATE = NO | ||
38 | EXTRACT_STATIC = NO | ||
39 | EXTRACT_LOCAL_CLASSES = YES | ||
40 | EXTRACT_LOCAL_METHODS = NO | ||
41 | HIDE_UNDOC_MEMBERS = NO | ||
42 | HIDE_UNDOC_CLASSES = NO | ||
43 | HIDE_FRIEND_COMPOUNDS = NO | ||
44 | HIDE_IN_BODY_DOCS = NO | ||
45 | INTERNAL_DOCS = NO | ||
46 | CASE_SENSE_NAMES = YES | ||
47 | HIDE_SCOPE_NAMES = NO | ||
48 | SHOW_INCLUDE_FILES = NO | ||
49 | INLINE_INFO = YES | ||
50 | SORT_MEMBER_DOCS = YES | ||
51 | SORT_BRIEF_DOCS = NO | ||
52 | SORT_BY_SCOPE_NAME = YES | ||
53 | GENERATE_TODOLIST = YES | ||
54 | GENERATE_TESTLIST = YES | ||
55 | GENERATE_BUGLIST = YES | ||
56 | GENERATE_DEPRECATEDLIST= YES | ||
57 | ENABLED_SECTIONS = | ||
58 | MAX_INITIALIZER_LINES = 30 | ||
59 | SHOW_USED_FILES = NO | ||
60 | SHOW_DIRECTORIES = YES | ||
61 | |||
62 | #--------------------------------------------------------------------------- | ||
63 | # configuration options related to warning and progress messages | ||
64 | #--------------------------------------------------------------------------- | ||
65 | |||
66 | QUIET = NO | ||
67 | WARNINGS = YES | ||
68 | WARN_IF_UNDOCUMENTED = YES | ||
69 | WARN_IF_DOC_ERROR = YES | ||
70 | WARN_FORMAT = "$file:$line: $text" | ||
71 | WARN_LOGFILE = | ||
72 | |||
73 | #--------------------------------------------------------------------------- | ||
74 | # configuration options related to the input files | ||
75 | #--------------------------------------------------------------------------- | ||
76 | |||
77 | INPUT = \ | ||
78 | @srcdir@/include/midillo/ | ||
79 | FILE_PATTERNS = *.h | ||
80 | RECURSIVE = NO | ||
81 | EXCLUDE = | ||
82 | EXCLUDE_SYMLINKS = NO | ||
83 | EXCLUDE_PATTERNS = | ||
84 | EXAMPLE_PATH = | ||
85 | EXAMPLE_PATTERNS = | ||
86 | EXAMPLE_RECURSIVE = NO | ||
87 | IMAGE_PATH = | ||
88 | INPUT_FILTER = | ||
89 | FILTER_PATTERNS = | ||
90 | FILTER_SOURCE_FILES = NO | ||
91 | |||
92 | #--------------------------------------------------------------------------- | ||
93 | # configuration options related to source browsing | ||
94 | #--------------------------------------------------------------------------- | ||
95 | |||
96 | SOURCE_BROWSER = NO | ||
97 | INLINE_SOURCES = NO | ||
98 | STRIP_CODE_COMMENTS = YES | ||
99 | REFERENCED_BY_RELATION = YES | ||
100 | REFERENCES_RELATION = YES | ||
101 | VERBATIM_HEADERS = YES | ||
102 | |||
103 | #--------------------------------------------------------------------------- | ||
104 | # configuration options related to the alphabetical class index | ||
105 | #--------------------------------------------------------------------------- | ||
106 | |||
107 | ALPHABETICAL_INDEX = YES | ||
108 | COLS_IN_ALPHA_INDEX = 2 | ||
109 | IGNORE_PREFIX = | ||
110 | |||
111 | #--------------------------------------------------------------------------- | ||
112 | # configuration options related to the HTML output | ||
113 | #--------------------------------------------------------------------------- | ||
114 | |||
115 | GENERATE_HTML = YES | ||
116 | HTML_OUTPUT = html | ||
117 | HTML_FILE_EXTENSION = .html | ||
118 | HTML_HEADER = | ||
119 | HTML_FOOTER = | ||
120 | HTML_STYLESHEET = | ||
121 | HTML_ALIGN_MEMBERS = YES | ||
122 | GENERATE_HTMLHELP = NO | ||
123 | CHM_FILE = | ||
124 | HHC_LOCATION = | ||
125 | GENERATE_CHI = NO | ||
126 | BINARY_TOC = NO | ||
127 | TOC_EXPAND = NO | ||
128 | DISABLE_INDEX = NO | ||
129 | ENUM_VALUES_PER_LINE = 4 | ||
130 | GENERATE_TREEVIEW = NO | ||
131 | TREEVIEW_WIDTH = 250 | ||
132 | |||
133 | #--------------------------------------------------------------------------- | ||
134 | # configuration options related to the LaTeX output | ||
135 | #--------------------------------------------------------------------------- | ||
136 | |||
137 | GENERATE_LATEX = NO | ||
138 | LATEX_OUTPUT = latex | ||
139 | LATEX_CMD_NAME = latex | ||
140 | MAKEINDEX_CMD_NAME = makeindex | ||
141 | COMPACT_LATEX = NO | ||
142 | PAPER_TYPE = a4wide | ||
143 | EXTRA_PACKAGES = | ||
144 | LATEX_HEADER = | ||
145 | PDF_HYPERLINKS = NO | ||
146 | USE_PDFLATEX = NO | ||
147 | LATEX_BATCHMODE = NO | ||
148 | LATEX_HIDE_INDICES = NO | ||
149 | |||
150 | #--------------------------------------------------------------------------- | ||
151 | # configuration options related to the RTF output | ||
152 | #--------------------------------------------------------------------------- | ||
153 | |||
154 | GENERATE_RTF = NO | ||
155 | RTF_OUTPUT = rtf | ||
156 | COMPACT_RTF = NO | ||
157 | RTF_HYPERLINKS = NO | ||
158 | RTF_STYLESHEET_FILE = | ||
159 | RTF_EXTENSIONS_FILE = | ||
160 | |||
161 | #--------------------------------------------------------------------------- | ||
162 | # configuration options related to the man page output | ||
163 | #--------------------------------------------------------------------------- | ||
164 | |||
165 | GENERATE_MAN = NO | ||
166 | MAN_OUTPUT = man | ||
167 | MAN_EXTENSION = .3 | ||
168 | MAN_LINKS = YES | ||
169 | |||
170 | #--------------------------------------------------------------------------- | ||
171 | # configuration options related to the XML output | ||
172 | #--------------------------------------------------------------------------- | ||
173 | |||
174 | GENERATE_XML = YES | ||
175 | XML_OUTPUT = xml | ||
176 | XML_SCHEMA = | ||
177 | XML_DTD = | ||
178 | XML_PROGRAMLISTING = YES | ||
179 | |||
180 | #--------------------------------------------------------------------------- | ||
181 | # configuration options for the AutoGen Definitions output | ||
182 | #--------------------------------------------------------------------------- | ||
183 | |||
184 | GENERATE_AUTOGEN_DEF = NO | ||
185 | |||
186 | #--------------------------------------------------------------------------- | ||
187 | # configuration options related to the Perl module output | ||
188 | #--------------------------------------------------------------------------- | ||
189 | |||
190 | GENERATE_PERLMOD = NO | ||
191 | PERLMOD_LATEX = NO | ||
192 | PERLMOD_PRETTY = YES | ||
193 | PERLMOD_MAKEVAR_PREFIX = | ||
194 | |||
195 | #--------------------------------------------------------------------------- | ||
196 | # Configuration options related to the preprocessor | ||
197 | #--------------------------------------------------------------------------- | ||
198 | |||
199 | ENABLE_PREPROCESSING = YES | ||
200 | MACRO_EXPANSION = NO | ||
201 | EXPAND_ONLY_PREDEF = NO | ||
202 | SEARCH_INCLUDES = YES | ||
203 | INCLUDE_PATH = | ||
204 | INCLUDE_FILE_PATTERNS = | ||
205 | PREDEFINED = | ||
206 | EXPAND_AS_DEFINED = | ||
207 | SKIP_FUNCTION_MACROS = YES | ||
208 | |||
209 | #--------------------------------------------------------------------------- | ||
210 | # Configuration::additions related to external references | ||
211 | #--------------------------------------------------------------------------- | ||
212 | |||
213 | TAGFILES = | ||
214 | GENERATE_TAGFILE = | ||
215 | ALLEXTERNALS = NO | ||
216 | EXTERNAL_GROUPS = YES | ||
217 | PERL_PATH = /usr/bin/perl | ||
218 | |||
219 | #--------------------------------------------------------------------------- | ||
220 | # Configuration options related to the dot tool | ||
221 | #--------------------------------------------------------------------------- | ||
222 | |||
223 | CLASS_DIAGRAMS = YES | ||
224 | HIDE_UNDOC_RELATIONS = YES | ||
225 | HAVE_DOT = @HAVE_DOT@ | ||
226 | CLASS_GRAPH = YES | ||
227 | COLLABORATION_GRAPH = YES | ||
228 | UML_LOOK = NO | ||
229 | TEMPLATE_RELATIONS = YES | ||
230 | INCLUDE_GRAPH = YES | ||
231 | INCLUDED_BY_GRAPH = YES | ||
232 | CALL_GRAPH = NO | ||
233 | GRAPHICAL_HIERARCHY = YES | ||
234 | DOT_IMAGE_FORMAT = png | ||
235 | DOT_PATH = @DOT@ | ||
236 | DOTFILE_DIRS = | ||
237 | MAX_DOT_GRAPH_WIDTH = 1024 | ||
238 | MAX_DOT_GRAPH_HEIGHT = 1024 | ||
239 | MAX_DOT_GRAPH_DEPTH = 0 | ||
240 | GENERATE_LEGEND = YES | ||
241 | DOT_CLEANUP = YES | ||
242 | |||
243 | #--------------------------------------------------------------------------- | ||
244 | # Configuration::additions related to the search engine | ||
245 | #--------------------------------------------------------------------------- | ||
246 | |||
247 | SEARCHENGINE = NO | ||
diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..5a2a2c7 --- a/dev/null +++ b/Makefile.am | |||
@@ -0,0 +1,22 @@ | |||
1 | SUBDIRS=include lib tools man | ||
2 | EXTRA_DIST= NEWS NEWS.xml NEWS.xsl | ||
3 | |||
4 | DISTCHECK_CONFIGURE_FLAGS=--with-pkgconfigdir=$${dc_install_base}/lib/pkgconfig | ||
5 | if HAVE_PKGCONFIG | ||
6 | pkgconfigdir=@PKGCONFIG_DIR@ | ||
7 | pkgconfig_DATA=midillo.pc | ||
8 | endif | ||
9 | |||
10 | all-local: NEWS | ||
11 | if HAVE_DOXYGEN | ||
12 | clean-local: | ||
13 | rm -rf doxydox | ||
14 | endif | ||
15 | |||
16 | NEWS: NEWS.xsl NEWS.xml | ||
17 | ${XSLTPROC} -o $@ NEWS.xsl NEWS.xml | ||
18 | |||
19 | if HAVE_DOXYGEN | ||
20 | dox: | ||
21 | ${DOXYGEN} | ||
22 | endif | ||
diff --git a/NEWS.xml b/NEWS.xml new file mode 100644 index 0000000..f30ed3b --- a/dev/null +++ b/NEWS.xml | |||
@@ -0,0 +1,6 @@ | |||
1 | <?xml version="1.0" encoding="us-ascii"?> | ||
2 | <news> | ||
3 | <version version="0.0" date="August 1st, 2006"> | ||
4 | <ni>Initial release</ni> | ||
5 | </version> | ||
6 | </news> | ||
diff --git a/NEWS.xsl b/NEWS.xsl new file mode 100644 index 0000000..7c71307 --- a/dev/null +++ b/NEWS.xsl | |||
@@ -0,0 +1,24 @@ | |||
1 | <?xml version="1.0" encoding="us-ascii"?> | ||
2 | <xsl:stylesheet version="1.0" | ||
3 | xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | ||
4 | > | ||
5 | <xsl:output | ||
6 | method="text" | ||
7 | encoding="us-ascii" | ||
8 | media-type="text/plain" /> | ||
9 | |||
10 | <xsl:template match="news"> | ||
11 | <xsl:apply-templates/> | ||
12 | </xsl:template> | ||
13 | <xsl:template match="version"> | ||
14 | <xsl:value-of select="concat(@version,' (',@date,')
')"/> | ||
15 | <xsl:apply-templates/> | ||
16 | </xsl:template> | ||
17 | <xsl:template match="ni"> | ||
18 | <xsl:text> - </xsl:text> | ||
19 | <xsl:apply-templates mode="text"/> | ||
20 | <xsl:text>
</xsl:text> | ||
21 | </xsl:template> | ||
22 | <xsl:template match="*|text()"/> | ||
23 | |||
24 | </xsl:stylesheet> | ||
diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..ec2c50f --- a/dev/null +++ b/acinclude.m4 | |||
@@ -0,0 +1,80 @@ | |||
1 | dnl AC_WITH_PKGCONFIG([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]]) | ||
2 | dnl Outputs: | ||
3 | dnl AC_SUBST: PKGCONFIG_PKGCONFIG PKGCONFIG_DIR | ||
4 | dnl AM_CONDTIONAL: HAVE_PKGCONFIG | ||
5 | AC_DEFUN([AC_WITH_PKGCONFIG],[ | ||
6 | PKGCONFIG_PKGCONFIG="" | ||
7 | PKGCONFIG_DIR="" | ||
8 | HAVE_PKGCONFIG="no" | ||
9 | EXPLICIT_PKGCONFIGDIR="no" | ||
10 | test -z "${WANT_PKGCONFIG}" && WANT_PKGCONFIG="" | ||
11 | AC_PATH_PROG([PKGCONFIG_PKGCONFIG],[pkg-config],[false]) | ||
12 | if test "${PKGCONFIG_PKGCONFIG}" != "false" ; then | ||
13 | AC_ARG_WITH([pkgconfigdir], | ||
14 | AC_HELP_STRING([--with-pkgconfigdir=dir],[Specify pkgconfig directory]), | ||
15 | [ | ||
16 | if test "${withval}" = "no" ; then | ||
17 | WANT_PKGCONFIG="no" | ||
18 | else | ||
19 | PKGCONFIG_DIR="${withval}" | ||
20 | EXPLICIT_PKGCONFIGDIR="yes" | ||
21 | fi | ||
22 | ],[ | ||
23 | AC_MSG_CHECKING([for pkgconfig directory]) | ||
24 | PKGCONFIG_DIR="`${PKGCONFIG_PKGCONFIG} --debug 2>&1 | grep '^Scanning'| head -n 1 | cut -d\' -f2-|cut -d\' -f1`" | ||
25 | AC_MSG_RESULT([${PKGCONFIG_DIR}]) | ||
26 | ] | ||
27 | ) | ||
28 | if test -d "${PKGCONFIG_DIR}" ; then | ||
29 | HAVE_PKGCONFIG=yes | ||
30 | AC_SUBST([PKGCONFIG_PKGCONFIG]) | ||
31 | AC_SUBST([PKGCONFIG_DIR]) | ||
32 | else | ||
33 | AC_MSG_NOTICE([unexistent pkgconfig directory: ${PKGCONFIG_DIR}]) | ||
34 | if test "${EXPLICIT_PKGCONFIGDIR}" = "yes" ; then | ||
35 | HAVE_PKGCONFIG=yes | ||
36 | AC_SUBST([PKGCONFIG_PKGCONFIG]) | ||
37 | AC_SUBST([PKGCONFIG_DIR]) | ||
38 | else | ||
39 | ifelse([$2], , :, [$2]) | ||
40 | fi | ||
41 | fi | ||
42 | fi | ||
43 | AM_CONDITIONAL([HAVE_PKGCONFIG],[test "${HAVE_PKGCONFIG}" = "yes"]) | ||
44 | ]) | ||
45 | |||
46 | dnl AC_WITH_DOXYGEN([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]]) | ||
47 | dnl Outputs: | ||
48 | dnl AC_SUBST: DOXYGEN HAVE_DOXYGEN | ||
49 | dnl AM_CONDTIONAL: HAVE_DOXYGEN | ||
50 | AC_DEFUN([AC_WITH_DOXYGEN],[ | ||
51 | HAVE_DOXYGEN="no" | ||
52 | AC_PATH_PROG([DOXYGEN],[doxygen],[false]) | ||
53 | if test "${DOXYGEN}" = "false" ; then | ||
54 | ifelse([$2], , :, [$2]) | ||
55 | else | ||
56 | HAVE_DOXYGEN="yes" | ||
57 | AC_SUBST([DOXYGEN]) | ||
58 | $1 | ||
59 | fi | ||
60 | AC_SUBST([HAVE_DOXYGEN]) | ||
61 | AM_CONDITIONAL([HAVE_DOXYGEN],[test "${HAVE_DOXYGEN}" = "yes"]) | ||
62 | ]) | ||
63 | |||
64 | dnl AC_WITH_DOT([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]]) | ||
65 | dnl Outputs: | ||
66 | dnl AC_SUBST: DOT HAVE_DOT | ||
67 | dnl AM_CONDITIONAL: HAVE_DOT | ||
68 | AC_DEFUN([AC_WITH_DOT],[ | ||
69 | HAVE_DOT="no" | ||
70 | AC_PATH_PROG([DOT],[dot],[false]) | ||
71 | if test "${DOT}" = "false" ; then | ||
72 | ifelse([$2], , :, [$2]) | ||
73 | else | ||
74 | HAVE_DOT="yes" | ||
75 | AC_SUBST([DOT]) | ||
76 | $1 | ||
77 | fi | ||
78 | AC_SUBST([HAVE_DOT]) | ||
79 | AM_CONDITIONAL([HAVE_DOT],[test "${HAVE_DOT}" = "yes"]) | ||
80 | ]) | ||
diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..ba27501 --- a/dev/null +++ b/autogen.sh | |||
@@ -0,0 +1,9 @@ | |||
1 | #!/bin/sh | ||
2 | WANT_AUTOMAKE=1.8 | ||
3 | export WANT_AUTOMAKE | ||
4 | libtoolize -f \ | ||
5 | && aclocal \ | ||
6 | && autoheader \ | ||
7 | && automake -a \ | ||
8 | && autoconf \ | ||
9 | && ./configure "$@" | ||
diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..040b9cf --- a/dev/null +++ b/configure.ac | |||
@@ -0,0 +1,55 @@ | |||
1 | AC_INIT([midillo], [0.0], [midillo-bugs@klever.net]) | ||
2 | AC_CONFIG_SRCDIR([include/midillo/SMF.h]) | ||
3 | AC_CONFIG_HEADERS([config.h]) | ||
4 | AM_INIT_AUTOMAKE([dist-bzip2]) | ||
5 | |||
6 | AC_PROG_INSTALL | ||
7 | AC_PROG_AWK | ||
8 | AC_PROG_CXX | ||
9 | AC_PROG_CC | ||
10 | AC_PROG_LIBTOOL | ||
11 | |||
12 | AC_HEADER_STDC | ||
13 | AC_CHECK_HEADERS([sys/types.h sys/stat.h]) | ||
14 | AC_CHECK_DECLS([environ],,,[ | ||
15 | #include <unistd.h> | ||
16 | ]) | ||
17 | |||
18 | AC_C_CONST | ||
19 | |||
20 | AC_FUNC_MALLOC | ||
21 | AC_FUNC_REALLOC | ||
22 | |||
23 | AC_PATH_PROG([XSLTPROC],[xsltproc],[true]) | ||
24 | |||
25 | AC_WITH_PKGCONFIG | ||
26 | |||
27 | PKG_CHECK_MODULES([KONFORKA],[konforka],,[ | ||
28 | AC_MSG_ERROR([no konforka library found. get one from http://kin.klever.net/konforka/]) | ||
29 | ]) | ||
30 | |||
31 | WANT_DOXYGEN="yes" | ||
32 | AC_ARG_ENABLE([doxygen], | ||
33 | AC_HELP_STRING([--disable-doxygen],[do not generate documentation]), | ||
34 | [ | ||
35 | test "${enableval}" = "no" && WANT_DOXYGEN="no" | ||
36 | ] | ||
37 | ) | ||
38 | if test "${WANT_DOXYGEN}" = "yes" ; then | ||
39 | AC_WITH_DOXYGEN | ||
40 | AC_WITH_DOT | ||
41 | else | ||
42 | AM_CONDITIONAL([HAVE_DOXYGEN],[false]) | ||
43 | AM_CONDITIONAL([HAVE_DOT],[false]) | ||
44 | fi | ||
45 | |||
46 | AC_CONFIG_FILES([ | ||
47 | Makefile | ||
48 | midillo.pc | ||
49 | Doxyfile | ||
50 | include/Makefile | ||
51 | lib/Makefile | ||
52 | tools/Makefile | ||
53 | man/Makefile | ||
54 | ]) | ||
55 | AC_OUTPUT | ||
diff --git a/include/.gitignore b/include/.gitignore new file mode 100644 index 0000000..282522d --- a/dev/null +++ b/include/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | Makefile | ||
2 | Makefile.in | ||
diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..edfb186 --- a/dev/null +++ b/include/Makefile.am | |||
@@ -0,0 +1,5 @@ | |||
1 | nobase_include_HEADERS = \ | ||
2 | midillo/util.h midillo/exception.h \ | ||
3 | midillo/SMF.h \ | ||
4 | midillo/chunk.h midillo/MTrk.h midillo/MThd.h \ | ||
5 | midillo/event.h midillo/message.h | ||
diff --git a/include/midillo/MThd.h b/include/midillo/MThd.h new file mode 100644 index 0000000..20263cd --- a/dev/null +++ b/include/midillo/MThd.h | |||
@@ -0,0 +1,74 @@ | |||
1 | #ifndef __MIDILLO_MTHD_H | ||
2 | #define __MIDILLO_MTHD_H | ||
3 | |||
4 | #include <istream> | ||
5 | #include <ostream> | ||
6 | #include <midillo/chunk.h> | ||
7 | |||
8 | /** | ||
9 | * @file | ||
10 | * @brief the MThd_t -- MThd header chunk class | ||
11 | */ | ||
12 | |||
13 | namespace midillo { | ||
14 | using std::istream; | ||
15 | using std::ostream; | ||
16 | |||
17 | /** | ||
18 | * MThd header chunk container | ||
19 | */ | ||
20 | class MThd_t : public chunk_t { | ||
21 | public: | ||
22 | enum { | ||
23 | fmt_0 = 0, fmt_1 = 1, fmt_2 = 2, | ||
24 | fmt_singletrack = fmt_0, | ||
25 | fmt_multitrack = fmt_1, | ||
26 | fmt_tracksequence = fmt_2 | ||
27 | }; | ||
28 | /** | ||
29 | * SMF format. 0 for single track, 1 for multitrack, 2 for track | ||
30 | * sequence. | ||
31 | */ | ||
32 | int fmt; | ||
33 | /** | ||
34 | * Number of tracks in the file | ||
35 | */ | ||
36 | int ntracks; | ||
37 | /** | ||
38 | * The number of pulses per quarter note | ||
39 | */ | ||
40 | int division; | ||
41 | |||
42 | /** | ||
43 | * Load MThd chunk from the stream | ||
44 | * @param s input stream | ||
45 | */ | ||
46 | void load(istream& s); | ||
47 | |||
48 | /** | ||
49 | * Read MThd chunk data from the stream. This function assumes that | ||
50 | * header is already read. | ||
51 | * @param s input stream | ||
52 | */ | ||
53 | void load_data(istream& s); | ||
54 | |||
55 | /** | ||
56 | * Save MThd chunk to the stream | ||
57 | * @param s output stream | ||
58 | */ | ||
59 | void save(ostream& s) const; | ||
60 | |||
61 | /** | ||
62 | * Dump textual representation of MThd chunk to stream | ||
63 | * @param s output stream | ||
64 | */ | ||
65 | void dump(ostream& s) const; | ||
66 | }; | ||
67 | |||
68 | inline ostream& operator<<(ostream& s,const MThd_t& mthd) { | ||
69 | mthd.dump(s); return s; | ||
70 | } | ||
71 | |||
72 | } | ||
73 | |||
74 | #endif /* MIDILLO_MTHD_H */ | ||
diff --git a/include/midillo/MTrk.h b/include/midillo/MTrk.h new file mode 100644 index 0000000..0884388 --- a/dev/null +++ b/include/midillo/MTrk.h | |||
@@ -0,0 +1,54 @@ | |||
1 | #ifndef __MIDILLO_MTRK_H | ||
2 | #define __MIDILLO_MTRK_H | ||
3 | |||
4 | #include <istream> | ||
5 | #include <ostream> | ||
6 | #include <list> | ||
7 | #include <midillo/chunk.h> | ||
8 | #include <midillo/event.h> | ||
9 | |||
10 | /** | ||
11 | * @file | ||
12 | * @brief MTrk -- track chunk container | ||
13 | */ | ||
14 | |||
15 | namespace midillo { | ||
16 | using std::istream; | ||
17 | using std::ostream; | ||
18 | |||
19 | /** | ||
20 | * MTrk track chunk container class | ||
21 | */ | ||
22 | class MTrk_t : public chunk_t { | ||
23 | public: | ||
24 | /** | ||
25 | * MIDI events contained in the track | ||
26 | */ | ||
27 | events_t events; | ||
28 | |||
29 | /** | ||
30 | * Load MTrk chunk from the stream | ||
31 | * @param s input stream | ||
32 | */ | ||
33 | void load(istream& s); | ||
34 | |||
35 | /** | ||
36 | * Save MTrk chunk to the stream | ||
37 | * @param s output stream | ||
38 | */ | ||
39 | void save(ostream& s) const; | ||
40 | |||
41 | /** | ||
42 | * Dump textual representation of MTrk chunk to stream | ||
43 | * @param s output stream | ||
44 | */ | ||
45 | void dump(ostream& s) const; | ||
46 | }; | ||
47 | |||
48 | inline ostream& operator<<(ostream& s,const MTrk_t& mtrk) { | ||
49 | mtrk.dump(s); return s; | ||
50 | } | ||
51 | |||
52 | } | ||
53 | |||
54 | #endif /* __MIDILLO_MTRK_H */ | ||
diff --git a/include/midillo/SMF.h b/include/midillo/SMF.h new file mode 100644 index 0000000..bec9f7a --- a/dev/null +++ b/include/midillo/SMF.h | |||
@@ -0,0 +1,87 @@ | |||
1 | #ifndef __MIDILLO_SMF_H | ||
2 | #define __MIDILLO_SMF_H | ||
3 | |||
4 | #include <istream> | ||
5 | #include <ostream> | ||
6 | #include <list> | ||
7 | #include <midillo/MThd.h> | ||
8 | #include <midillo/MTrk.h> | ||
9 | |||
10 | /** | ||
11 | * @file | ||
12 | * @brief the SMF_t -- standard midi file | ||
13 | */ | ||
14 | |||
15 | namespace midillo { | ||
16 | using std::istream; | ||
17 | using std::vector; | ||
18 | using std::ostream; | ||
19 | |||
20 | /** | ||
21 | * Standard midi file object | ||
22 | */ | ||
23 | class SMF_t { | ||
24 | public: | ||
25 | /** | ||
26 | * MThd header chunk | ||
27 | */ | ||
28 | MThd_t mthd; | ||
29 | /** | ||
30 | * The type for collection of MTrk track chunks | ||
31 | */ | ||
32 | typedef list<MTrk_t> tracks_t; | ||
33 | /** | ||
34 | * MTrk track chunks collection for the file | ||
35 | */ | ||
36 | tracks_t tracks; | ||
37 | |||
38 | SMF_t() { } | ||
39 | /** | ||
40 | * Construct object from the file | ||
41 | * @see load(const char *f,bool stdinable) | ||
42 | */ | ||
43 | SMF_t(const char *f,bool stdinable=true) { load(f,stdinable); } | ||
44 | /** | ||
45 | * Construct object from the stream | ||
46 | * @see load(istream& s) | ||
47 | */ | ||
48 | SMF_t(istream& s) { load(s); } | ||
49 | |||
50 | /** | ||
51 | * Load MIDI data from the file | ||
52 | * @param f filename | ||
53 | * @param stdinable true if '-' is treatead as cin input stream | ||
54 | */ | ||
55 | void load(const char *f,bool stdinable=true); | ||
56 | /** | ||
57 | * Load midi data from the stream | ||
58 | * @param s input stream | ||
59 | */ | ||
60 | void load(istream& s); | ||
61 | |||
62 | /** | ||
63 | * Save MIDI data to the file | ||
64 | * @param f filename | ||
65 | * @param stdoutable true if '-' is treated as cout output stream | ||
66 | */ | ||
67 | void save(const char *f,bool stdoutable=true) const; | ||
68 | /** | ||
69 | * Save MIDI data to the stream | ||
70 | * @param s output stream | ||
71 | */ | ||
72 | void save(ostream& s) const; | ||
73 | |||
74 | /** | ||
75 | * Dump textual representation of SMF to stream | ||
76 | * @param s output stream | ||
77 | */ | ||
78 | void dump(ostream& s) const; | ||
79 | }; | ||
80 | |||
81 | inline ostream& operator<<(ostream& s,const SMF_t& smf) { | ||
82 | smf.dump(s); return s; | ||
83 | } | ||
84 | |||
85 | } | ||
86 | |||
87 | #endif /* __MIDILLO_SMF_H */ | ||
diff --git a/include/midillo/chunk.h b/include/midillo/chunk.h new file mode 100644 index 0000000..8b6c034 --- a/dev/null +++ b/include/midillo/chunk.h | |||
@@ -0,0 +1,88 @@ | |||
1 | #ifndef __MIDILLO_CHUNK_H | ||
2 | #define __MIDILLO_CHUNK_H | ||
3 | |||
4 | #include <istream> | ||
5 | #include <ostream> | ||
6 | |||
7 | /** | ||
8 | * @file | ||
9 | * @brief Generic SMF chunk manipulation | ||
10 | */ | ||
11 | |||
12 | namespace midillo { | ||
13 | using std::istream; | ||
14 | using std::ostream; | ||
15 | |||
16 | enum { | ||
17 | chunk_id_MThd = 0x6468544d, | ||
18 | chunk_id_MTrk = 0x6b72544d | ||
19 | }; | ||
20 | /** | ||
21 | * Chunk header data structure | ||
22 | */ | ||
23 | struct chunk_header_t { | ||
24 | /** | ||
25 | * Track signature data | ||
26 | */ | ||
27 | union { | ||
28 | /** | ||
29 | * ASCII representation | ||
30 | */ | ||
31 | char id_chars[4]; | ||
32 | /** | ||
33 | * long integer representation | ||
34 | */ | ||
35 | unsigned long id_number; | ||
36 | }; | ||
37 | /** | ||
38 | * Chunk length | ||
39 | */ | ||
40 | unsigned long length; | ||
41 | |||
42 | chunk_header_t() | ||
43 | : id_number(0), length(0) { } | ||
44 | chunk_header_t(const chunk_header_t& s) | ||
45 | : id_number(s.id_number), length(s.length) { }; | ||
46 | |||
47 | chunk_header_t& operator=(const chunk_header_t& s) { | ||
48 | id_number=s.id_number; length=s.length; | ||
49 | return *this; | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * Load chunk header from the stream | ||
54 | * @param s input stream | ||
55 | */ | ||
56 | void load(istream& s); | ||
57 | /** | ||
58 | * Save chunk header to the stream | ||
59 | * @param s output stream | ||
60 | */ | ||
61 | void save(ostream& s) const; | ||
62 | |||
63 | /** | ||
64 | * Dump textual representation of chunk header to stream | ||
65 | * @param s output stream | ||
66 | */ | ||
67 | void dump(ostream& s) const; | ||
68 | |||
69 | }; | ||
70 | |||
71 | inline ostream& operator<<(ostream& s,const chunk_header_t& ch) { | ||
72 | ch.dump(s); return s; | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * Base class for specific chunk containers | ||
77 | */ | ||
78 | class chunk_t { | ||
79 | public: | ||
80 | /** | ||
81 | * Chunk header data | ||
82 | */ | ||
83 | chunk_header_t header; | ||
84 | }; | ||
85 | |||
86 | } | ||
87 | |||
88 | #endif /* __MIDILLO_CHUNK_H */ | ||
diff --git a/include/midillo/event.h b/include/midillo/event.h new file mode 100644 index 0000000..85f6175 --- a/dev/null +++ b/include/midillo/event.h | |||
@@ -0,0 +1,99 @@ | |||
1 | #ifndef __MIDILLO_EVENT_H | ||
2 | #define __MIDILLO_EVENT_H | ||
3 | |||
4 | #include <istream> | ||
5 | #include <ostream> | ||
6 | #include <list> | ||
7 | #include <midillo/message.h> | ||
8 | |||
9 | /** | ||
10 | * @file | ||
11 | * @brief midi event container | ||
12 | */ | ||
13 | |||
14 | namespace midillo { | ||
15 | using std::istream; | ||
16 | using std::ostream; | ||
17 | using std::list; | ||
18 | |||
19 | /** | ||
20 | * MIDI event container class | ||
21 | */ | ||
22 | class event_t { | ||
23 | public: | ||
24 | /** | ||
25 | * delta time since the last event | ||
26 | */ | ||
27 | long deltat; | ||
28 | /** | ||
29 | * MIDI message itself | ||
30 | */ | ||
31 | message_t message; | ||
32 | |||
33 | /** | ||
34 | * Load MIDI event from the stream | ||
35 | * @param rs reference to the running status | ||
36 | * @param s input stream | ||
37 | */ | ||
38 | void load(int& rs,istream& s); | ||
39 | |||
40 | /** | ||
41 | * Save MIDI event to the stream | ||
42 | * @param rs reference to the running status | ||
43 | * @param s output stream | ||
44 | */ | ||
45 | void save(int& rs,ostream& s) const; | ||
46 | |||
47 | /** | ||
48 | * Calculate the amount of data that would be written to stream in | ||
49 | * case of save | ||
50 | * @param rs reference to the running status | ||
51 | * @return the number of bytes | ||
52 | */ | ||
53 | unsigned long calculate_save_size(int& rs) const; | ||
54 | |||
55 | /** | ||
56 | * Dump textual representation of event to stream | ||
57 | * @param s output stream | ||
58 | */ | ||
59 | void dump(ostream& s) const; | ||
60 | }; | ||
61 | |||
62 | inline ostream& operator<<(ostream& s,const event_t& e) { | ||
63 | e.dump(s); return s; | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * MIDI events list container | ||
68 | */ | ||
69 | class events_t : public list<event_t> { | ||
70 | public: | ||
71 | |||
72 | /** | ||
73 | * Append empty event to the end of the list | ||
74 | * @return iterator, pointing to the appended event | ||
75 | */ | ||
76 | iterator append_event(); | ||
77 | |||
78 | /** | ||
79 | * Load MIDI events (track data) from the stream | ||
80 | * @param s input stream | ||
81 | */ | ||
82 | void load(istream& s); | ||
83 | /** | ||
84 | * Save MIDI events (track data) to the stream | ||
85 | * @param s output stream | ||
86 | */ | ||
87 | void save(ostream& s) const; | ||
88 | |||
89 | /** | ||
90 | * Calculate the size of the track data that would be written to | ||
91 | * the stream by save() | ||
92 | * @return the number of bytes | ||
93 | */ | ||
94 | unsigned long calculate_save_size() const; | ||
95 | }; | ||
96 | |||
97 | } | ||
98 | |||
99 | #endif /* __MIDILLO_EVENT_H */ | ||
diff --git a/include/midillo/exception.h b/include/midillo/exception.h new file mode 100644 index 0000000..fb6da27 --- a/dev/null +++ b/include/midillo/exception.h | |||
@@ -0,0 +1,55 @@ | |||
1 | #ifndef __MIDILLO_EXCEPTION_H | ||
2 | #define __MIDILLO_EXCEPTION_H | ||
3 | |||
4 | #include <konforka/exception.h> | ||
5 | |||
6 | /** | ||
7 | * @file | ||
8 | * @brief midillo specific exceptions | ||
9 | */ | ||
10 | |||
11 | namespace midillo { | ||
12 | using std::string; | ||
13 | |||
14 | /** | ||
15 | * Base midillo exception class | ||
16 | */ | ||
17 | class exception : public konforka::exception { | ||
18 | public: | ||
19 | explicit exception(const string& fi,const string& fu,int l,const string& w) | ||
20 | : konforka::exception(fi,fu,l,w) { } | ||
21 | }; | ||
22 | |||
23 | class exception_io_error : public exception { | ||
24 | public: | ||
25 | explicit exception_io_error(const string& fi,const string& fu,int l,const string& w) | ||
26 | : exception(fi,fu,l,w) { } | ||
27 | }; | ||
28 | |||
29 | class exception_input_error : public exception_io_error { | ||
30 | public: | ||
31 | explicit exception_input_error(const string& fi,const string& fu,int l,const string& w) | ||
32 | : exception_io_error(fi,fu,l,w) { } | ||
33 | }; | ||
34 | |||
35 | class exception_invalid_input : public exception_input_error { | ||
36 | public: | ||
37 | explicit exception_invalid_input(const string& fi,const string& fu,int l,const string& w) | ||
38 | : exception_input_error(fi,fu,l,w) { } | ||
39 | }; | ||
40 | |||
41 | class exception_unexpected_input : public exception_invalid_input { | ||
42 | public: | ||
43 | explicit exception_unexpected_input(const string& fi,const string& fu,int l,const string& w) | ||
44 | : exception_invalid_input(fi,fu,l,w) { } | ||
45 | }; | ||
46 | |||
47 | class exception_output_error : public exception_io_error { | ||
48 | public: | ||
49 | explicit exception_output_error(const string& fi,const string& fu,int l,const string& w) | ||
50 | : exception_io_error(fi,fu,l,w) { } | ||
51 | }; | ||
52 | |||
53 | }; | ||
54 | |||
55 | #endif /* __MIDILLO_EXCEPTION_H */ | ||
diff --git a/include/midillo/message.h b/include/midillo/message.h new file mode 100644 index 0000000..d6f0f36 --- a/dev/null +++ b/include/midillo/message.h | |||
@@ -0,0 +1,200 @@ | |||
1 | #ifndef __MIDILLO_MESSAGE_H | ||
2 | #define __MIDILLO_MESSAGE_H | ||
3 | |||
4 | #include <istream> | ||
5 | #include <ostream> | ||
6 | #include <vector> | ||
7 | |||
8 | /** | ||
9 | * @file | ||
10 | * @brief MIDI message | ||
11 | */ | ||
12 | |||
13 | namespace midillo { | ||
14 | using std::istream; | ||
15 | using std::ostream; | ||
16 | using std::vector; | ||
17 | |||
18 | enum { | ||
19 | // bits | ||
20 | status_bit = 0x80, | ||
21 | status_event_bits = 0xF0, | ||
22 | status_channel_bits = 0x0F, | ||
23 | status_system_bits = 0xFF, | ||
24 | // channel voice messages | ||
25 | status_note_off = 0x80, | ||
26 | status_note_on = 0x90, | ||
27 | status_polyphonic_key_pressure = 0xA0, | ||
28 | status_aftertouch = status_polyphonic_key_pressure, | ||
29 | status_control_change = 0xB0, | ||
30 | status_program_change = 0xC0, | ||
31 | status_channel_pressure = 0xD0, | ||
32 | status_pitch_wheel_change = 0xE0, | ||
33 | status_system = 0xF0, | ||
34 | // system common messages | ||
35 | status_system_sysex = 0xF0, | ||
36 | status_system_MTC_quarter_frame = 0xF1, | ||
37 | status_system_song_position_pointer = 0xF2, | ||
38 | status_system_song_select = 0xF3, | ||
39 | status_system_tune_request = 0xF6, | ||
40 | status_system_end_of_sysex = 0xF7, | ||
41 | // system real-time messages | ||
42 | status_system_timing_clock = 0xF8, | ||
43 | status_system_midi_clock = status_system_timing_clock, | ||
44 | status_system_midi_tick = 0xF9, | ||
45 | status_system_start = 0xFA, | ||
46 | status_system_midi_start = status_system_start, | ||
47 | status_system_continue = 0xFB, | ||
48 | status_system_midi_continue = status_system_continue, | ||
49 | status_system_stop = 0xFC, | ||
50 | status_system_midi_stop = status_system_stop, | ||
51 | status_system_active_sense = 0xFE, | ||
52 | status_system_rest = 0xFF, | ||
53 | status_system_reset = status_system_rest, | ||
54 | // midi file specific | ||
55 | status_system_meta = 0xFF | ||
56 | }; | ||
57 | enum { | ||
58 | // meta events | ||
59 | meta_sequence_number = 0x00, | ||
60 | meta_text = 0x01, | ||
61 | meta_copyright = 0x02, | ||
62 | meta_seq_track_name = 0x03, | ||
63 | meta_instrument = 0x04, | ||
64 | meta_lyric = 0x05, | ||
65 | meta_marker = 0x06, | ||
66 | meta_cue_point = 0x07, | ||
67 | meta_patch_name = 0x08, | ||
68 | meta_port_name = 0x09, | ||
69 | meta_EOT = 0x2F, | ||
70 | meta_tempo = 0x51, | ||
71 | meta_SMPTE_offset = 0x54, | ||
72 | meta_time_sig = 0x58, | ||
73 | meta_key_sig = 0x59, | ||
74 | meta_proprietary = 0x7F, | ||
75 | // obsolete meta events | ||
76 | meta_midi_channel = 0x20, | ||
77 | meta_midi_port = 0x21 | ||
78 | }; | ||
79 | |||
80 | /** | ||
81 | * MIDI message container | ||
82 | */ | ||
83 | class message_t { | ||
84 | public: | ||
85 | /** | ||
86 | * MIDI status byte | ||
87 | */ | ||
88 | int status; | ||
89 | /** | ||
90 | * MIDI meta event type | ||
91 | */ | ||
92 | int meta_status; | ||
93 | typedef unsigned char byte_t; | ||
94 | typedef vector<byte_t> bytes_t; | ||
95 | /** | ||
96 | * MIDI message data -- content is message-specific | ||
97 | */ | ||
98 | bytes_t data; | ||
99 | |||
100 | message_t() | ||
101 | : status(-1) { } | ||
102 | message_t(const message_t& m) | ||
103 | : status(m.status), meta_status(m.meta_status), data(m.data) { } | ||
104 | |||
105 | message_t& operator=(const message_t& m) { | ||
106 | status = m.status; | ||
107 | meta_status = m.meta_status; | ||
108 | data = m.data; | ||
109 | return *this; | ||
110 | } | ||
111 | |||
112 | /** | ||
113 | * Load MIDI message from the stream | ||
114 | * @param rs reference to the running status | ||
115 | * @param s input stream | ||
116 | */ | ||
117 | void load(int& rs,istream& s); | ||
118 | /** | ||
119 | * Save MIDI message to the stream | ||
120 | * @param rs reference to the running status | ||
121 | * @param s output stream | ||
122 | */ | ||
123 | void save(int& rs,ostream& s) const; | ||
124 | /** | ||
125 | * Calculate the amount of data that would be written to stream in | ||
126 | * case of save() | ||
127 | * @param rs reference to the running status | ||
128 | * @return the number of bytes | ||
129 | */ | ||
130 | unsigned long calculate_save_size(int& rs) const; | ||
131 | |||
132 | /** | ||
133 | * Load data so that we have c bytes of data for the event | ||
134 | * @param s input stream | ||
135 | * @param c size of data needed for the event | ||
136 | */ | ||
137 | void load_data(istream& s,int c); | ||
138 | /** | ||
139 | * Load sysex data from the stream | ||
140 | * @param s input stream | ||
141 | */ | ||
142 | void load_sysex(istream& s); | ||
143 | |||
144 | /** | ||
145 | * Save data to the stream | ||
146 | * @param s output stream | ||
147 | */ | ||
148 | void save_data(ostream& s) const; | ||
149 | /** | ||
150 | * Save data to the stream and verify if the amount of data is | ||
151 | * correct | ||
152 | * @param s output stream | ||
153 | * @param c data bytes count | ||
154 | */ | ||
155 | void save_data(ostream& s,int c) const; | ||
156 | /** | ||
157 | * Save sysex data to the stream | ||
158 | * @param s output stream | ||
159 | */ | ||
160 | void save_sysex(ostream& s) const; | ||
161 | |||
162 | /** | ||
163 | * See if the event is meta event | ||
164 | * @return true if yes | ||
165 | */ | ||
166 | bool is_meta() const { | ||
167 | return status==status_system_meta; | ||
168 | } | ||
169 | /** | ||
170 | * Check whether the event is a specific meta event | ||
171 | * @param meta meta event type | ||
172 | * @return true if yes | ||
173 | */ | ||
174 | bool is_meta(int meta) const { | ||
175 | return is_meta() && (meta_status==meta); | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * See if the event is system event | ||
180 | * @return true if yes | ||
181 | */ | ||
182 | bool is_system() const { | ||
183 | return (status&status_event_bits)==status_system && !is_meta(); | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * Dump textual representation of midi message to stream | ||
188 | * @param s output stream | ||
189 | */ | ||
190 | void dump(ostream& s) const; | ||
191 | |||
192 | }; | ||
193 | |||
194 | inline ostream& operator<<(ostream& s,const message_t& m) { | ||
195 | m.dump(s); return s; | ||
196 | } | ||
197 | |||
198 | } | ||
199 | |||
200 | #endif /* __MIDILLO_MESSAGE_H */ | ||
diff --git a/include/midillo/util.h b/include/midillo/util.h new file mode 100644 index 0000000..f9c8430 --- a/dev/null +++ b/include/midillo/util.h | |||
@@ -0,0 +1,63 @@ | |||
1 | #ifndef __MIDILLO_UTIL_H | ||
2 | #define __MIDILLO_UTIL_H | ||
3 | |||
4 | #include <istream> | ||
5 | #include <ostream> | ||
6 | |||
7 | /** | ||
8 | * @file | ||
9 | * @brief utilities | ||
10 | */ | ||
11 | |||
12 | namespace midillo { | ||
13 | using std::istream; | ||
14 | using std::ostream; | ||
15 | |||
16 | /** | ||
17 | * read 32 bits word from the stream | ||
18 | * @param s input stream | ||
19 | * @return the data acquired | ||
20 | */ | ||
21 | unsigned long read32(istream& s); | ||
22 | /** | ||
23 | * read 16 bits word from the stream | ||
24 | * @param s input stream | ||
25 | * @return the data acquired | ||
26 | */ | ||
27 | unsigned int read16(istream& s); | ||
28 | /** | ||
29 | * read the variable length quantity from the stream | ||
30 | * @param s input stream | ||
31 | * @return the data acquired | ||
32 | */ | ||
33 | unsigned long readVL(istream& s); | ||
34 | |||
35 | /** | ||
36 | * write 32 bits word to the stream | ||
37 | * @param s output stream | ||
38 | * @param d data to write | ||
39 | */ | ||
40 | void write32(ostream& s,unsigned long d); | ||
41 | /** | ||
42 | * write 16 bits word to the stream | ||
43 | * @param s output stream | ||
44 | * @param d data to write | ||
45 | */ | ||
46 | void write16(ostream& s,unsigned int d); | ||
47 | /** | ||
48 | * write the variable length quantity to the stream | ||
49 | * @param s output stream | ||
50 | * @param d data to write | ||
51 | */ | ||
52 | void writeVL(ostream& s,unsigned long d); | ||
53 | |||
54 | /** | ||
55 | * calculate the amount of data that would be written by writeVL | ||
56 | * @param d data that would be written | ||
57 | * @return the number of bytes | ||
58 | */ | ||
59 | unsigned long calcVLsize(unsigned long d); | ||
60 | |||
61 | } | ||
62 | |||
63 | #endif /* __MIDILLO_UTIL_H */ | ||
diff --git a/lib/.gitignore b/lib/.gitignore new file mode 100644 index 0000000..dc5e416 --- a/dev/null +++ b/lib/.gitignore | |||
@@ -0,0 +1,7 @@ | |||
1 | *.lo | ||
2 | *.o | ||
3 | Makefile.in | ||
4 | .libs | ||
5 | .deps | ||
6 | Makefile | ||
7 | *.la | ||
diff --git a/lib/MThd.cc b/lib/MThd.cc new file mode 100644 index 0000000..110c98a --- a/dev/null +++ b/lib/MThd.cc | |||
@@ -0,0 +1,38 @@ | |||
1 | #include <midillo/MThd.h> | ||
2 | #include <midillo/util.h> | ||
3 | #include <midillo/exception.h> | ||
4 | |||
5 | namespace midillo { | ||
6 | using std::endl; | ||
7 | |||
8 | void MThd_t::load(istream& s) { | ||
9 | header.load(s); | ||
10 | if(header.id_number!=chunk_id_MThd) | ||
11 | throw exception_unexpected_input(CODEPOINT,"MThd chunk expected"); | ||
12 | if(header.length!=6) | ||
13 | throw exception_invalid_input(CODEPOINT,"MThd chunk is not 6 bytes long"); | ||
14 | load_data(s); | ||
15 | } | ||
16 | |||
17 | void MThd_t::load_data(istream& s) { | ||
18 | fmt = read16(s); | ||
19 | ntracks = read16(s); | ||
20 | division = read16(s); | ||
21 | } | ||
22 | |||
23 | void MThd_t::save(ostream& s) const { | ||
24 | header.save(s); | ||
25 | write16(s,fmt); | ||
26 | write16(s,ntracks); | ||
27 | write16(s,division); | ||
28 | } | ||
29 | |||
30 | void MThd_t::dump(ostream& s) const { | ||
31 | std::ios::fmtflags ff = s.flags(); | ||
32 | s.unsetf(std::ios::hex); s.setf(std::ios::dec); | ||
33 | s << " " << header << endl | ||
34 | << " fmt=" << fmt << ", " << ntracks << " track(s), division=" << division << endl; | ||
35 | s.flags(ff); | ||
36 | } | ||
37 | |||
38 | } | ||
diff --git a/lib/MTrk.cc b/lib/MTrk.cc new file mode 100644 index 0000000..fa1e0f8 --- a/dev/null +++ b/lib/MTrk.cc | |||
@@ -0,0 +1,34 @@ | |||
1 | #include <algorithm> | ||
2 | #include <iterator> | ||
3 | #include <midillo/MTrk.h> | ||
4 | #include <midillo/exception.h> | ||
5 | |||
6 | namespace midillo { | ||
7 | using std::copy; | ||
8 | using std::ostream_iterator; | ||
9 | using std::endl; | ||
10 | |||
11 | void MTrk_t::load(istream& s) { | ||
12 | header.load(s); | ||
13 | if(header.id_number!=chunk_id_MTrk) | ||
14 | throw exception_unexpected_input(CODEPOINT,"MTrk chunk expected"); | ||
15 | events.load(s); | ||
16 | } | ||
17 | |||
18 | void MTrk_t::save(ostream& s) const { | ||
19 | chunk_header_t h = header; | ||
20 | h.id_number = chunk_id_MTrk; | ||
21 | h.length = events.calculate_save_size(); | ||
22 | h.save(s); | ||
23 | events.save(s); | ||
24 | } | ||
25 | |||
26 | void MTrk_t::dump(ostream& s) const { | ||
27 | s << " " << header << endl | ||
28 | << " "; | ||
29 | copy( | ||
30 | events.begin(), events.end(), | ||
31 | ostream_iterator<event_t>(s,"\n ") ); | ||
32 | } | ||
33 | |||
34 | } | ||
diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 0000000..de49c97 --- a/dev/null +++ b/lib/Makefile.am | |||
@@ -0,0 +1,15 @@ | |||
1 | lib_LTLIBRARIES = libmidillo.la | ||
2 | |||
3 | INCLUDES = -I${top_srcdir}/include -I${top_srcdir} | ||
4 | AM_CXXFLAGS = ${KONFORKA_CFLAGS} | ||
5 | LDADD = ${KONFORKA_LIBS} | ||
6 | |||
7 | libmidillo_la_SOURCES = \ | ||
8 | util.cc \ | ||
9 | SMF.cc \ | ||
10 | chunk.cc \ | ||
11 | MThd.cc MTrk.cc \ | ||
12 | event.cc \ | ||
13 | message.cc | ||
14 | |||
15 | libmidillo_la_LDFLAGS = -version-info 0:0:0 | ||
diff --git a/lib/SMF.cc b/lib/SMF.cc new file mode 100644 index 0000000..ba3179d --- a/dev/null +++ b/lib/SMF.cc | |||
@@ -0,0 +1,62 @@ | |||
1 | #include <iostream> | ||
2 | #include <fstream> | ||
3 | #include <algorithm> | ||
4 | #include <iterator> | ||
5 | #include <midillo/SMF.h> | ||
6 | |||
7 | namespace midillo { | ||
8 | using std::ifstream; | ||
9 | using std::ofstream; | ||
10 | using std::cin; | ||
11 | using std::cout; | ||
12 | using std::copy; | ||
13 | using std::ostream_iterator; | ||
14 | using std::endl; | ||
15 | |||
16 | void SMF_t::load(const char *f,bool stdinable) { | ||
17 | if(stdinable && !strcmp(f,"-")) { | ||
18 | load(cin); | ||
19 | }else{ | ||
20 | ifstream s(f,std::ios::in|std::ios::binary); | ||
21 | load(s); | ||
22 | } | ||
23 | } | ||
24 | |||
25 | void SMF_t::load(istream& s) { | ||
26 | mthd.load(s); | ||
27 | tracks.resize(mthd.ntracks); | ||
28 | tracks_t::iterator i = tracks.begin(); | ||
29 | for(int t=0;t<mthd.ntracks;++t,++i) { | ||
30 | i->load(s); | ||
31 | } | ||
32 | } | ||
33 | |||
34 | void SMF_t::save(const char *f,bool stdoutable) const { | ||
35 | if(stdoutable && !strcmp(f,"-")) { | ||
36 | save(cout); | ||
37 | }else{ | ||
38 | ofstream s(f,std::ios::out|std::ios::trunc|std::ios::binary); | ||
39 | save(s); | ||
40 | } | ||
41 | } | ||
42 | |||
43 | void SMF_t::save(ostream& s) const { | ||
44 | mthd.save(s); | ||
45 | for(tracks_t::const_iterator i=tracks.begin();i!=tracks.end();++i) { | ||
46 | i->save(s); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | void SMF_t::dump(ostream& s) const { | ||
51 | std::ios::fmtflags ff = s.flags(); | ||
52 | s.unsetf(std::ios::hex); s.setf(std::ios::dec); | ||
53 | s | ||
54 | << "SMF with " << tracks.size() << " track(s)" << endl | ||
55 | << mthd << endl; | ||
56 | copy( | ||
57 | tracks.begin(), tracks.end(), | ||
58 | ostream_iterator<MTrk_t>(s,"\n") ); | ||
59 | s.flags(ff); | ||
60 | } | ||
61 | |||
62 | } | ||
diff --git a/lib/chunk.cc b/lib/chunk.cc new file mode 100644 index 0000000..7cc15ff --- a/dev/null +++ b/lib/chunk.cc | |||
@@ -0,0 +1,31 @@ | |||
1 | #include <midillo/chunk.h> | ||
2 | #include <midillo/util.h> | ||
3 | #include <midillo/exception.h> | ||
4 | |||
5 | namespace midillo { | ||
6 | |||
7 | void chunk_header_t::load(istream& s) { | ||
8 | s.read((char*)id_chars,sizeof(id_chars)); | ||
9 | if(!s.good()) | ||
10 | throw exception_input_error(CODEPOINT,"Error reading chunk header"); | ||
11 | length = read32(s); | ||
12 | } | ||
13 | |||
14 | void chunk_header_t::save(ostream& s) const { | ||
15 | s.write((char*)id_chars,sizeof(id_chars)); | ||
16 | if(!s.good()) | ||
17 | throw exception_output_error(CODEPOINT,"Error writing chunk header"); | ||
18 | write32(s,length); | ||
19 | } | ||
20 | |||
21 | void chunk_header_t::dump(ostream& s) const { | ||
22 | std::ios::fmtflags ff = s.flags(); | ||
23 | s.unsetf(std::ios::hex); s.setf(std::ios::dec); | ||
24 | s | ||
25 | << id_chars[0] << id_chars[1] | ||
26 | << id_chars[2] << id_chars[3] | ||
27 | << " chunk of " << length << " byte(s)"; | ||
28 | s.flags(ff); | ||
29 | } | ||
30 | |||
31 | } | ||
diff --git a/lib/event.cc b/lib/event.cc new file mode 100644 index 0000000..39438fa --- a/dev/null +++ b/lib/event.cc | |||
@@ -0,0 +1,58 @@ | |||
1 | #include <midillo/event.h> | ||
2 | #include <midillo/util.h> | ||
3 | |||
4 | namespace midillo { | ||
5 | |||
6 | void event_t::load(int& rs,istream& s) { | ||
7 | deltat = readVL(s); | ||
8 | message.load(rs,s); | ||
9 | } | ||
10 | |||
11 | void event_t::save(int& rs,ostream& s) const { | ||
12 | writeVL(s,deltat); | ||
13 | message.save(rs,s); | ||
14 | } | ||
15 | |||
16 | unsigned long event_t::calculate_save_size(int& rs) const { | ||
17 | return calcVLsize(deltat) + message.calculate_save_size(rs); | ||
18 | } | ||
19 | |||
20 | void event_t::dump(ostream& s) const { | ||
21 | std::ios::fmtflags ff = s.flags(); | ||
22 | s.unsetf(std::ios::hex); s.setf(std::ios::dec); | ||
23 | s << "deltat=" << deltat << " [" << message << "]"; | ||
24 | s.flags(ff); | ||
25 | } | ||
26 | |||
27 | |||
28 | events_t::iterator events_t::append_event() { | ||
29 | static event_t empty; | ||
30 | return insert(end(),empty); | ||
31 | } | ||
32 | |||
33 | void events_t::load(istream& s) { | ||
34 | int rs = -1; | ||
35 | for(;;) { | ||
36 | iterator i=append_event(); | ||
37 | i->load(rs,s); | ||
38 | if(i->message.is_meta(meta_EOT)) | ||
39 | break; | ||
40 | } | ||
41 | } | ||
42 | |||
43 | void events_t::save(ostream& s) const { | ||
44 | int rs = -1; | ||
45 | for(const_iterator i=begin();i!=end();++i) { | ||
46 | i->save(rs,s); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | unsigned long events_t::calculate_save_size() const { | ||
51 | unsigned long rv = 0; | ||
52 | int rs = -1; | ||
53 | for(const_iterator i=begin();i!=end();++i) { | ||
54 | rv += i->calculate_save_size(rs); | ||
55 | } | ||
56 | return rv; | ||
57 | } | ||
58 | } | ||
diff --git a/lib/message.cc b/lib/message.cc new file mode 100644 index 0000000..8f9e68a --- a/dev/null +++ b/lib/message.cc | |||
@@ -0,0 +1,247 @@ | |||
1 | #include <algorithm> | ||
2 | #include <iterator> | ||
3 | #include <midillo/message.h> | ||
4 | #include <midillo/util.h> | ||
5 | #include <midillo/exception.h> | ||
6 | |||
7 | namespace midillo { | ||
8 | using std::copy; | ||
9 | using std::ostream_iterator; | ||
10 | |||
11 | unsigned long message_t::calculate_save_size(int& rs) const { | ||
12 | unsigned long rv = 0; | ||
13 | if(status!=rs) { | ||
14 | ++rv; | ||
15 | rs = status; | ||
16 | }else if((status&status_event_bits)==status_system) { | ||
17 | rs = -1; | ||
18 | ++rv; // XXX: is it really needed? | ||
19 | } | ||
20 | switch(status&status_event_bits) { | ||
21 | case status_note_off: | ||
22 | case status_note_on: | ||
23 | case status_polyphonic_key_pressure: // aka status_aftertouch | ||
24 | case status_control_change: | ||
25 | case status_pitch_wheel_change: | ||
26 | rv += 2; break; | ||
27 | case status_program_change: | ||
28 | case status_channel_pressure: | ||
29 | ++rv; break; | ||
30 | case status_system: | ||
31 | switch(status&status_system_bits) { | ||
32 | case status_system_sysex: | ||
33 | case status_system_end_of_sysex: | ||
34 | rv += data.size()+1; break; | ||
35 | case status_system_MTC_quarter_frame: | ||
36 | case status_system_song_select: | ||
37 | ++rv; break; | ||
38 | case status_system_song_position_pointer: | ||
39 | rv += 2; break; | ||
40 | case status_system_tune_request: | ||
41 | case status_system_timing_clock: // aka status_system_midi_clock | ||
42 | case status_system_midi_tick: | ||
43 | case status_system_start: // aka status_system_midi_start | ||
44 | case status_system_stop: // aka status_system_midi_stop | ||
45 | case status_system_continue: // aka status_system_midi_continue | ||
46 | case status_system_active_sense: | ||
47 | break; /* XXX: ensure there is no data? */ | ||
48 | case status_system_meta: // also reset, but not for the purpose of midi file | ||
49 | ++rv; | ||
50 | rv += calcVLsize(data.size()); | ||
51 | rv += data.size(); | ||
52 | break; | ||
53 | default: | ||
54 | throw exception(CODEPOINT,"Internal error"); | ||
55 | break; | ||
56 | } | ||
57 | break; | ||
58 | default: | ||
59 | throw exception(CODEPOINT,"Internal error"); | ||
60 | break; | ||
61 | } | ||
62 | return rv; | ||
63 | } | ||
64 | |||
65 | void message_t::save(int& rs,ostream& s) const { | ||
66 | if(status!=rs) { | ||
67 | s.put(status); | ||
68 | if(!s.good()) | ||
69 | throw exception_output_error(CODEPOINT,"Error writing midi status byte"); | ||
70 | rs = status; | ||
71 | }else if((status&status_event_bits)==status_system) { | ||
72 | rs = -1; | ||
73 | s.put(status); // XXX: is it really needed? | ||
74 | if(!s.good()) | ||
75 | throw exception_output_error(CODEPOINT,"Error writing midi system status byte"); | ||
76 | } | ||
77 | switch(status&status_event_bits) { | ||
78 | case status_note_off: | ||
79 | case status_note_on: | ||
80 | case status_polyphonic_key_pressure: // aka status_aftertouch | ||
81 | case status_control_change: | ||
82 | case status_pitch_wheel_change: | ||
83 | save_data(s,2); break; | ||
84 | case status_program_change: | ||
85 | case status_channel_pressure: | ||
86 | save_data(s,1); break; | ||
87 | case status_system: | ||
88 | switch(status&status_system_bits) { | ||
89 | case status_system_sysex: | ||
90 | case status_system_end_of_sysex: | ||
91 | save_sysex(s); break; | ||
92 | case status_system_MTC_quarter_frame: | ||
93 | case status_system_song_select: | ||
94 | save_data(s,1); break; | ||
95 | case status_system_song_position_pointer: | ||
96 | save_data(s,2); break; | ||
97 | case status_system_tune_request: | ||
98 | case status_system_timing_clock: // aka status_system_midi_clock | ||
99 | case status_system_midi_tick: | ||
100 | case status_system_start: // aka status_system_midi_start | ||
101 | case status_system_stop: // aka status_system_midi_stop | ||
102 | case status_system_continue: // aka status_system_midi_continue | ||
103 | case status_system_active_sense: | ||
104 | break; /* XXX: ensure there is no data? */ | ||
105 | case status_system_meta: // also reset, but not for the purpose of midi file | ||
106 | s.put(meta_status&0xFF); | ||
107 | if(!s.good()) | ||
108 | throw exception_output_error(CODEPOINT,"Error writing meta event"); | ||
109 | writeVL(s,data.size()); | ||
110 | save_data(s); | ||
111 | break; | ||
112 | default: | ||
113 | throw exception(CODEPOINT,"Internal error"); | ||
114 | break; | ||
115 | } | ||
116 | break; | ||
117 | default: | ||
118 | throw exception(CODEPOINT,"Internal error"); | ||
119 | break; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | void message_t::load(int& rs,istream& s) { | ||
124 | data.clear(); | ||
125 | status = s.get(); | ||
126 | if(!s.good()) | ||
127 | throw exception_input_error(CODEPOINT,"Error reading MIDI event status byte"); | ||
128 | if(status&status_bit) { | ||
129 | if((status&status_event_bits)!=status_system) | ||
130 | rs = status; | ||
131 | }else{ | ||
132 | if(rs<0) | ||
133 | throw exception_invalid_input(CODEPOINT,"Attempt to rely on the absent running status"); | ||
134 | data.push_back(status); | ||
135 | status = rs; | ||
136 | } | ||
137 | switch(status&status_event_bits) { | ||
138 | case status_note_off: | ||
139 | case status_note_on: | ||
140 | case status_polyphonic_key_pressure: // a.k.a. status_aftertouch | ||
141 | case status_control_change: | ||
142 | case status_pitch_wheel_change: | ||
143 | load_data(s,2); break; | ||
144 | case status_program_change: | ||
145 | case status_channel_pressure: | ||
146 | load_data(s,1); break; | ||
147 | case status_system: | ||
148 | switch(status&status_system_bits) { | ||
149 | case status_system_sysex: | ||
150 | case status_system_end_of_sysex: | ||
151 | load_sysex(s); break; | ||
152 | case status_system_MTC_quarter_frame: | ||
153 | case status_system_song_select: | ||
154 | load_data(s,1); break; | ||
155 | case status_system_song_position_pointer: | ||
156 | load_data(s,2); break; | ||
157 | case status_system_tune_request: | ||
158 | case status_system_timing_clock: // a.k.a. status_system_midi_clock | ||
159 | case status_system_midi_tick: | ||
160 | case status_system_start: // a.k.a. status_system_midi_start | ||
161 | case status_system_stop: // a.k.a. status_system_midi_stop | ||
162 | case status_system_continue: // a.k.a. status_system_midi_continue | ||
163 | case status_system_active_sense: | ||
164 | break; | ||
165 | case status_system_meta: // also, reset, but not in midi files | ||
166 | { | ||
167 | meta_status = s.get(); | ||
168 | if(!s.good()) | ||
169 | throw exception_input_error(CODEPOINT,"Error reading meta event type"); | ||
170 | int l = readVL(s); | ||
171 | load_data(s,l); | ||
172 | } | ||
173 | break; | ||
174 | default: | ||
175 | throw exception(CODEPOINT,"Internal error"); | ||
176 | break; | ||
177 | } | ||
178 | break; | ||
179 | default: | ||
180 | throw exception(CODEPOINT,"Internal error"); | ||
181 | break; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | void message_t::save_data(ostream& s,int c) const { | ||
186 | if(c!=data.size()) | ||
187 | throw exception(CODEPOINT,"Writing corrupt data"); | ||
188 | save_data(s); | ||
189 | } | ||
190 | |||
191 | void message_t::save_data(ostream& s) const { | ||
192 | for(bytes_t::const_iterator i=data.begin();i!=data.end();++i) | ||
193 | s.put(*i); | ||
194 | if(!s.good()) | ||
195 | throw exception_output_error(CODEPOINT,"Error writing MIDI message data"); | ||
196 | } | ||
197 | |||
198 | void message_t::load_data(istream& s,int c) { | ||
199 | c -= data.size(); | ||
200 | if(c<0) | ||
201 | throw exception(CODEPOINT,"Internal error"); | ||
202 | while(c-- > 0) { | ||
203 | data.push_back(s.get()); | ||
204 | if(!s.good()) | ||
205 | throw exception_input_error(CODEPOINT,"Error reading MIDI data"); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | void message_t::save_sysex(ostream& s) const { | ||
210 | save_data(s); | ||
211 | s.put(0xF7); /* XXX: Or is it better to put it into data? */ | ||
212 | if(!s.good()) | ||
213 | throw exception_output_error(CODEPOINT,"Error writing sysex data"); | ||
214 | } | ||
215 | |||
216 | void message_t::load_sysex(istream& s) { | ||
217 | int b = s.get(); | ||
218 | if(!s.good()) | ||
219 | throw exception_input_error(CODEPOINT,"Error reading sysex data"); | ||
220 | assert(!(b&0x80)); // manufacturer ought to be 7 bit. not sure if it belongs here, it may well be continuation. | ||
221 | do { | ||
222 | data.push_back(b); | ||
223 | b = s.get(); | ||
224 | if(!s.good()) | ||
225 | throw exception_input_error(CODEPOINT,"Error reading sysex data"); | ||
226 | }while(b!=0xF7); | ||
227 | } | ||
228 | |||
229 | void message_t::dump(ostream& s) const { | ||
230 | std::ios::fmtflags ff = s.flags(); | ||
231 | int w = s.width(2); | ||
232 | s.unsetf(std::ios::dec); s.setf(std::ios::hex); | ||
233 | s << "status=" << status; | ||
234 | if(is_meta()) { | ||
235 | s << ", meta_status=" << meta_status; | ||
236 | } | ||
237 | if(!data.empty()) { | ||
238 | s << ", data: "; | ||
239 | copy( | ||
240 | data.begin(), data.end(), | ||
241 | ostream_iterator<int>(s," ") ); | ||
242 | } | ||
243 | s.width(w); | ||
244 | s.flags(ff); | ||
245 | } | ||
246 | |||
247 | } | ||
diff --git a/lib/util.cc b/lib/util.cc new file mode 100644 index 0000000..4bbe6f3 --- a/dev/null +++ b/lib/util.cc | |||
@@ -0,0 +1,96 @@ | |||
1 | #include <midillo/util.h> | ||
2 | #include <midillo/exception.h> | ||
3 | |||
4 | namespace midillo { | ||
5 | |||
6 | unsigned long read32(istream& s) { | ||
7 | unsigned long rv = 0; | ||
8 | for(int t=0;t<4;++t) { | ||
9 | rv<<=8; | ||
10 | rv|=0xFF&s.get(); | ||
11 | if(!s.good()) | ||
12 | throw exception_input_error(CODEPOINT,"Input error"); | ||
13 | } | ||
14 | return rv; | ||
15 | } | ||
16 | |||
17 | unsigned int read16(istream& s) { | ||
18 | unsigned int rv = 0; | ||
19 | for(int t=0;t<2;++t) { | ||
20 | rv<<=8; | ||
21 | rv|=0xFF&s.get(); | ||
22 | if(!s.good()) | ||
23 | throw exception_input_error(CODEPOINT,"Input error"); | ||
24 | } | ||
25 | return rv; | ||
26 | } | ||
27 | |||
28 | unsigned long readVL(istream& s) { | ||
29 | unsigned long rv=s.get(); | ||
30 | if(!s.good()) | ||
31 | throw exception_input_error(CODEPOINT,"Error reading VLQ"); | ||
32 | int b; | ||
33 | if(rv&0x80) { | ||
34 | rv&=0x7F; | ||
35 | do { | ||
36 | rv = (rv<<7)|( (b=s.get())&0x7F ); | ||
37 | if(!s.good()) | ||
38 | throw exception_input_error(CODEPOINT,"Error reading VLQ"); | ||
39 | }while(b&0x80); | ||
40 | } | ||
41 | return rv; | ||
42 | } | ||
43 | |||
44 | void write32(ostream& s,unsigned long d) { | ||
45 | for(int t=3;t>=0;--t) { | ||
46 | s.put(((const char*)&d)[t]); | ||
47 | if(!s.good()) | ||
48 | throw exception_output_error(CODEPOINT,"Output error"); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | void write16(ostream& s,unsigned int d) { | ||
53 | for(int t=1;t>=0;--t) { | ||
54 | s.put(((const char*)&d)[t]); | ||
55 | if(!s.good()) | ||
56 | throw exception_output_error(CODEPOINT,"Output error"); | ||
57 | } | ||
58 | } | ||
59 | |||
60 | void writeVL(ostream& s,unsigned long d) { | ||
61 | // TODO: I don't think this is perfectly written code | ||
62 | unsigned long tmp = d&0x7F; | ||
63 | while(d>>=7) { | ||
64 | tmp<<=8; | ||
65 | tmp |=((d&0x7F)|0x80); | ||
66 | } | ||
67 | for(;;) { | ||
68 | s.put(tmp&0xFF); | ||
69 | if(!s.good()) | ||
70 | throw exception_output_error(CODEPOINT,"Error writing VLQ"); | ||
71 | if(tmp&0x80) | ||
72 | tmp>>=8; | ||
73 | else | ||
74 | break; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | unsigned long calcVLsize(unsigned long d) { | ||
79 | unsigned long rv = 0; | ||
80 | // TODO: imperfect code revisited | ||
81 | unsigned long tmp = d&0x7F; | ||
82 | while(d>>=7) { | ||
83 | tmp<<=8; | ||
84 | tmp |=((d&0x7F)|0x80); | ||
85 | } | ||
86 | for(;;) { | ||
87 | ++rv; | ||
88 | if(tmp&0x80) | ||
89 | tmp>>=8; | ||
90 | else | ||
91 | break; | ||
92 | } | ||
93 | return rv; | ||
94 | } | ||
95 | |||
96 | } | ||
diff --git a/man/.gitignore b/man/.gitignore new file mode 100644 index 0000000..3dda729 --- a/dev/null +++ b/man/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | Makefile.in | ||
2 | Makefile | ||
diff --git a/man/Makefile.am b/man/Makefile.am new file mode 100644 index 0000000..13bcb82 --- a/dev/null +++ b/man/Makefile.am | |||
@@ -0,0 +1,3 @@ | |||
1 | man_MANS = midi2f0.1 midifilter.1 mididump.1 | ||
2 | |||
3 | EXTRA_DIST=${man_MANS} | ||
diff --git a/man/midi2f0.1 b/man/midi2f0.1 new file mode 100644 index 0000000..ae89ea8 --- a/dev/null +++ b/man/midi2f0.1 | |||
@@ -0,0 +1,85 @@ | |||
1 | .TH midi2f0 1 "August 11th, 2006" "midi2f0(1)" "Klever Group (http://www.klever.net/)" | ||
2 | .hla en | ||
3 | |||
4 | .SH NAME | ||
5 | |||
6 | midi2f0 \- Standard MIDI File converter | ||
7 | |||
8 | .SH SYNOPSYS | ||
9 | |||
10 | \fBmidi2f0\fR | ||
11 | [\fB-h\fR | \fB--help\fR | \fB--usage\fR] | ||
12 | [\fB-V\fR | \fB--version\fR] | ||
13 | [\fB-L\fR | \fB--license\fR] | ||
14 | [<input-file>[ <output-file>]] | ||
15 | |||
16 | .SH DESCRIPTION | ||
17 | |||
18 | midi2f0 converts Standard MIDI Files to Standard MIDI Files format 0, which | ||
19 | is single track midi file. You may want to perform such conversion before | ||
20 | putting the file on the memory card for some MIDI keyboard consumption. | ||
21 | |||
22 | if you want to load file from standard input or dump results to standard output | ||
23 | just omit corresponding file or specify '-'. | ||
24 | |||
25 | .SH OPTIONS | ||
26 | |||
27 | .TP | ||
28 | \fB-h\fR, \fB--help\fR, \fB--usage\fR | ||
29 | Display short usage message and exit. | ||
30 | .TP | ||
31 | \fB-V\fR, \fB--version\fR | ||
32 | Report version and exit. | ||
33 | .TP | ||
34 | \fB-L\fR, \fB--license\fR | ||
35 | Show licensing terms. | ||
36 | |||
37 | .SH EXAMPLE | ||
38 | |||
39 | .TP | ||
40 | .nf | ||
41 | \fBmidi2f0\fR midifile.mid \\ | ||
42 | | \fBmidifilter\fR \fB-f\fR \fBsysex,meta_unknown,meta_obsolete,meta_texts\fR \\ | ||
43 | >/mnt/card/casio_md/midifile.mid | ||
44 | .fi | ||
45 | |||
46 | This command converts file to SMF0 file, strips events not understood and not | ||
47 | used by the keyboard and puts it to the memory card. | ||
48 | |||
49 | .SH EXIT STATUS | ||
50 | |||
51 | Zero in case of success, non-zero otherwise. | ||
52 | |||
53 | .SH AUTHOR | ||
54 | |||
55 | Written by Michael 'hacker' Krelin <hacker@klever.net> | ||
56 | |||
57 | .SH COPYRIGHT | ||
58 | |||
59 | Copyright (c) 2006 Klever Group (http://www.klever.net/) | ||
60 | |||
61 | Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
62 | this software and associated documentation files (the "Software"), to deal in | ||
63 | the Software without restriction, including without limitation the rights to | ||
64 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | ||
65 | of the Software, and to permit persons to whom the Software is furnished to do | ||
66 | so, subject to the following conditions: | ||
67 | |||
68 | The above copyright notice and this permission notice shall be included in all | ||
69 | copies or substantial portions of the Software. | ||
70 | |||
71 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
72 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
73 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
74 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
75 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
76 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
77 | SOFTWARE. | ||
78 | |||
79 | .SH BUGS | ||
80 | |||
81 | You tell me. Send reports to <midillo-bugs@klever.net> | ||
82 | |||
83 | .SH SEE ALSO | ||
84 | \fBmidifilter\fR(1) | ||
85 | \fBmididump\fR(1) | ||
diff --git a/man/mididump.1 b/man/mididump.1 new file mode 100644 index 0000000..e236ddc --- a/dev/null +++ b/man/mididump.1 | |||
@@ -0,0 +1,72 @@ | |||
1 | .TH mididump 1 "August 11th, 2006" "mididump(1)" "Klever Group (http://www.klever.net/)" | ||
2 | .hla en | ||
3 | |||
4 | .SH NAME | ||
5 | |||
6 | mididump \- Standard MIDI File dump | ||
7 | |||
8 | .SH SYNOPSYS | ||
9 | |||
10 | \fBmididump\fR | ||
11 | [\fB-h\fR | \fB--help\fR | \fB--usage\fR] | ||
12 | [\fB-V\fR | \fB--version\fR] | ||
13 | [\fB-L\fR | \fB--license\fR] | ||
14 | [<input-file>[ <output-file>]] | ||
15 | |||
16 | .SH DESCRIPTION | ||
17 | |||
18 | mididump outputs ascii representation of the input SMF file. At this point it | ||
19 | may only be useful for debugging purpose. | ||
20 | |||
21 | if you want to load file from standard input or dump results to standard output | ||
22 | just omit corresponding file or specify '-'. | ||
23 | |||
24 | .SH OPTIONS | ||
25 | |||
26 | .TP | ||
27 | \fB-h\fR, \fB--help\fR, \fB--usage\fR | ||
28 | Display short usage message and exit. | ||
29 | .TP | ||
30 | \fB-V\fR, \fB--version\fR | ||
31 | Report version and exit. | ||
32 | .TP | ||
33 | \fB-L\fR, \fB--license\fR | ||
34 | Show licensing terms. | ||
35 | |||
36 | .SH EXIT STATUS | ||
37 | |||
38 | Zero in case of success, non-zero otherwise. | ||
39 | |||
40 | .SH AUTHOR | ||
41 | |||
42 | Written by Michael 'hacker' Krelin <hacker@klever.net> | ||
43 | |||
44 | .SH COPYRIGHT | ||
45 | |||
46 | Copyright (c) 2006 Klever Group (http://www.klever.net/) | ||
47 | |||
48 | Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
49 | this software and associated documentation files (the "Software"), to deal in | ||
50 | the Software without restriction, including without limitation the rights to | ||
51 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | ||
52 | of the Software, and to permit persons to whom the Software is furnished to do | ||
53 | so, subject to the following conditions: | ||
54 | |||
55 | The above copyright notice and this permission notice shall be included in all | ||
56 | copies or substantial portions of the Software. | ||
57 | |||
58 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
59 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
60 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
61 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
62 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
63 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
64 | SOFTWARE. | ||
65 | |||
66 | .SH BUGS | ||
67 | |||
68 | You tell me. Send reports to <midillo-bugs@klever.net> | ||
69 | |||
70 | .SH SEE ALSO | ||
71 | \fBmidi2f0\fR(1) | ||
72 | \fBmidifilter\fR(1) | ||
diff --git a/man/midifilter.1 b/man/midifilter.1 new file mode 100644 index 0000000..eddd66d --- a/dev/null +++ b/man/midifilter.1 | |||
@@ -0,0 +1,93 @@ | |||
1 | .TH midifilter 1 "August 11th, 2006" "midifilter(1)" "Klever Group (http://www.klever.net/)" | ||
2 | .hla en | ||
3 | |||
4 | .SH NAME | ||
5 | |||
6 | midifilter \- Standard MIDI File filter | ||
7 | |||
8 | .SH SYNOPSYS | ||
9 | |||
10 | \fBmidifilter\fR | ||
11 | [\fB-h\fR | \fB--help\fR | \fB--usage\fR] | ||
12 | [\fB-V\fR | \fB--version\fR] | ||
13 | [\fB-L\fR | \fB--license\fR] | ||
14 | [\fB-f\fR \fI<filters>\fR | \fB--filter=\fI<filters>\fR] | ||
15 | [\fB-l\fR | \fB--list-filters\fR] | ||
16 | [<input-file>[ <output-file>]] | ||
17 | |||
18 | .SH DESCRIPTION | ||
19 | |||
20 | midifilter simply strips unwanted events from the Standard MIDI File. You may | ||
21 | wish to strip some certain events if you know the events may break whatever | ||
22 | will do any further processing of the file or just to reduce file size. | ||
23 | |||
24 | if you want to load file from standard input or dump results to standard output | ||
25 | just omit corresponding file or specify '-'. | ||
26 | |||
27 | .SH OPTIONS | ||
28 | |||
29 | .TP | ||
30 | \fB-h\fR, \fB--help\fR, \fB--usage\fR | ||
31 | Display short usage message and exit. | ||
32 | .TP | ||
33 | \fB-V\fR, \fB--version\fR | ||
34 | Report version and exit. | ||
35 | .TP | ||
36 | \fB-L\fR, \fB--license\fR | ||
37 | Show licensing terms. | ||
38 | .TP | ||
39 | \fB-f\fR \fI<filters>\fR, \fB--filter=\fI<filters\fR | ||
40 | Specify the list of comma-separated filters to apply. | ||
41 | .TP | ||
42 | \fB-l\fR, \fB--list-filters\fR | ||
43 | List available filters. | ||
44 | |||
45 | .SH EXAMPLE | ||
46 | |||
47 | .TP | ||
48 | .nf | ||
49 | \fBmidi2f0\fR midifile.mid \\ | ||
50 | | \fBmidifilter\fR \fB-f\fR \fBsysex,meta_unknown,meta_obsolete,meta_texts\fR \\ | ||
51 | >/mnt/card/casio_md/midifile.mid | ||
52 | .fi | ||
53 | |||
54 | This command converts file to SMF0 file, strips events not understood and not | ||
55 | used by the keyboard and puts it to the memory card. | ||
56 | |||
57 | .SH EXIT STATUS | ||
58 | |||
59 | Zero in case of success, non-zero otherwise. | ||
60 | |||
61 | .SH AUTHOR | ||
62 | |||
63 | Written by Michael 'hacker' Krelin <hacker@klever.net> | ||
64 | |||
65 | .SH COPYRIGHT | ||
66 | |||
67 | Copyright (c) 2006 Klever Group (http://www.klever.net/) | ||
68 | |||
69 | Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
70 | this software and associated documentation files (the "Software"), to deal in | ||
71 | the Software without restriction, including without limitation the rights to | ||
72 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | ||
73 | of the Software, and to permit persons to whom the Software is furnished to do | ||
74 | so, subject to the following conditions: | ||
75 | |||
76 | The above copyright notice and this permission notice shall be included in all | ||
77 | copies or substantial portions of the Software. | ||
78 | |||
79 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
80 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
81 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
82 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
83 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
84 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
85 | SOFTWARE. | ||
86 | |||
87 | .SH BUGS | ||
88 | |||
89 | You tell me. Send reports to <midillo-bugs@klever.net> | ||
90 | |||
91 | .SH SEE ALSO | ||
92 | \fBmidi2f0\fR(1) | ||
93 | \fBmididump\fR(1) | ||
diff --git a/midillo.pc.in b/midillo.pc.in new file mode 100644 index 0000000..dd57130 --- a/dev/null +++ b/midillo.pc.in | |||
@@ -0,0 +1,11 @@ | |||
1 | prefix=@prefix@ | ||
2 | exec_prefix=@exec_prefix@ | ||
3 | libdir=@libdir@ | ||
4 | includedir=@includedir@ | ||
5 | |||
6 | Name: midillo | ||
7 | Description: C++ midi manipulation library | ||
8 | Version: @VERSION@ | ||
9 | Requires: konforka | ||
10 | Libs: -L${libdir} -lmidillo | ||
11 | Cflags: -I${includedir} | ||
diff --git a/tools/.gitignore b/tools/.gitignore new file mode 100644 index 0000000..6d68099 --- a/dev/null +++ b/tools/.gitignore | |||
@@ -0,0 +1,11 @@ | |||
1 | Makefile.in | ||
2 | *.o | ||
3 | midifilter | ||
4 | midi2f0 | ||
5 | mididump | ||
6 | .libs | ||
7 | .deps | ||
8 | Makefile | ||
9 | COPYING.cc | ||
10 | filters_enumeration.cc | ||
11 | filters_definition.cc | ||
diff --git a/tools/Makefile.am b/tools/Makefile.am new file mode 100644 index 0000000..811c4f8 --- a/dev/null +++ b/tools/Makefile.am | |||
@@ -0,0 +1,31 @@ | |||
1 | bin_PROGRAMS = midi2f0 midifilter mididump | ||
2 | |||
3 | INCLUDES = -I${top_srcdir}/include ${KONFORKA_CFLAGS} | ||
4 | LIBS += ${top_builddir}/lib/libmidillo.la ${KONFORKA_LIBS} | ||
5 | |||
6 | midi2f0_SOURCES = midi2f0.cc \ | ||
7 | COPYING.cc | ||
8 | midi2f0_DEPENDENCIES = ${top_builddir}/lib/libmidillo.la | ||
9 | |||
10 | midifilter_SOURCES = midifilter.cc \ | ||
11 | COPYING.cc \ | ||
12 | filters.list \ | ||
13 | enflesh_filters_list.sh | ||
14 | midifilter_DEPENDENCIES = ${top_builddir}/lib/libmidillo.la | ||
15 | ${srcdir}/midifilter.cc: filters_enumeration.cc filters_definition.cc | ||
16 | filters_enumeration.cc filters_definition.cc: enflesh_filters_list.sh filters.list | ||
17 | sh $^ \ | ||
18 | filters_enumeration.cc filters_definition.cc | ||
19 | |||
20 | mididump_SOURCES = mididump.cc \ | ||
21 | COPYING.cc | ||
22 | mididump_DEPENDENCIES = ${top_builddir}/lib/libmidillo.la | ||
23 | |||
24 | clean-local: | ||
25 | rm -f filters_enumeration.cc filters_definition.cc | ||
26 | |||
27 | |||
28 | COPYING.cc: ${top_srcdir}/COPYING | ||
29 | echo "const char * COPYING =" >$@ || (rm $@;exit 1) | ||
30 | sed 's/"/\\"/g' $< | sed 's/^/\"/' | sed 's/$$/\\n\"/' >>$@ || (rm $@;exit 1) | ||
31 | echo ";" >>$@ || (rm $@;exit 1) | ||
diff --git a/tools/enflesh_filters_list.sh b/tools/enflesh_filters_list.sh new file mode 100644 index 0000000..f1d8dfc --- a/dev/null +++ b/tools/enflesh_filters_list.sh | |||
@@ -0,0 +1,20 @@ | |||
1 | #!/bin/sh | ||
2 | srcfile="${1}" | ||
3 | enumfile="${2}" | ||
4 | deffile="${3}" | ||
5 | IFS=':' | ||
6 | exec 5>${enumfile} | ||
7 | exec 6>${deffile} | ||
8 | SEQN=0 | ||
9 | LN=0 | ||
10 | cat ${srcfile} \ | ||
11 | | while read id ids help ; do | ||
12 | LN="`expr ${LN} + 1`" | ||
13 | test -z "${id}" && continue | ||
14 | test "${id}" != "${id# }" && continue | ||
15 | echo "#line ${LN} \"${srcfile}\"" >&5 | ||
16 | echo " filter_${id} = ${SEQN}," >&5 | ||
17 | echo "#line ${LN} \"${srcfile}\"" >&6 | ||
18 | echo ' { { "'$(echo $ids|sed -e 's-/-", "-g')'", 0 }, "'"${help}"'", false },' >&6 | ||
19 | SEQN="`expr ${SEQN} + 1`" | ||
20 | done | ||
diff --git a/tools/filters.list b/tools/filters.list new file mode 100644 index 0000000..c0fb951 --- a/dev/null +++ b/tools/filters.list | |||
@@ -0,0 +1,36 @@ | |||
1 | system:system:strip all system messages | ||
2 | meta:meta:strip all meta events (except for EOT) | ||
3 | |||
4 | sysex:sysex:strip sysex messages | ||
5 | MTC_quarter_frame:MTC_quarter_frame/quarter_frame:strip 'MTC quarter frame' messages | ||
6 | song_position_pointer:song_position_pointer:strip 'song position pointer' messages | ||
7 | song_select:song_select:strip 'song select' messages | ||
8 | tune_request:tune_request:strip 'tune request' messages | ||
9 | |||
10 | midi_clock:midi_clock/timing_clock:strip 'midi clock' messages | ||
11 | midi_tick:midi_tick:strip 'midi tick' messages | ||
12 | midi_start:midi_start/start:strip 'midi start' messages | ||
13 | midi_continue:midi_continue/continue:strip 'midi continue' messages | ||
14 | midi_stop:midi_stop/stop:strip 'midi stop' messages | ||
15 | active_sense:active_sense:strip 'active sense' messages | ||
16 | |||
17 | meta_sequence_number:meta_sequence_number:strip 'sequence number' meta events | ||
18 | meta_text:meta_text:strip 'text' meta events | ||
19 | meta_copyright:meta_copyright:strip 'copyright' meta events | ||
20 | meta_seq_track_name:meta_seq_track_name:strip 'sequence track name' meta events | ||
21 | meta_instrument:meta_instrument:strip 'instrument' meta events | ||
22 | meta_lyric:meta_lyric/meta_lyrics:strip 'lyric' meta events | ||
23 | meta_marker:meta_marker:strip 'marker' meta events | ||
24 | meta_cue_point:meta_cue_point:strip 'cue point' meta events | ||
25 | meta_patch_name:meta_patch_name/meta_program_name:strip 'patch name' meta events | ||
26 | meta_port_name:meta_port_name/meta_device_name:strip 'port name' meta events | ||
27 | meta_tempo:meta_temp:strip 'tempo' meta events | ||
28 | meta_SMPTE_offset:meta_SMPTE_offset:strip 'SMPTE offset' meta events | ||
29 | meta_time_sig:meta_time_sig:strip 'time signature' meta events | ||
30 | meta_key_sig:meta_key_sig:strip 'key signature' meta events | ||
31 | meta_proprietary:meta_proprietary:strip 'proprietary' meta events | ||
32 | |||
33 | meta_midi_channel:meta_midi_channel:strip 'midi channel' meta events | ||
34 | meta_midi_port:meta_midi_port:strip 'midi port' meta events | ||
35 | |||
36 | meta_unknown:meta_unknown:strip meta events not known by midillo | ||
diff --git a/tools/midi2f0.cc b/tools/midi2f0.cc new file mode 100644 index 0000000..dc95be6 --- a/dev/null +++ b/tools/midi2f0.cc | |||
@@ -0,0 +1,151 @@ | |||
1 | #include <getopt.h> | ||
2 | #include <iostream> | ||
3 | #include <algorithm> | ||
4 | using namespace std; | ||
5 | #include <konforka/exception.h> | ||
6 | #include <midillo/SMF.h> | ||
7 | using namespace midillo; | ||
8 | |||
9 | #include "config.h" | ||
10 | #define PHEADER PACKAGE " " VERSION " - midi2f0 - convert to midi format 0" | ||
11 | #define PCOPY "Copyright (c) 2006 Klever Group" | ||
12 | |||
13 | static void usage(const char *p) { | ||
14 | cerr << PHEADER << endl | ||
15 | << PCOPY << endl << endl | ||
16 | << " " << p << " [options] [<input-file>[ <output-file>]]" << endl << endl | ||
17 | << " -h, --help" << endl | ||
18 | << " --usage display this text" << endl | ||
19 | << " -V, --version display version number" << endl | ||
20 | << " -L, --license show license" << endl; | ||
21 | } | ||
22 | |||
23 | static bool MTrk_is_empty(const MTrk_t& t) { | ||
24 | return | ||
25 | t.events.empty() | ||
26 | || t.events.front().message.is_meta(meta_EOT); | ||
27 | } | ||
28 | |||
29 | static bool MTrk_deltat_lt(const MTrk_t& a,const MTrk_t& b) { | ||
30 | // we assume tracks aren't empty | ||
31 | return a.events.front().deltat < b.events.front().deltat; | ||
32 | } | ||
33 | |||
34 | static bool event_has_nonzero_deltat_or_is_EOT(const event_t& e) { | ||
35 | return e.deltat!=0 || e.message.is_meta(meta_EOT); | ||
36 | } | ||
37 | |||
38 | main(int argc,char **argv) { | ||
39 | try { | ||
40 | while(true) { | ||
41 | static struct option opts[] = { | ||
42 | { "help", no_argument, 0, 'h' }, | ||
43 | { "usage", no_argument, 0, 'h' }, | ||
44 | { "version", no_argument, 0, 'V' }, | ||
45 | { "license", no_argument, 0, 'L' }, | ||
46 | { NULL, 0, 0, 0 } | ||
47 | }; | ||
48 | int c = getopt_long(argc,argv,"hVL",opts,NULL); | ||
49 | if(c==-1) | ||
50 | break; | ||
51 | switch(c) { | ||
52 | case 'h': | ||
53 | usage(*argv); | ||
54 | exit(0); | ||
55 | break; | ||
56 | case 'V': | ||
57 | cerr << VERSION << endl; | ||
58 | exit(0); | ||
59 | break; | ||
60 | case 'L': | ||
61 | extern const char *COPYING; | ||
62 | cerr << COPYING << endl; | ||
63 | exit(0); | ||
64 | break; | ||
65 | default: | ||
66 | cerr << "Huh??" << endl; | ||
67 | break; | ||
68 | } | ||
69 | } | ||
70 | const char *infile = "-"; | ||
71 | if(optind<argc) | ||
72 | infile = argv[optind++]; | ||
73 | const char *oufile = "-"; | ||
74 | if(optind<argc) | ||
75 | oufile = argv[optind++]; | ||
76 | if(optind<argc) { | ||
77 | usage(*argv); | ||
78 | exit(1); | ||
79 | } | ||
80 | SMF_t in(infile); | ||
81 | if(in.mthd.fmt==MThd_t::fmt_0) { | ||
82 | cerr << "File is already SMF 0" << endl; | ||
83 | in.save(oufile); | ||
84 | }else if(in.mthd.fmt==MThd_t::fmt_1) { | ||
85 | cerr << "Converting from SMF 1 to SMF 0" << endl; | ||
86 | SMF_t ou; | ||
87 | ou.mthd = in.mthd; | ||
88 | ou.mthd.fmt = MThd_t::fmt_0; ou.mthd.ntracks = 1; | ||
89 | ou.tracks.resize(1); | ||
90 | MTrk_t& mtrk = ou.tracks.front(); | ||
91 | events_t& evs = mtrk.events; | ||
92 | for(;;) { | ||
93 | // Cleaning up empty tracks | ||
94 | in.tracks.erase( | ||
95 | remove_if( | ||
96 | in.tracks.begin(),in.tracks.end(), | ||
97 | MTrk_is_empty), | ||
98 | in.tracks.end() ); | ||
99 | if(in.tracks.empty()) | ||
100 | break; | ||
101 | // Find the least deltat | ||
102 | unsigned long mindt = min_element( | ||
103 | in.tracks.begin(), in.tracks.end(), | ||
104 | MTrk_deltat_lt )->events.front().deltat; | ||
105 | int t=0; | ||
106 | bool reset = false; | ||
107 | for(SMF_t::tracks_t::iterator i=in.tracks.begin();i!=in.tracks.end();++i) { | ||
108 | if(i->events.front().deltat > mindt) { | ||
109 | i->events.front().deltat-=mindt; | ||
110 | }else{ | ||
111 | do{ | ||
112 | evs.splice( | ||
113 | evs.end(), | ||
114 | i->events,i->events.begin() ); | ||
115 | if(reset) | ||
116 | evs.back().deltat = 0; | ||
117 | else | ||
118 | reset = true; | ||
119 | events_t::iterator lze=find_if( | ||
120 | i->events.begin(),i->events.end(), | ||
121 | event_has_nonzero_deltat_or_is_EOT ); | ||
122 | evs.splice( | ||
123 | evs.end(), | ||
124 | i->events,i->events.begin(),lze ); | ||
125 | }while( (!MTrk_is_empty(*i)) && i->events.front().deltat==0 ); | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | event_t& eot = *evs.append_event(); | ||
130 | eot.deltat=0; | ||
131 | eot.message.status = status_system_meta; | ||
132 | eot.message.meta_status = meta_EOT; | ||
133 | ou.save(oufile); | ||
134 | }else if(in.mthd.fmt==MThd_t::fmt_2) { | ||
135 | // TODO | ||
136 | cerr << "Not implemented" << endl; | ||
137 | }else{ | ||
138 | cerr << "Unknown MIDI file format" << endl; | ||
139 | } | ||
140 | return 0; | ||
141 | }catch(konforka::exception& e) { | ||
142 | cerr << "Oops... Konforka exception:" << endl | ||
143 | << " what: " << e.what() << endl | ||
144 | << " where: " << e.where() << endl; | ||
145 | return 1; | ||
146 | }catch(exception& e) { | ||
147 | cerr << "Oops... Exception:" << endl | ||
148 | << " what: " << e.what() << endl; | ||
149 | return 1; | ||
150 | } | ||
151 | } | ||
diff --git a/tools/mididump.cc b/tools/mididump.cc new file mode 100644 index 0000000..83b7086 --- a/dev/null +++ b/tools/mididump.cc | |||
@@ -0,0 +1,84 @@ | |||
1 | #include <getopt.h> | ||
2 | #include <iostream> | ||
3 | #include <fstream> | ||
4 | #include <string> | ||
5 | #include <algorithm> | ||
6 | using namespace std; | ||
7 | #include <konforka/exception.h> | ||
8 | #include <midillo/SMF.h> | ||
9 | using namespace midillo; | ||
10 | |||
11 | #include "config.h" | ||
12 | #define PHEADER PACKAGE " " VERSION " - mididump - dump midi files" | ||
13 | #define PCOPY "Copyright (c) 2006 Klever Group" | ||
14 | |||
15 | static void usage(const char *p) { | ||
16 | cerr << PHEADER << endl | ||
17 | << PCOPY << endl << endl | ||
18 | << " " << p << " [options] [<input-file>[ <output-file>]]" << endl << endl | ||
19 | << " -h, --help" << endl | ||
20 | << " --usage display this text" << endl | ||
21 | << " -V, --version display version number" << endl | ||
22 | << " -L, --license show license" << endl; | ||
23 | } | ||
24 | |||
25 | main(int argc,char **argv) { | ||
26 | try { | ||
27 | while(true) { | ||
28 | static struct option opts[] = { | ||
29 | { "help", no_argument, 0, 'h' }, | ||
30 | { "usage", no_argument, 0, 'h' }, | ||
31 | { "version", no_argument, 0, 'V' }, | ||
32 | { "license", no_argument, 0, 'L' }, | ||
33 | { NULL, 0, 0, 0 } | ||
34 | }; | ||
35 | int c = getopt_long(argc,argv,"f:hVLl",opts,NULL); | ||
36 | if(c==-1) | ||
37 | break; | ||
38 | switch(c) { | ||
39 | case 'h': | ||
40 | usage(*argv); | ||
41 | exit(0); | ||
42 | break; | ||
43 | case 'V': | ||
44 | cerr << VERSION << endl; | ||
45 | exit(0); | ||
46 | break; | ||
47 | case 'L': | ||
48 | extern const char *COPYING; | ||
49 | cerr << COPYING << endl; | ||
50 | exit(0); | ||
51 | break; | ||
52 | default: | ||
53 | cerr << "Huh??" << endl; | ||
54 | break; | ||
55 | } | ||
56 | } | ||
57 | const char *infile = "-"; | ||
58 | if(optind<argc) | ||
59 | infile = argv[optind++]; | ||
60 | const char *oufile = "-"; | ||
61 | if(optind<argc) | ||
62 | oufile = argv[optind++]; | ||
63 | if(optind<argc) { | ||
64 | usage(*argv); | ||
65 | exit(1); | ||
66 | } | ||
67 | SMF_t in(infile); | ||
68 | if(strcmp(oufile,"-")) { | ||
69 | ofstream s(oufile); s << in; | ||
70 | }else{ | ||
71 | cout << in; | ||
72 | } | ||
73 | return 0; | ||
74 | }catch(konforka::exception& e) { | ||
75 | cerr << "Oops... Konforka exception:" << endl | ||
76 | << " what: " << e.what() << endl | ||
77 | << " where: " << e.where() << endl; | ||
78 | return 1; | ||
79 | }catch(exception& e) { | ||
80 | cerr << "Oops... Exception:" << endl | ||
81 | << " what: " << e.what() << endl; | ||
82 | return 1; | ||
83 | } | ||
84 | } | ||
diff --git a/tools/midifilter.cc b/tools/midifilter.cc new file mode 100644 index 0000000..1c130de --- a/dev/null +++ b/tools/midifilter.cc | |||
@@ -0,0 +1,295 @@ | |||
1 | #include <getopt.h> | ||
2 | #include <iostream> | ||
3 | #include <string> | ||
4 | #include <algorithm> | ||
5 | #include <iterator> | ||
6 | using namespace std; | ||
7 | #include <konforka/exception.h> | ||
8 | #include <midillo/SMF.h> | ||
9 | using namespace midillo; | ||
10 | |||
11 | #include "config.h" | ||
12 | #define PHEADER PACKAGE " " VERSION " - midifilter - midi filter tool" | ||
13 | #define PCOPY "Copyright (c) 2006 Klever Group" | ||
14 | |||
15 | enum { | ||
16 | # include "filters_enumeration.cc" | ||
17 | total_filters | ||
18 | }; | ||
19 | |||
20 | struct filter_t { | ||
21 | const char *ids[5]; | ||
22 | const char *help; | ||
23 | bool filter; | ||
24 | } filters[] = { | ||
25 | # include "filters_definition.cc" | ||
26 | {0,0,0} | ||
27 | }; | ||
28 | #define FILTER(f) filters[filter_##f].filter | ||
29 | |||
30 | inline ostream& operator<<(ostream& s,const filter_t& f) { | ||
31 | ios::fmtflags ff = s.flags(); | ||
32 | int w = s.width(25); | ||
33 | s.unsetf(ios::right); s.setf(ios::left); | ||
34 | s << *f.ids << " " << f.help; | ||
35 | s.width(w); | ||
36 | s.flags(ff); | ||
37 | return s; | ||
38 | } | ||
39 | |||
40 | static bool message_is_filtered(const message_t& m) { | ||
41 | if(m.is_meta(meta_EOT)) | ||
42 | return false; | ||
43 | |||
44 | if(FILTER(sysex) && (m.status==status_system_sysex || m.status==status_system_end_of_sysex)) | ||
45 | return true; | ||
46 | if(FILTER(MTC_quarter_frame) && m.status==status_system_MTC_quarter_frame) | ||
47 | return true; | ||
48 | if(FILTER(song_position_pointer) && m.status==status_system_song_position_pointer) | ||
49 | return true; | ||
50 | if(FILTER(song_select) && m.status==status_system_song_select) | ||
51 | return true; | ||
52 | if(FILTER(tune_request) && m.status==status_system_tune_request) | ||
53 | return true; | ||
54 | if(FILTER(midi_clock) && m.status==status_system_midi_clock) | ||
55 | return true; | ||
56 | if(FILTER(midi_tick) && m.status==status_system_midi_tick) | ||
57 | return true; | ||
58 | if(FILTER(midi_start) && m.status==status_system_midi_start) | ||
59 | return true; | ||
60 | if(FILTER(midi_continue) && m.status==status_system_midi_continue) | ||
61 | return true; | ||
62 | if(FILTER(midi_stop) && m.status==status_system_midi_stop) | ||
63 | return true; | ||
64 | if(FILTER(active_sense) && m.status==status_system_active_sense) | ||
65 | return true; | ||
66 | |||
67 | if(FILTER(meta_sequence_number) && m.is_meta(meta_sequence_number)) | ||
68 | return true; | ||
69 | if(FILTER(meta_text) && m.is_meta(meta_text)) | ||
70 | return true; | ||
71 | if(FILTER(meta_copyright) && m.is_meta(meta_copyright)) | ||
72 | return true; | ||
73 | if(FILTER(meta_seq_track_name) && m.is_meta(meta_seq_track_name)) | ||
74 | return true; | ||
75 | if(FILTER(meta_instrument) && m.is_meta(meta_instrument)) | ||
76 | return true; | ||
77 | if(FILTER(meta_lyric) && m.is_meta(meta_lyric)) | ||
78 | return true; | ||
79 | if(FILTER(meta_marker) && m.is_meta(meta_marker)) | ||
80 | return true; | ||
81 | if(FILTER(meta_cue_point) && m.is_meta(meta_cue_point)) | ||
82 | return true; | ||
83 | if(FILTER(meta_patch_name) && m.is_meta(meta_patch_name)) | ||
84 | return true; | ||
85 | if(FILTER(meta_port_name) && m.is_meta(meta_port_name)) | ||
86 | return true; | ||
87 | if(FILTER(meta_tempo) && m.is_meta(meta_tempo)) | ||
88 | return true; | ||
89 | if(FILTER(meta_SMPTE_offset) && m.is_meta(meta_SMPTE_offset)) | ||
90 | return true; | ||
91 | if(FILTER(meta_time_sig) && m.is_meta(meta_time_sig)) | ||
92 | return true; | ||
93 | if(FILTER(meta_key_sig) && m.is_meta(meta_key_sig)) | ||
94 | return true; | ||
95 | if(FILTER(meta_proprietary) && m.is_meta(meta_proprietary)) | ||
96 | return true; | ||
97 | |||
98 | if(FILTER(meta_midi_channel) && m.is_meta(meta_midi_channel)) | ||
99 | return true; | ||
100 | if(FILTER(meta_midi_port) && m.is_meta(meta_midi_port)) | ||
101 | return true; | ||
102 | |||
103 | if(FILTER(meta_unknown) && m.is_meta()) { | ||
104 | const int known_metas[] = { | ||
105 | meta_sequence_number, meta_text, meta_copyright, meta_seq_track_name, | ||
106 | meta_instrument, meta_lyric, meta_marker, meta_cue_point, | ||
107 | meta_patch_name, meta_port_name, meta_EOT, meta_tempo, | ||
108 | meta_SMPTE_offset, meta_time_sig, meta_key_sig, meta_proprietary, | ||
109 | meta_midi_channel, meta_midi_port }; | ||
110 | const int* lastknown = &known_metas[sizeof(known_metas)/sizeof(*known_metas)]; | ||
111 | if( find( | ||
112 | known_metas, lastknown, | ||
113 | m.meta_status ) == lastknown ) { | ||
114 | return true; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | if(FILTER(meta) && m.is_meta()) | ||
119 | return true; | ||
120 | |||
121 | return false; | ||
122 | } | ||
123 | |||
124 | static bool event_is_filtered(const event_t& e) { | ||
125 | return message_is_filtered(e.message); | ||
126 | } | ||
127 | |||
128 | static bool MTrk_is_empty(const MTrk_t& t) { | ||
129 | return | ||
130 | t.events.empty() | ||
131 | || t.events.front().message.is_meta(meta_EOT); | ||
132 | } | ||
133 | |||
134 | struct filter_preset_t { | ||
135 | const char *id; | ||
136 | const char *help; | ||
137 | int filters[total_filters]; | ||
138 | } filter_presets[] = { | ||
139 | { "system_common", "strip system common messages", | ||
140 | { filter_sysex, filter_song_position_pointer, filter_song_select, | ||
141 | filter_tune_request, -1 } }, | ||
142 | { "system_runtime", "strip system runtime messages", | ||
143 | { filter_midi_clock, filter_midi_tick, filter_midi_start, | ||
144 | filter_midi_continue, filter_midi_stop, filter_active_sense, -1 } }, | ||
145 | { "meta_obsolete", "strip obsolete meta events", | ||
146 | { filter_meta_midi_channel, filter_meta_midi_port, -1 } }, | ||
147 | { "meta_texts", "strip textual meta events", | ||
148 | { filter_meta_text, filter_meta_copyright, | ||
149 | filter_meta_seq_track_name, filter_meta_instrument, | ||
150 | filter_meta_lyric, filter_meta_marker, filter_meta_cue_point, | ||
151 | filter_meta_patch_name, filter_meta_port_name, -1 } } | ||
152 | }; | ||
153 | |||
154 | inline ostream& operator<<(ostream& s,const filter_preset_t& fp) { | ||
155 | ios::fmtflags ff = s.flags(); | ||
156 | int w = s.width(25); | ||
157 | s.unsetf(ios::right); s.setf(ios::left); | ||
158 | s << fp.id << " " << fp.help; | ||
159 | s.width(w); | ||
160 | s.flags(ff); | ||
161 | return s; | ||
162 | } | ||
163 | |||
164 | static void usage(const char *p) { | ||
165 | cerr << PHEADER << endl | ||
166 | << PCOPY << endl << endl | ||
167 | << " " << p << " [options] [<input-file>[ <output-file>]]" << endl << endl | ||
168 | << " -h, --help" << endl | ||
169 | << " --usage display this text" << endl | ||
170 | << " -V, --version display version number" << endl | ||
171 | << " -L, --license show license" << endl | ||
172 | << " -f <filters>, --filter=<filters>" | ||
173 | << " specify the list of events (comma-separated) to" << endl | ||
174 | << " strip" << endl | ||
175 | << " -l, --list-filters" << endl | ||
176 | << " list available filters" << endl; | ||
177 | } | ||
178 | |||
179 | main(int argc,char **argv) { | ||
180 | try { | ||
181 | while(true) { | ||
182 | static struct option opts[] = { | ||
183 | { "help", no_argument, 0, 'h' }, | ||
184 | { "usage", no_argument, 0, 'h' }, | ||
185 | { "version", no_argument, 0, 'V' }, | ||
186 | { "license", no_argument, 0, 'L' }, | ||
187 | { "filter", no_argument, 0, 'f' }, | ||
188 | { "list-filters", no_argument, 0, 'l' }, | ||
189 | { NULL, 0, 0, 0 } | ||
190 | }; | ||
191 | int c = getopt_long(argc,argv,"f:hVLl",opts,NULL); | ||
192 | if(c==-1) | ||
193 | break; | ||
194 | switch(c) { | ||
195 | case 'h': | ||
196 | usage(*argv); | ||
197 | exit(0); | ||
198 | break; | ||
199 | case 'V': | ||
200 | cerr << VERSION << endl; | ||
201 | exit(0); | ||
202 | break; | ||
203 | case 'L': | ||
204 | extern const char *COPYING; | ||
205 | cerr << COPYING << endl; | ||
206 | exit(0); | ||
207 | break; | ||
208 | case 'f': | ||
209 | { | ||
210 | string fs = optarg; | ||
211 | while(!fs.empty()) { | ||
212 | string::size_type ns = fs.find_first_not_of(" :/,;"); | ||
213 | if(ns==string::npos) | ||
214 | break; | ||
215 | if(ns) | ||
216 | fs.erase(ns); | ||
217 | string::size_type s = fs.find_first_of(" :/,;"); | ||
218 | string f; | ||
219 | if(s==string::npos) { | ||
220 | f = fs; fs.clear(); | ||
221 | }else{ | ||
222 | f = fs.substr(0,ns); | ||
223 | fs.erase(0,ns+1); | ||
224 | } | ||
225 | for(int fn=0;fn<total_filters;++fn) { | ||
226 | filter_t& filter = filters[fn]; | ||
227 | for(int fid=0;fid<(sizeof(filter.ids)/sizeof(*filter.ids)) && filter.ids[fid];++fid) { | ||
228 | if(f == filter.ids[fid]) | ||
229 | filter.filter = true; | ||
230 | } | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | break; | ||
235 | case 'l': | ||
236 | cerr << PHEADER << endl | ||
237 | << PCOPY << endl << endl; | ||
238 | copy( | ||
239 | filters, &filters[total_filters], | ||
240 | ostream_iterator<filter_t>(cerr,"\n") ); | ||
241 | copy( | ||
242 | filter_presets, &filter_presets[sizeof(filter_presets)/sizeof(*filter_presets)], | ||
243 | ostream_iterator<filter_preset_t>(cerr,"\n") ); | ||
244 | exit(0); | ||
245 | break; | ||
246 | default: | ||
247 | cerr << "Huh??" << endl; | ||
248 | break; | ||
249 | } | ||
250 | } | ||
251 | const char *infile = "-"; | ||
252 | if(optind<argc) | ||
253 | infile = argv[optind++]; | ||
254 | const char *oufile = "-"; | ||
255 | if(optind<argc) | ||
256 | oufile = argv[optind++]; | ||
257 | if(optind<argc) { | ||
258 | usage(*argv); | ||
259 | exit(1); | ||
260 | } | ||
261 | SMF_t in(infile); | ||
262 | for(SMF_t::tracks_t::iterator t=in.tracks.begin();t!=in.tracks.end();++t) { | ||
263 | for(events_t::iterator e=t->events.begin();e!=t->events.end();) { | ||
264 | if(event_is_filtered(*e)) { | ||
265 | events_t::iterator i = e++; | ||
266 | // we assume it is not the last event, since the last event | ||
267 | // (meta_EOT) is unfilterable | ||
268 | e->deltat += i->deltat; | ||
269 | t->events.erase(i); | ||
270 | }else | ||
271 | ++e; | ||
272 | } | ||
273 | } | ||
274 | in.tracks.erase( | ||
275 | remove_if( | ||
276 | in.tracks.begin(),in.tracks.end(), | ||
277 | MTrk_is_empty), | ||
278 | in.tracks.end() ); | ||
279 | if(in.tracks.empty()) { | ||
280 | cerr << "We have no MIDI data in the output file"; | ||
281 | } | ||
282 | in.mthd.ntracks = in.tracks.size(); | ||
283 | in.save(oufile); | ||
284 | return 0; | ||
285 | }catch(konforka::exception& e) { | ||
286 | cerr << "Oops... Konforka exception:" << endl | ||
287 | << " what: " << e.what() << endl | ||
288 | << " where: " << e.where() << endl; | ||
289 | return 1; | ||
290 | }catch(exception& e) { | ||
291 | cerr << "Oops... Exception:" << endl | ||
292 | << " what: " << e.what() << endl; | ||
293 | return 1; | ||
294 | } | ||
295 | } | ||