/*
* Copyright (C) 2015-2017 たんらる
*/
package fourthline.mabiicco.ui;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;
import java.lang.reflect.Field;
import java.util.stream.Stream;
import javax.imageio.ImageIO;
import javax.swing.JViewport;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import fourthline.UseLoadingDLS;
import fourthline.mabiicco.MabiIccoProperties;
import fourthline.mabiicco.midi.MabiDLS;
import fourthline.mmlTools.MMLEventList;
import fourthline.mmlTools.MMLNoteEvent;
import fourthline.mmlTools.MMLScore;
import fourthline.mmlTools.MMLTrack;
import fourthline.mmlTools.Marker;
public final class MMLSeqViewTest extends UseLoadingDLS {
private static boolean viewMarker;
@BeforeClass
public static void initialize() {
viewMarker = MabiIccoProperties.getInstance().enableViewMarker.get();
MabiIccoProperties.getInstance().enableViewMarker.set(true);
}
@AfterClass
public static void cleanup() {
MabiIccoProperties.getInstance().enableViewMarker.set(viewMarker);
}
private MMLSeqView obj;
@Before
public void initilizeObj() {
obj = new MMLSeqView(null);
}
@Before @After
public void initMute() {
for (int i = 0; i < MabiDLS.MAX_MIDI_PART; i++) {
MabiDLS.getInstance().setMute(i, false);
}
}
private Object getField(String fieldName) throws Exception {
Field f = MMLSeqView.class.getDeclaredField(fieldName);
f.setAccessible(true);
return f.get(obj);
}
@Test
public void testUndoRedo() {
MMLScore score = new MMLScore();
// rank9 のMML生成.
StringBuilder sb = new StringBuilder("MML@");
String rank9 = "Rank 9 ( 800, 0, 0 )";
String rank1 = "Rank 1 ( 1200, 0, 0 )";
Stream.iterate(0, i -> i++).limit(800).forEach(t -> sb.append('a'));
score.addTrack(new MMLTrack().setMML( sb.toString() ));
obj.setMMLScore(score);
assertEquals(1, obj.getMMLScore().getTrackCount());
// redo, undoは無効.
assertEquals(false, obj.getFileState().canRedo());
assertEquals(false, obj.getFileState().canUndo());
assertEquals(false, obj.getFileState().isModified());
// generate前は *Rank表記.
assertEquals("*"+rank9, obj.getSelectedTrack().mmlRankFormat());
obj.updateActivePart(false);
// updateActivePart で generate なし.
assertEquals("*"+rank9, obj.getSelectedTrack().mmlRankFormat());
// updateActivePart で generate.
obj.updateActivePart(true);
assertEquals(rank9, obj.getSelectedTrack().mmlRankFormat());
// redo, undoは無効.
assertEquals(false, obj.getFileState().canRedo());
assertEquals(false, obj.getFileState().canUndo());
assertEquals(false, obj.getFileState().isModified());
// Track追加.
Stream.iterate(0, i -> i++).limit(400).forEach(t -> sb.append('a'));
obj.addMMLTrack(new MMLTrack().setMML( sb.toString() ));
assertEquals(2, obj.getMMLScore().getTrackCount());
obj.updateActivePart(true);
// undoは有効.
assertEquals(false, obj.getFileState().canRedo());
assertEquals(true, obj.getFileState().canUndo());
assertEquals(true, obj.getFileState().isModified());
// undo実行.
obj.undo();
assertEquals(true, obj.getFileState().canRedo());
assertEquals(false, obj.getFileState().canUndo());
assertEquals(false, obj.getFileState().isModified());
assertEquals(1, obj.getMMLScore().getTrackCount());
// Rank表記は generate後.
assertEquals(rank9, obj.getSelectedTrack().mmlRankFormat());
obj.updateActivePart(true);
String recoveryData = obj.getRecoveryData();
// redo実行.
obj.redo();
assertEquals(false, obj.getFileState().canRedo());
assertEquals(true, obj.getFileState().canUndo());
assertEquals(true, obj.getFileState().isModified());
assertEquals(2, obj.getMMLScore().getTrackCount());
// 次のTrackを選択.
obj.switchTrack(true);
// Rank表記は generate後.
assertEquals(rank1, obj.getSelectedTrack().mmlRankFormat());
// Rank9のデータへリカバリー.
System.out.println(recoveryData);
obj.recovery(recoveryData);
System.out.println(obj.getRecoveryData());
obj.updateActivePart(true);
System.out.println(recoveryData);
System.out.println(obj.getRecoveryData());
assertEquals(1, obj.getMMLScore().getTrackCount());
assertEquals(rank9, obj.getSelectedTrack().mmlRankFormat());
assertEquals(recoveryData, obj.getRecoveryData());
}
@Test
public void testAddRemoveTrack() {
assertEquals(1, obj.getMMLScore().getTrackCount());
// Track追加.
obj.addMMLTrack(null);
assertEquals(2, obj.getMMLScore().getTrackCount());
assertEquals("Track2", obj.getSelectedTrack().getTrackName());
// 13個ふやす.
Stream.iterate(0, i -> i++).limit(13).forEach(t -> {
obj.addMMLTrack(null);
});
assertEquals(15, obj.getMMLScore().getTrackCount());
assertEquals("Track15", obj.getSelectedTrack().getTrackName());
// 最大
obj.addMMLTrack(null);
assertEquals(16, obj.getMMLScore().getTrackCount());
assertEquals("Track16", obj.getSelectedTrack().getTrackName());
// 増えない.
obj.addMMLTrack(null);
assertEquals(16, obj.getMMLScore().getTrackCount());
assertEquals("Track16", obj.getSelectedTrack().getTrackName());
// 14個へらす.
Stream.iterate(0, i -> i++).limit(14).forEach(t -> {
obj.removeMMLTrack();
});
assertEquals(2, obj.getMMLScore().getTrackCount());
assertEquals("Track2", obj.getSelectedTrack().getTrackName());
// 最小
obj.removeMMLTrack();
assertEquals(1, obj.getMMLScore().getTrackCount());
assertEquals("Track1", obj.getSelectedTrack().getTrackName());
// へらない.
obj.removeMMLTrack();
assertEquals(1, obj.getMMLScore().getTrackCount());
assertEquals("Track18", obj.getSelectedTrack().getTrackName());
}
@Test
public void testMute() {
assertEquals(1, obj.getMMLScore().getTrackCount());
// Track追加.
obj.addMMLTrack(null);
obj.addMMLTrack(null);
obj.addMMLTrack(null);
assertEquals(4, obj.getMMLScore().getTrackCount());
// Track3をMute設定.
MabiDLS.getInstance().toggleMute(2);
assertEquals(false, MabiDLS.getInstance().getMute(0));
assertEquals(false, MabiDLS.getInstance().getMute(1));
assertEquals(true, MabiDLS.getInstance().getMute(2));
assertEquals(false, MabiDLS.getInstance().getMute(3));
// Track2を選択.
obj.switchTrack(false);
obj.switchTrack(false);
assertEquals("Track2", obj.getSelectedTrack().getTrackName());
// Track削除.
obj.removeMMLTrack();
// Track2がMute, Track3はMute解除.
assertEquals(false, MabiDLS.getInstance().getMute(0));
assertEquals(true, MabiDLS.getInstance().getMute(1));
assertEquals(false, MabiDLS.getInstance().getMute(2));
assertEquals(false, MabiDLS.getInstance().getMute(3));
// 新規TrackはMute解除.
MabiDLS.getInstance().toggleMute(3);
assertEquals(true, MabiDLS.getInstance().getMute(3));
obj.addMMLTrack(null);
assertEquals(false, MabiDLS.getInstance().getMute(3));
}
@Test
public void test_setMMLselectedTrack() {
MMLScore score = new MMLScore();
score.addTrack(new MMLTrack().setMML("MML@ct150cc"));
obj.setMMLScore(score);
assertEquals(1, obj.getMMLScore().getTrackCount());
assertEquals(150, obj.getMMLScore().getTempoOnTick(96));
// t150テンポがクリアされてることを確認する.
obj.setMMLselectedTrack(new MMLTrack().setMML("MML@t130ccc"));
assertEquals(1, obj.getMMLScore().getTrackCount());
assertEquals(130, obj.getMMLScore().getTempoOnTick(96));
}
private void check_nextStepTime(MMLSeqView obj, int time) {
int tick = 96 * time;
assertEquals(0, obj.getEditSequencePosition());
obj.nextStepTimeTo(true);
assertEquals(tick, obj.getEditSequencePosition());
obj.nextStepTimeTo(true);
// 右側はOver許容.
assertEquals(tick*2, obj.getEditSequencePosition());
obj.nextStepTimeTo(false);
assertEquals(tick, obj.getEditSequencePosition());
obj.nextStepTimeTo(false);
assertEquals(0, obj.getEditSequencePosition());
// 0が最小.
obj.nextStepTimeTo(false);
assertEquals(0, obj.getEditSequencePosition());
}
@Test
public void test_nextStepTimeTo() {
// 4/4
obj.setMMLselectedTrack(new MMLTrack().setMML("MML@c1"));
check_nextStepTime(obj, 4);
// 3/4
obj.getMMLScore().setTimeCountOnly(3);
check_nextStepTime(obj, 3);
}
@Test
public void test_addRemoveTicks() {
obj.setMMLselectedTrack(new MMLTrack().setMML("MML@cccc,dddd,eeee,ffff;"));
obj.addMMLTrack(new MMLTrack().setMML("MML@gggg,aaaa,bbbb,>cccc;"));
assertEquals(96*4, obj.getMMLScore().getTotalTickLength());
// 2拍目に1拍追加する.
obj.getMMLScore().setTimeCountOnly(2);
obj.nextStepTimeTo(true);
obj.addTicks(96);
assertEquals("MML@ccrcc,ddrdd,eeree,ffrff;", obj.getMMLScore().getTrack(0).getOriginalMML());
assertEquals("MML@ggrgg,aaraa,bbrbb,>ccrcc;", obj.getMMLScore().getTrack(1).getOriginalMML());
assertEquals(96*5, obj.getMMLScore().getTotalTickLength());
// 先頭の1拍を削除する.
obj.nextStepTimeTo(false);
obj.removeTicks(96);
assertEquals("MML@crcc,drdd,eree,frff;", obj.getMMLScore().getTrack(0).getOriginalMML());
assertEquals("MML@grgg,araa,brbb,>crcc;", obj.getMMLScore().getTrack(1).getOriginalMML());
assertEquals(96*4, obj.getMMLScore().getTotalTickLength());
}
private void checkImage(PianoRollView view, String filename) throws Exception {
JViewport viewport = new JViewport();
int width = view.convertTicktoX( obj.getMMLScore().getTotalTickLength() );
int height = view.getTotalHeight();
viewport.setExtentSize(new Dimension(width, height));
// PianoRollView画像の作成.
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
view.setSize(width, height);
view.setViewportAndParent(viewport, obj);
view.paintComponent(image.getGraphics());
ImageIO.write(image, "png", new File(filename+"_pianoRoll.png"));
// ColumnPanel画像の作成.
ColumnPanel columnView = (ColumnPanel) getField("columnView");
BufferedImage image2 = new BufferedImage(width, columnView.getPreferredSize().height, BufferedImage.TYPE_INT_ARGB);
columnView.setSize(width, columnView.getPreferredSize().height);
columnView.paintComponent(image2.getGraphics());
ImageIO.write(image2, "png", new File(filename+"_column.png"));
// KeyboardView画像の作成.
KeyboardView keyboardView = (KeyboardView) getField("keyboardView");
keyboardView.playNote(80, 11);
BufferedImage image3 = new BufferedImage(keyboardView.getPreferredSize().width, height, BufferedImage.TYPE_INT_ARGB);
keyboardView.paintComponent(image3.getGraphics());
keyboardView.offNote();
ImageIO.write(image3, "png", new File(filename+"_keyboard.png"));
}
@Test
public void test_pianoRollView() throws Exception {
PianoRollView view = (PianoRollView) getField("pianoRollView");
obj.setMMLselectedTrack(new MMLTrack().setMML("MML@t160l1cccc,l1dddd,l1eeee,l1ffff;"));
obj.addMMLTrack(new MMLTrack().setMML("MML@>l1cccc,>l1dddd,>l1eeee,>l1ffff;"));
obj.addMMLTrack(new MMLTrack().setMML("MML@<l1cccc,<l1dddd,<l1eeee,<l1ffff;"));
obj.getMMLScore().getMarkerList().add(new Marker("Marker", 96*3));
// 拡大
assertEquals(6.0, view.getWideScale(), 0.001);
Stream.of(6.0, 5.0, 4.0, 3.0, 2.0, 1.5, 1.0, 0.75, 0.5, 0.375, 0.25) .forEach(t -> {
assertEquals(t.doubleValue(), view.getWideScale(), 0.001);
obj.expandPianoViewWide(0);
});
assertEquals(0.25, view.getWideScale(), 0.001);
checkImage(view, "sample1");
// 縮小
Stream.of(0.25, 0.375, 0.5, 0.75, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0) .forEach(t -> {
assertEquals(t.doubleValue(), view.getWideScale(), 0.001);
obj.reducePianoViewWide(0);
});
assertEquals(6.0, view.getWideScale(), 0.001);
checkImage(view, "sample2");
}
/**
* 編集できず REVERTする.
*/
@Test
public void test_editRevert() {
obj.getActiveMMLPart().addMMLNoteEvent(new MMLNoteEvent(10, 1, 0));
assertFalse(obj.getFileState().isModified());
assertEquals(1, obj.getActiveMMLPart().getMMLNoteEventList().size());
obj.updateActivePart(true);
assertEquals(0, obj.getActiveMMLPart().getMMLNoteEventList().size());
assertFalse(obj.getFileState().isModified());
}
/**
* 楽器の変更.
*/
@Test
public void test_updateActiveTrackProgram() {
assertFalse(obj.getFileState().isModified());
obj.updateActiveTrackProgram(obj.getActiveTrackIndex(), obj.getActivePartProgram()+1, 0);
assertTrue(obj.getFileState().isModified());
}
/**
* 任意のfuncを実行したあとのActiveTrackを検査する.
*/
private class TP1 {
private Runnable func;
private int track;
private int part;
/**
* @param func 実行する内容.
* @param track funcを実行したあとに期待するTrackのIndex.
* @param part funcを実行したあとに期待するPartのIndex.
*/
private TP1(Runnable func, int track, int part) {
this.func = func;
this.track = track;
this.part = part;
}
private void check() {
func.run();
MMLEventList expect = obj.getMMLScore().getTrack(track).getMMLEventAtIndex(part);
MMLEventList actual = obj.getActiveMMLPart();
System.out.println(track+" "+part+" "+expect+" <=> "+actual);
assertSame( expect, actual );
}
}
@Test
public void test_switchTrack() {
obj.setMMLselectedTrack(new MMLTrack().setMML("MML@c"));
obj.addMMLTrack(new MMLTrack().setMML("MML@d"));
obj.addMMLTrack(new MMLTrack().setMML("MML@e"));
Runnable toNext = () -> obj.switchTrack(true);
Runnable toPrev = () -> obj.switchTrack(false);
Stream.of(
new TP1(toNext, 2, 0),
new TP1(toPrev, 1, 0),
new TP1(toPrev, 0, 0),
new TP1(toPrev, 0, 0),
new TP1(toNext, 1, 0),
new TP1(toNext, 2, 0),
new TP1(toNext, 2, 0)).forEach(t -> t.check());
}
@Test
public void test_switchMMLPart() {
obj.setMMLselectedTrack(new MMLTrack().setMML("MML@a,b,c,d"));
obj.addMMLTrack(null);
obj.addMMLTrack(new MMLTrack().setMML("MML@e,f,g,a"));
Runnable toNext = () -> obj.switchMMLPart(true);
Runnable toPrev = () -> obj.switchMMLPart(false);
Stream.of(
new TP1(toNext, 2, 1),
new TP1(toNext, 2, 2),
new TP1(toNext, 2, 2),
new TP1(toPrev, 2, 1),
new TP1(toPrev, 2, 0),
new TP1(toPrev, 2, 0)).forEach(t -> t.check());
// コーラスパート有効.
obj.updateActiveTrackProgram(obj.getActiveTrackIndex(), 1, 100);
obj.updateActivePart(true);
Stream.of(
new TP1(toNext, 2, 1),
new TP1(toNext, 2, 2),
new TP1(toNext, 2, 3),
new TP1(toNext, 2, 3)).forEach(t -> t.check());
}
@Test
public void test_moveTrack1() {
MMLTrack track1 = new MMLTrack().setMML("MML@c");
MMLTrack track2 = new MMLTrack().setMML("MML@d");
MMLTrack track3 = new MMLTrack().setMML("MML@e");
obj.setMMLselectedTrack(track1);
obj.addMMLTrack(track2);
obj.addMMLTrack(track3);
MabiDLS dls = MabiDLS.getInstance();
dls.setMute(1, true);
assertEquals(false, dls.getMute(0));
assertEquals(true, dls.getMute(1));
assertEquals(false, dls.getMute(2));
obj.moveTrack(0); // 2 - 0
assertSame(track3, obj.getMMLScore().getTrack(0));
assertSame(track1, obj.getMMLScore().getTrack(1));
assertSame(track2, obj.getMMLScore().getTrack(2));
assertEquals(false, dls.getMute(0));
assertEquals(false, dls.getMute(1));
assertEquals(true, dls.getMute(2));
obj.moveTrack(2); // 0 - 2
assertSame(track1, obj.getMMLScore().getTrack(0));
assertSame(track2, obj.getMMLScore().getTrack(1));
assertSame(track3, obj.getMMLScore().getTrack(2));
assertEquals(false, dls.getMute(0));
assertEquals(true, dls.getMute(1));
assertEquals(false, dls.getMute(2));
}
}