package com.xenoage.zong.commands.player.convert;
import com.xenoage.utils.document.command.TransparentCommand;
import com.xenoage.utils.filter.AllFilter;
import com.xenoage.utils.iterators.It;
import com.xenoage.utils.jse.io.JseInputStream;
import com.xenoage.utils.jse.settings.FileSettings;
import com.xenoage.utils.lang.Lang;
import com.xenoage.zong.Voc;
import com.xenoage.zong.core.Score;
import com.xenoage.zong.desktop.io.midi.out.JseMidiSequenceWriter;
import com.xenoage.zong.io.midi.out.MidiConverter;
import com.xenoage.zong.io.musicxml.FileType;
import com.xenoage.zong.io.musicxml.in.FileTypeReader;
import javafx.stage.DirectoryChooser;
import javafx.stage.Window;
import lombok.AllArgsConstructor;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
import java.io.File;
import java.io.IOException;
import java.util.List;
import static com.xenoage.utils.jse.io.JseFileUtils.listFiles;
import static com.xenoage.zong.desktop.App.app;
import static com.xenoage.zong.io.midi.out.MidiConverter.Options.optionsForFileExport;
import static com.xenoage.zong.player.Player.pApp;
/**
* This command lets the user select a directory whose MusicXML files
* are then converted into MIDI files.
*
* MusicXML files with multiple scores are also supported. In this case
* each score gets its own MIDI file.
*
* @author Andreas Wenger
*/
@AllArgsConstructor public class DirToMidiConvert
extends TransparentCommand {
private Window ownerWindow;
@Override public void execute() {
DirectoryChooser dc = new DirectoryChooser();
//use last document directory
File initDir = FileSettings.getLastDir();
if (initDir != null)
dc.setInitialDirectory(initDir);
/* TODO - how to extend the DirectoryChooser in JavaFX?
//see http://stackoverflow.com/questions/25982945/javafx-filechooser-and-directorychooser-accessory-component
JCheckBox chkSubdir = new JCheckBox(Lang.get(Voc.IncludeSubdirectories), true);
JCheckBox chkCancel = new JCheckBox(Lang.get(Voc.CancelAtFirstError), false);
JPanel pnlOptions = new JPanel();
pnlOptions.setLayout(new BoxLayout(pnlOptions, BoxLayout.Y_AXIS));
pnlOptions.add(chkSubdir);
pnlOptions.add(chkCancel);
fc.setAccessory(pnlOptions); */
boolean subDirs = true; //TODO
boolean cancelOnFirstError = false; //TODO
File dir = dc.showDialog(ownerWindow);
if (dir != null) {
//remember directory
FileSettings.rememberDir(dir);
//start conversion - TODO: show progress
List<File> files = listFiles(dir, subDirs);
int countOK = 0;
int countFailed = 0;
for (File file : files) {
try {
//only process MusicXML files
FileType fileType = FileTypeReader.getFileType(new JseInputStream(file));
if (fileType != null) {
String filePath = file.getAbsolutePath();
List<Score> scores = pApp().loadMxlScores(filePath, new AllFilter<>());
if ((scores.size() == 0) /* TODO && chkCancel.isSelected() */) {
countFailed++;
break;
}
boolean useNumber = scores.size() > 1;
It<Score> scoresIt = new It<>(scores);
for (Score score : scoresIt) {
Sequence seq = MidiConverter.convertToSequence(
score, optionsForFileExport, new JseMidiSequenceWriter()).getSequence();
String number = (useNumber ? ("-" + (scoresIt.getIndex() + 1)) : "");
String newPath = filePath;
if (filePath.toLowerCase().endsWith(".xml") ||
filePath.toLowerCase().endsWith(".mxl")) {
newPath = newPath.substring(0, filePath.length() - 4);
}
newPath += (number + ".mid");
MidiSystem.write(seq, 1, new File(newPath));
countOK++;
}
}
} catch (IOException ex) {
countFailed++;
if (cancelOnFirstError) {
break;
}
}
}
app().showMessageDialog(
Lang.get(Voc.DirectoryConversionResult, "" + countOK, "" + countFailed));
}
}
}