Skip to content

Commit

Permalink
Fixed nagging little errors in parsing MIDI files.
Browse files Browse the repository at this point in the history
  • Loading branch information
ahlstromcj committed Dec 17, 2023
1 parent 1d841d0 commit 60daea2
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 79 deletions.
23 changes: 9 additions & 14 deletions TODO
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
TO DO for Seq66 0.99.12
Chris Ahlstrom
2019-04-13 to 2023-12-15
2019-04-13 to 2023-12-17

Misc:

- Clang-16:
- CLANG and LO_TT_IMMEDIATE: warning: compound literals are a
C99-specific feature [-Wc99-extensions]. See
#define LO_TT_IMMEDIATE ((lo_timetag){0U,1U}) in lo_osc_types.h.
- clang-16: warning: optimization flag '-fno-fat-lto-objects'
is not supported [-Wignored-optimization-argument]
- PortMidi autoconf build: segfault in release mode. For seq66cli,
mastermidibus_pm.h not found in main module.
- Grid-mode options:
- Needs to be made a queued solo; how to handle
mod_replace (Key_Home) and mod_snapshot (Ins)
Expand All @@ -21,19 +13,22 @@ Misc:
MIDI automation of these displays in the pattern editor.
- Make sure metronome buttons etc. still work. Recorded measures
not saved.
- The Hide button gets focus automatically and it should not.
- Opening a MIDI file should stop playback.
- Show time-sigs in grid slot?
- trilogy.mid errors basically fixed with new 'rc' work-around.
- Write a module to show SysEx (and optionally store them as
a macro).
- Improve the output of text events in the slot_dump() function.
- Test F7 SysEx continuation messages.
- Dixie04.mid has proven to be quite intractable.
- Consider an option to remove all SysEx from a pattern or
tune.
tune or ignore it on reading.
- The Carpet song has PPQN = 120 and displays weirdly in pattern editor.
Too difficult to fix at this time; converted it to 192.
- Clang-16:
- clang-16: warning: optimization flag '-fno-fat-lto-objects'
is not supported [-Wignored-optimization-argument]. That
flag does not prevent this warning. Ignoring it for now.
- PortMidi autoconf build: segfault in release mode. For seq66cli,
mastermidibus_pm.h not found in main module.
- Show time-sigs in grid slot?

Mutes:

Expand Down
Binary file modified contrib/midi/CountryStrum.mid
Binary file not shown.
4 changes: 3 additions & 1 deletion libseq66/include/midi/midifile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
* \library seq66 application
* \author Chris Ahlstrom
* \date 2015-07-24
* \updates 2023-12-15
* \updates 2023-12-17
* \license GNU GPLv2 or above
*
* The Seq24 MIDI file is a standard, Format 1 MIDI file, with some extra
Expand Down Expand Up @@ -435,7 +435,9 @@ class midifile
bool write_seqspec_track (performer & p);
long varinum_size (long len) const;
long prop_item_size (long datalen) const;
bool track_error (const std::string & context, int track);
bool set_error (const std::string & msg);
bool append_error (const std::string & msg);
bool set_error_dump (const std::string & msg);
bool set_error_dump (const std::string & msg, unsigned long p);

Expand Down
139 changes: 75 additions & 64 deletions libseq66/src/midi/midifile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* \library seq66 application
* \author Chris Ahlstrom
* \date 2015-07-24
* \updates 2023-12-15
* \updates 2023-12-17
* \license GNU GPLv2 or above
*
* For a quick guide to the MIDI format, see, for example:
Expand Down Expand Up @@ -362,7 +362,7 @@ midifile::read_byte ()
return m_data[m_pos++];
}
else if (! m_disable_reported)
(void) set_error_dump("'End-of-file', aborting MIDI reading");
(void) set_error_dump("End-of-file; aborting reading");

return 0;
}
Expand Down Expand Up @@ -690,7 +690,7 @@ midifile::read_gap (size_t sz)
{
p = m_file_size - 1;
if (! m_disable_reported)
(void) set_error_dump("'End-of-file', MIDI reading disabled");
(void) set_error_dump("End-of-file; reading disabled");
}
m_pos = p;
}
Expand Down Expand Up @@ -724,7 +724,7 @@ midifile::grab_input_stream (const std::string & tag)
m_file_size = file_size(m_name);
if (m_name.empty() || m_file_size == 0)
{
return set_error("Bad MIDI file");
return set_error("No MIDI file or data.");
}

std::ifstream file(m_name, std::ios::in | std::ios::binary | std::ios::ate);
Expand All @@ -745,7 +745,7 @@ midifile::grab_input_stream (const std::string & tag)
#endif
if (m_file_size < c_minimum_midi_file_size)
{
result = set_error("File too small");
result = set_error("File too small.");
}
else
{
Expand All @@ -757,7 +757,7 @@ midifile::grab_input_stream (const std::string & tag)
}
catch (const std::bad_alloc & ex)
{
result = set_error("MIDI file stream memory allocation failed");
result = set_error("File stream memory allocation failed.");
}
file.close();
}
Expand Down Expand Up @@ -939,7 +939,7 @@ midifile::parse_smf_0 (performer & p, int screenset)
p.smf_format(1); /* converted to SMF 1 */
}
else
result = set_error("No SMF 0 track found, bad MIDI file");
result = append_error("SMF 0 split failed.");
}
}
else if (result)
Expand Down Expand Up @@ -1313,7 +1313,7 @@ midifile::parse_smf_1 (performer & p, int screenset, bool is_smf0)
{
case EVENT_META_SEQ_NUMBER: /* FF 00 02 ss */

if (! checklen(len, mtype))
if (! checklen(len, mtype)) /* might log error */
return false;

seqnum = read_short();
Expand Down Expand Up @@ -1695,20 +1695,8 @@ midifile::parse_smf_1 (performer & p, int screenset, bool is_smf0)
* running status after a SysEx event.
*/

std::string msg = "Bad MIDI event";
if (m_running_status_action == rsaction::skip)
{
char temp[64];
snprintf
(
temp, sizeof temp,
"skipping to end of track %d", track
);
msg += "; ";
msg += temp;
skip_to_end = true;
}
(void) set_error_dump(msg, midilong(status));
std::string msg = "Bad event";
skip_to_end = track_error(msg, track);
if (m_running_status_action == rsaction::abort)
return true; /* don't process more tracks */
else
Expand All @@ -1717,8 +1705,8 @@ midifile::parse_smf_1 (performer & p, int screenset, bool is_smf0)
break;
}
if (at_end())
done = true;
} /* while loading Trk chunks */
break;
} /* while loading Trk chunks */

/*
* Sequence has been filled, add it to the performance or SMF 0
Expand All @@ -1728,47 +1716,48 @@ midifile::parse_smf_1 (performer & p, int screenset, bool is_smf0)
* order in the file are used as defaults."
*/

if (at_end())
if (at_end() && ! done) /* done == end-of-track found */
{
break;
std::string msg = "Premature end-of-file";
(void) track_error(msg, track);
if (m_running_status_action == rsaction::abort)
break;
}
else
if (seqnum == c_midishort_max)
seqnum = track;

if (seqnum < c_prop_seq_number)
{
if (seqnum == c_midishort_max)
seqnum = track;
s.set_midi_channel(tentative_channel);
if (! is_null_buss(buss_override))
(void) s.set_midi_bus(buss_override);

if (seqnum < c_prop_seq_number)
if (rc().verbose())
{
s.set_midi_channel(tentative_channel);
if (! is_null_buss(buss_override))
(void) s.set_midi_bus(buss_override);

if (rc().verbose())
{
char temp[64];
snprintf
(
temp, sizeof temp, "%d events in track %d",
evcount, track
);
info_message(temp);
}
if (is_smf0)
(void) m_smf0_splitter.log_main_sequence(s, seqnum);
else
finalize_sequence(p, s, seqnum, screenset);
char temp[64];
snprintf
(
temp, sizeof temp, "%d events in track %d",
evcount, track
);
info_message(temp);
}
if (is_smf0)
(void) m_smf0_splitter.log_main_sequence(s, seqnum);
else
finalize_sequence(p, s, seqnum, screenset);
}
}
else
{
if (track > 0) /* non-fatal later */
{
(void) set_error_dump("Unknown MIDI track ID, skipping...", ID);
(void) set_error_dump("Bad track ID", ID);
break;
}
else /* fatal in 1st one */
{
result = set_error_dump("First track unsupported track ID", ID);
result = set_error_dump("First track has bad ID", ID);
break;
}
skip(TrackLength);
Expand Down Expand Up @@ -1973,11 +1962,11 @@ midifile::parse_seqspec_track (performer & p, int file_size)
m_error_is_fatal = false;
result = set_error_dump
(
"No sequence number in SeqSpec, extra data"
"No track number in SeqSpec, extra data"
);
}
else
result = set_error("Unexpected sequence number in SeqSpec");
result = append_error("Unexpected track number in SeqSpec.");
}
}
else
Expand Down Expand Up @@ -3420,6 +3409,25 @@ midifile::write_track_end ()
write_byte(0); /* no data */
}

/**
* Common code for track-reading errors.
*/

bool
midifile::track_error (const std::string & context, int track)
{
bool skip = m_running_status_action == rsaction::skip;
std::string msg = context;
char temp[80];
snprintf(temp, sizeof temp, " track %d", track);
msg += temp;
if (skip)
msg += " Skipping to end-of-track";

(void) set_error_dump(msg);
return skip;
}

/**
* A new function that just sets the fatal-error status and the error message.
*
Expand All @@ -3440,6 +3448,16 @@ midifile::set_error (const std::string & msg)
return false;
}

bool
midifile::append_error (const std::string & msg)
{
m_error_message += ". ";
m_error_message += msg;
errprint(msg.c_str());
m_error_is_fatal = true;
return false;
}

/**
* Helper function to emit more useful error messages. It adds the file
* offset to the message.
Expand All @@ -3460,19 +3478,12 @@ midifile::set_error_dump (const std::string & msg)
char temp[80];
snprintf
(
temp, sizeof temp, "Offset 0x%zx of 0x%zx bytes: ", m_pos, m_file_size

/*
* Too much:
*
* "Offset ~0x%zx of 0x%zx bytes (%zu/%zu): ",
* m_pos, m_file_size, m_pos, m_file_size
*/
temp, sizeof temp, "byte 0x%02x at 0x%zx of 0x%zx",
unsigned(m_data[m_pos]), m_pos, m_file_size
);
std::string result = temp;
result += "\n";
result += " ";
result += msg;
std::string result = msg;
result += ": ";
result += temp;
msgprintf(msglevel::error, "%s", result.c_str());
m_error_message = result;
m_error_is_fatal = true;
Expand Down

0 comments on commit 60daea2

Please sign in to comment.