--- /dev/null
+package camidion.chordhelper;
+
+import java.awt.Desktop;
+import java.awt.event.ActionEvent;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.ImageIcon;
+import javax.swing.JEditorPane;
+import javax.swing.JOptionPane;
+import javax.swing.event.HyperlinkEvent;
+
+import camidion.chordhelper.ChordHelperApplet.VersionInfo;
+/**
+ * バージョン情報表示欄
+ */
+public class AboutMessagePane extends JEditorPane {
+ private Action openAction;
+ /**
+ * このバージョン情報表示欄を開くためのアクションを返します。
+ */
+ public Action getOpenAction() { return openAction; }
+ /**
+ * バージョン情報表示欄を構築します。
+ * @param imageIcon 画像アイコン
+ */
+ public AboutMessagePane(ImageIcon imageIcon) {
+ super("text/html", "");
+ openAction = new AbstractAction() {
+ {
+ putValue(NAME, "Version info");
+ putValue(SHORT_DESCRIPTION, VersionInfo.NAME + " " + VersionInfo.VERSION);
+ }
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JOptionPane.showMessageDialog(
+ null, AboutMessagePane.this, getValue(NAME).toString(),
+ JOptionPane.INFORMATION_MESSAGE, imageIcon
+ );
+ }
+ };
+ boolean linkEnabled = Desktop.isDesktopSupported();
+ String linkString = VersionInfo.URL;
+ String tooltip = null;
+ if( linkEnabled ) {
+ tooltip = "Click to open on web browser - Webブラウザで開く";
+ linkString = "<a href=\""+linkString+"\" title=\""+tooltip+"\">"+linkString+"</a>";
+ }
+ setText("<html><center><font size=\"+1\">" +
+ VersionInfo.NAME + "</font> " +
+ VersionInfo.VERSION + "<br/><br/>" +
+ VersionInfo.COPYRIGHT + " " +
+ VersionInfo.AUTHER + "<br/>" +
+ linkString + "</center></html>");
+ setToolTipText(tooltip);
+ setOpaque(false);
+ putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
+ setEditable(false);
+ if( ! linkEnabled ) return;
+ URI uri;
+ try {
+ uri = new URI(VersionInfo.URL);
+ }catch( URISyntaxException use ) {
+ use.printStackTrace();
+ return;
+ }
+ addHyperlinkListener(e->{
+ if( e.getEventType() == HyperlinkEvent.EventType.ACTIVATED ) {
+ try{
+ Desktop.getDesktop().browse(uri);
+ }catch(IOException ioe) {
+ ioe.printStackTrace();
+ }
+ }
+ });
+ }
+}
\ No newline at end of file
package camidion.chordhelper;
import java.awt.BorderLayout;
import java.awt.Color;
-import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.InputEvent;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
-import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.AccessControlException;
import java.util.Arrays;
import javax.sound.midi.InvalidMidiDataException;
-import javax.sound.midi.MetaEventListener;
import javax.sound.midi.MetaMessage;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
-import javax.swing.AbstractAction;
-import javax.swing.Action;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JComponent;
-import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
-import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JSplitPane;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import javax.swing.event.HyperlinkEvent;
-import javax.swing.event.HyperlinkListener;
import camidion.chordhelper.anogakki.AnoGakkiPane;
import camidion.chordhelper.chorddiagram.CapoComboBoxModel;
* 未保存の修正済み MIDI ファイルがあるかどうか調べます。
* @return 未保存の修正済み MIDI ファイルがあれば true
*/
- public boolean isModified() { return playlistModel.isModified(); }
+ public boolean isModified() {
+ return playlistModel.getSequenceModelList().stream().anyMatch(m -> m.isModified());
+ }
/**
* 指定された小節数の曲を、乱数で自動作曲してプレイリストへ追加します。
* @param measureLength 小節数
try {
return playlistModel.addSequenceFromURL(midiFileUrl);
} catch( URISyntaxException|IOException|InvalidMidiDataException e ) {
- midiEditor.showWarning(e.getMessage());
+ midiEditor.showWarning(e);
} catch( AccessControlException e ) {
- e.printStackTrace();
- midiEditor.showError(e.getMessage());
+ midiEditor.showError(e);
}
return -1;
}
try {
return playlistModel.addSequence(d.getMIDIData(), filename);
} catch (Exception e) {
- e.printStackTrace();
- midiEditor.showWarning(e.toString());
+ midiEditor.showWarning(e);
return -1;
}
}
* シーケンサへロードして再生します。
* @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
*/
- public void play() throws InvalidMidiDataException { play(playlistModel.sequenceListSelectionModel.getMinSelectionIndex()); }
+ public void play() throws InvalidMidiDataException {
+ play(playlistModel.sequenceListSelectionModel.getMinSelectionIndex());
+ }
/**
* 指定されたインデックス値が示すプレイリスト上のMIDIシーケンスを、
* シーケンサへロードして再生します。
*/
public static class VersionInfo {
public static final String NAME = "MIDI Chord Helper";
- public static final String VERSION = "Ver.20170304.1";
+ public static final String VERSION = "Ver.20170320.1";
public static final String COPYRIGHT = "Copyright (C) 2004-2017";
public static final String AUTHER = "@きよし - Akiyoshi Kamide";
public static final String URL = "http://www.yk.rim.or.jp/~kamide/music/chordhelper/";
+ " " + VersionInfo.AUTHER
+ " " + VersionInfo.URL;
}
- private class AboutMessagePane extends JEditorPane {
- URI uri;
- public AboutMessagePane() {
- super("text/html", "");
- boolean linkEnabled = Desktop.isDesktopSupported();
- String linkString = VersionInfo.URL;
- String tooltip = null;
- if( linkEnabled ) {
- tooltip = "Click this URL to open with your web browser - URLをクリックしてWebブラウザで開く";
- linkString = "<a href=\""+linkString+"\" title=\""+tooltip+"\">"+linkString+"</a>";
- }
- setText("<html><center><font size=\"+1\">" +
- VersionInfo.NAME + "</font> " +
- VersionInfo.VERSION + "<br/><br/>" +
- VersionInfo.COPYRIGHT + " " +
- VersionInfo.AUTHER + "<br/>" +
- linkString + "</center></html>");
- setToolTipText(tooltip);
- setOpaque(false);
- putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
- setEditable(false);
- //
- // メッセージ内の <a href=""> ~ </a> によるリンクを
- // 実際に機能させる(ブラウザで表示されるようにする)ための設定
- //
- if( ! linkEnabled ) return;
- try {
- uri = new URI(VersionInfo.URL);
- }catch( URISyntaxException use ) {
- use.printStackTrace();
- return;
- }
- addHyperlinkListener(new HyperlinkListener() {
- public void hyperlinkUpdate(HyperlinkEvent e) {
- if( e.getEventType() == HyperlinkEvent.EventType.ACTIVATED ) {
- try{
- Desktop.getDesktop().browse(uri);
- }catch(IOException ioe) {
- ioe.printStackTrace();
- }
- }
- }
- });
- }
- /**
- * バージョン情報を開くアクション
- */
- public Action openAction = new AbstractAction() {
- {
- putValue(NAME, "Version info");
- putValue(SHORT_DESCRIPTION, VersionInfo.NAME + " " + VersionInfo.VERSION);
- }
- @Override
- public void actionPerformed(ActionEvent e) {
- JOptionPane.showMessageDialog(
- null, AboutMessagePane.this, getValue(NAME).toString(),
- JOptionPane.INFORMATION_MESSAGE, imageIcon
- );
- }
- };
- }
- /**
- * アプリケーションのイメージアイコン
- */
- public ImageIcon imageIcon;
- /**
- * アプリケーションのアイコンイメージ
- */
- public Image iconImage;
- private static final String IMAGE_ICON_PATH = "midichordhelper.png";
- private void loadIconImage() {
- URL imageIconUrl = getClass().getResource(IMAGE_ICON_PATH);
- if( imageIconUrl == null ) {
- System.out.println("Icon image " + IMAGE_ICON_PATH + " not found");
- }
- else {
- iconImage = (imageIcon = new ImageIcon(imageIconUrl)).getImage();
- }
- }
/**
* ボタンの余白を詰めたいときに setMargin() の引数に指定するインセット
*/
public static final Insets ZERO_INSETS = new Insets(0,0,0,0);
- //
- //
+
+ // GUIコンポーネント
MidiSequenceEditorDialog midiEditor;
PlaylistTableModel playlistModel;
MidiSequencerModel sequencerModel;
private JToggleButton anoGakkiToggleButton;
private MidiDeviceTreeModel deviceTreeModel;
+ // アイコン画像
+ private Image iconImage;
+ public Image getIconImage() { return iconImage; }
+ private ImageIcon imageIcon;
+ public ImageIcon getImageIcon() { return imageIcon; }
+
public void init() {
- loadIconImage();
+ // アイコン画像のロード
+ URL imageIconUrl = getClass().getResource("midichordhelper.png");
+ if( imageIconUrl != null ) {
+ iconImage = (imageIcon = new ImageIcon(imageIconUrl)).getImage();
+ }
+ AboutMessagePane about = new AboutMessagePane(imageIcon);
//
// 背景色の取得
rootPaneDefaultBgcolor = getContentPane().getBackground();
}
public void chordChanged() { chordOn(); }
});
- capoSelecter.checkbox.addItemListener(new ItemListener() {
- public void itemStateChanged(ItemEvent e) {
- chordOn();
- keyboardPanel.keyboardCenterPanel.keyboard.chordDisplay.clear();
- chordDiagram.clear();
- }
+ capoSelecter.checkbox.addItemListener(e->{
+ chordOn();
+ keyboardPanel.keyboardCenterPanel.keyboard.chordDisplay.clear();
+ chordDiagram.clear();
});
- capoSelecter.valueSelecter.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- chordOn();
- keyboardPanel.keyboardCenterPanel.keyboard.chordDisplay.clear();
- chordDiagram.clear();
- }
+ capoSelecter.valueSelecter.addActionListener(e->{
+ chordOn();
+ keyboardPanel.keyboardCenterPanel.keyboard.chordDisplay.clear();
+ chordDiagram.clear();
});
}};
keysigLabel = new KeySignatureLabel() {{
addMouseListener(new MouseAdapter() {
+ @Override
public void mousePressed(MouseEvent e) { chordMatrix.setKeySignature(getKey()); }
});
}};
@Override
public void pianoKeyPressed(int n, InputEvent e) { chordDiagram.clear(); }
});
- keySelecter.getKeysigCombobox().addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- chordMatrix.setKeySignature(keySelecter.getSelectedKey().transposedKey(-chordMatrix.capoSelecter.getCapo()));
- }
- });
+ keySelecter.getKeysigCombobox().addActionListener(
+ e -> chordMatrix.setKeySignature(
+ keySelecter.getSelectedKey().transposedKey(
+ -chordMatrix.capoSelecter.getCapo()
+ )
+ )
+ );
keyboardCenterPanel.keyboard.setPreferredSize(new Dimension(571, 80));
}};
VirtualMidiDevice guiMidiDevice = keyboardPanel.keyboardCenterPanel.keyboard.midiDevice;
keyboardPanel.setEventDialog(midiEditor.eventDialog);
//
// 歌詞表示
- (lyricDisplay = new ChordTextField(sequencerModel)).addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent event) {
- chordMatrix.setSelectedChord(event.getActionCommand().trim().split("[ \t\r\n]")[0]);
- }
+ (lyricDisplay = new ChordTextField(sequencerModel)).addActionListener((ActionEvent e)->{
+ chordMatrix.setSelectedChord(e.getActionCommand().trim().split("[ \t\r\n]")[0]);
});
lyricDisplayDefaultBorder = lyricDisplay.getBorder();
lyricDisplayDefaultBgcolor = lyricDisplay.getBackground();
// メタイベント(テンポ・拍子・調号)を受信して表示するリスナーを登録
TempoSelecter tempoSelecter = new TempoSelecter() {{ setEditable(false); }};
TimeSignatureSelecter timesigSelecter = new TimeSignatureSelecter() {{ setEditable(false); }};
- sequencerModel.getSequencer().addMetaEventListener(new MetaEventListener() {
- @Override
- public void meta(MetaMessage msg) {
- switch(msg.getType()) {
- case 0x51: // Tempo (3 bytes) - テンポ
- byte[] qpm = msg.getData();
- if( SwingUtilities.isEventDispatchThread() ) {
- tempoSelecter.setTempo(qpm);
- } else {
- // MIDIシーケンサのスレッドから呼ばれた場合、GUI更新は自分で行わず、
- // AWTイベントディスパッチスレッドに依頼する。
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() { tempoSelecter.setTempo(qpm);}
- });
- }
- break;
- case 0x58: // Time signature (4 bytes) - 拍子
- byte[] timesig = msg.getData();
- if( SwingUtilities.isEventDispatchThread() ) {
- timesigSelecter.setValue(timesig);
- } else {
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() { timesigSelecter.setValue(timesig);}
- });
- }
- break;
- case 0x59: // Key signature (2 bytes) : 調号
- Key key = new Key(msg.getData());
- if( SwingUtilities.isEventDispatchThread() ) {
- setKeySignature(key);
- } else {
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() { setKeySignature(key); }
- });
- }
- break;
- }
+ sequencerModel.getSequencer().addMetaEventListener(msg->{
+ switch(msg.getType()) {
+ case 0x51: // Tempo (3 bytes) - テンポ
+ SwingUtilities.invokeLater(()->tempoSelecter.setTempo(msg.getData()));
+ break;
+ case 0x58: // Time signature (4 bytes) - 拍子
+ SwingUtilities.invokeLater(()->timesigSelecter.setValue(msg.getData()));
+ break;
+ case 0x59: // Key signature (2 bytes) : 調号
+ SwingUtilities.invokeLater(()->setKeySignature(new Key(msg.getData())));
+ break;
}
-
});
//シーケンサーの時間スライダーの値が変わったときのリスナーを登録
JLabel songTitleLabel = new JLabel();
- sequencerModel.addChangeListener(new ChangeListener() {
- @Override
- public void stateChanged(ChangeEvent e) {
- SequenceTrackListTableModel sequenceTableModel = sequencerModel.getSequenceTrackListTableModel();
- int loadedSequenceIndex = playlistModel.indexOfSequenceOnSequencer();
- songTitleLabel.setText(
- "<html>"+(
- loadedSequenceIndex < 0 ? "[No MIDI file loaded]" :
- "MIDI file " + loadedSequenceIndex + ": " + (
- sequenceTableModel == null ||
- sequenceTableModel.toString() == null ||
- sequenceTableModel.toString().isEmpty() ?
- "[Untitled]" :
- "<font color=maroon>"+sequenceTableModel+"</font>"
- )
- )+"</html>"
- );
- Sequencer sequencer = sequencerModel.getSequencer();
- chordMatrix.setPlaying(sequencer.isRunning());
- if( sequenceTableModel != null ) {
- SequenceTickIndex tickIndex = sequenceTableModel.getSequenceTickIndex();
- long tickPos = sequencer.getTickPosition();
- tickIndex.tickToMeasure(tickPos);
- chordMatrix.setBeat(tickIndex);
- if( sequencerModel.getValueIsAdjusting() || ! (sequencer.isRunning() || sequencer.isRecording()) ) {
- MetaMessage msg;
- msg = tickIndex.lastMetaMessageAt(
- SequenceTickIndex.MetaMessageType.TIME_SIGNATURE, tickPos
- );
- timesigSelecter.setValue(msg==null ? null : msg.getData());
- msg = tickIndex.lastMetaMessageAt(
- SequenceTickIndex.MetaMessageType.TEMPO, tickPos
- );
- tempoSelecter.setTempo(msg==null ? null : msg.getData());
- msg = tickIndex.lastMetaMessageAt(
- SequenceTickIndex.MetaMessageType.KEY_SIGNATURE, tickPos
- );
- if(msg == null) keysigLabel.clear();
- else setKeySignature(new Key(msg.getData()));
- }
+ sequencerModel.addChangeListener(e->{
+ SequenceTrackListTableModel sequenceTableModel = sequencerModel.getSequenceTrackListTableModel();
+ int loadedSequenceIndex = playlistModel.indexOfSequenceOnSequencer();
+ songTitleLabel.setText(
+ "<html>"+(
+ loadedSequenceIndex < 0 ? "[No MIDI file loaded]" :
+ "MIDI file " + loadedSequenceIndex + ": " + (
+ sequenceTableModel == null ||
+ sequenceTableModel.toString() == null ||
+ sequenceTableModel.toString().isEmpty() ?
+ "[Untitled]" :
+ "<font color=maroon>"+sequenceTableModel+"</font>"
+ )
+ )+"</html>"
+ );
+ Sequencer sequencer = sequencerModel.getSequencer();
+ chordMatrix.setPlaying(sequencer.isRunning());
+ if( sequenceTableModel != null ) {
+ SequenceTickIndex tickIndex = sequenceTableModel.getSequenceTickIndex();
+ long tickPos = sequencer.getTickPosition();
+ tickIndex.tickToMeasure(tickPos);
+ chordMatrix.setBeat(tickIndex);
+ if( sequencerModel.getValueIsAdjusting() || ! (sequencer.isRunning() || sequencer.isRecording()) ) {
+ MetaMessage msg;
+ msg = tickIndex.lastMetaMessageAt(
+ SequenceTickIndex.MetaMessageType.TIME_SIGNATURE, tickPos
+ );
+ timesigSelecter.setValue(msg==null ? null : msg.getData());
+ msg = tickIndex.lastMetaMessageAt(
+ SequenceTickIndex.MetaMessageType.TEMPO, tickPos
+ );
+ tempoSelecter.setTempo(msg==null ? null : msg.getData());
+ msg = tickIndex.lastMetaMessageAt(
+ SequenceTickIndex.MetaMessageType.KEY_SIGNATURE, tickPos
+ );
+ if(msg == null) keysigLabel.clear();
+ else setKeySignature(new Key(msg.getData()));
}
}
});
add( Box.createHorizontalStrut(5) );
add( darkModeToggleButton = new JToggleButton(new ButtonIcon(ButtonIcon.DARK_MODE_ICON)) {{
setMargin(ZERO_INSETS);
- addItemListener(new ItemListener() {
- public void itemStateChanged(ItemEvent e) {
- innerSetDarkMode(darkModeToggleButton.isSelected());
- }
- });
+ addItemListener(e->innerSetDarkMode(darkModeToggleButton.isSelected()));
setToolTipText("Light / Dark - 明かりを点灯/消灯");
setBorder(null);
}});
setMargin(ZERO_INSETS);
setBorder( null );
setToolTipText("あの楽器");
- addItemListener(new ItemListener() {
- public void itemStateChanged(ItemEvent e) {
- keyboardPanel.keyboardCenterPanel.keyboard.anoGakkiPane
- = anoGakkiToggleButton.isSelected() ? anoGakkiPane : null ;
- }
- });
+ addItemListener(
+ e -> keyboardPanel.keyboardCenterPanel.keyboard.anoGakkiPane
+ = anoGakkiToggleButton.isSelected() ? anoGakkiPane : null
+ );
}} );
add( Box.createHorizontalStrut(5) );
add( inversionOmissionButton = new InversionAndOmissionLabel() );
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(new JPanel() {{
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
- add( Box.createHorizontalStrut(12) );
- add( keysigLabel );
- add( Box.createHorizontalStrut(12) );
- add( timesigSelecter );
- add( Box.createHorizontalStrut(12) );
- add( tempoSelecter );
- add( Box.createHorizontalStrut(12) );
- add( new SequencerMeasureView(sequencerModel) );
- add( Box.createHorizontalStrut(12) );
- add( songTitleLabel );
- add( Box.createHorizontalStrut(12) );
- add( new JButton(midiEditor.openAction) {{ setMargin(ZERO_INSETS); }});
+ add(Box.createHorizontalStrut(12));
+ add(keysigLabel);
+ add(Box.createHorizontalStrut(12));
+ add(timesigSelecter);
+ add(Box.createHorizontalStrut(12));
+ add(tempoSelecter);
+ add(Box.createHorizontalStrut(12));
+ add(new SequencerMeasureView(sequencerModel));
+ add(Box.createHorizontalStrut(12));
+ add(songTitleLabel);
+ add(Box.createHorizontalStrut(12));
+ add(new JButton(midiEditor.openAction) {{ setMargin(ZERO_INSETS); }});
}});
add(new JPanel() {{
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(new JSlider(sequencerModel));
add(new SequencerTimeView(sequencerModel));
add(Box.createHorizontalStrut(5));
- add(new JButton(playlistModel.moveToTopAction) {{ setMargin(ZERO_INSETS); }});
- add(new JButton(sequencerModel.moveBackwardAction) {{ setMargin(ZERO_INSETS); }});
- add(new JToggleButton(sequencerModel.startStopAction));
- add(new JButton(sequencerModel.moveForwardAction) {{ setMargin(ZERO_INSETS); }});
- add(new JButton(playlistModel.moveToBottomAction) {{ setMargin(ZERO_INSETS); }});
- add(new JToggleButton(playlistModel.toggleRepeatAction) {{ setMargin(ZERO_INSETS); }});
+ add(new JButton(playlistModel.getMoveToTopAction()) {{ setMargin(ZERO_INSETS); }});
+ add(new JButton(sequencerModel.getMoveBackwardAction()) {{ setMargin(ZERO_INSETS); }});
+ add(new JToggleButton(sequencerModel.getStartStopAction()));
+ add(new JButton(sequencerModel.getMoveForwardAction()) {{ setMargin(ZERO_INSETS); }});
+ add(new JButton(playlistModel.getMoveToBottomAction()) {{ setMargin(ZERO_INSETS); }});
+ add(new JToggleButton(playlistModel.getToggleRepeatAction()) {{ setMargin(ZERO_INSETS); }});
add( Box.createHorizontalStrut(10) );
}});
add(new JPanel() {{
add(new JButton(midiDeviceDialog.openAction));
- add(new JButton((new AboutMessagePane()).openAction));
+ add(new JButton(about.getOpenAction()));
}});
}});
}};
}
private void setKeySignature(Key key) {
- keysigLabel.setKeySignature(key);
+ keysigLabel.setKey(key);
chordMatrix.setKeySignature(key);
}
/**
* 和音を発音します。
* <p>この関数を直接呼ぶとアルペジオが効かないので、
- * chord_matrix.setSelectedChord() を使うことを推奨
+ * chordMatrix.setSelectedChord() を使うことを推奨
* </p>
*/
public void chordOn() {
import java.util.HashMap;
import java.util.Map;
-import javax.sound.midi.MetaEventListener;
-import javax.sound.midi.MetaMessage;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
// To reduce resized height, set maximum size to screen size.
//
setMaximumSize(java.awt.Toolkit.getDefaultToolkit().getScreenSize());
- (this.sequencerModel = sequencerModel).getSequencer().addMetaEventListener(new MetaEventListener() {
- @Override
- public void meta(MetaMessage msg) {
- int t = msg.getType();
- switch(t) {
- case 0x01: // Text(任意のテキスト:コメントなど)
- case 0x05: // Lyrics(歌詞)
- case 0x02: // Copyright(著作権表示)
- case 0x03: // Sequence Name / Track Name(曲名またはトラック名)
- case 0x06: // Marker
- byte[] d = msg.getData();
- if( SwingUtilities.isEventDispatchThread() ) {
- addText(t,d);
- } else {
- // MIDIシーケンサのEDTから呼ばれた場合
- // 表示処理をSwingのEDTに振り直す
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() { addText(t,d); }
- });
- }
- break;
- default:
- break;
- }
+ (this.sequencerModel = sequencerModel).getSequencer().addMetaEventListener(msg->{
+ int t = msg.getType();
+ switch(t) {
+ case 0x01: // Text(任意のテキスト:コメントなど)
+ case 0x05: // Lyrics(歌詞)
+ case 0x02: // Copyright(著作権表示)
+ case 0x03: // Sequence Name / Track Name(曲名またはトラック名)
+ case 0x06: // Marker
+ SwingUtilities.invokeLater(()->addText(t, msg.getData()));
+ break;
+ default:
+ break;
}
});
}
String currentText = getText();
if(
currentText != null && ! currentText.isEmpty()
- && (
- isSoon ||
- ! additionalText.isEmpty() && additionalText.length() <= 8
- )
+ && (isSoon || ! additionalText.isEmpty() && additionalText.length() <= 8)
) {
// 既存歌詞がある場合、頻繁に来たか短い歌詞だったら追加
currentText += " " + additionalText;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
import javax.swing.event.TableModelEvent;
-import javax.swing.event.TableModelListener;
import camidion.chordhelper.midieditor.PlaylistTableModel;
import camidion.chordhelper.midieditor.SequenceTrackListTableModel;
* @throws Exception 何らかの異常が発生した場合にスローされる
*/
public static void main(String[] args) throws Exception {
- for( String arg : args ) fileList.add(new File(arg));
- SwingUtilities.invokeLater(new Runnable(){
- @Override
- public void run() { new AppletFrame(new ChordHelperApplet(), fileList); }
- });
+ for(String arg : args) fileList.add(new File(arg));
+ SwingUtilities.invokeLater(()->new AppletFrame(new ChordHelperApplet(), fileList));
}
private static class AppletFrame extends JFrame implements AppletStub, AppletContext {
private JLabel status_ = new JLabel("Welcome to "+ChordHelperApplet.VersionInfo.NAME) {
}
setTitle(title);
}
- public AppletFrame(final ChordHelperApplet applet, List<File> fileList) {
+ public AppletFrame(ChordHelperApplet applet, List<File> fileList) {
setTitle(ChordHelperApplet.VersionInfo.NAME);
add( applet, BorderLayout.CENTER );
add( status_, BorderLayout.SOUTH );
applet.setStub(this);
applet.init();
- setIconImage(applet.iconImage);
+ setIconImage(applet.getIconImage());
setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE );
pack();
setLocationRelativeTo(null);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent event) {
- if( ! applet.playlistModel.isModified() || applet.midiEditor.confirm(
+ if( ! applet.isModified() || applet.midiEditor.confirm(
"MIDI file not saved, exit anyway ?\n"+
"保存されていないMIDIファイルがありますが、終了してよろしいですか?"
- )) {
- applet.destroy();
- System.exit(0);
- }
+ )) { applet.destroy(); System.exit(0); }
}
});
- applet.sequencerModel.addChangeListener(new ChangeListener() {
- /**
- * シーケンサで切り替わった再生対象ファイル名をタイトルバーに反映
- */
- @Override
- public void stateChanged(ChangeEvent event) {
+ // シーケンサで切り替わった再生対象ファイル名をタイトルバーに反映
+ applet.sequencerModel.addChangeListener(e->setFilenameToTitle(applet.sequencerModel.getSequenceTrackListTableModel()));
+ // プレイリスト上で変更された再生対象ファイル名をタイトルバーに反映
+ applet.playlistModel.addTableModelListener(tme->{
+ int col = tme.getColumn();
+ if( col == PlaylistTableModel.Column.FILENAME.ordinal() || col == TableModelEvent.ALL_COLUMNS ) {
setFilenameToTitle(applet.sequencerModel.getSequenceTrackListTableModel());
}
});
- applet.playlistModel.addTableModelListener(new TableModelListener() {
- /**
- * プレイリスト上で変更された再生対象ファイル名をタイトルバーに反映
- */
- @Override
- public void tableChanged(TableModelEvent event) {
- int col = event.getColumn();
- if( col == PlaylistTableModel.Column.FILENAME.ordinal() || col == TableModelEvent.ALL_COLUMNS ) {
- setFilenameToTitle(applet.sequencerModel.getSequenceTrackListTableModel());
- }
- }
- });
applet.midiEditor.loadAndPlay(fileList);
}
@Override
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Stroke;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.util.Iterator;
import java.util.LinkedList;
*/
public AnoGakkiPane() {
setOpaque(false);
- timer = new Timer(
- INTERVAL_MS,
- new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent event) {
- synchronized(queue) {
- Iterator<QueueEntry> i = queue.iterator();
- while( i.hasNext() )
- if( i.next().countDown() <= 0 )i.remove();
- }
- if(queue.isEmpty()) timer.stop();
- repaint();
- }
- }
- ) {
- {
- setCoalesce(true);
- setRepeats(true);
+ timer = new Timer(INTERVAL_MS, e->{
+ synchronized(queue) {
+ Iterator<QueueEntry> i = queue.iterator();
+ while(i.hasNext()) if(i.next().countDown() <= 0) i.remove();
}
+ if(queue.isEmpty()) timer.stop();
+ repaint();
+ }) {
+ {setCoalesce(true);setRepeats(true);}
};
}
private Timer timer;
g2.setColor(color);
synchronized(queue) {
Iterator<QueueEntry> i = queue.iterator();
- while( i.hasNext() ) {
+ while(i.hasNext()) {
QueueEntry entry = i.next();
entry.shape.draw(g2, entry);
}
return;
}
point = SwingUtilities.convertPoint(source, point, this);
- synchronized (queue) {
- queue.add(new QueueEntry(point));
- }
+ synchronized (queue) { queue.add(new QueueEntry(point)); }
timer.start();
prevStartedAt = startedAt;
}
package camidion.chordhelper.chorddiagram;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
* カポ選択ビューを構築します。
*/
public CapoSelecterView() {
- checkbox.addItemListener(new ItemListener() {
- @Override
- public void itemStateChanged(ItemEvent e) {
- valueSelecter.setVisible(checkbox.isSelected());
- }
- });
+ checkbox.addItemListener(e->valueSelecter.setVisible(checkbox.isSelected()));
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(checkbox);
add(valueSelecter);
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Insets;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.AdjustmentEvent;
-import java.awt.event.AdjustmentListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
add(new JPanel() {
{
setOpaque(false);
- for(JRadioButton rb : instButtons.values())
- add(rb);
+ for(JRadioButton rb : instButtons.values()) add(rb);
setAlignmentY((float)1.0);
}
});
JRadioButton radioButton = new JRadioButton(label) {
{
setOpaque(false);
- addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- diagramDisplay.tune(instrument);
- }
- });
+ addActionListener(e->diagramDisplay.tune(instrument));
}
};
buttonGroup.add(radioButton);
private JScrollBar variationScrollbar = new JScrollBar(JScrollBar.VERTICAL) {
{
setModel(diagramDisplay.chordVariations.indexModel);
- addAdjustmentListener(
- new AdjustmentListener() {
- @Override
- public void adjustmentValueChanged(AdjustmentEvent e) {
- setToolTipText(diagramDisplay.chordVariations.getIndexDescription());
- }
- }
- );
+ addAdjustmentListener(e->setToolTipText(diagramDisplay.chordVariations.getIndexDescription()));
}
};
private JScrollBar fretRangeScrollbar = new JScrollBar(JScrollBar.HORIZONTAL) {
* カポ位置選択コンボボックス
*/
public CapoSelecterView capoSelecterView = new CapoSelecterView() {
- {
- checkbox.addItemListener(new ItemListener() {
- @Override
- public void itemStateChanged(ItemEvent e) { clear(); }
- });
- }
+ { checkbox.addItemListener(e->clear()); }
};
@Override
public void setBackground(Color bgColor) {
import javax.swing.DefaultBoundedRangeModel;
import javax.swing.JComponent;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
import camidion.chordhelper.chorddiagram.ChordDiagram.Instrument;
import camidion.chordhelper.music.Chord;
fretIndex++
) {
if( fretIndex == 0 || fretIndex > fretViewIndexModel.getValue() ) {
- int chordNoteIndex = chord.indexOf(
- notesWhenOpen[stringIndex]+fretIndex
- );
+ int chordNoteIndex = chord.indexOf(notesWhenOpen[stringIndex]+fretIndex);
if( chordNoteIndex >= 0 ) {
possiblePressingPoints[stringIndex].add(
new PressingPoint(fretIndex,chordNoteIndex,stringIndex)
public ChordDiagramDisplay(ChordDiagram.Instrument inst) {
addMouseListener(this);
addMouseMotionListener(this);
- addComponentListener(
- new ComponentAdapter() {
- @Override
- public void componentResized(ComponentEvent e) {
- tune();
- }
- }
- );
- chordVariations.indexModel.addChangeListener(
- new ChangeListener() {
- @Override
- public void stateChanged(ChangeEvent e) {
- repaint();
- }
- }
- );
- fretViewIndexModel.addChangeListener(
- new ChangeListener() {
- @Override
- public void stateChanged(ChangeEvent e) {
- setChord(); // To reconstruct chord variations
- }
- }
- );
+ addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) { tune(); }
+ });
+ chordVariations.indexModel.addChangeListener(e->repaint());
+ // To reconstruct chord variations
+ fretViewIndexModel.addChangeListener(e->setChord());
setMinimumSize(new Dimension(100,70));
tune(inst);
}
}
}
}
- private void drawIndicator(
- Graphics2D g2, PressingPoint pp, boolean drawAllPoints
- ) {
+ private void drawIndicator(Graphics2D g2, PressingPoint pp, boolean drawAllPoints) {
Rectangle r;
int i_chord = pp.chordNoteIndex;
g2.setColor(
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DragSource;
-import java.awt.dnd.DragSourceDragEvent;
-import java.awt.dnd.DragSourceMotionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.Hashtable;
import java.util.List;
-import javax.sound.midi.MidiDevice;
import javax.sound.midi.Receiver;
import javax.sound.midi.Transmitter;
import javax.swing.JComponent;
public void internalFrameDeactivated(InternalFrameEvent e) { repaint(); }
@Override
public void internalFrameClosing(InternalFrameEvent e) {
- JInternalFrame frame = e.getInternalFrame();
- if( ! (frame instanceof MidiDeviceFrame) ) return;
- MidiDeviceFrame f = (MidiDeviceFrame)frame;
- MidiDeviceModel m = f.getMidiDeviceModel();
- MidiDevice d = m.getMidiDevice();
- List<Receiver> rxList = d.getReceivers();
- for( Receiver rx : rxList ) rxToColor.remove(rx);
+ JInternalFrame f = e.getInternalFrame();
+ if( ! (f instanceof MidiDeviceFrame) ) return;
+ MidiDeviceModel m = ((MidiDeviceFrame)f).getMidiDeviceModel();
+ m.getMidiDevice().getReceivers().forEach(rx->rxToColor.remove(rx));
repaint();
}
};
this.desktopPane = desktopPane;
setOpaque(false);
setVisible(true);
- DragSource.getDefaultDragSource().addDragSourceMotionListener(new DragSourceMotionListener() {
- @Override
- public void dragMouseMoved(DragSourceDragEvent dsde) {
- // OSのスクリーン座標系から、このケーブル画面の座標系に変換する
- Point origin = getLocationOnScreen();
- (draggingLocation = dsde.getLocation()).translate(-origin.x, -origin.y);
- repaint();
- }
+ DragSource.getDefaultDragSource().addDragSourceMotionListener(dsde->{
+ // OSのスクリーン座標系から、このケーブル画面の座標系に変換する
+ Point origin = getLocationOnScreen();
+ (draggingLocation = dsde.getLocation()).translate(-origin.x, -origin.y);
+ repaint();
});
}
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.beans.PropertyVetoException;
-import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
import javax.sound.midi.MidiUnavailableException;
import javax.swing.JDesktopPane;
public void treeNodesRemoved(TreeModelEvent e) { }
@Override
public void treeStructureChanged(TreeModelEvent e) {
+ // USBから切断されてツリーから消滅したMIDIデバイスモデルのフレームを削除
+ frameMap.keySet().stream().filter(m-> ! deviceTreeModel.contains(m))
+ .collect(Collectors.toList()).stream().map(m-> frameMap.remove(m))
+ .filter(f-> f != null).forEach(f-> remove(f));
//
- // 削除されたデバイスモデルに対するデバイスフレームをマップから外す
- List<MidiDeviceModel> deviceModelsToRemove = new ArrayList<>();
- for( MidiDeviceModel m : frameMap.keySet() ) {
- if( ! deviceTreeModel.contains(m) ) deviceModelsToRemove.add(m);
- }
- for( MidiDeviceModel m : deviceModelsToRemove ) {
- MidiDeviceFrame frame = frameMap.remove(m);
- if( frame != null ) remove(frame);
- }
- //
- // 新しいデバイスモデルに対するデバイスフレームを生成してマップに登録
- for( MidiDeviceModel deviceModel : deviceTreeModel ) {
- if( frameMap.containsKey(deviceModel) ) continue;
- MidiDeviceFrame frame = new MidiDeviceFrame(deviceModel, cablePane);
- frameMap.put(deviceModel, frame);
+ // ツリーに追加されたMIDIデバイスモデルのフレームを生成
+ deviceTreeModel.stream().filter(dm -> ! frameMap.containsKey(dm)).forEach(dm->{
+ MidiDeviceFrame frame = new MidiDeviceFrame(dm, cablePane);
+ frameMap.put(dm, frame);
//
// トランスミッタリストモデルが変化したときにMIDIケーブルを再描画
- TransmitterListModel txListModel = deviceModel.getTransmitterListModel();
+ TransmitterListModel txListModel = dm.getTransmitterListModel();
if( txListModel != null ) txListModel.addListDataListener(cablePane.midiConnecterListDataListener);
//
// レシーバリストモデルが変化したときにMIDIケーブルを再描画
- ReceiverListModel rxListModel = deviceModel.getReceiverListModel();
+ ReceiverListModel rxListModel = dm.getReceiverListModel();
if( rxListModel != null ) rxListModel.addListDataListener(cablePane.midiConnecterListDataListener);
//
// デバイスフレームが開閉したときの動作
frame.addComponentListener(cablePane.midiDeviceFrameComponentListener);
//
// サイズを設定したフレームをデスクトップに追加
- frame.setSize(250, deviceModel.getInOutType() == MidiDeviceInOutType.MIDI_IN_OUT ? 90 : 70);
+ frame.setSize(250, dm.getInOutType() == MidiDeviceInOutType.MIDI_IN_OUT ? 90 : 70);
add(frame);
//
// デバイスが開いていたら表示
- if( deviceModel.getMidiDevice().isOpen() ) {
- frame.setVisible(true);
- }
- }
+ if( dm.getMidiDevice().isOpen() ) frame.setVisible(true);
+ });
}
};
deviceTreeModel.addTreeModelListener(treeModelListener);
package camidion.chordhelper.mididevice;
import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
putValue(LARGE_ICON_KEY, MIDI_CONNECTER_ICON);
}
@Override
- public void actionPerformed(ActionEvent event) {
- setVisible(true);
- }
+ public void actionPerformed(ActionEvent event) { setVisible(true); }
};
/**
* MIDIデバイスダイアログを構築します。
add(new JPanel() {{
add(new JButton("Detect USB MIDI devices", new ButtonIcon(ButtonIcon.REPEAT_ICON)) {{
setToolTipText("Update view for USB MIDI device newly plugged or removed");
- addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- deviceTreeModel.updateMidiDeviceList();
- deviceTreeView.expandAll();
- }
+ addActionListener(e->{
+ deviceTreeModel.updateMidiDeviceList();
+ deviceTreeView.expandAll();
});
}});
add(new JButton("Reset Tx timestamp", new ButtonIcon(ButtonIcon.TOP_ICON)) {{
setToolTipText("Reset timestamp on transmittable MIDI devices");
- addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- deviceTreeModel.resetMicrosecondPosition();
- }
- });
+ addActionListener(e->deviceTreeModel.resetMicrosecondPosition());
}});
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
}});
this.description = description;
this.shortName = shortName;
}
+ /**
+ * 指定されたMIDIデバイスがどの入出力タイプに該当するかを返します。
+ * @param device MIDIデバイス
+ * @return 指定されたMIDIデバイスに対する入出力タイプ
+ */
public static MidiDeviceInOutType getValueFor(MidiDevice device) {
// tx:IN rx:OUT
return device.getMaxReceivers() == 0 ?
package camidion.chordhelper.mididevice;
+import java.util.AbstractCollection;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
+import java.util.stream.Collectors;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
public int size() { return deviceModelList.size(); }
@Override
public MidiDeviceModel get(int index) { return deviceModelList.get(index); }
+ /**
+ * このリストの内容を反映したツリー構造のマップ
+ */
protected Map<MidiDeviceInOutType, List<MidiDeviceModel>> deviceModelTree; {
deviceModelTree = new EnumMap<>(MidiDeviceInOutType.class);
deviceModelTree.put(MidiDeviceInOutType.MIDI_OUT, new ArrayList<>());
deviceModelTree.put(MidiDeviceInOutType.MIDI_IN_OUT, new ArrayList<>());
};
/**
- * {@link #add()}の非public版です。
+ * {@link AbstractList#add(E)}の操作を内部的に行います。
+ * 指定された要素をこのリストの最後に追加し、ツリー構造にも反映します。
+ *
* @param dm 追加するMIDIデバイスモデル
- * @return true({@link AbstractList#add()}ã\81¨å\90\8cã\81\98ï¼\89
+ * @return true({@link AbstractList#add(E)} ã\81¨å\90\8cæ§\98ï¼\89
*/
protected boolean addInternally(MidiDeviceModel dm) {
if( ! deviceModelList.add(dm) ) return false;
return true;
}
/**
- * {@link #removeAll()}の非public版です。
+ * {@link AbstractCollection#removeAll(Collection)}の操作を内部的に行います。
+ * 指定されたコレクションに該当するすべての要素を、このリストから削除します。
+ * このリストが変更された場合、ツリー構造にも反映されます。
* @param c 削除する要素のコレクション
- * @return {@link AbstractList#removeAll()}と同じ
+ * @return このリストが変更された場合はtrue({@link AbstractCollection#removeAll(Collection)} と同様)
*/
protected boolean removeAllInternally(Collection<?> c) {
if( ! deviceModelList.removeAll(c) ) return false;
- for( Object o : c ) {
- if( o instanceof MidiDeviceModel ) {
- MidiDeviceInOutType ioType = ((MidiDeviceModel)o).getInOutType();
- deviceModelTree.get(ioType).remove(o);
- }
- }
+ c.stream().filter(o -> o instanceof MidiDeviceModel).map(o -> (MidiDeviceModel)o)
+ .forEach(mdm -> deviceModelTree.get(mdm.getInOutType()).remove(mdm));
return true;
}
- // ツリーモデル用インターフェース
@Override
public Object getRoot() { return this; }
@Override
}
/**
- * {@link MidiSystem#getMidiDeviceInfo()} ã\81®çµ\90æ\9e\9cã\82\92ã\80\81不変の {@link List} として返します。
+ * {@link MidiSystem#getMidiDeviceInfo()} ã\81\8cè¿\94ã\81\97ã\81\9fé\85\8då\88\97ã\82\92不変の {@link List} として返します。
*
* <p>注意点:MIDIデバイスをUSBから抜いて、他のデバイスとの接続を切断せずに
* {@link MidiSystem#getMidiDeviceInfo()}を呼び出すと
* @param guiVirtualDevice 管理対象に含めるGUI仮想MIDIデバイス
*/
public MidiDeviceTreeModel(VirtualMidiDevice guiVirtualDevice) {
+ MidiDeviceModel synthModel = null;
+ MidiDeviceModel firstMidiInModel = null;
+ MidiDeviceModel firstMidiOutModel = null;
+ // GUI
MidiDeviceModel guiModel = new MidiDeviceModel(guiVirtualDevice, this);
addInternally(guiModel);
+ // シーケンサー
try {
addInternally(sequencerModel = new MidiSequencerModel(MidiSystem.getSequencer(false), this));
} catch( MidiUnavailableException e ) {
System.out.println(ChordHelperApplet.VersionInfo.NAME +" : MIDI sequencer unavailable");
e.printStackTrace();
}
- MidiDeviceModel synthModel = null;
- MidiDeviceModel firstMidiInModel = null;
- MidiDeviceModel firstMidiOutModel = null;
- for( MidiDevice.Info info : getMidiDeviceInfo() ) {
- MidiDevice device;
+ // システムで使用可能な全MIDIデバイス(シーケンサーはすでに取得済みなので除外)
+ for( MidiDevice device : getMidiDeviceInfo().stream().map(info -> {
try {
- device = MidiSystem.getMidiDevice(info);
+ return MidiSystem.getMidiDevice(info);
} catch( MidiUnavailableException e ) {
e.printStackTrace();
- continue;
+ return null;
}
- if( device instanceof Sequencer ) continue; // シーケンサはすでに取得済み
- if( device instanceof Synthesizer ) { // Java内蔵シンセサイザ
+ }).filter(
+ device -> device != null && ! (device instanceof Sequencer)
+ ).collect(Collectors.toList()) ) {
+ if( device instanceof Synthesizer ) { // Java内蔵シンセサイザの場合
try {
addInternally(synthModel = new MidiDeviceModel(MidiSystem.getSynthesizer(), this));
} catch( MidiUnavailableException e ) {
// 開く順序が逆になると「進みすぎるから遅らせよう」として無用なレイテンシーが発生する原因になる。
//
List<MidiDeviceModel> openedMidiDeviceModelList = new ArrayList<>();
- for( MidiDeviceModel toOpen : Arrays.asList(
- synthModel, firstMidiOutModel, sequencerModel, guiModel, firstMidiInModel) ) {
- if( toOpen == null ) continue;
+ Arrays.asList(
+ synthModel,
+ firstMidiOutModel,
+ sequencerModel,
+ guiModel,
+ firstMidiInModel
+ ).stream().filter(mdm -> mdm != null).forEach(mdm->{
try {
- toOpen.open();
+ mdm.open();
+ openedMidiDeviceModelList.add(mdm);
} catch( MidiUnavailableException ex ) {
String title = ChordHelperApplet.VersionInfo.NAME;
- String message = "Cannot open MIDI device '"+toOpen+"'\n"
- + "MIDIデバイス "+toOpen+" を開くことができません。\n\n"
- + ex.getMessage();
+ String message = "Cannot open MIDI device '"+mdm+"'\n"
+ + "MIDIデバイス "+mdm+" を開くことができません。\n\n" + ex;
JOptionPane.showMessageDialog(null, message, title, JOptionPane.ERROR_MESSAGE);
- continue;
}
- openedMidiDeviceModelList.add(toOpen);
- }
+ });
// 初期接続マップを作成(開いたデバイスを相互に接続する)
+ // 自身のTx/Rx同士の接続は、シーケンサーモデルはなし、それ以外(GUIデバイスモデル)はあり。
Map<MidiDeviceModel, Collection<MidiDeviceModel>> initialConnection = new LinkedHashMap<>();
- for( MidiDeviceModel rxm : openedMidiDeviceModelList ) {
- if( rxm.getReceiverListModel() == null ) continue;
+ openedMidiDeviceModelList.stream().filter(rxm ->
+ rxm.getReceiverListModel() != null
+ ).forEach(rxm -> {
List<MidiDeviceModel> txmList;
initialConnection.put(rxm, txmList = new ArrayList<>());
- for( MidiDeviceModel txm : openedMidiDeviceModelList ) {
- if( txm.getTransmitterListModel() == null ) continue;
- //
- // Tx/Rx両方を持つデバイスでは
- // ・シーケンサーモデルは自分自身には接続しない
- // ・GUIデバイスモデルでは自分自身にも接続する
- if( txm == sequencerModel && txm == rxm ) continue;
- //
- txmList.add(txm);
- }
- }
+ openedMidiDeviceModelList.stream().filter(txm ->
+ txm.getTransmitterListModel() != null
+ && !(txm == sequencerModel && txm == rxm)
+ ).forEach(txm -> txmList.add(txm));
+ });
// 初期接続を実行
connectDevices(initialConnection);
}
* すべてのMIDIデバイスを閉じます。
*/
public void closeAllDevices() {
- for(MidiDeviceModel m : deviceModelList) m.getMidiDevice().close();
+ deviceModelList.forEach(m -> m.getMidiDevice().close());
}
/**
* デバイス間の接続をすべて切断します。
*/
public Map<MidiDeviceModel, Collection<MidiDeviceModel>> disconnectAllDevices() {
Map<MidiDeviceModel, Collection<MidiDeviceModel>> rxToTxConnections = new LinkedHashMap<>();
- for(MidiDeviceModel m : deviceModelList) {
+ deviceModelList.stream().forEach(m -> {
ReceiverListModel rxListModel = m.getReceiverListModel();
- if( rxListModel == null ) continue;
+ if( rxListModel == null ) return;
Collection<MidiDeviceModel> txDeviceModels = rxListModel.closeTransmitters();
- if( txDeviceModels.isEmpty() ) continue;
- rxToTxConnections.put(m, txDeviceModels);
- }
+ if( ! txDeviceModels.isEmpty() ) rxToTxConnections.put(m, txDeviceModels);
+ });
return rxToTxConnections;
}
/**
* </ul>
*/
public void connectDevices(Map<MidiDeviceModel, Collection<MidiDeviceModel>> rxToTxConnections) {
- for( MidiDeviceModel rxm : rxToTxConnections.keySet() ) {
- if( rxm == null ) continue;
+ rxToTxConnections.keySet().stream().filter(rxm -> rxm != null).forEach(rxm -> {
Receiver rx = rxm.getReceiverListModel().getTransceivers().get(0);
- for( MidiDeviceModel txm : rxToTxConnections.get(rxm) ) {
- if( txm == null ) continue;
+ rxToTxConnections.get(rxm).stream().filter(txm -> txm != null).forEach(txm -> {
try {
txm.getTransmitterListModel().openTransmitter().setReceiver(rx);
} catch( MidiUnavailableException e ) {
e.printStackTrace();
}
- }
- }
+ });
+ });
}
/**
* USB-MIDIデバイスの着脱後、MIDIデバイスリストを最新の状態に更新します。
//
// 追加・削除されたMIDIデバイスを特定
List<MidiDevice.Info> toAdd = new Vector<>(getMidiDeviceInfo());
- List<MidiDeviceModel> toRemove = new Vector<>();
- for(MidiDeviceModel m : deviceModelList) {
+ List<MidiDeviceModel> toRemove = deviceModelList.stream().filter(m -> {
MidiDevice d = m.getMidiDevice();
- if( d instanceof VirtualMidiDevice || toAdd.remove(d.getDeviceInfo()) ) continue;
- d.close();
- toRemove.add(m);
- }
+ if( d instanceof VirtualMidiDevice || toAdd.remove(d.getDeviceInfo()) ) return false;
+ d.close(); return true;
+ }).collect(Collectors.toList());
// 削除されたデバイスのモデルを除去
if( removeAllInternally(toRemove) ) {
Set<MidiDeviceModel> rxModels = rxToTxConnections.keySet();
rxModels.removeAll(toRemove);
- for( MidiDeviceModel m : rxModels ) rxToTxConnections.get(m).removeAll(toRemove);
+ rxModels.forEach(m -> rxToTxConnections.get(m).removeAll(toRemove));
}
// 追加されたデバイスのモデルを登録
- for( MidiDevice.Info info : toAdd ) {
+ toAdd.forEach(info -> {
try {
addInternally(new MidiDeviceModel(info, this));
} catch( MidiUnavailableException e ) {
e.printStackTrace();
}
- }
+ });
// 再接続
connectDevices(rxToTxConnections);
//
* {@link MidiDeviceModel#resetMicrosecondPosition()}でマイクロ秒位置をリセットします。
*/
public void resetMicrosecondPosition() {
- for(MidiDeviceModel m : deviceModelList) {
- TransmitterListModel txListModel = m.getTransmitterListModel();
- if( txListModel != null ) txListModel.resetMicrosecondPosition();
- }
+ deviceModelList.stream().map(dm -> dm.getTransmitterListModel())
+ .filter(tlm -> tlm != null)
+ .forEach(tlm -> tlm.resetMicrosecondPosition());
}
}
package camidion.chordhelper.mididevice;
import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import camidion.chordhelper.midieditor.SequencerSpeedSlider;
/**
- * MIDIシーケンサモデル
+ * MIDIシーケンサモデル(再生位置モデルのインターフェース付き)
*/
public class MidiSequencerModel extends MidiDeviceModel implements BoundedRangeModel {
/**
super(sequencer, deviceModelTree);
}
/**
- * このシーケンサーの再生スピード調整モデル
+ * このシーケンサーの再生スピード
*/
public BoundedRangeModel speedSliderModel = new DefaultBoundedRangeModel(0, 0, -7, 7) {{
- addChangeListener(new ChangeListener() {
- @Override
- public void stateChanged(ChangeEvent e) {
- getSequencer().setTempoFactor(SequencerSpeedSlider.tempoFactorOf(getValue()));
- }
- });
+ addChangeListener(e->getSequencer().setTempoFactor(SequencerSpeedSlider.tempoFactorOf(getValue())));
}};
/**
* MIDIシーケンサを返します。
/**
* 開始終了アクション
*/
- public StartStopAction startStopAction = new StartStopAction();
- /**
- * 開始終了アクション
- */
- class StartStopAction extends AbstractAction {
+ public Action getStartStopAction() { return startStopAction; }
+ private StartStopAction startStopAction = new StartStopAction();
+ private class StartStopAction extends AbstractAction {
private Map<Boolean,Icon> iconMap = new HashMap<Boolean,Icon>() {
{
put(Boolean.FALSE, new ButtonIcon(ButtonIcon.PLAY_ICON));
}
};
{
- putValue(
- SHORT_DESCRIPTION,
- "Start/Stop recording or playing - 録音または再生の開始/停止"
- );
+ putValue(SHORT_DESCRIPTION, "Start/Stop recording or playing - 録音または再生の開始/停止");
setRunning(false);
}
@Override
public void actionPerformed(ActionEvent event) {
if(timeRangeUpdater.isRunning()) stop(); else start();
}
- /**
- * 開始されているかどうかを設定します。
- * @param isRunning 開始されていたらtrue
- */
private void setRunning(boolean isRunning) {
putValue(LARGE_ICON_KEY, iconMap.get(isRunning));
putValue(SELECTED_KEY, isRunning);
}
}
/**
- * シーケンサに合わせてミリ秒位置を更新するタイマー
- */
- private javax.swing.Timer timeRangeUpdater = new javax.swing.Timer( 20,
- new ActionListener(){
- @Override
- public void actionPerformed(ActionEvent e) {
- if( valueIsAdjusting || ! getSequencer().isRunning() ) {
- // 手動で移動中の場合や、シーケンサが止まっている場合は、
- // タイマーによる更新は不要
- return;
- }
- // リスナーに読み込みを促す
- fireStateChanged();
- }
- }
- );
- /**
* このモデルのMIDIシーケンサを開始します。
*
* <p>録音するMIDIチャンネルがMIDIエディタで指定されている場合、
public void setValueIsAdjusting(boolean valueIsAdjusting) {
this.valueIsAdjusting = valueIsAdjusting;
}
+ /**
+ * シーケンサに合わせてミリ秒位置を更新するタイマー
+ */
+ private javax.swing.Timer timeRangeUpdater = new javax.swing.Timer(20, e->{
+ if( valueIsAdjusting || ! getSequencer().isRunning() ) {
+ // 手動で移動中の場合や、シーケンサが止まっている場合は、
+ // タイマーによる更新は不要
+ return;
+ }
+ // リスナーに読み込みを促す
+ fireStateChanged();
+ });
@Override
public void setRangeProperties(int value, int extent, int min, int max, boolean valueIsAdjusting) {
getSequencer().setMicrosecondPosition(RESOLUTION_MICROSECOND * (long)value);
/**
* 1小節戻るアクション
*/
- public Action moveBackwardAction = new AbstractAction() {
+ public Action getMoveBackwardAction() { return moveBackwardAction; }
+ private Action moveBackwardAction = new AbstractAction() {
{
putValue(SHORT_DESCRIPTION, "Move backward 1 measure - 1小節戻る");
putValue(LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.BACKWARD_ICON));
/**
*1小節進むアクション
*/
- public Action moveForwardAction = new AbstractAction() {
+ public Action getMoveForwardAction() { return moveForwardAction; }
+ private Action moveForwardAction = new AbstractAction() {
{
putValue(SHORT_DESCRIPTION, "Move forward 1 measure - 1小節進む");
putValue(LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.FORWARD_ICON));
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
import camidion.chordhelper.midieditor.SequenceTickIndex;
import camidion.chordhelper.midieditor.SequenceTrackListTableModel;
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(measurePositionLabel = new MeasurePositionLabel());
add(measureLengthLabel = new MeasureLengthLabel());
- model.addChangeListener(new ChangeListener() {
- @Override
- public void stateChanged(ChangeEvent e) {
- Object source = e.getSource();
- if( ! (source instanceof MidiSequencerModel) ) return;
- MidiSequencerModel model = (MidiSequencerModel)source;
- Sequencer sequencer = model.getSequencer();
- SequenceTrackListTableModel sequenceTableModel = model.getSequenceTrackListTableModel();
- SequenceTickIndex tickIndex = (
- sequenceTableModel == null ? null : sequenceTableModel.getSequenceTickIndex()
- );
- if( ! sequencer.isRunning() || sequencer.isRecording() ) {
- // 停止中または録音中の場合、長さが変わることがあるので表示を更新
- if( tickIndex == null ) {
- measureLengthLabel.setMeasure(0);
- }
- else {
- long tickLength = sequencer.getTickLength();
- int measureLength = tickIndex.tickToMeasure(tickLength);
- measureLengthLabel.setMeasure(measureLength);
- }
- }
- // 小節位置の表示を更新
+ model.addChangeListener(e -> {
+ Object source = e.getSource();
+ if( ! (source instanceof MidiSequencerModel) ) return;
+ MidiSequencerModel sourceModel = (MidiSequencerModel)source;
+ Sequencer sequencer = sourceModel.getSequencer();
+ SequenceTrackListTableModel sequenceTableModel = sourceModel.getSequenceTrackListTableModel();
+ SequenceTickIndex tickIndex = (
+ sequenceTableModel == null ? null : sequenceTableModel.getSequenceTickIndex()
+ );
+ if( ! sequencer.isRunning() || sequencer.isRecording() ) {
+ // 停止中または録音中の場合、長さが変わることがあるので表示を更新
if( tickIndex == null ) {
- measurePositionLabel.setMeasure(0, 0);
+ measureLengthLabel.setMeasure(0);
}
else {
- long tickPosition = sequencer.getTickPosition();
- int measurePosition = tickIndex.tickToMeasure(tickPosition);
- measurePositionLabel.setMeasure(measurePosition, tickIndex.lastBeat);
+ long tickLength = sequencer.getTickLength();
+ int measureLength = tickIndex.tickToMeasure(tickLength);
+ measureLengthLabel.setMeasure(measureLength);
}
}
+ // 小節位置の表示を更新
+ if( tickIndex == null ) {
+ measurePositionLabel.setMeasure(0, 0);
+ }
+ else {
+ long tickPosition = sequencer.getTickPosition();
+ int measurePosition = tickIndex.tickToMeasure(tickPosition);
+ measurePositionLabel.setMeasure(measurePosition, tickIndex.lastBeat);
+ }
});
}
private static abstract class MeasureLabel extends JLabel {
setToolTipText("Measure:beat position - 何小節目:何拍目");
}
public boolean setMeasure(int measure, int beat) {
- if( ! super.setMeasure(measure) && this.beat == beat )
- return false;
+ if( ! super.setMeasure(measure) && this.beat == beat ) return false;
setText(String.format("%04d:%02d", measure+1, beat+1));
return true;
}
setToolTipText("Measure length - 小節の数");
}
public boolean setMeasure(int measure) {
- if( ! super.setMeasure(measure) )
- return false;
+ if( ! super.setMeasure(measure) ) return false;
setText(String.format("/%04d", measure));
return true;
}
try {
midiData = getMIDIData();
} catch(Exception e) {
- e.printStackTrace();
error("Base64デコードに失敗しました。\n"+e);
return;
}
try {
midiEditor.sequenceListTable.getModel().addSequence(midiData, null);
} catch(Exception e) {
- e.printStackTrace();
error("Base64デコードされたデータが正しいMIDI形式になっていません。\n"+e);
return;
}
private Key key;
public KeySignatureLabel() { clear(); }
public Key getKey() { return key; }
- public void setKeySignature( Key key ) {
- this.key = key;
- if( key == null ) {
+ public void setKey(Key key) {
+ if( (this.key = key) == null ) {
setText("Key:C");
setToolTipText("Key: Unknown");
setEnabled(false);
);
setEnabled(true);
}
- public void clear() { setKeySignature( (Key)null ); }
+ public void clear() { setKey((Key)null); }
}
\ No newline at end of file
import java.awt.FlowLayout;
import java.awt.GridLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import javax.swing.Action;
import javax.swing.JButton;
add(okButton = new JButton("OK"));
add(cancelButton = new JButton("Cancel"));
}});
- cancelButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- setVisible(false);
- }
- });
+ cancelButton.addActionListener(e->setVisible(false));
}
public void openForm(
String title, Action okAction, int midiChannel,
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
import java.nio.charset.Charset;
import javax.sound.midi.InvalidMidiDataException;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JPanel;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
import camidion.chordhelper.music.Key;
import camidion.chordhelper.music.MIDISpec;
private PianoKeyboardPanel keyboardPanel = new PianoKeyboardPanel() {
{
keyboard.setPreferredSize(new Dimension(300,40));
- keyboard.addPianoKeyboardListener(
- new PianoKeyboardAdapter() {
- public void pianoKeyPressed(int n, InputEvent e) {
- data1Text.setValue(n);
- if( midiChannels == null ) return;
- midiChannels[channelText.getSelectedChannel()].noteOn(n, data2Text.getValue());
- }
- public void pianoKeyReleased(int n, InputEvent e) {
- if( midiChannels == null ) return;
- midiChannels[channelText.getSelectedChannel()].noteOff(n, data2Text.getValue());
- }
+ keyboard.addPianoKeyboardListener(new PianoKeyboardAdapter() {
+ public void pianoKeyPressed(int n, InputEvent e) {
+ data1Text.setValue(n);
+ if( midiChannels == null ) return;
+ midiChannels[channelText.getSelectedChannel()].noteOn(n, data2Text.getValue());
}
- );
+ public void pianoKeyReleased(int n, InputEvent e) {
+ if( midiChannels == null ) return;
+ midiChannels[channelText.getSelectedChannel()].noteOff(n, data2Text.getValue());
+ }
+ });
}
};
/**
* テンポ選択
*/
private TempoSelecter tempoSelecter = new TempoSelecter() {
- {
- tempoSpinnerModel.addChangeListener(new ChangeListener() {
- @Override
- public void stateChanged(ChangeEvent e) {
- dataText.setValue(getTempoByteArray());
- }
- });
- }
+ { tempoSpinnerModel.addChangeListener(e->dataText.setValue(getTempoByteArray())); }
};
/**
* 拍子選択
*/
private TimeSignatureSelecter timesigSelecter = new TimeSignatureSelecter() {
{
- upperTimesigModel.addChangeListener(new ChangeListener() {
- @Override
- public void stateChanged(ChangeEvent e) { update(); }
- });
- lowerTimesigView.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) { update(); }
- });
+ upperTimesigModel.addChangeListener(e->update());
+ lowerTimesigView.addActionListener(e->update());
}
private void update() { dataText.setValue(getByteArray()); }
};
*/
private KeySignatureSelecter keysigSelecter = new KeySignatureSelecter(new Key("C")) {
{
- keysigCombobox.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) { update(); }
- });
- minorCheckbox.addItemListener(new ItemListener() {
- @Override
- public void itemStateChanged(ItemEvent e) { update(); }
- });
+ keysigCombobox.addActionListener(e->update());
+ minorCheckbox.addItemListener(e->update());
}
private void update() { dataText.setValue(getSelectedKey().getBytes()); }
};
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileOutputStream;
* エラーメッセージダイアログを表示します。
* @param message エラーメッセージ
*/
- public void showError(String message) { showMessage(message, JOptionPane.ERROR_MESSAGE); }
+ public void showError(Object message) { showMessage(message, JOptionPane.ERROR_MESSAGE); }
/**
* 警告メッセージダイアログを表示します。
* @param message 警告メッセージ
*/
- public void showWarning(String message) { showMessage(message, JOptionPane.WARNING_MESSAGE); }
- private void showMessage(String message, int messageType) {
+ public void showWarning(Object message) { showMessage(message, JOptionPane.WARNING_MESSAGE); }
+ private void showMessage(Object message, int messageType) {
JOptionPane.showMessageDialog(this, message, ChordHelperApplet.VersionInfo.NAME, messageType);
}
/**
* @param message 確認メッセージ
* @return 確認OKのときtrue
*/
- public boolean confirm(String message) {
+ public boolean confirm(Object message) {
return JOptionPane.showConfirmDialog(this, message, ChordHelperApplet.VersionInfo.NAME,
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION ;
}
try {
loadAndPlay((List<File>)support.getTransferable().getTransferData(DataFlavor.javaFileListFlavor));
return true;
- } catch (Exception e) {
- e.printStackTrace();
- showError(e.getMessage());
- return false;
- }
+ } catch (Exception e) { showError(e); return false; }
}
};
try {
indexOfAddedTop = playlist.addSequences(fileList);
} catch(IOException|InvalidMidiDataException e) {
- showWarning(e.getMessage());
+ showWarning(e);
} catch(AccessControlException e) {
- e.printStackTrace();
- showError(e.getMessage());
+ showError(e);
}
MidiSequencerModel sequencerModel = playlist.getSequencerModel();
if( sequencerModel.getSequencer().isRunning() ) {
if( indexOfAddedTop >= 0 ) {
try {
playlist.loadToSequencer(indexOfAddedTop);
- } catch (InvalidMidiDataException ex) {
- ex.printStackTrace();
- showError(ex.getMessage());
- return;
- }
+ } catch (InvalidMidiDataException e) { showError(e); return; }
sequencerModel.start();
}
}
//
// タイトルに合計シーケンス長を表示
if( lengthColumn != null ) {
- int sec = getModel().getTotalSeconds();
+ int sec = getModel().getTotalTimeInSeconds();
String title = PlaylistTableModel.Column.LENGTH.title;
title = String.format(title+" [%02d:%02d]", sec/60, sec%60);
lengthColumn.setHeaderValue(title);
) {
try {
getModel().loadToSequencer(row);
- } catch (InvalidMidiDataException ex) {
- ex.printStackTrace();
- showError(ex.getMessage());
- }
+ } catch (InvalidMidiDataException ex) { showError(ex); }
fireEditingStopped();
return null;
}
implements TableCellEditor, TableCellRenderer
{
private JToggleButton playButton = new JToggleButton(
- getModel().getSequencerModel().startStopAction
+ getModel().getSequencerModel().getStartStopAction()
) {
{ setMargin(ZERO_INSETS); }
};
//
// セル内にプレイボタンがあれば、シングルクリックを受け付ける。
// プレイボタンのないセルは、ダブルクリックのみ受け付ける。
- return model.getSequenceList().get(row).isOnSequencer() || me.getClickCount() == 2;
+ return model.getSequenceModelList().get(row).isOnSequencer() || me.getClickCount() == 2;
}
@Override
public Object getCellEditorValue() { return null; }
/**
* {@inheritDoc}
*
- * <p>この実装では、行の表すシーケンスが
- * シーケンサーにロードされている場合にプレイボタンを返します。
- * そうでない場合は、
- * そのシーケンスをシーケンサーにロードしてnullを返します。
+ * <p>この実装では、行の表すシーケンスがシーケンサーにロードされている場合にプレイボタンを返します。
+ * そうでない場合は、そのシーケンスをシーケンサーにロードしてnullを返します。
* </p>
*/
@Override
) {
fireEditingStopped();
PlaylistTableModel model = getModel();
- if( model.getSequenceList().get(row).isOnSequencer() ) return playButton;
+ if( model.getSequenceModelList().get(row).isOnSequencer() ) return playButton;
try {
model.loadToSequencer(row);
- } catch (InvalidMidiDataException ex) {
- ex.printStackTrace();
- showError(ex.getMessage());
- }
+ } catch (InvalidMidiDataException ex) { showError(ex); }
return null;
}
@Override
boolean hasFocus, int row, int column
) {
PlaylistTableModel model = getModel();
- if(model.getSequenceList().get(row).isOnSequencer()) return playButton;
+ if(model.getSequenceModelList().get(row).isOnSequencer()) return playButton;
Class<?> cc = model.getColumnClass(column);
TableCellRenderer defaultRenderer = table.getDefaultRenderer(cc);
return defaultRenderer.getTableCellRendererComponent(
* @return プレイリストモデル
*/
@Override
- public PlaylistTableModel getModel() { return (PlaylistTableModel)super.getModel(); }
+ public PlaylistTableModel getModel() {
+ return (PlaylistTableModel)super.getModel();
+ }
/**
* シーケンスを削除するアクション
*/
try {
model.removeSelectedSequence();
} catch (InvalidMidiDataException ex) {
- ex.printStackTrace();
- showError(ex.getMessage());
+ showError(ex);
}
}
};
sequenceModel.setModified(false);
playlistModel.fireSequenceModified(sequenceModel, false);
}
- catch( IOException ex ) {
- ex.printStackTrace();
- showError( ex.getMessage() );
- }
+ catch( IOException ex ) { showError(ex); }
}
};
/**
if( showOpenDialog((Component)event.getSource()) != JFileChooser.APPROVE_OPTION ) return;
try {
loadAndPlay(getSelectedFile());
- } catch (InvalidMidiDataException ex) {
- ex.printStackTrace();
- showError(ex.getMessage());
- }
+ } catch (InvalidMidiDataException ex) { showError(ex); }
}
};
};
private JToggleButton.ToggleButtonModel
pairNoteOnOffModel = new JToggleButton.ToggleButtonModel() {
{
- addItemListener(new ItemListener() {
- public void itemStateChanged(ItemEvent e) {
- eventDialog.midiMessageForm.durationForm.setEnabled(isSelected());
- }
- });
+ addItemListener(e->eventDialog.midiMessageForm.durationForm.setEnabled(isSelected()));
setSelected(true);
}
};
}
add(Box.createRigidArea(new Dimension(5, 0)));
PlaylistTableModel playlistTableModel = sequenceListTable.getModel();
- add(new JButton(playlistTableModel.moveToTopAction) {{ setMargin(ZERO_INSETS); }});
+ add(new JButton(playlistTableModel.getMoveToTopAction()) {{ setMargin(ZERO_INSETS); }});
add(Box.createRigidArea(new Dimension(5, 0)));
- add(new JButton(playlistTableModel.moveToBottomAction) {{ setMargin(ZERO_INSETS); }});
+ add(new JButton(playlistTableModel.getMoveToBottomAction()) {{ setMargin(ZERO_INSETS); }});
if( sequenceListTable.midiFileChooser != null ) {
add(Box.createRigidArea(new Dimension(5, 0)));
add(new JButton(sequenceListTable.midiFileChooser.saveMidiFileAction) {
@Override
public void actionPerformed(ActionEvent event) {
try {
- playlist.addSequenceAndPlay(getMidiSequence());
+ int index = playlist.addSequenceAndPlay(getMidiSequence());
+ playlist.getSequenceModelList().get(index).setModified(true);
} catch (InvalidMidiDataException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(
}});
add(new JButton("Randomize (Tempo, Time signature, Chord progression)") {{
setMargin(ZERO_INSETS);
- addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- setRandomChordProgression(
- measureSelecter.getMeasureDuration()
- );
- }
- });
+ addActionListener(e->setRandomChordProgression(measureSelecter.getMeasureDuration()));
}});
add(new JPanel() {{
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
add(new JLabel("Transpose"));
add(new JButton(" + Up ") {{
setMargin(ZERO_INSETS);
- addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- ChordProgression cp = createChordProgression();
- cp.transpose(1);
- setChordProgression(cp);
- }
+ addActionListener(e->{
+ ChordProgression cp = createChordProgression();
+ cp.transpose(1);
+ setChordProgression(cp);
});
}});
add(new JButton(" - Down ") {{
setMargin(ZERO_INSETS);
- addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- ChordProgression cp = createChordProgression();
- cp.transpose(-1);
- setChordProgression(cp);
- }
+ addActionListener(e->{
+ ChordProgression cp = createChordProgression();
+ cp.transpose(-1);
+ setChordProgression(cp);
});
}});
add(new JButton(" Enharmonic ") {{
setMargin(ZERO_INSETS);
- addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- ChordProgression cp = createChordProgression();
- cp.toggleEnharmonically();
- setChordProgression(cp);
- }
+ addActionListener(e->{
+ ChordProgression cp = createChordProgression();
+ cp.toggleEnharmonically();
+ setChordProgression(cp);
});
}});
add(new JButton("Relative key") {{
setMargin(ZERO_INSETS);
- addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- ChordProgression cp = createChordProgression();
- cp.toggleKeyMajorMinor();
- setChordProgression(cp);
- }
+ addActionListener(e->{
+ ChordProgression cp = createChordProgression();
+ cp.toggleKeyMajorMinor();
+ setChordProgression(cp);
});
}});
}});
trackSelecter.addActionListener(this);
chSelecter.comboBox.addActionListener(this);
keyboardPanel.keyboard.velocityModel.addChangeListener(
- new ChangeListener() {
- public void stateChanged(ChangeEvent e) {
- AbstractNoteTrackSpec ants = getTrackSpec();
- ants.velocity = keyboardPanel.keyboard.velocityModel.getValue();
- }
- }
+ e -> getTrackSpec().velocity = keyboardPanel.keyboard.velocityModel.getValue()
);
pgSelecter.addActionListener(this);
}
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Vector;
import javax.sound.midi.InvalidMidiDataException;
-import javax.sound.midi.MetaEventListener;
-import javax.sound.midi.MetaMessage;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
}
};
/** 再生中のシーケンサーの秒位置リスナー */
- private ChangeListener secondPosition = new ChangeListener() {
+ private ChangeListener mmssPosition = new ChangeListener() {
private int value = 0;
@Override
public void stateChanged(ChangeEvent event) {
int newValue = ((MidiSequencerModel)src).getValue() / 1000;
if(value == newValue) return;
value = newValue;
- int rowIndex = indexOfSequenceOnSequencer();
- fireTableCellUpdated(rowIndex, Column.POSITION.ordinal());
+ fireTableCellUpdated(indexOfSequenceOnSequencer(), Column.POSITION.ordinal());
}
}
@Override
*/
public PlaylistTableModel(MidiSequencerModel sequencerModel) {
this.sequencerModel = sequencerModel;
- sequencerModel.addChangeListener(secondPosition);
- sequencerModel.getSequencer().addMetaEventListener(new MetaEventListener() {
- /**
- * {@inheritDoc}
- *
- * <p>EOT (End Of Track、type==0x2F) を受信したとき、次の曲へ進みます。
- * </p>
- * <p>多くの場合、このメソッドは Swing の EDT(Event Dispatch Thread) ではなく
- * MIDI シーケンサの EDT から起動されるので、GUI 処理を Swing EDT に振り直します。
- * </p>
- */
- @Override
- public void meta(MetaMessage msg) {
- if( msg.getType() == 0x2F ) {
- if( SwingUtilities.isEventDispatchThread() ) {
- goNext();
- } else {
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() { goNext(); }
- });
- }
- }
- }
+ sequencerModel.addChangeListener(mmssPosition);
+ // EOF(0x2F)が来たら曲の終わりなので次の曲へ進める
+ sequencerModel.getSequencer().addMetaEventListener(msg->{
+ if(msg.getType() == 0x2F) SwingUtilities.invokeLater(()->goNext());
});
emptyTrackListTableModel = new SequenceTrackListTableModel(this, null, null);
emptyEventListTableModel = new TrackEventListTableModel(emptyTrackListTableModel, null);
/**
* 次の曲へ進みます。
*
- * <p>リピートモードの場合は同じ曲をもう一度再生、
- * そうでない場合は次の曲へ進んで再生します。
- * 次の曲がなければ、そこで停止します。
- * いずれの場合も曲の先頭へ戻ります。
+ * <p>リピートモードの場合は同じ曲をもう一度再生、そうでない場合は次の曲へ進んで再生します。
+ * 次の曲がなければ、そこで停止します。いずれの場合も曲の先頭へ戻ります。
* </p>
*/
private void goNext() {
// とりあえず曲の先頭へ戻る
sequencerModel.getSequencer().setMicrosecondPosition(0);
if( (Boolean)toggleRepeatAction.getValue(Action.SELECTED_KEY) || loadNext(1) ) {
- // リピートモードのときはもう一度同じ曲を、
- // そうでない場合は次の曲を再生開始
+ // リピートモードのときはもう一度同じ曲を、そうでない場合は次の曲を再生開始
sequencerModel.start();
}
else {
// 最後の曲が終わったので、停止状態にする
sequencerModel.stop();
- // ここでボタンが停止状態に変わったはずなので、
- // 通常であれば再生ボタンが自力で再描画するところだが、
- //
- // セルのレンダラーが描く再生ボタンには効かないようなので、
- // セルを突っついて再表示させる。
- int rowIndex = indexOfSequenceOnSequencer();
- int colIndex = Column.PLAY.ordinal();
- fireTableCellUpdated(rowIndex, colIndex);
+ // ここでボタンが停止状態に変わったはずなので、通常であれば再生ボタンが自力で再描画するところだが、
+ // セルのレンダラーが描く再生ボタンには効かないようなので、セルを突っついて再表示させる。
+ fireTableCellUpdated(indexOfSequenceOnSequencer(), Column.PLAY.ordinal());
}
}
/**
* シーケンスリスト
*/
- private List<SequenceTrackListTableModel> sequenceList = new Vector<>();
+ private List<SequenceTrackListTableModel> sequenceModelList = new Vector<>();
/**
* このプレイリストが保持している {@link SequenceTrackListTableModel} のリストを返します。
*/
- public List<SequenceTrackListTableModel> getSequenceList() { return sequenceList; }
+ public List<SequenceTrackListTableModel> getSequenceModelList() {
+ return sequenceModelList;
+ }
/**
* 行が選択されているときだけイネーブルになるアクション
*/
/**
* 繰り返し再生ON/OFF切り替えアクション
*/
- public Action toggleRepeatAction = new AbstractAction() {
+ public Action getToggleRepeatAction() { return toggleRepeatAction; }
+ private Action toggleRepeatAction = new AbstractAction() {
{
putValue(SHORT_DESCRIPTION, "Repeat - 繰り返し再生");
putValue(LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.REPEAT_ICON));
/**
* 曲の先頭または前の曲へ戻るアクション
*/
- public Action moveToTopAction = new AbstractAction() {
+ public Action getMoveToTopAction() { return moveToTopAction; }
+ private Action moveToTopAction = new AbstractAction() {
{
putValue(SHORT_DESCRIPTION,
"Move to top or previous song - 曲の先頭または前の曲へ戻る"
/**
* 次の曲へ進むアクション
*/
- public Action moveToBottomAction = new AbstractAction() {
+ public Action getMoveToBottomAction() { return moveToBottomAction; }
+ private Action moveToBottomAction = new AbstractAction() {
{
putValue(SHORT_DESCRIPTION, "Move to next song - 次の曲へ進む");
putValue(LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.BOTTOM_ICON));
if(loadNext(1)) sequencerModel.setValue(0);
}
};
-
/**
* 列の列挙型
*/
public boolean isCellEditable() { return true; } // ダブルクリックだけ有効
@Override
public Object getValueOf(SequenceTrackListTableModel sequenceModel) {
- return sequenceModel.isOnSequencer() ? sequenceModel.getParent().secondPosition : "";
+ return sequenceModel.isOnSequencer() ? sequenceModel.getParent().mmssPosition : "";
}
},
/** シーケンスの時間長(分:秒) */
DIVISION_TYPE("DivType", String.class, 50) {
@Override
public Object getValueOf(SequenceTrackListTableModel sequenceModel) {
- float divType = sequenceModel.getSequence().getDivisionType();
- if( divType == Sequence.PPQ ) return "PPQ";
- else if( divType == Sequence.SMPTE_24 ) return "SMPTE_24";
- else if( divType == Sequence.SMPTE_25 ) return "SMPTE_25";
- else if( divType == Sequence.SMPTE_30 ) return "SMPTE_30";
- else if( divType == Sequence.SMPTE_30DROP ) return "SMPTE_30DROP";
- else return "[Unknown]";
+ float dt = sequenceModel.getSequence().getDivisionType();
+ String dtLabel = divisionTypeLabels.get(dt);
+ return dtLabel == null ? "[Unknown]" : dtLabel;
+ }
+ };
+ /**
+ * タイミング分割形式に対応するラベル文字列
+ */
+ private static final Map<Float,String> divisionTypeLabels = new HashMap<Float,String>() {
+ {
+ put(Sequence.PPQ, "PPQ");
+ put(Sequence.SMPTE_24, "SMPTE_24");
+ put(Sequence.SMPTE_25, "SMPTE_25");
+ put(Sequence.SMPTE_30, "SMPTE_30");
+ put(Sequence.SMPTE_30DROP, "SMPTE_30DROP");
}
};
String title;
}
@Override
- public int getRowCount() { return sequenceList.size(); }
+ public int getRowCount() { return sequenceModelList.size(); }
@Override
public int getColumnCount() { return Column.values().length; }
@Override
@Override
public Object getValueAt(int row, int column) {
PlaylistTableModel.Column c = Column.values()[column];
- return c == Column.NUMBER ? row : c.getValueOf(sequenceList.get(row));
+ return c == Column.NUMBER ? row : c.getValueOf(sequenceModelList.get(row));
}
@Override
public void setValueAt(Object val, int row, int column) {
switch(Column.values()[column]) {
case FILENAME:
// ファイル名の変更
- sequenceList.get(row).setFilename((String)val);
+ sequenceModelList.get(row).setFilename((String)val);
fireTableCellUpdated(row, column);
break;
case NAME:
// シーケンス名の設定または変更
- if( sequenceList.get(row).setName((String)val) )
+ if( sequenceModelList.get(row).setName((String)val) )
fireTableCellUpdated(row, Column.MODIFIED.ordinal());
fireTableCellUpdated(row, column);
break;
case CHARSET:
// 文字コードの変更
- SequenceTrackListTableModel seq = sequenceList.get(row);
+ SequenceTrackListTableModel seq = sequenceModelList.get(row);
seq.charset = Charset.forName(val.toString());
fireTableCellUpdated(row, column);
// シーケンス名の表示更新
* このプレイリストに読み込まれた全シーケンスの合計時間長を返します。
* @return 全シーケンスの合計時間長 [秒]
*/
- public int getTotalSeconds() {
+ public int getTotalTimeInSeconds() {
int total = 0;
long usec;
- for( SequenceTrackListTableModel m : sequenceList ) {
+ for( SequenceTrackListTableModel m : sequenceModelList ) {
usec = m.getSequence().getMicrosecondLength();
total += (int)( (usec < 0 ? usec += 0x100000000L : usec)/1000L/1000L );
}
return total;
}
/**
- * 未保存の修正内容を持つシーケンスがあるか調べます。
- * @return 未保存の修正内容を持つシーケンスがあればtrue
- */
- public boolean isModified() {
- for( SequenceTrackListTableModel m : sequenceList ) if( m.isModified() ) return true;
- return false;
- }
- /**
- * 選択したシーケンスに未保存の修正内容があることを記録します。
- * @param selModel 選択状態
- * @param isModified 未保存の修正内容があるときtrue
- */
- public void setModified(boolean isModified) {
- int minIndex = sequenceListSelectionModel.getMinSelectionIndex();
- int maxIndex = sequenceListSelectionModel.getMaxSelectionIndex();
- for( int i = minIndex; i <= maxIndex; i++ ) {
- if( sequenceListSelectionModel.isSelectedIndex(i) ) {
- sequenceList.get(i).setModified(isModified);
- fireTableCellUpdated(i, Column.MODIFIED.ordinal());
- }
- }
- }
- /**
* 選択されたMIDIシーケンスのテーブルモデルを返します。
* @return 選択されたMIDIシーケンスのテーブルモデル(非選択時はnull)
*/
public SequenceTrackListTableModel getSelectedSequenceModel() {
if( sequenceListSelectionModel.isSelectionEmpty() ) return null;
int selectedIndex = sequenceListSelectionModel.getMinSelectionIndex();
- if( selectedIndex >= sequenceList.size() ) return null;
- return sequenceList.get(selectedIndex);
+ if( selectedIndex >= sequenceModelList.size() ) return null;
+ return sequenceModelList.get(selectedIndex);
}
/**
* 指定されたシーケンスの更新済みフラグを変更して全ての列を再表示します。
* @param isModified 更新済みフラグ
*/
public void fireSequenceModified(SequenceTrackListTableModel sequenceTableModel, boolean isModified) {
- int index = sequenceList.indexOf(sequenceTableModel);
+ int index = sequenceModelList.indexOf(sequenceTableModel);
if( index < 0 ) return;
sequenceTableModel.setModified(isModified);
fireTableRowsUpdated(index, index);
int minIndex = sequenceListSelectionModel.getMinSelectionIndex();
int maxIndex = sequenceListSelectionModel.getMaxSelectionIndex();
for( int index = minIndex; index <= maxIndex; index++ ) {
- sequenceList.get(index).setModified(isModified);
+ sequenceModelList.get(index).setModified(isModified);
}
fireTableRowsUpdated(minIndex, maxIndex);
}
/**
- * ファイル名つきのMIDIシーケンスを追加します。
- * @param sequence MIDIシーケンス
- * @param filename ファイル名
+ * MIDIシーケンスを追加します。
+ * @param sequence MIDIシーケンス(nullの場合、シーケンスを自動生成して追加)
+ * @param filename ファイル名(nullの場合、ファイル名なし)
* @return 追加されたシーケンスのインデックス(先頭が 0)
*/
public int addSequence(Sequence sequence, String filename) {
- sequenceList.add( new SequenceTrackListTableModel(this, sequence, filename) );
- int lastIndex = sequenceList.size() - 1;
+ if( sequence == null ) sequence = (new ChordProgression()).toMidiSequence();
+ sequenceModelList.add(new SequenceTrackListTableModel(this, sequence, filename));
+ //
+ // 末尾に行が追加されたので、再描画してもらう
+ int lastIndex = sequenceModelList.size() - 1;
fireTableRowsInserted(lastIndex, lastIndex);
+ sequenceListSelectionModel.setSelectionInterval(lastIndex, lastIndex);
return lastIndex;
}
/**
- * デフォルトの内容でMIDIシーケンスを作成して追加します。
- * @return 追加されたMIDIシーケンスのインデックス(先頭が 0)
- */
- public int addSequence() {
- Sequence seq = (new ChordProgression()).toMidiSequence();
- return seq == null ? -1 : addSequence(seq,null);
- }
- /**
* バイト列とファイル名からMIDIシーケンスを追加します。
- * バイト列が null の場合、空のMIDIシーケンスを追加します。
- * @param data バイト列
+ * @param data バイト列(nullの場合、シーケンスを自動生成して追加)
* @param filename ファイル名
* @return 追加先インデックス(先頭が 0)
- * @throws IOException ã\83\95ã\82¡ã\82¤ã\83«読み込みに失敗した場合
+ * @throws IOException ã\83\90ã\82¤ã\83\88å\88\97ã\81®読み込みに失敗した場合
* @throws InvalidMidiDataException MIDIデータが正しくない場合
*/
public int addSequence(byte[] data, String filename) throws IOException, InvalidMidiDataException {
- if( data == null ) return addSequence();
- int lastIndex;
- try (InputStream in = new ByteArrayInputStream(data)) {
- lastIndex = addSequence(MidiSystem.getSequence(in), filename);
- } catch( IOException|InvalidMidiDataException e ) {
- throw e;
+ Sequence sequence = null;
+ if( data != null ) {
+ try (InputStream in = new ByteArrayInputStream(data)) {
+ sequence = MidiSystem.getSequence(in);
+ } catch( IOException|InvalidMidiDataException e ) {
+ throw e;
+ }
}
- sequenceListSelectionModel.setSelectionInterval(lastIndex, lastIndex);
- return lastIndex;
+ return addSequence(sequence, filename);
}
/**
* MIDIファイルを追加します。
- * ファイルが null の場合、デフォルトのMIDIシーケンスを追加します。
- * @param midiFile MIDIファイル
+ * @param midiFile MIDIファイル(nullの場合、シーケンスを自動生成して追加)
* @return 追加先インデックス(先頭が 0)
- * @throws InvalidMidiDataException ファイル内のMIDIデータが正しくない場合
* @throws IOException ファイル入出力に失敗した場合
+ * @throws InvalidMidiDataException ファイル内のMIDIデータが正しくない場合
*/
public int addSequence(File midiFile) throws InvalidMidiDataException, IOException {
- if( midiFile == null ) return addSequence();
- int lastIndex;
- try (FileInputStream in = new FileInputStream(midiFile)) {
- Sequence seq = MidiSystem.getSequence(in);
- String filename = midiFile.getName();
- lastIndex = addSequence(seq, filename);
- } catch( InvalidMidiDataException|IOException e ) {
- throw e;
+ Sequence sequence = null;
+ String filename = null;
+ if( midiFile != null ) {
+ try (FileInputStream in = new FileInputStream(midiFile)) {
+ sequence = MidiSystem.getSequence(in);
+ } catch( IOException|InvalidMidiDataException e ) {
+ throw e;
+ }
+ filename = midiFile.getName();
}
- return lastIndex;
+ return addSequence(sequence, filename);
}
/**
* MIDIシーケンスを追加し、再生されていなかった場合は追加したシーケンスから再生を開始します。
public void removeSelectedSequence() throws InvalidMidiDataException {
if( sequenceListSelectionModel.isSelectionEmpty() ) return;
int selectedIndex = sequenceListSelectionModel.getMinSelectionIndex();
- SequenceTrackListTableModel removedSequence = sequenceList.remove(selectedIndex);
+ SequenceTrackListTableModel removedSequence = sequenceModelList.remove(selectedIndex);
if( removedSequence.isOnSequencer() ) sequencerModel.setSequenceTrackListTableModel(null);
fireTableRowsDeleted(selectedIndex, selectedIndex);
}
*/
public void loadToSequencer(int newRowIndex) throws InvalidMidiDataException {
SequenceTrackListTableModel oldSeq = sequencerModel.getSequenceTrackListTableModel();
- SequenceTrackListTableModel newSeq = (newRowIndex < 0 ? null : sequenceList.get(newRowIndex));
+ SequenceTrackListTableModel newSeq = (newRowIndex < 0 ? null : sequenceModelList.get(newRowIndex));
if( oldSeq == newSeq ) return;
sequencerModel.setSequenceTrackListTableModel(newSeq);
int columnIndices[] = {
Column.POSITION.ordinal(),
};
if( oldSeq != null ) {
- int oldRowIndex = sequenceList.indexOf(oldSeq);
+ int oldRowIndex = sequenceModelList.indexOf(oldSeq);
for( int columnIndex : columnIndices ) fireTableCellUpdated(oldRowIndex, columnIndex);
}
if( newSeq != null ) {
* @return 現在シーケンサにロードされているシーケンスのインデックス
*/
public int indexOfSequenceOnSequencer() {
- return sequenceList.indexOf(sequencerModel.getSequenceTrackListTableModel());
+ return sequenceModelList.indexOf(sequencerModel.getSequenceTrackListTableModel());
}
/**
* 引数で示された数だけ次へ進めたシーケンスをロードします。
* @param offset 進みたいシーケンス数
* @return true:ロード成功、false:これ以上進めない
- * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
*/
public boolean loadNext(int offset) {
int loadedIndex = indexOfSequenceOnSequencer();
int index = (loadedIndex < 0 ? 0 : loadedIndex + offset);
- if( index < 0 || index >= sequenceList.size() ) return false;
+ if( index < 0 || index >= sequenceModelList.size() ) return false;
try {
loadToSequencer(index);
} catch (InvalidMidiDataException ex) {
- ex.printStackTrace();
- JOptionPane.showMessageDialog(
- null, ex.getMessage(),
- ChordHelperApplet.VersionInfo.NAME, JOptionPane.ERROR_MESSAGE);
+ JOptionPane.showMessageDialog(null, ex, ChordHelperApplet.VersionInfo.NAME, JOptionPane.ERROR_MESSAGE);
return false;
}
return true;
package camidion.chordhelper.midieditor;
import java.awt.Dimension;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
{
setSize(new Dimension(20,20));
setMargin(ChordHelperApplet.ZERO_INSETS);
- addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- int max = maxFactors.size() - 1;
- if( index >= max ) return;
- changeSliderScale(maxFactors.get(++index));
- if( index >= max ) {
- setEnabled(false);
- push.requestFocusInWindow();
- return;
- }
- push.setEnabled(true);
+ addActionListener(e->{
+ int max = maxFactors.size() - 1;
+ if( index >= max ) return;
+ changeSliderScale(maxFactors.get(++index));
+ if( index >= max ) {
+ setEnabled(false);
+ push.requestFocusInWindow();
+ return;
}
+ push.setEnabled(true);
});
}
});
setSize(new Dimension(20,20));
setMargin(ChordHelperApplet.ZERO_INSETS);
setEnabled(false);
- addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- if( index <= 0 ) return;
- changeSliderScale(maxFactors.get(--index));
- if( index <= 0 ) {
- setEnabled(false);
- pull.requestFocusInWindow();
- return;
- }
- pull.setEnabled(true);
+ addActionListener(e->{
+ if( index <= 0 ) return;
+ changeSliderScale(maxFactors.get(--index));
+ if( index <= 0 ) {
+ setEnabled(false);
+ pull.requestFocusInWindow();
+ return;
}
+ pull.setEnabled(true);
});
}
});
* コード進行をもとに MIDI シーケンスを生成します。
* @return MIDIシーケンス
*/
- public Sequence toMidiSequence() {
- return toMidiSequence(48);
- }
+ public Sequence toMidiSequence() { return toMidiSequence(48); }
/**
* 指定のタイミング解像度で、
* コード進行をもとに MIDI シーケンスを生成します。
*/
public Sequence toMidiSequence(
int ppq, int startMeasure, int endMeasure,
- FirstTrackSpec firstTrack,
- Vector<AbstractNoteTrackSpec> trackSpecs
+ FirstTrackSpec firstTrack, Vector<AbstractNoteTrackSpec> trackSpecs
) {
Sequence seq;
try {
seq = new Sequence(Sequence.PPQ, ppq);
- } catch ( InvalidMidiDataException e ) {
- e.printStackTrace();
- return null;
+ } catch( InvalidMidiDataException imde ) {
+ throw new IllegalArgumentException("Unexpected error", imde);
}
// マスタートラックの生成
- if( firstTrack == null ) {
- firstTrack = new FirstTrackSpec();
- }
+ if( firstTrack == null ) firstTrack = new FirstTrackSpec();
firstTrack.key = this.key;
firstTrack.createTrack( seq, startMeasure, endMeasure );
//