* @return 未保存の修正済み MIDI ファイルがあれば true\r
*/\r
public boolean isModified() {\r
- return editorDialog.sequenceListTable.getModel().isModified();\r
+ return deviceModelList.editorDialog.sequenceListTable.getModel().isModified();\r
}\r
/**\r
* 指定された小節数の曲を、乱数で自動作曲してプレイリストへ追加します。\r
* @return 追加先のインデックス値(0から始まる)。追加できなかったときは -1\r
*/\r
public int addRandomSongToPlaylist(int measureLength) {\r
- editorDialog.newSequenceDialog.setRandomChordProgression(measureLength);\r
- Sequence sequence = editorDialog.newSequenceDialog.getMidiSequence();\r
- return editorDialog.sequenceListTable.getModel().addSequenceAndPlay(sequence);\r
+ deviceModelList.editorDialog.newSequenceDialog.setRandomChordProgression(measureLength);\r
+ Sequence sequence = deviceModelList.editorDialog.newSequenceDialog.getMidiSequence();\r
+ return deviceModelList.editorDialog.sequenceListTable.getModel().addSequenceAndPlay(sequence);\r
}\r
/**\r
* URLで指定されたMIDIファイルをプレイリストへ追加します。\r
*/\r
public int addToPlaylist(String midiFileUrl) {\r
try {\r
- return editorDialog.sequenceListTable.getModel().addSequenceFromURL(midiFileUrl);\r
+ return deviceModelList.editorDialog.sequenceListTable.getModel().addSequenceFromURL(midiFileUrl);\r
} catch( URISyntaxException|IOException|InvalidMidiDataException e ) {\r
- editorDialog.showWarning(e.getMessage());\r
+ deviceModelList.editorDialog.showWarning(e.getMessage());\r
} catch( AccessControlException e ) {\r
e.printStackTrace();\r
- editorDialog.showError(e.getMessage());\r
+ deviceModelList.editorDialog.showError(e.getMessage());\r
}\r
return -1;\r
}\r
* @return 追加先のインデックス値(0から始まる)。追加できなかったときは -1\r
*/\r
public int addToPlaylistBase64(String base64EncodedText, String filename) {\r
- Base64Dialog d = editorDialog.base64Dialog;\r
+ Base64Dialog d = deviceModelList.editorDialog.base64Dialog;\r
d.setBase64Data(base64EncodedText);\r
try {\r
- return editorDialog.sequenceListTable.getModel().addSequence(d.getMIDIData(), filename);\r
+ return deviceModelList.editorDialog.sequenceListTable.getModel().addSequence(d.getMIDIData(), filename);\r
} catch (IOException | InvalidMidiDataException e) {\r
e.printStackTrace();\r
- editorDialog.showWarning(e.getMessage());\r
+ deviceModelList.editorDialog.showWarning(e.getMessage());\r
return -1;\r
}\r
}\r
* シーケンサへロードして再生します。\r
*/\r
public void play() {\r
- play(editorDialog.sequenceListTable.getModel().sequenceListSelectionModel.getMinSelectionIndex());\r
+ play(deviceModelList.editorDialog.sequenceListTable.getModel().sequenceListSelectionModel.getMinSelectionIndex());\r
}\r
/**\r
* 指定されたインデックス値が示すプレイリスト上のMIDIシーケンスを、\r
* @param index インデックス値(0から始まる)\r
*/\r
public void play(int index) {\r
- editorDialog.sequenceListTable.getModel().loadToSequencer(index);\r
+ deviceModelList.editorDialog.sequenceListTable.getModel().loadToSequencer(index);\r
deviceModelList.sequencerModel.start();\r
}\r
/**\r
*/\r
public String getMidiDataBase64() {\r
SequenceTrackListTableModel sequenceModel =\r
- editorDialog.sequenceListTable.getModel().sequencerModel.getSequenceTrackListTableModel();\r
- editorDialog.base64Dialog.setMIDIData(sequenceModel.getMIDIdata());\r
- return editorDialog.base64Dialog.getBase64Data();\r
+ deviceModelList.editorDialog.sequenceListTable.getModel().sequencerModel.getSequenceTrackListTableModel();\r
+ deviceModelList.editorDialog.base64Dialog.setMIDIData(sequenceModel.getMIDIdata());\r
+ return deviceModelList.editorDialog.base64Dialog.getBase64Data();\r
}\r
/**\r
* 現在シーケンサにロードされているMIDIファイルのファイル名を返します。\r
*/\r
public static class VersionInfo {\r
public static final String NAME = "MIDI Chord Helper";\r
- public static final String VERSION = "Ver.20131218.1";\r
+ public static final String VERSION = "Ver.20131220.1";\r
public static final String COPYRIGHT = "Copyright (C) 2004-2013";\r
public static final String AUTHER = "@きよし - Akiyoshi Kamide";\r
public static final String URL = "http://www.yk.rim.or.jp/~kamide/music/chordhelper/";\r
private JToggleButton darkModeToggleButton;\r
MidiDeviceModelList deviceModelList;\r
MidiDeviceDialog midiConnectionDialog;\r
- MidiEditor editorDialog;\r
ChordDiagram chordDiagram;\r
TempoSelecter tempoSelecter;\r
TimeSignatureSelecter timesigSelecter;\r
keyboardPanel = new MidiKeyboardPanel(chordMatrix) {{\r
keyboardCenterPanel.keyboard.addPianoKeyboardListener(\r
new PianoKeyboardAdapter() {\r
+ @Override\r
public void pianoKeyPressed(int n, InputEvent e) {\r
chordDiagram.clear();\r
}\r
);\r
keySelecter.keysigCombobox.addActionListener(\r
new ActionListener() {\r
+ @Override\r
public void actionPerformed(ActionEvent e) {\r
Music.Key key = keySelecter.getKey();\r
key.transpose( - chordMatrix.capoSelecter.getCapo() );\r
}\r
}\r
);\r
- editorDialog = new MidiEditor(deviceModelList.sequencerModel);\r
- editorDialog.setIconImage(iconImage);\r
- deviceModelList.setMidiEditor(editorDialog);\r
- new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, editorDialog, true);\r
- keyboardPanel.setEventDialog(editorDialog.eventDialog);\r
+ deviceModelList.editorDialog.setIconImage(iconImage);\r
+ new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, deviceModelList.editorDialog, true);\r
+ keyboardPanel.setEventDialog(deviceModelList.editorDialog.eventDialog);\r
midiConnectionDialog = new MidiDeviceDialog(deviceModelList);\r
midiConnectionDialog.setIconImage(iconImage);\r
- lyricDisplay = new ChordTextField() {\r
- {\r
- deviceModelList.sequencerModel.getSequencer().addMetaEventListener(this);\r
- addActionListener(new ActionListener() {\r
- @Override\r
- public void actionPerformed(ActionEvent event) {\r
- chordMatrix.setSelectedChord(\r
- event.getActionCommand().trim().split("[ \t\r\n]")[0]\r
- );\r
- }\r
- });\r
- }\r
- };\r
+ lyricDisplay = new ChordTextField() {{\r
+ deviceModelList.sequencerModel.getSequencer().addMetaEventListener(this);\r
+ addActionListener(new ActionListener() {\r
+ @Override\r
+ public void actionPerformed(ActionEvent event) {\r
+ chordMatrix.setSelectedChord(\r
+ event.getActionCommand().trim().split("[ \t\r\n]")[0]\r
+ );\r
+ }\r
+ });\r
+ }};\r
lyricDisplayDefaultBorder = lyricDisplay.getBorder();\r
lyricDisplayDefaultBgcolor = lyricDisplay.getBackground();\r
//\r
@Override\r
public void stateChanged(ChangeEvent e) {\r
SequenceTrackListTableModel sequenceTableModel = deviceModelList.sequencerModel.getSequenceTrackListTableModel();\r
- int loadedSequenceIndex = editorDialog.sequenceListTable.getModel().indexOfSequenceOnSequencer();\r
+ int loadedSequenceIndex = deviceModelList.editorDialog.sequenceListTable.getModel().indexOfSequenceOnSequencer();\r
songTitleLabel.setText(\r
"<html>"+(\r
loadedSequenceIndex < 0 ? "[No MIDI file loaded]" :\r
add( Box.createHorizontalStrut(12) );\r
add( songTitleLabel );\r
add( Box.createHorizontalStrut(12) );\r
- add( new JButton(editorDialog.openAction) {{ setMargin(ZERO_INSETS); }});\r
+ add( new JButton(deviceModelList.editorDialog.openAction) {{ setMargin(ZERO_INSETS); }});\r
}});\r
add(new JPanel() {{\r
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));\r
add( new JSlider(deviceModelList.sequencerModel) );\r
add( new TimeIndicator(deviceModelList.sequencerModel) );\r
add( Box.createHorizontalStrut(5) );\r
- add( new JButton(editorDialog.sequenceListTable.getModel().moveToTopAction) {{\r
+ add( new JButton(deviceModelList.editorDialog.sequenceListTable.getModel().moveToTopAction) {{\r
setMargin(ZERO_INSETS);\r
}});\r
add(new JButton(deviceModelList.sequencerModel.moveBackwardAction) {{\r
add(new JButton(deviceModelList.sequencerModel.moveForwardAction) {{\r
setMargin(ZERO_INSETS);\r
}});\r
- add(new JButton(editorDialog.sequenceListTable.getModel().moveToBottomAction) {{\r
+ add(new JButton(deviceModelList.editorDialog.sequenceListTable.getModel().moveToBottomAction) {{\r
setMargin(ZERO_INSETS);\r
}});\r
- add(new JToggleButton(editorDialog.sequenceListTable.getModel().toggleRepeatAction) {{\r
+ add(new JToggleButton(deviceModelList.editorDialog.sequenceListTable.getModel().toggleRepeatAction) {{\r
setMargin(ZERO_INSETS);\r
}});\r
add( Box.createHorizontalStrut(10) );\r
import java.awt.event.ComponentAdapter;\r
import java.awt.event.ComponentEvent;\r
import java.awt.event.ComponentListener;\r
+import java.awt.event.WindowEvent;\r
+import java.awt.event.WindowListener;\r
import java.beans.PropertyVetoException; // PropertyVetoException\r
import java.util.Hashtable;\r
import java.util.List;\r
*/\r
MidiConnecterListView listView;\r
/**\r
+ * デバイスのタイムスタンプを更新するタイマー\r
+ */\r
+ Timer timer;\r
+ /**\r
* MIDIデバイスのモデルからフレームビューを構築します。\r
* @param model MIDIデバイスのTransmitter/Receiverリストモデル\r
*/\r
}\r
}\r
);\r
- setLayout( new BoxLayout( getContentPane(), BoxLayout.Y_AXIS ) );\r
+ setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));\r
add(new JScrollPane(listView));\r
add(new JPanel() {{\r
if( listView.getModel().txSupported() ) {\r
}});\r
}\r
add(new JLabel() {{\r
- Timer t = new Timer(50, new ActionListener() {\r
+ timer = new Timer(50, new ActionListener() {\r
private long sec = -2;\r
private MidiDevice dev = listView.getModel().getMidiDevice();\r
@Override\r
setText(text);\r
}\r
});\r
- t.start();\r
}});\r
}});\r
setSize(250,100);\r
return description;\r
}\r
}\r
-\r
/**\r
* MIDIデバイスツリーモデル\r
*/\r
*/\r
MidiSequencerModel sequencerModel;\r
/**\r
+ * MIDIエディタ\r
+ */\r
+ MidiEditor editorDialog;\r
+ /**\r
+ * MIDIシンセサイザーモデル\r
+ */\r
+ private MidiConnecterListModel editorDialogModel;\r
+ /**\r
* MIDIシンセサイザーモデル\r
*/\r
private MidiConnecterListModel synthModel;\r
);\r
e.printStackTrace();\r
}\r
+ editorDialog = new MidiEditor(sequencerModel);\r
+ editorDialogModel = addMidiDevice(editorDialog.virtualMidiDevice);\r
for( MidiDevice.Info info : devInfos ) {\r
MidiDevice device;\r
try {\r
firstMidiOutModel,\r
sequencerModel,\r
firstMidiInModel,\r
+ editorDialogModel,\r
};\r
for( MidiConnecterListModel m : openModels ) {\r
if( m != null ) m.openDevice();\r
if( sequencerModel != null ) {\r
for( MidiConnecterListModel m : guiModels )\r
sequencerModel.connectToReceiverOf(m);\r
- sequencerModel.connectToReceiverOf(firstMidiOutModel);\r
sequencerModel.connectToReceiverOf(synthModel);\r
+ sequencerModel.connectToReceiverOf(firstMidiOutModel);\r
}\r
- }\r
- /**\r
- * MIDIエディタを設定します。\r
- *\r
- * <p>MIDIエディタが持つ仮想MIDIデバイスからMIDIデバイスモデルを生成し、\r
- * このデバイスモデルリストに追加します。\r
- * </p>\r
- * @param editorDialog MIDIエディタ\r
- */\r
- public void setMidiEditor(MidiEditor editorDialog) {\r
- MidiConnecterListModel mclm = addMidiDevice(editorDialog.virtualMidiDevice);\r
- try {\r
- mclm.openDevice();\r
- } catch( MidiUnavailableException ex ) {\r
- ex.printStackTrace();\r
+ if( editorDialogModel != null ) {\r
+ editorDialogModel.connectToReceiverOf(synthModel);\r
+ editorDialogModel.connectToReceiverOf(firstMidiOutModel);\r
}\r
- mclm.connectToReceiverOf(synthModel);\r
- mclm.connectToReceiverOf(firstMidiOutModel);\r
}\r
/**\r
* 指定のMIDIデバイスからMIDIデバイスモデルを生成して追加します。\r
Object obj = getLastSelectedPathComponent();\r
if( obj instanceof MidiConnecterListModel ) {\r
MidiConnecterListModel deviceModel = (MidiConnecterListModel)obj;\r
- MidiDevice device = deviceModel.getMidiDevice();\r
- MidiDevice.Info info = device.getDeviceInfo();\r
+ MidiDevice.Info info = deviceModel.getMidiDevice().getDeviceInfo();\r
html += "<b>"+deviceModel+"</b><br/>";\r
html += "<table border=\"1\"><tbody>";\r
html += "<tr><th>Version</th><td>"+info.getVersion()+"</td></tr>";\r
setOneTouchExpandable(true);\r
setDividerLocation(250);\r
}});\r
+ addWindowListener(new WindowListener() {\r
+ @Override\r
+ public void windowOpened(WindowEvent e) {\r
+ }\r
+ @Override\r
+ public void windowClosing(WindowEvent e) {\r
+ desktopPane.setAllDeviceTimestampTimers(false);\r
+ }\r
+ @Override\r
+ public void windowClosed(WindowEvent e) {\r
+ }\r
+ @Override\r
+ public void windowIconified(WindowEvent e) {\r
+ }\r
+ @Override\r
+ public void windowDeiconified(WindowEvent e) {\r
+ }\r
+ @Override\r
+ public void windowActivated(WindowEvent e) {\r
+ desktopPane.setAllDeviceTimestampTimers(true);\r
+ }\r
+ @Override\r
+ public void windowDeactivated(WindowEvent e) {\r
+ }\r
+ });\r
}\r
@Override\r
public void actionPerformed(ActionEvent event) {\r
public MidiDeviceFrame getFrameOf(MidiConnecterListModel deviceModel) {\r
JInternalFrame[] frames = getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER);\r
for( JInternalFrame frame : frames ) {\r
- if( frame instanceof MidiDeviceFrame ) {\r
- MidiDeviceFrame deviceFrame = (MidiDeviceFrame)frame;\r
- if( deviceFrame.listView.getModel() == deviceModel )\r
- return deviceFrame;\r
- }\r
+ if( ! (frame instanceof MidiDeviceFrame) )\r
+ continue;\r
+ MidiDeviceFrame deviceFrame = (MidiDeviceFrame)frame;\r
+ if( deviceFrame.listView.getModel() == deviceModel )\r
+ return deviceFrame;\r
}\r
return null;\r
}\r
+ private boolean isTimerStarted;\r
+ /**\r
+ * タイムスタンプを更新するタイマーを開始または停止します。\r
+ * @param toStart trueで開始、falseで停止\r
+ */\r
+ public void setAllDeviceTimestampTimers(boolean toStart) {\r
+ if( isTimerStarted == toStart ) return;\r
+ isTimerStarted = toStart;\r
+ JInternalFrame[] frames = getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER);\r
+ for( JInternalFrame frame : frames ) {\r
+ if( ! (frame instanceof MidiDeviceFrame) )\r
+ continue;\r
+ MidiDeviceFrame deviceFrame = (MidiDeviceFrame)frame;\r
+ Timer timer = deviceFrame.timer;\r
+ if( toStart ) timer.start(); else timer.stop();\r
+ }\r
+ }\r
}\r
\r
/**\r