import camidion.chordhelper.chordmatrix.ChordMatrix;
import camidion.chordhelper.chordmatrix.ChordMatrixListener;
import camidion.chordhelper.mididevice.MidiDeviceDialog;
-import camidion.chordhelper.mididevice.MidiDeviceModelList;
+import camidion.chordhelper.mididevice.MidiDeviceModelManager;
import camidion.chordhelper.mididevice.MidiSequencerModel;
import camidion.chordhelper.mididevice.SequencerMeasureView;
import camidion.chordhelper.mididevice.SequencerTimeView;
*/
public static class VersionInfo {
public static final String NAME = "MIDI Chord Helper";
- public static final String VERSION = "Ver.20160922.1";
+ public static final String VERSION = "Ver.20161005.1";
public static final String COPYRIGHT = "Copyright (C) 2004-2016";
public static final String AUTHER = "@きよし - Akiyoshi Kamide";
public static final String URL = "http://www.yk.rim.or.jp/~kamide/music/chordhelper/";
private KeySignatureLabel keysigLabel;
private AnoGakkiPane anoGakkiPane;
private JToggleButton anoGakkiToggleButton;
- private MidiDeviceModelList deviceModelList;
+ private MidiDeviceModelManager deviceModelManager;
public void init() {
loadIconImage();
}};
VirtualMidiDevice guiMidiDevice = keyboardPanel.keyboardCenterPanel.keyboard.midiDevice;
//
- // MIDIデバイス一覧を構築
- deviceModelList = new MidiDeviceModelList(Arrays.asList(guiMidiDevice));
- MidiDeviceDialog midiDeviceDialog = new MidiDeviceDialog(deviceModelList);
+ // MIDIデバイスマネージャを構築
+ deviceModelManager = new MidiDeviceModelManager(guiMidiDevice);
+ MidiDeviceDialog midiDeviceDialog = new MidiDeviceDialog(deviceModelManager);
midiDeviceDialog.setIconImage(iconImage);
//
// MIDIデバイス一覧のシーケンサと連携するプレイリストを構築
- playlistModel = new PlaylistTableModel(sequencerModel = deviceModelList.getSequencerModel());
+ playlistModel = new PlaylistTableModel(sequencerModel = deviceModelManager.getSequencerModel());
//
// MIDIエディタダイアログの構築
(midiEditor = new MidiSequenceEditorDialog(playlistModel, guiMidiDevice)).setIconImage(iconImage);
}
@Override
public void destroy() {
- deviceModelList.closeAllDevices();
+ deviceModelManager.close();
super.destroy();
}
@Override
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;
if( ! (frame instanceof MidiDeviceFrame) ) return;
MidiDeviceFrame f = (MidiDeviceFrame)frame;
MidiDeviceModel m = f.getMidiDeviceModel();
- List<Receiver> rxList = m.getMidiDevice().getReceivers();
+ MidiDevice d = m.getMidiDevice();
+ List<Receiver> rxList = d.getReceivers();
for( Receiver rx : rxList ) rxToColor.remove(rx);
repaint();
}
public void intervalRemoved(ListDataEvent e) { repaint(); }
};
- private MidiOpenedDevicesView desktopPane;
- public MidiCablePane(MidiOpenedDevicesView desktopPane) {
+ private MidiDeviceDesktopPane desktopPane;
+ public MidiCablePane(MidiDeviceDesktopPane desktopPane) {
this.desktopPane = desktopPane;
setOpaque(false);
setVisible(true);
super.paint(g);
Graphics2D g2 = (Graphics2D)g;
JInternalFrame[] frames = desktopPane.getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER);
- //
- // 各フレームをスキャン
- for( JInternalFrame frame : frames ) {
- if( ! (frame instanceof MidiDeviceFrame) ) continue;
- MidiDeviceFrame fromFrame = (MidiDeviceFrame)frame;
- MidiDeviceModel fromDeviceModel = fromFrame.getMidiDeviceModel();
- //
- // Transmitterをスキャン
+ for( JInternalFrame fromFrame : frames ) {
+ if( ! (fromFrame instanceof MidiDeviceFrame) || ! fromFrame.isVisible() ) continue;
+ MidiDeviceFrame fromDeviceFrame = (MidiDeviceFrame)fromFrame;
+ MidiDeviceModel fromDeviceModel = fromDeviceFrame.getMidiDeviceModel();
TransmitterListModel txListModel = fromDeviceModel.getTransmitterListModel();
int ntx = txListModel == null ? 0 : txListModel.getSize();
for( int index=0 ; index < ntx; index++ ) {
continue;
}
// Transmitterの表示場所を特定
- Rectangle txBounds = fromFrame.getBoundsOf(tx);
+ Rectangle txBounds = fromDeviceFrame.getBoundsOf(tx);
if( txBounds == null ) continue;
int r = (txBounds.height - 5) / 2;
txBounds.translate(r+4, r+4);
if( rx != null ) {
// Receiverの表示場所を探す
for( JInternalFrame toFrame : frames ) {
- if( ! (toFrame instanceof MidiDeviceFrame) ) continue;
- Rectangle rxBounds = ((MidiDeviceFrame)toFrame).getBoundsOf(rx);
+ if( ! (toFrame instanceof MidiDeviceFrame) || ! toFrame.isVisible()) continue;
+ MidiDeviceFrame toDeviceFrame = (MidiDeviceFrame)toFrame;
+ Rectangle rxBounds = toDeviceFrame.getBoundsOf(rx);
if( rxBounds == null ) continue;
r = (rxBounds.height - 5) / 2;
rxBounds.translate(r+4, r+4);
// Receiverからドラッグ中のケーブルを描画
if( draggingLocation != null && fromDeviceModel.getMidiDevice().getReceivers().contains(draggingSource) ) {
Receiver rx = (Receiver)draggingSource;
- Rectangle rxBounds = fromFrame.getBoundsOf(rx);
+ Rectangle rxBounds = fromDeviceFrame.getBoundsOf(rx);
if( rxBounds != null ) {
int r = (rxBounds.height - 5) / 2;
rxBounds.translate(r+4, r+4);
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 javax.sound.midi.MidiUnavailableException;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.TransferHandler;
+import javax.swing.event.TreeModelEvent;
+import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;
/**
* 開いているMIDIデバイスを置くためのデスクトップビュー
*/
-public class MidiOpenedDevicesView extends JDesktopPane implements TreeSelectionListener {
+public class MidiDeviceDesktopPane extends JDesktopPane implements TreeSelectionListener {
/**
* MIDIデバイスモデルからフレームを割り出すためのマップ
*/
- private Map<MidiDeviceModel, MidiDeviceFrame> modelToFrame = new HashMap<>();
+ private Map<MidiDeviceModel, MidiDeviceFrame> frameMap = new HashMap<>();
+ /**
+ * MIDIデバイスモデルに対応するMIDIデバイスフレームを返すマップを返します。
+ */
+ public Map<MidiDeviceModel, MidiDeviceFrame> getFrameMap() {
+ return frameMap;
+ }
/**
* ツリー上で選択状態が変わったとき、このデスクトップ上のフレームの選択状態に反映します。
*/
MidiDeviceModel deviceModel = (MidiDeviceModel)lastSelected;
if( deviceModel.getMidiDevice().isOpen() ) {
// 開いているMIDIデバイスがツリー上で選択されたら、対応するフレームを選択
- MidiDeviceFrame deviceFrame = modelToFrame.get(deviceModel);
+ MidiDeviceFrame deviceFrame = frameMap.get(deviceModel);
+ if( deviceFrame == null ) return;
deviceFrame.toFront();
try {
deviceFrame.setSelected(true);
}
}
- public MidiOpenedDevicesView(MidiDeviceTreeView deviceTreeView,
+ public MidiDeviceDesktopPane(MidiDeviceTreeView deviceTreeView,
MidiDeviceInfoPane deviceInfoPane, MidiDeviceDialog dialog)
{
MidiCablePane cablePane = new MidiCablePane(this);
add(cablePane, JLayeredPane.PALETTE_LAYER);
+ //
+ // リサイズ時、表示時にMIDIケーブルを再描画
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
@Override
public void componentShown(ComponentEvent e) { cablePane.repaint(); }
});
+ // デバイスツリーが変更されたときの更新処理を予約
+ MidiDeviceTreeModel deviceTreeModel = deviceTreeView.getModel();
+ List<MidiDeviceModel> deviceModelList = deviceTreeModel.getDeviceModelList();
+ TreeModelListener treeModelListener = new TreeModelListener() {
+ @Override
+ public void treeNodesChanged(TreeModelEvent e) { }
+ @Override
+ public void treeNodesInserted(TreeModelEvent e) { }
+ @Override
+ public void treeNodesRemoved(TreeModelEvent e) { }
+ @Override
+ public void treeStructureChanged(TreeModelEvent e) {
+ //
+ // 削除されたデバイスモデルに対するデバイスフレームをマップから外す
+ List<MidiDeviceModel> removingDeviceModels = new ArrayList<>();
+ for( MidiDeviceModel m : frameMap.keySet() ) {
+ if( ! deviceModelList.contains(m) ) removingDeviceModels.add(m);
+ }
+ for( MidiDeviceModel m : removingDeviceModels ) {
+ MidiDeviceFrame frame = frameMap.remove(m);
+ if( frame != null ) remove(frame);
+ }
+ removingDeviceModels.clear();
+ //
+ // 新しいデバイスモデルに対するデバイスフレームを生成してマップに登録
+ for( MidiDeviceModel deviceModel : deviceModelList ) {
+ if( frameMap.containsKey(deviceModel) ) continue;
+ MidiDeviceFrame frame = new MidiDeviceFrame(deviceModel, cablePane);
+ frameMap.put(deviceModel, frame);
+ //
+ // トランスミッタリストモデルが変化したときにMIDIケーブルを再描画
+ TransmitterListModel txListModel = deviceModel.getTransmitterListModel();
+ if( txListModel != null ) txListModel.addListDataListener(cablePane.midiConnecterListDataListener);
+ //
+ // レシーバリストモデルが変化したときにMIDIケーブルを再描画
+ ReceiverListModel rxListModel = deviceModel.getReceiverListModel();
+ if( rxListModel != null ) rxListModel.addListDataListener(cablePane.midiConnecterListDataListener);
+ //
+ // デバイスフレームが開閉したときの動作
+ frame.addInternalFrameListener(cablePane.midiDeviceFrameListener);
+ frame.addInternalFrameListener(deviceTreeView.midiDeviceFrameListener);
+ frame.addInternalFrameListener(deviceInfoPane.midiDeviceFrameListener);
+ //
+ // 移動または変形時の動作
+ frame.addComponentListener(cablePane.midiDeviceFrameComponentListener);
+ //
+ // サイズを設定したフレームをデスクトップに追加
+ frame.setSize(250, deviceModel.getInOutType() == MidiDeviceInOutType.MIDI_IN_OUT ? 90 : 70);
+ add(frame);
+ //
+ // デバイスが開いていたら表示
+ if( deviceModel.getMidiDevice().isOpen() ) {
+ frame.setVisible(true);
+ }
+ }
+ }
+ };
+ deviceTreeModel.addTreeModelListener(treeModelListener);
+ treeModelListener.treeStructureChanged(null);
+ //
+ // 表示したデバイスフレームを整列
int toX = 10;
int toY = 10;
- MidiDeviceModelList deviceModels = deviceTreeView.getModel().getDeviceModelList();
- for( MidiDeviceModel deviceModel : deviceModels ) {
- MidiDeviceFrame frame = new MidiDeviceFrame(deviceModel, cablePane);
- modelToFrame.put(deviceModel, frame);
- //
- // トランスミッタリストモデルが変化したときにMIDIケーブルを再描画
- TransmitterListModel txListModel = deviceModel.getTransmitterListModel();
- if( txListModel != null ) txListModel.addListDataListener(cablePane.midiConnecterListDataListener);
- //
- // レシーバリストモデルが変化したときにMIDIケーブルを再描画
- ReceiverListModel rxListModel = deviceModel.getReceiverListModel();
- if( rxListModel != null ) rxListModel.addListDataListener(cablePane.midiConnecterListDataListener);
- //
- // デバイスフレームが開閉したときの動作
- frame.addInternalFrameListener(cablePane.midiDeviceFrameListener);
- frame.addInternalFrameListener(deviceTreeView.midiDeviceFrameListener);
- frame.addInternalFrameListener(deviceInfoPane.midiDeviceFrameListener);
- //
- // 移動または変形時の動作
- frame.addComponentListener(cablePane.midiDeviceFrameComponentListener);
- //
- // ダイアログが閉じたときの動作
- dialog.addWindowListener(frame.windowListener);
- //
- frame.setSize(250, deviceModel.getMidiDeviceInOutType() == MidiDeviceInOutType.MIDI_IN_OUT ? 90 : 70);
- add(frame);
- if( deviceModel.getMidiDevice().isOpen() ) {
- frame.setLocation(toX, toY);
- frame.setVisible(true);
- toX = (toX == 10 ? 270 : 10);
- toY += 50;
- }
+ for( MidiDeviceModel deviceModel : deviceModelList ) {
+ if( ! deviceModel.getMidiDevice().isOpen() ) continue;
+ frameMap.get(deviceModel).setLocation(toX, toY);
+ toX = (toX == 10 ? 270 : 10);
+ toY += 50;
}
+ deviceTreeView.expandAll();
+ //
+ // ドロップ設定
setTransferHandler(new TransferHandler() {
@Override
public boolean canImport(TransferSupport support) {
MidiDeviceModel deviceModel = null;
try {
deviceModel = (MidiDeviceModel)support.getTransferable().getTransferData(flavor);
+ MidiDeviceFrame deviceFrame = frameMap.get(deviceModel);
+ if( deviceFrame == null ) return false;
deviceModel.open();
if( ! deviceModel.getMidiDevice().isOpen() ) {
throw new MidiUnavailableException("開いたはずのMIDIデバイスが、開かれた状態になっていません。");
}
- MidiDeviceFrame deviceFrame = modelToFrame.get(deviceModel);
if( ! deviceFrame.isVisible() ) {
deviceFrame.setLocation(support.getDropLocation().getDropPoint());
deviceFrame.setVisible(true);
*/
public class MidiDeviceDialog extends JDialog {
public static final Icon MIDI_CONNECTER_ICON = new ButtonIcon(ButtonIcon.MIDI_CONNECTOR_ICON);
+ public static final String MSGS = "Microsoft GS Wavetable Synth";
/**
* MIDIデバイスダイアログを開くアクション
*/
};
/**
* MIDIデバイスダイアログを構築します。
- * @param deviceModelList デバイスモデル(MIDIコネクタリストモデル)のリスト
+ * @param deviceModelManager デバイスモデルマネージャ
*/
- public MidiDeviceDialog(final MidiDeviceModelList deviceModelList) {
+ public MidiDeviceDialog(final MidiDeviceModelManager deviceModelManager) {
setTitle(openAction.getValue(Action.NAME).toString());
- setBounds( 300, 300, 800, 500 );
- MidiDeviceTreeModel deviceTreeModel = new MidiDeviceTreeModel(deviceModelList);
- MidiDeviceTreeView deviceTreeView = new MidiDeviceTreeView(deviceTreeModel);
+ setBounds( 300, 300, 820, 540 );
+ MidiDeviceTreeView deviceTreeView = new MidiDeviceTreeView(deviceModelManager.getTreeModel());
final MidiDeviceInfoPane deviceInfoPane = new MidiDeviceInfoPane();
deviceTreeView.addTreeSelectionListener(deviceInfoPane);
- MidiOpenedDevicesView desktopPane = new MidiOpenedDevicesView(deviceTreeView, deviceInfoPane, this);
+ MidiDeviceDesktopPane desktopPane = new MidiDeviceDesktopPane(deviceTreeView, deviceInfoPane, this);
deviceTreeView.addTreeSelectionListener(desktopPane);
deviceTreeView.setSelectionRow(0);
add(new JSplitPane(
JSplitPane.VERTICAL_SPLIT,
new JScrollPane(deviceTreeView),
new JPanel() {{
- add(new JScrollPane(deviceInfoPane));
- add(new JButton("Reset time on MIDI devices") {{
- addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- deviceModelList.resetMicrosecondPosition();
- }
- });
+ 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) {
+ deviceModelManager.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) {
+ deviceModelManager.resetMicrosecondPosition();
+ }
+ });
+ }});
+ setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
}});
+ add(new JScrollPane(deviceInfoPane));
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
}}
){{
- setDividerLocation(260);
+ setDividerLocation(230);
}},
desktopPane
){{
setOneTouchExpandable(true);
- setDividerLocation(250);
+ setDividerLocation(260);
}});
}
}
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-import java.awt.event.WindowListener;
-import javax.sound.midi.MidiDevice;
import javax.sound.midi.Receiver;
import javax.sound.midi.Transmitter;
import javax.swing.JInternalFrame;
* MIDIデバイスフレームビュー
*/
public class MidiDeviceFrame extends JInternalFrame {
+ private static final String LABEL_NO_VALUE = "--:--";
private MidiDeviceModel deviceModel;
private TransmitterListView transmitterListView;
private ReceiverListView receiverListView;
private JScrollPane scrollPane;
private JPanel trxPanel, txPanel, rxPanel;
- private Timer timer;
/**
* このデバイスフレームに表示内容を提供しているMIDIデバイスモデルを取得します。
* @return MIDIデバイスモデル
*/
public ReceiverListView getMidiReceiverListView() { return receiverListView; }
/**
- * ダイアログウィンドウがアクティブなときだけタイムスタンプ更新を有効にするためのリスナー
- */
- public final WindowListener windowListener = new WindowAdapter() {
- @Override
- public void windowClosing(WindowEvent e) { timer.stop(); }
- @Override
- public void windowActivated(WindowEvent e) { timer.start(); }
- };
- /**
* MIDIデバイスモデルからフレームビューを構築します。
*/
public MidiDeviceFrame(MidiDeviceModel deviceModel, MidiCablePane cablePane) {
super( null, true, true, false, false );
this.deviceModel = deviceModel;
- setTitle("[" + deviceModel.getMidiDeviceInOutType().getShortName() + "] " + deviceModel);
+ setTitle("[" + deviceModel.getInOutType().getShortName() + "] " + deviceModel);
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
setLayout(new BorderLayout());
- add(new JLabel("--:--") {{
- timer = new Timer(50, new ActionListener() {
+ add(new JLabel(LABEL_NO_VALUE) {
+ Timer timer = new Timer(50, new ActionListener() {
private long sec = -2;
- private MidiDevice device = getMidiDeviceModel().getMidiDevice();
@Override
public void actionPerformed(ActionEvent event) {
- long usec = device.getMicrosecondPosition();
+ if( ! isVisible() ) return;
+ long usec = deviceModel.getMidiDevice().getMicrosecondPosition();
long sec = (usec == -1 ? -1 : usec/1000000);
if( sec == this.sec ) return;
this.sec = sec;
- setText(sec == -1?"--:--":String.format("%02d:%02d",sec/60,sec%60));
+ setText(sec == -1?LABEL_NO_VALUE:String.format("%02d:%02d",sec/60,sec%60));
cablePane.repaint();
}
});
- }}, BorderLayout.SOUTH);
+ { timer.start(); }
+ }, BorderLayout.SOUTH);
add(scrollPane = new JScrollPane(trxPanel = new JPanel() {{
setLayout(new BorderLayout());
ReceiverListModel rxListModel = getMidiDeviceModel().getReceiverListModel();
* このリストのMIDIデバイスの入出力タイプを返します。
* @return このリストのMIDIデバイスの入出力タイプ
*/
- public MidiDeviceInOutType getMidiDeviceInOutType() { return ioType; }
- private MidiDeviceInOutType ioType;
+ public MidiDeviceInOutType getInOutType() { return ioType; }
+ private MidiDeviceInOutType ioType = MidiDeviceInOutType.MIDI_NONE;
/**
* 対象MIDIデバイスを返します。
* @return 対象MIDIデバイス
* 対象MIDIデバイスの名前を返します。
*/
@Override
- public String toString() { return device.getDeviceInfo().toString(); }
+ public String toString() {
+ return device.getDeviceInfo().toString();
+ }
/**
* {@link Transmitter} のリストモデルを返します。サポートしていない場合はnullを返します。
* @return リストモデルまたはnull
/**
* このMIDIデバイスモデルを収容しているリストを返します。
*/
- public MidiDeviceModelList getDeviceModelList() { return deviceModelList; }
- protected MidiDeviceModelList deviceModelList;
+ public MidiDeviceModelManager getDeviceModelManager() { return deviceModelManager; }
+ protected MidiDeviceModelManager deviceModelManager;
/**
* MIDIデバイスモデルを構築します。
*
* @param device 対象MIDIデバイス
- * @param deviceModelList このMIDIデバイスモデルを収容しているリスト(接続相手となりうるMIDIデバイス)
+ * @param deviceModelManager このMIDIデバイスモデルのマネージャー(接続相手となりうるMIDIデバイス)
*/
- public MidiDeviceModel(MidiDevice device, MidiDeviceModelList deviceModelList) {
+ public MidiDeviceModel(MidiDevice device, MidiDeviceModelManager deviceModelManager) {
+ this.deviceModelManager = deviceModelManager;
this.device = device;
- this.deviceModelList = deviceModelList;
- if( device.getMaxTransmitters() != 0 ) txListModel = new TransmitterListModel(this);
+ if( device.getMaxTransmitters() != 0 ) {
+ txListModel = new TransmitterListModel(this);
+ }
if( device.getMaxReceivers() != 0 ) {
rxListModel = new ReceiverListModel(this);
ioType = txListModel != null ? MidiDeviceInOutType.MIDI_IN_OUT :MidiDeviceInOutType.MIDI_OUT;
else {
ioType = txListModel != null ? MidiDeviceInOutType.MIDI_IN :MidiDeviceInOutType.MIDI_NONE;
}
- treePath = new TreePath(new Object[] {deviceModelList, ioType ,this});
+ treePath = new TreePath(new Object[] {deviceModelManager, ioType ,this});
}
/**
- * ã\81\93ã\81®MIDIã\83\87ã\83\90ã\82¤ã\82¹ã\83¢ã\83\87ã\83«ã\82\92é\96\8bã\81\8dã\81¾ã\81\99ã\80\82
+ * このMIDIデバイスを開きます。
* MIDIデバイスを {@link MidiDevice#open()} で開き、
* レシーバをサポートしている場合は {@link MidiDevice#getReceiver()} でレシーバを1個開きます。
*
+++ /dev/null
-package camidion.chordhelper.mididevice;
-
-import java.util.List;
-import java.util.Vector;
-
-import javax.sound.midi.MidiDevice;
-import javax.sound.midi.MidiSystem;
-import javax.sound.midi.MidiUnavailableException;
-import javax.sound.midi.Sequencer;
-import javax.sound.midi.Synthesizer;
-import javax.sound.midi.Transmitter;
-
-import camidion.chordhelper.ChordHelperApplet;
-
-/**
- * 仮想MIDIデバイスを含めたすべてのMIDIデバイスモデル {@link MidiDeviceModel} を収容するリスト
- */
-public class MidiDeviceModelList extends Vector<MidiDeviceModel> {
-
- public String toString() { return "MIDI devices"; }
-
- private MidiSequencerModel sequencerModel;
- public MidiSequencerModel getSequencerModel() { return sequencerModel; }
-
- public MidiDeviceModelList(List<VirtualMidiDevice> guiVirtualDeviceList) {
- //
- // GUI仮想MIDIデバイス
- MidiDeviceModel guiModels[] = new MidiDeviceModel[guiVirtualDeviceList.size()];
- for( int i=0; i<guiVirtualDeviceList.size(); i++ ) {
- addElement(guiModels[i] = new MidiDeviceModel(guiVirtualDeviceList.get(i), this));
- }
- // シーケンサの取得
- Sequencer sequencer;
- try {
- sequencer = MidiSystem.getSequencer(false);
- addElement(sequencerModel = new MidiSequencerModel(sequencer, this));
- } catch( MidiUnavailableException e ) {
- System.out.println(ChordHelperApplet.VersionInfo.NAME +" : MIDI sequencer unavailable");
- e.printStackTrace();
- }
- // その他のリアルMIDIデバイスの取得
- MidiDeviceModel synthModel = null;
- MidiDeviceModel firstMidiInModel = null;
- MidiDeviceModel firstMidiOutModel = null;
- MidiDevice.Info[] deviceInfos = MidiSystem.getMidiDeviceInfo();
- for( MidiDevice.Info info : deviceInfos ) {
- MidiDevice device;
- try {
- device = MidiSystem.getMidiDevice(info);
- } catch( MidiUnavailableException e ) {
- e.printStackTrace(); continue;
- }
- // シーケンサはすでに取得済みなのでスキップ
- if( device instanceof Sequencer ) continue;
- //
- // Java内蔵シンセサイザ
- if( device instanceof Synthesizer ) {
- try {
- addElement(synthModel = new MidiDeviceModel(MidiSystem.getSynthesizer(), this));
- } catch( MidiUnavailableException e ) {
- System.out.println(ChordHelperApplet.VersionInfo.NAME +
- " : Java internal MIDI synthesizer unavailable");
- e.printStackTrace();
- }
- continue;
- }
- // その他のMIDIデバイス
- MidiDeviceModel m;
- addElement(m = new MidiDeviceModel(device, this));
- if( firstMidiOutModel == null && m.getReceiverListModel() != null ) firstMidiOutModel = m;
- if( firstMidiInModel == null && m.getTransmitterListModel() != null ) firstMidiInModel = m;
- }
- // MIDIデバイスを開く。
- // NOTE: 必ず MIDI OUT Rx デバイスを先に開くこと。
- //
- // そうすれば、後から開いた MIDI IN Tx デバイスからの
- // タイムスタンプのほうが「若く」なる。これにより、
- // 先に開かれ「少し歳を食った」Rx デバイスは
- // 「信号が遅れてやってきた」と認識するので、
- // 遅れを取り戻そうとして即座に音を出してくれる。
- //
- // 開く順序が逆になると「進みすぎるから遅らせよう」として
- // 無用なレイテンシーが発生する原因になる。
- try {
- MidiDeviceModel openModels[] = {
- synthModel,
- firstMidiOutModel,
- sequencerModel,
- firstMidiInModel,
- };
- for( MidiDeviceModel m : openModels ) if( m != null ) m.open();
- for( MidiDeviceModel m : guiModels ) m.open();
- //
- // 初期接続
- TransmitterListModel txListModel;
- for( MidiDeviceModel mtx : guiModels ) {
- if( (txListModel = mtx.getTransmitterListModel() ) != null) {
- for( MidiDeviceModel m : guiModels ) txListModel.connectToFirstReceiverOfDevice(m);
- txListModel.connectToFirstReceiverOfDevice(sequencerModel);
- txListModel.connectToFirstReceiverOfDevice(synthModel);
- txListModel.connectToFirstReceiverOfDevice(firstMidiOutModel);
- }
- }
- if( firstMidiInModel != null && (txListModel = firstMidiInModel.getTransmitterListModel()) != null) {
- for( MidiDeviceModel m : guiModels ) txListModel.connectToFirstReceiverOfDevice(m);
- txListModel.connectToFirstReceiverOfDevice(sequencerModel);
- txListModel.connectToFirstReceiverOfDevice(synthModel);
- txListModel.connectToFirstReceiverOfDevice(firstMidiOutModel);
- }
- if( sequencerModel != null && (txListModel = sequencerModel.getTransmitterListModel()) != null) {
- for( MidiDeviceModel m : guiModels ) txListModel.connectToFirstReceiverOfDevice(m);
- txListModel.connectToFirstReceiverOfDevice(synthModel);
- txListModel.connectToFirstReceiverOfDevice(firstMidiOutModel);
- }
- } catch( MidiUnavailableException ex ) {
- ex.printStackTrace();
- }
- }
- /**
- * {@link Transmitter}を持つすべてのデバイス(例:MIDIキーボードなど)について、
- * {@link MidiDeviceModel#resetMicrosecondPosition()}でマイクロ秒位置をリセットします。
- */
- public void resetMicrosecondPosition() {
- for(MidiDeviceModel m : this) {
- TransmitterListModel txListModel = m.getTransmitterListModel();
- if( txListModel != null ) txListModel.resetMicrosecondPosition();
- }
- }
- /**
- * すべてのMIDIデバイスを閉じます。
- */
- public void closeAllDevices() { for(MidiDeviceModel m : this) m.getMidiDevice().close(); }
-}
--- /dev/null
+package camidion.chordhelper.mididevice;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Synthesizer;
+import javax.sound.midi.Transmitter;
+
+import camidion.chordhelper.ChordHelperApplet;
+
+/**
+ * 仮想MIDIデバイスを含めたすべてのMIDIデバイスモデル {@link MidiDeviceModel} を管理するオブジェクト
+ */
+public class MidiDeviceModelManager {
+
+ private List<MidiDeviceModel> deviceModelList = new Vector<>();
+ public List<MidiDeviceModel> getDeviceModelList() { return deviceModelList; }
+
+ private MidiSequencerModel sequencerModel;
+ public MidiSequencerModel getSequencerModel() { return sequencerModel; }
+
+ private MidiDeviceTreeModel treeModel;
+ public MidiDeviceTreeModel getTreeModel() { return treeModel; }
+ public void setTreeModel(MidiDeviceTreeModel treeModel) { this.treeModel = treeModel; }
+
+ public MidiDeviceModelManager(VirtualMidiDevice guiVirtualDevice) {
+ List<MidiDevice.Info> deviceInfos = Arrays.asList(MidiSystem.getMidiDeviceInfo());
+ //
+ // GUI仮想MIDIデバイス
+ MidiDeviceModel guiModel = new MidiDeviceModel(guiVirtualDevice, this);
+ deviceModelList.add(guiModel);
+ //
+ // シーケンサ
+ Sequencer sequencer = null;
+ try {
+ sequencer = MidiSystem.getSequencer(false);
+ deviceModelList.add(sequencerModel = new MidiSequencerModel(sequencer, this));
+ } catch( MidiUnavailableException e ) {
+ System.out.println(ChordHelperApplet.VersionInfo.NAME +" : MIDI sequencer unavailable");
+ e.printStackTrace();
+ }
+ // その他のリアルMIDIデバイス
+ MidiDeviceModel synthModel = null;
+ MidiDeviceModel firstMidiInModel = null;
+ MidiDeviceModel firstMidiOutModel = null;
+ for( MidiDevice.Info info : deviceInfos ) {
+ MidiDevice device;
+ try {
+ device = MidiSystem.getMidiDevice(info);
+ } catch( MidiUnavailableException e ) {
+ e.printStackTrace();
+ continue;
+ }
+ // シーケンサはすでに取得済みなのでスキップ
+ if( device instanceof Sequencer ) continue;
+ //
+ // Java内蔵シンセサイザ
+ if( device instanceof Synthesizer ) {
+ try {
+ device = MidiSystem.getSynthesizer();
+ deviceModelList.add(synthModel = new MidiDeviceModel(device, this));
+ } catch( MidiUnavailableException e ) {
+ System.out.println(ChordHelperApplet.VersionInfo.NAME +
+ " : Java internal MIDI synthesizer unavailable");
+ e.printStackTrace();
+ }
+ continue;
+ }
+ // その他のMIDIデバイス
+ MidiDeviceModel m;
+ deviceModelList.add(m = new MidiDeviceModel(device, this));
+ //
+ // 最初の MIDI OUT(Windowsの場合は通常、内蔵音源 Microsoft GS Wavetable SW Synth)
+ if( firstMidiOutModel == null && m.getReceiverListModel() != null ) firstMidiOutModel = m;
+ //
+ // 最初の MIDI IN(USB MIDI インターフェースにつながったMIDIキーボードなど)
+ if( firstMidiInModel == null && m.getTransmitterListModel() != null ) firstMidiInModel = m;
+ }
+ // MIDIデバイスを開く。
+ // NOTE: 必ず MIDI OUT Rx デバイスを先に開くこと。
+ //
+ // そうすれば、後から開いた MIDI IN Tx デバイスからのタイムスタンプのほうが「若く」なるので、
+ // 相手の MIDI OUT Rx デバイスは「信号が遅れてやってきた」と認識、遅れを取り戻そうとして
+ // 即座に音を出してくれる。
+ //
+ // 開く順序が逆になると「進みすぎるから遅らせよう」として無用なレイテンシーが発生する原因になる。
+ try {
+ // デバイスを開く
+ MidiDeviceModel modelsToOpen[] = {synthModel, firstMidiOutModel, sequencerModel, firstMidiInModel};
+ for( MidiDeviceModel m : modelsToOpen ) if( m != null ) m.open();
+ guiModel.open();
+ //
+ // 初期接続
+ // GUI → GUI、各音源、シーケンサ
+ TransmitterListModel txListModel;
+ if( (txListModel = guiModel.getTransmitterListModel() ) != null) {
+ txListModel.connectToFirstReceiverOfDevices(guiModel,sequencerModel,synthModel,firstMidiOutModel);
+ }
+ // MIDI IN → GUI、各音源、シーケンサ
+ if( firstMidiInModel != null && (txListModel = firstMidiInModel.getTransmitterListModel()) != null) {
+ txListModel.connectToFirstReceiverOfDevices(guiModel,sequencerModel,synthModel,firstMidiOutModel);
+ }
+ // シーケンサ → GUI、各音源
+ if( sequencerModel != null && (txListModel = sequencerModel.getTransmitterListModel()) != null) {
+ txListModel.connectToFirstReceiverOfDevices(guiModel,synthModel,firstMidiOutModel);
+ }
+ } catch( MidiUnavailableException ex ) {
+ ex.printStackTrace();
+ }
+ treeModel = new MidiDeviceTreeModel(deviceModelList);
+ }
+ /**
+ * MIDIデバイスリストを最新の状態に更新します。USB-MIDIデバイスの着脱後に使います。
+ */
+ public void updateMidiDeviceList() {
+ //
+ // USBから抜いたMIDIデバイスを相手のMIDIデバイスに接続したまま
+ // MidiSystem.getMidiDeviceInfo()を呼ぶと、Java VM が落ちることがある。
+ //
+ // それを回避するため、接続を一旦全部閉じる。
+ //
+ // 各Receiverごとに相手のTransmitterを閉じ、デバイスモデル同士の接続を覚えておく。
+ Map<MidiDeviceModel, Set<MidiDeviceModel>> rxToTxConnections = new HashMap<>();
+ for(MidiDeviceModel m : deviceModelList) {
+ ReceiverListModel rxListModel = m.getReceiverListModel();
+ if( rxListModel == null ) continue;
+ Set<MidiDeviceModel> txDeviceModels = rxListModel.closePeerTransmitters();
+ if( txDeviceModels.isEmpty() ) continue;
+ rxToTxConnections.put(m, txDeviceModels);
+ }
+ // 最新のMIDIデバイス情報を取得
+ MidiDevice.Info[] infoArray = MidiSystem.getMidiDeviceInfo();
+ //
+ // 追加されたデバイスの情報
+ List<MidiDevice.Info> additionalDeviceInfos = new Vector<>(Arrays.asList(infoArray));
+ //
+ // 取り外されたデバイスのモデル
+ List<MidiDeviceModel> removingDeviceModels = new Vector<>();
+ //
+ // 既存デバイスをスキャン
+ for(MidiDeviceModel m : deviceModelList) {
+ MidiDevice device = m.getMidiDevice();
+ if( device instanceof VirtualMidiDevice ) continue;
+ if( ! additionalDeviceInfos.remove(device.getDeviceInfo()) ) {
+ // 最新のMIDIデバイス情報リストから除去しようとして、すでに存在していなかった場合、
+ // そのデバイスはすでに取り外されている
+ m.close();
+ removingDeviceModels.add(m);
+ }
+ }
+ // 取り外されたデバイスのモデルを除去
+ deviceModelList.removeAll(removingDeviceModels);
+ //
+ // 追加されたデバイスをモデル化してデバイスモデルリストに追加
+ for( MidiDevice.Info info : additionalDeviceInfos ) {
+ try {
+ MidiDevice device = MidiSystem.getMidiDevice(info);
+ MidiDeviceModel m = new MidiDeviceModel(device, this);
+ deviceModelList.add(m);
+ } catch( MidiUnavailableException e ) {
+ e.printStackTrace();
+ }
+ }
+ // デバイスモデル同士の接続を復元
+ Set<MidiDeviceModel> rxDeviceModels = rxToTxConnections.keySet();
+ for( MidiDeviceModel rxm : rxDeviceModels ) {
+ if( ! deviceModelList.contains(rxm) ) continue;
+ List<Receiver> rxList = rxm.getReceiverListModel().getTransceivers();
+ for( Receiver rx : rxList ) {
+ Set<MidiDeviceModel> txDeviceModels = rxToTxConnections.get(rxm);
+ for( MidiDeviceModel txm : txDeviceModels ) {
+ try {
+ txm.getTransmitterListModel().openTransmitter().setReceiver(rx);
+ } catch( MidiUnavailableException e ) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ // デバイスツリーの更新を通知
+ treeModel.setDeviceModelList(deviceModelList);
+ }
+ /**
+ * {@link Transmitter}を持つすべてのデバイス(例:MIDIキーボードなど)について、
+ * {@link MidiDeviceModel#resetMicrosecondPosition()}でマイクロ秒位置をリセットします。
+ */
+ public void resetMicrosecondPosition() {
+ for(MidiDeviceModel m : deviceModelList) {
+ TransmitterListModel txListModel = m.getTransmitterListModel();
+ if( txListModel != null ) txListModel.resetMicrosecondPosition();
+ }
+ }
+ /**
+ * すべてのMIDIデバイスを閉じます。
+ */
+ public void close() {
+ for(MidiDeviceModel m : deviceModelList) m.getMidiDevice().close();
+ deviceModelList.clear();
+ treeModel = null;
+ }
+}
package camidion.chordhelper.mididevice;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+
import javax.swing.event.EventListenerList;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreePath;
/**
- * {@link MidiDeviceModelList}に収容されたMIDIデバイスを
- * {@link MidiDeviceInOutType}で分類して参照できるようにするツリーモデル
+ * MIDIデバイスを{@link MidiDeviceInOutType}で分類して参照できるようにするツリーモデル
*/
public class MidiDeviceTreeModel implements TreeModel {
- private MidiDeviceModelList trxListModelList;
+ private List<MidiDeviceModel> deviceModelList;
+ public List<MidiDeviceModel> getDeviceModelList() { return deviceModelList; }
+ public void setDeviceModelList(List<MidiDeviceModel> deviceModelList) {
+ group.clear();
+ this.deviceModelList = deviceModelList;
+ createGroup();
+ fireTreeStructureChanged(this, null, null, null);
+ }
- public MidiDeviceModelList getDeviceModelList() { return trxListModelList; }
+ private Map<MidiDeviceInOutType, List<MidiDeviceModel>> group = new EnumMap<>(MidiDeviceInOutType.class);
+ private void createGroup() {
+ for(MidiDeviceInOutType ioType : MidiDeviceInOutType.values()) {
+ if( ioType != MidiDeviceInOutType.MIDI_NONE ) group.put(ioType, new ArrayList<>());
+ }
+ for( MidiDeviceModel m : deviceModelList ) group.get(m.getInOutType()).add(m);
+ }
+ public Map<MidiDeviceInOutType, List<MidiDeviceModel>> getGroup() { return group; }
- public MidiDeviceTreeModel(MidiDeviceModelList trxListModelList) {
- this.trxListModelList = trxListModelList;
+ public MidiDeviceTreeModel(List<MidiDeviceModel> deviceModelList) {
+ this.deviceModelList = deviceModelList;
+ createGroup();
}
@Override
- public Object getRoot() { return trxListModelList; }
+ public String toString() { return "MIDI devices"; }
@Override
- public Object getChild(Object parent, int index) {
- if( parent == getRoot() ) return MidiDeviceInOutType.values()[index + 1];
- if( parent instanceof MidiDeviceInOutType ) {
- MidiDeviceInOutType ioType = (MidiDeviceInOutType)parent;
- for( MidiDeviceModel deviceModel : trxListModelList )
- if( deviceModel.getMidiDeviceInOutType() == ioType ) {
- if( index == 0 ) return deviceModel;
- index--;
- }
- }
- return null;
- }
+ public Object getRoot() { return this; }
@Override
public int getChildCount(Object parent) {
if( parent == getRoot() ) return MidiDeviceInOutType.values().length - 1;
- int childCount = 0;
- if( parent instanceof MidiDeviceInOutType ) {
- MidiDeviceInOutType ioType = (MidiDeviceInOutType)parent;
- for( MidiDeviceModel deviceModel : trxListModelList )
- if( deviceModel.getMidiDeviceInOutType() == ioType ) childCount++;
- }
- return childCount;
+ if( parent instanceof MidiDeviceInOutType ) return group.get(parent).size();
+ return 0;
+ }
+ @Override
+ public Object getChild(Object parent, int index) {
+ if( parent == getRoot() ) return MidiDeviceInOutType.values()[index + 1];
+ if( parent instanceof MidiDeviceInOutType ) return group.get(parent).get(index);
+ return null;
}
@Override
public int getIndexOfChild(Object parent, Object child) {
- if( parent == getRoot() ) {
- if( child instanceof MidiDeviceInOutType ) {
- MidiDeviceInOutType ioType = (MidiDeviceInOutType)child;
- return ioType.ordinal() - 1;
- }
- }
- if( parent instanceof MidiDeviceInOutType ) {
- MidiDeviceInOutType ioType = (MidiDeviceInOutType)parent;
- int index = 0;
- for( MidiDeviceModel deviceModel : trxListModelList ) {
- if( deviceModel.getMidiDeviceInOutType() == ioType ) {
- if( deviceModel == child ) return index;
- index++;
- }
- }
- }
+ if( parent == getRoot() ) return ((MidiDeviceInOutType)child).ordinal() - 1;
+ if( parent instanceof MidiDeviceInOutType ) return group.get(parent).indexOf(child);
return -1;
}
@Override
public void removeTreeModelListener(TreeModelListener listener) {
listenerList.remove(TreeModelListener.class, listener);
}
- public void fireTreeNodesChanged(
- Object source, Object[] path, int[] childIndices, Object[] children
- ) {
+ protected void fireTreeStructureChanged(Object source, Object[] path, int[] childIndices, Object[] children) {
Object[] listeners = listenerList.getListenerList();
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==TreeModelListener.class) {
- ((TreeModelListener)listeners[i+1]).treeNodesChanged(
+ ((TreeModelListener)listeners[i+1]).treeStructureChanged(
new TreeModelEvent(source,path,childIndices,children)
);
}
}
}
-}
\ No newline at end of file
+}
@Override
public MidiDeviceTreeModel getModel() { return (MidiDeviceTreeModel) super.getModel(); }
/**
+ * ツリーノードを開き、ルートを選択した状態にします。
+ */
+ public void expandAll() {
+ for( int row = 0; row < getRowCount() ; row++ ) expandRow(row);
+ }
+ /**
* MIDIデバイスツリービューを構築します。
* @param model このビューにデータを提供するモデル
*/
return this;
}
});
- // ツリーノードを開き、ルートを選択した状態にする
- for( int row = 0; row < getRowCount() ; row++ ) expandRow(row);
//
// ツリーノードのToolTipを有効化
ToolTipManager.sharedInstance().registerComponent(this);
* @param sequencer シーケンサーMIDIデバイス
* @param deviceModelList 親のMIDIデバイスモデルリスト
*/
- public MidiSequencerModel(Sequencer sequencer, MidiDeviceModelList deviceModelList) {
+ public MidiSequencerModel(Sequencer sequencer, MidiDeviceModelManager deviceModelList) {
super(sequencer, deviceModelList);
}
/**
timeRangeUpdater.start();
SequenceTrackListTableModel sequenceTableModel = getSequenceTrackListTableModel();
if( sequenceTableModel != null && sequenceTableModel.hasRecordChannel() ) {
- deviceModelList.resetMicrosecondPosition();
+ deviceModelManager.resetMicrosecondPosition();
System.gc();
sequencer.startRecording();
}
package camidion.chordhelper.mididevice;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiUnavailableException;
if( device.getReceivers().isEmpty() ) device.getReceiver();
}
/**
- * このリストモデルの{@link Receiver}に接続された他デバイスの{@link Transmitter}を全て閉じます。
+ * このリストモデルの{@link Receiver}に接続された{@link Transmitter}を全て閉じます。
+ *
+ * @return 閉じた{@link Transmitter}の{@link MidiDeviceModel}の集合
*/
- public void closePeerTransmitters() {
+ public Set<MidiDeviceModel> closePeerTransmitters() {
List<Receiver> rxList = deviceModel.getMidiDevice().getReceivers();
- MidiDeviceModelList deviceModelList = deviceModel.getDeviceModelList();
+ List<MidiDeviceModel> deviceModelList = deviceModel.getDeviceModelManager().getDeviceModelList();
+ Set<MidiDeviceModel> peedDeviceModels = new HashSet<>();
for( Receiver rx : rxList ) {
- for( MidiDeviceModel m : deviceModelList ) {
- if( m == deviceModel ) continue;
- TransmitterListModel txListModel = m.getTransmitterListModel();
- if( txListModel == null ) continue;
- txListModel.closePeerTransmitterOf(rx);
+ for( MidiDeviceModel peedDeviceModel : deviceModelList ) {
+ if( peedDeviceModel == deviceModel ) continue;
+ TransmitterListModel txListModel = peedDeviceModel.getTransmitterListModel();
+ if( txListModel == null || txListModel.closeTransmittersConnectedTo(rx).isEmpty() ) continue;
+ peedDeviceModels.add(peedDeviceModel);
}
}
+ return peedDeviceModels;
}
}
* 相手のMIDIデバイスが持つ最初の{@link Receiver}を、
* このリストモデルの新規{@link Transmitter}に接続します。
*
- * @param anotherDeviceModel 接続相手のMIDIデバイス
+ * @param anotherDeviceModels 接続相手のMIDIデバイス(複数指定可)
* @throws MidiUnavailableException リソースの制約のためにトランスミッタを使用できない場合にスローされる
*/
- public void connectToFirstReceiverOfDevice(MidiDeviceModel anotherDeviceModel) throws MidiUnavailableException {
- List<Receiver> rxList = anotherDeviceModel.getMidiDevice().getReceivers();
- if( rxList.isEmpty() ) return;
- deviceModel.getTransmitterListModel().openTransmitter().setReceiver(rxList.get(0));
+ public void connectToFirstReceiverOfDevices(MidiDeviceModel... anotherDeviceModels) throws MidiUnavailableException {
+ for( MidiDeviceModel anotherDeviceModel : anotherDeviceModels ) {
+ List<Receiver> rxList = anotherDeviceModel.getMidiDevice().getReceivers();
+ if( ! rxList.isEmpty() ) deviceModel.getTransmitterListModel().openTransmitter().setReceiver(rxList.get(0));
+ }
}
/**
* 指定の{@link Transmitter}を閉じ、要素数が1個減ったことをこのモデルを参照しているビューへ通知します。
* このリストモデルにある{@link Transmitter}のうち、
* 引数で指定された{@link Receiver}へデータを送信しているものを全て閉じます。
* 閉じるとリストから自動的に削除されるので、表示の更新も行います。
+ * @return 閉じた{@link Transmitter}のリスト
*/
- public void closePeerTransmitterOf(Receiver rx) {
- List<Transmitter> closingTxList = new Vector<Transmitter>();
+ public List<Transmitter> closeTransmittersConnectedTo(Receiver rx) {
+ List<Transmitter> closeTxList = new Vector<Transmitter>();
List<Transmitter> txList = getTransceivers();
- for( Transmitter tx : txList ) if( tx.getReceiver() == rx ) closingTxList.add(tx);
- if( closingTxList.isEmpty() ) return;
- int length = getSize();
- for( Transmitter tx : closingTxList ) tx.close();
- fireIntervalRemoved(this, 0, length);
+ for( Transmitter tx : txList ) if( tx.getReceiver() == rx ) closeTxList.add(tx);
+ if( ! closeTxList.isEmpty() ) {
+ int length = getSize();
+ for( Transmitter tx : closeTxList ) tx.close();
+ fireIntervalRemoved(this, 0, length);
+ }
+ return closeTxList;
}
/**
* マイクロ秒位置をリセットします。
*/
public void resetMicrosecondPosition() {
MidiDevice device = deviceModel.getMidiDevice();
- //
- // シーケンサはこのメソッドでのリセット対象外
- if( device instanceof Sequencer ) return;
+ if( device instanceof Sequencer || ! device.isOpen() ) return;
//
// デバイスを閉じる前に接続状態を把握
List<Receiver> peerRxList = new Vector<Receiver>();
if( rx != null ) peerRxList.add(rx);
}
List<Transmitter> peerTxList = new Vector<Transmitter>();
- MidiDeviceModelList deviceModelList = deviceModel.getDeviceModelList();
+ List<MidiDeviceModel> deviceModelList = deviceModel.getDeviceModelManager().getDeviceModelList();
List<Receiver> rxList = device.getReceivers();
for( Receiver rx : rxList ) {
for( MidiDeviceModel m : deviceModelList ) {