Skip to content

Commit

Permalink
fixed exporter bugs and unified newline symbols in META messages
Browse files Browse the repository at this point in the history
- bugfix in MidicaPLExporter
- bugfix in AldaExporter
- optimized handling of different newline symbols in META messages
  - display of newlines in FlowLabels
  - meta messages in MidicaPLExporter
  • Loading branch information
truj committed Aug 30, 2023
1 parent c8a9f8e commit d96029f
Show file tree
Hide file tree
Showing 12 changed files with 167 additions and 52 deletions.
Binary file modified midica.jar
Binary file not shown.
4 changes: 2 additions & 2 deletions src/org/midica/Midica.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ public class Midica {
* After switching to a new major version, this has to be set to "-1" manually, so that
* precommit.pl starts with "0" again.
*/
private static final int VERSION_MINOR = 7;
private static final int VERSION_MINOR = 8;

/** UNIX timestamp of the last commit */
public static final int COMMIT_TIME = 1692861685;
public static final int COMMIT_TIME = 1693413781;

/** Branch name. Automatically changed by precommit.pl */
public static final String BRANCH = "master";
Expand Down
2 changes: 2 additions & 0 deletions src/org/midica/config/Dict.java
Original file line number Diff line number Diff line change
Expand Up @@ -1701,6 +1701,7 @@ public class Dict {

// AldaImporter
public static final String ERROR_ALDA_NO_MIDI_FILE = "error_alda_no_midi_file";
public static final String ERROR_ALDA_MIDI_FILE_EMPTY = "error_alda_midi_file_empty";

// LilypondImporter
public static final String ERROR_LILYPOND_NO_MIDI_FILE = "error_lilypond_no_midi_file";
Expand Down Expand Up @@ -3419,6 +3420,7 @@ private static void initLanguageEnglish() {

// AldaImporter
set( ERROR_ALDA_NO_MIDI_FILE, "<html>ALDA failed to create a MIDI file.<br>In most cases that means:<br>Too many Instruments." );
set( ERROR_ALDA_MIDI_FILE_EMPTY, "ALDA created an empty MIDI file." );

// LilypondImporter
set( ERROR_LILYPOND_NO_MIDI_FILE, "<html>LilyPond didn't create any MIDI file.<br>Did you forget to include a \\midi block?" );
Expand Down
23 changes: 22 additions & 1 deletion src/org/midica/file/read/AldaImporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@
*/
public class AldaImporter extends MidiParser {

// how often shall we sleep to wait for ALDA to create the MIDI file?
private static final int MAX_SLEEP_COUNT = 100;

// how long shall we sleep each time (in milliseconds)
private static final int SLEEP_TIME = 200;

// foreign program description for error messages
private static String programName = Dict.get(Dict.FOREIGN_PROG_ALDA);

Expand Down Expand Up @@ -98,6 +104,21 @@ else if (versionStr.startsWith("client version: 1")) {
throw new ParseException(Dict.get(Dict.ERROR_ALDA_NO_MIDI_FILE));
}

// sometimes alda 2 needs a little more time to fill the MIDI file
if (0L == tempfile.length()) {
for (int i = 0; i < MAX_SLEEP_COUNT; i++) {
Thread.sleep(SLEEP_TIME);

// file not empty any more?
if (tempfile.length() > 0L)
break;
}

// file still empty?
if (0L == tempfile.length())
throw new ParseException(Dict.get(Dict.ERROR_ALDA_MIDI_FILE_EMPTY));
}

// get MIDI from tempfile
Sequence sequence = MidiSystem.getSequence(tempfile);

Expand All @@ -108,7 +129,7 @@ else if (versionStr.startsWith("client version: 1")) {
createSequence(sequence);
postprocessSequence(sequence, chosenCharset); // analyze the original sequence
}
catch (ForeignException | InvalidMidiDataException | IOException e) {
catch (ForeignException | InvalidMidiDataException | IOException | InterruptedException e) {
throw new ParseException(e.getMessage());
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/org/midica/file/read/MidicaPLParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -3112,11 +3112,11 @@ else if (iPat == 2)
* @throws ParseException if a MIDI problem occurs.
*/
private void applySyllable(String syllable, long tick) throws ParseException {
syllable = syllable.replaceAll( Pattern.quote(LYRICS_SPACE), " " );
syllable = syllable.replaceAll( Pattern.quote(LYRICS_COMMA), "," );
syllable = syllable.replace(LYRICS_SPACE, " ");
syllable = syllable.replace(LYRICS_COMMA, ",");
if (!isSoftKaraoke) {
syllable = syllable.replaceAll( Pattern.quote(LYRICS_CR), "\r" );
syllable = syllable.replaceAll( Pattern.quote(LYRICS_LF), "\n" );
syllable = syllable.replace(LYRICS_CR, "\r");
syllable = syllable.replace(LYRICS_LF, "\n");
}

try {
Expand Down
5 changes: 5 additions & 0 deletions src/org/midica/file/write/AldaExporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,11 @@ else if ("key".equals(cmdId)) {
*/
private void createChordNotes(Slice slice, byte channel, long tick, TreeMap<String, TreeMap<Byte, String>> events) {

// don't know how the events can be empty here, but in some cases they can...
// TODO: fix this in the decompiler
if (events.isEmpty())
return;

// first usage in the current slice?
if (!usedInSlice.contains(srcInstrByChannel.get(channel))) {

Expand Down
45 changes: 26 additions & 19 deletions src/org/midica/file/write/MidicaPLExporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.midica.file.read.MidicaPLParser;
import org.midica.file.read.ParseException;
import org.midica.midi.KaraokeAnalyzer;
import org.midica.midi.LyricUtil;
import org.midica.midi.SequenceAnalyzer;

/**
Expand Down Expand Up @@ -207,8 +208,7 @@ private void createMetaBlock() {
HashMap<String, String> metaInfo = (HashMap<String, String>) sequenceInfo.get("meta_info");
HashMap<String, Object> karaokeInfo = KaraokeAnalyzer.getKaraokeInfo();
String copyright = (String) metaInfo.get("copyright");
if (copyright != null)
copyright = copyright.replace("\n", "\\n").replace("\r", "\\r"); // TODO: support multiple lines in MidicaPL
copyright = LyricUtil.getInstance().unifyNewlinesToLf(copyright);
String[] fields = {"copyright", "title", "composer", "lyricist", "artist"};
String[] values = new String[5];
String[] mplIds = {
Expand Down Expand Up @@ -288,14 +288,14 @@ private String createSoftKaraokeBlock(HashMap<String, Object> karaokeInfo) {

// read value
String value = (String) karaokeInfo.get(fields[i]);
if (null == value) {
if (null == value)
continue;
}
else {
// Escaping \r and \n not allowed in soft karaoke.
// But newlines must be thrown out anyway.
value = value.replace("\n", " ").replace("\r", " ");
}

// Escaping \r and \n not allowed in soft karaoke.
// But newlines must be thrown out anyway.
// So we replace them with a space.
value = LyricUtil.getInstance().unifyNewlinesToLf(value);
value = value.replace("\n", " ");

// append the line
block.append("\t\t" + String.format("%-12s", mplIds[i]) + " " + value + NEW_LINE);
Expand All @@ -306,12 +306,19 @@ private String createSoftKaraokeBlock(HashMap<String, Object> karaokeInfo) {
if (infos != null) {
for (String info : infos) {

// append info line
if (! "".equals(info))
block.append(
"\t\t" + String.format("%-12s", MidicaPLParser.META_SK_INFO) + " "
+ info + NEW_LINE
);
// handle illegal newlines inside a single info message (@I...)
info = LyricUtil.getInstance().unifyNewlinesToLf(info);
String[] infoLineParts = info.split("\n");

for (String infoPart : infoLineParts) {

// append info line
if (! "".equals(infoPart))
block.append(
"\t\t" + String.format("%-12s", MidicaPLParser.META_SK_INFO) + " "
+ infoPart + NEW_LINE
);
}
}
}

Expand Down Expand Up @@ -1196,17 +1203,17 @@ private String escapeSyllable(String syllable) {

// escape \r and \n
if (isSoftKaraoke) {
syllable = syllable.replaceAll("\n", "_").replaceAll("\r", "_");
syllable = syllable.replace("\n", "_").replace("\r", "_");
}
else {
syllable = syllable.replaceAll("\n", "\\\\n").replaceAll("\r", "\\\\r");
syllable = syllable.replace("\n", "\\\\n").replace("\r", "\\\\r");
}

// escape space and comma
syllable = syllable.replaceAll(" ", "_").replaceAll(",", "\\\\c");
syllable = syllable.replace(" ", "_").replace(",", "\\\\c");

// escape comment symbols
syllable = syllable.replaceAll(MidicaPLParser.COMMENT, "/\\\\/");
syllable = syllable.replace(MidicaPLParser.COMMENT, "/\\\\/");

return syllable;
}
Expand Down
51 changes: 51 additions & 0 deletions src/org/midica/midi/LyricUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.midica.file.write.MidicaPLExporter;
import org.midica.ui.widget.FlowLabel;

/**
* This class provides methods to deal with Lyrics events, especially according to RP-026.
*
Expand Down Expand Up @@ -214,6 +217,54 @@ public final String removeTags(String text) {
return text;
}

/**
* Unifies different kinds of newlines in the given text.
* Transforms them all to \n.
*
* - CRLF ==> LF
* - LF ==> LF
* - CR ==> LF
*
* This is needed by the {@link FlowLabel} in order to display text from MIDI files.
* It's also needed by the {@link MidicaPLExporter} to correctly interpret Meta messages.
*
* @param text the original text
* @return the unified text
*/
public final String unifyNewlinesToLf(String text) {

if (null == text)
return text;

try {
MessageDigest md = MessageDigest.getInstance("MD5");

// create placeholders
String cr = new BigInteger(1, md.digest("\r".getBytes("ISO-8859-1"))).toString(16);
String lf = new BigInteger(1, md.digest("\n".getBytes("ISO-8859-1"))).toString(16);
String crlf = new BigInteger(1, md.digest("\r\n".getBytes("ISO-8859-1"))).toString(16);

// replace every possible cr-lf combination
text = text
.replace("\r\n", crlf)
.replace("\n", lf)
.replace("\r", cr);

// convert \r\n to \n
text = text
.replace(crlf, lf)
.replace(cr, lf);

// convert remaining placeholder back to \n
return text.replace(lf, "\n");
}
catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
e.printStackTrace();
}

return text;
}

/**
* Replaces escaped characters with their hash values
* so that they don't disturb regexes.
Expand Down
8 changes: 4 additions & 4 deletions src/org/midica/ui/UiController.java
Original file line number Diff line number Diff line change
Expand Up @@ -618,10 +618,10 @@ else if (FileSelector.FILE_TYPE_MSCORE_EXP.equals(type)) {
private void showErrorMessage(String message) {

if (Cli.isCliMode) {
message = message.replaceAll( "<br>", "\n" );
message = message.replaceAll( "</?b>", "" );
message = message.replaceAll( "</?html>", "" );
message = message.replaceAll( "&nbsp;", " " );
message = message.replace("<br>", "\n");
message = message.replaceAll("</?b>", "");
message = message.replaceAll("</?html>", "");
message = message.replace("&nbsp;", " ");
System.err.println(message);
return;
}
Expand Down
6 changes: 3 additions & 3 deletions src/org/midica/ui/model/MidicaTreeNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,9 @@ public String getToolTip() {
if (toolTipAttachment != null) {
return "<html>"
+ toString()
.replaceAll("&", "&amp;")
.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;")
.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
+ toolTipAttachment;
}

Expand Down
5 changes: 3 additions & 2 deletions src/org/midica/ui/widget/FlowLabel.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import javax.swing.border.Border;

import org.midica.config.Laf;
import org.midica.midi.LyricUtil;

/**
* This class provides a replacement for a {@link JLabel} that enables smoother
Expand Down Expand Up @@ -52,10 +53,10 @@ public class FlowLabel extends JScrollPane {
public FlowLabel(String content, int charsPerLine, int prefWidth) {

// Create the label inside the scroll pane.
this.text = content;
this.text = LyricUtil.getInstance().unifyNewlinesToLf(content);
this.charsPerLine = charsPerLine;
this.preferredWidth = prefWidth;
this.label = new JTextArea(content);
this.label = new JTextArea(text);

// background color for nimbus
if (Laf.isNimbus) {
Expand Down
Loading

0 comments on commit d96029f

Please sign in to comment.