*/
public static class VersionInfo {
public static final String NAME = "MIDI Chord Helper";
- public static final String VERSION = "Ver.20160618.1";
+ public static final String VERSION = "Ver.20160619.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/";
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;
for( JInternalFrame frame : frames ) {
if( ! (frame instanceof MidiDeviceFrame) ) continue;
MidiDeviceFrame fromFrame = (MidiDeviceFrame)frame;
- MidiDevice fromDevice = fromFrame.getMidiDeviceModel().getMidiDevice();
+ MidiDeviceModel fromDeviceModel = fromFrame.getMidiDeviceModel();
//
// Receiverからドラッグされている線を描画
- if( draggingPoint != null && fromDevice.getReceivers().indexOf(dragging.getData()) >= 0 ) {
+ if( draggingPoint != null && fromDeviceModel.getMidiDevice().getReceivers().contains(dragging.getData()) ) {
Receiver rx = (Receiver)dragging.getData();
Rectangle rxBounds = fromFrame.getBoundsOf(rx);
if( rxBounds == null ) continue;
g2.drawLine(rxBounds.x, rxBounds.y, draggingPoint.x, draggingPoint.y);
}
// Transmitterを全部スキャン
- List<Transmitter> txList = fromDevice.getTransmitters();
- for( Transmitter tx : txList ) {
+ MidiDeviceModel.TransmitterListModel txListModel = fromDeviceModel.getTransmitterListModel();
+ int ntx = txListModel == null ? 0 : txListModel.getSize();
+ for( int index=0 ; index < ntx; index++ ) {
+ Transmitter tx = txListModel.getElementAt(index);
//
// Transmitterの場所を特定
Rectangle txBounds = fromFrame.getBoundsOf(tx);
* @param element 探したい要素
* @return 位置のインデックス(先頭が 0、見つからないとき -1)
*/
- public int indexOf(Receiver element) { return device.getReceivers().indexOf(element); }
+ public int indexOf(Object element) { return device.getReceivers().indexOf(element); }
+ /**
+ * {@link MidiDevice#getReceiver()} でレシーバを1個開きます。
+ * すでに1個開いている場合は無視されます。
+ *
+ * @throws MidiUnavailableException リソースの制約のためにレシーバを使用できない場合にスローされる
+ */
+ public void openReceiver() throws MidiUnavailableException {
+ if( device.getReceivers().isEmpty() ) device.getReceiver();
+ }
+ /**
+ * このリストモデルの{@link Receiver}に接続された他デバイスの{@link Transmitter}を全て閉じます。
+ */
+ public void closePeerTransmitters() {
+ List<Receiver> rxList = device.getReceivers();
+ for( Receiver rx : rxList ) {
+ for( MidiDeviceModel m : deviceModelList ) {
+ if( m == MidiDeviceModel.this || m.txListModel == null ) continue;
+ m.txListModel.closePeerTransmitterOf(rx);
+ }
+ }
+ }
}
/**
*/
public class TransmitterListModel extends AbstractListModel<Transmitter> {
private NewTransmitter newTransmitter = new NewTransmitter() {
+ private Receiver receiver;
@Override
- public void setReceiver(Receiver receiver) { }
+ public void setReceiver(Receiver receiver) { this.receiver = receiver; }
@Override
- public Receiver getReceiver() { return null; }
+ public Receiver getReceiver() { return receiver; }
@Override
public void close() { }
};
* @param element 探したい要素
* @return 位置
*/
- public int indexOf(Transmitter element) {
+ public int indexOf(Object element) {
List<Transmitter> txList = device.getTransmitters();
return element.equals(newTransmitter) ? txList.size() : txList.indexOf(element);
}
return tx;
}
/**
- * 指定の位置にある接続可能な{@link Transmitter}を返します。
- * 新規Transmitterの場合、{@link #getUnconnectedTransmitter()}からの値を返します。
- * @param index 位置(0が先頭、最後が新規)
- * @return
+ * このリストモデルの{@link #getUnconnectedTransmitter()}が返した{@link Transmitter}を、
+ * 相手のMIDIデバイスが持つ最初の{@link Receiver}に接続します。
+ *
+ * @param anotherDeviceModel 接続相手のMIDIデバイス
* @throws MidiUnavailableException リソースの制約のためにトランスミッタを使用できない場合にスローされる
*/
- public Transmitter getConnectableTransmitterAt(int index) throws MidiUnavailableException {
- Transmitter tx = getElementAt(index);
- if( tx instanceof NewTransmitter ) tx = getUnconnectedTransmitter();
- return tx;
+ public void connectToFirstReceiverOfDevice(MidiDeviceModel anotherDeviceModel) throws MidiUnavailableException {
+ List<Receiver> rxList = anotherDeviceModel.device.getReceivers();
+ if( ! rxList.isEmpty() ) txListModel.getUnconnectedTransmitter().setReceiver(rxList.get(0));
}
/**
- * このリストモデルで開いている指定の{@link Transmitter}があれば、
- * それを閉じて表示を更新します。
- * ない場合は無視されます。
+ * 指定の{@link Transmitter}がリストにあれば、それを閉じます。
+ * 閉じるとリストから自動的に削除されるので、表示の更新も行います。
+ *
* @param tx このリストモデルで開いている{@link Transmitter}
*/
public void close(Transmitter tx) {
fireIntervalRemoved(this, 0, getSize());
}
/**
- * このリストモデルの{@link #getUnconnectedTransmitter()}が返した{@link Transmitter}を、
- * 相手のMIDIデバイスが持つ最初の{@link Receiver}に接続します。
- *
- * @param anotherDeviceModel 接続相手のMIDIデバイス
- * @throws MidiUnavailableException リソースの制約のためにトランスミッタを使用できない場合にスローされる
- */
- public void connectToFirstReceiverOfDevice(MidiDeviceModel anotherDeviceModel) throws MidiUnavailableException {
- if( ! anotherDeviceModel.rxSupported() ) return;
- List<Receiver> rxList = anotherDeviceModel.device.getReceivers();
- if( rxList.isEmpty() ) return;
- txListModel.getUnconnectedTransmitter().setReceiver(rxList.get(0));
- }
- /**
* このリストモデルにある{@link Transmitter}のうち、
* 引数で指定された{@link Receiver}へデータを送信しているものを全て閉じます。
+ * 閉じるとリストから自動的に削除されるので、表示の更新も行います。
*/
private void closePeerTransmitterOf(Receiver rx) {
List<Transmitter> originalTxList = device.getTransmitters();
*/
public void open() throws MidiUnavailableException {
device.open();
- if( rxListModel != null && device.getReceivers().isEmpty() ) device.getReceiver();
+ if( rxListModel != null ) rxListModel.openReceiver();
}
/**
* このMIDIデバイスを {@link MidiDevice#close()} で閉じます。
* それらも全て閉じます。
*/
public void close() {
- if( rxListModel != null ) {
- List<Receiver> rxList = device.getReceivers();
- for( Receiver rx : rxList ) {
- for( MidiDeviceModel m : deviceModelList ) {
- if( m != this && m.txListModel != null ) m.txListModel.closePeerTransmitterOf(rx);
- }
- }
- }
+ if( rxListModel != null ) rxListModel.closePeerTransmitters();
device.close();
}
}
dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, dgl);
dragSource.addDragSourceMotionListener(cablePane);
//
- // トランスミッタのドロップを受け付ける
+ // 外からドラッグされたトランスミッタを、ドロップした場所のレシーバに接続する
DropTargetListener dtl = new DropTargetAdapter() {
@Override
public void dragEnter(DropTargetDragEvent event) {
try {
Object sourceTx = t.getTransferData(DraggingTransceiver.transmitterFlavor);
if( sourceTx != null ) {
- int targetRxIndex = locationToIndex(event.getLocation());
- ((Transmitter)sourceTx).setReceiver(getModel().getElementAt(targetRxIndex));
+ ((Transmitter)sourceTx).setReceiver(getModel().getElementAt(locationToIndex(event.getLocation())));
event.dropComplete(true);
return;
}
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
+import camidion.chordhelper.mididevice.MidiDeviceModel.NewTransmitter;
+
/**
* MIDIトランスミッタ({@link Transmitter})のリストビューです。
* トランスミッタをこのビューからドラッグし、
public void dragGestureRecognized(DragGestureEvent event) {
if( (event.getDragAction() & DnDConstants.ACTION_COPY_OR_MOVE) == 0 ) return;
int draggingIndex = locationToIndex(event.getDragOrigin());
- try {
- MidiCablePane.dragging.setData(getModel().getConnectableTransmitterAt(draggingIndex));
- } catch (Exception exception) {
- exception.printStackTrace();
- return;
- }
+ MidiCablePane.dragging.setData(getModel().getElementAt(draggingIndex));
event.startDrag(DragSource.DefaultLinkDrop, MidiCablePane.dragging, new DragSourceAdapter() {
@Override
public void dragDropEnd(DragSourceDropEvent event) {
- if( ! event.getDropSuccess() ) getModel().close((Transmitter)MidiCablePane.dragging.getData());
+ Transmitter droppedTx = (Transmitter)MidiCablePane.dragging.getData();
+ if( ! event.getDropSuccess() ) {
+ // 所定の場所にドロップされなかったトランスミッタを閉じる
+ getModel().close(droppedTx);
+ } else if( droppedTx instanceof MidiDeviceModel.NewTransmitter ) {
+ // ドロップされたダミートランスミッタに接続されたレシーバを
+ // 新しい本物のトランスミッタに付け替える
+ try {
+ getModel().getUnconnectedTransmitter().setReceiver(droppedTx.getReceiver());
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ droppedTx.setReceiver(null);
+ }
cablePane.dragSourceListener.dragDropEnd(event);
}
});
dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, dgl);
dragSource.addDragSourceMotionListener(cablePane);
//
- // レシーバのドロップを受け付ける
+ // 外からドラッグされたレシーバを、ドロップした場所のトランスミッタに接続する
DropTargetListener dtl = new DropTargetAdapter() {
@Override
public void dragEnter(DropTargetDragEvent event) {
try {
Object sourceRx = t.getTransferData(DraggingTransceiver.receiverFlavor);
if( sourceRx != null ) {
- int targetTxIndex = locationToIndex(event.getLocation());
- getModel().getConnectableTransmitterAt(targetTxIndex).setReceiver((Receiver)sourceRx);
+ Transmitter tx = getModel().getElementAt(locationToIndex(event.getLocation()));
+ if( tx instanceof NewTransmitter ) tx = getModel().getUnconnectedTransmitter();
+ tx.setReceiver((Receiver)sourceRx);
event.dropComplete(true);
return;
}
import javax.swing.event.ListDataListener;
import camidion.chordhelper.ChordDisplayLabel;
+import camidion.chordhelper.ChordHelperApplet;
import camidion.chordhelper.anogakki.AnoGakkiPane;
import camidion.chordhelper.chordmatrix.ChordMatrix;
import camidion.chordhelper.mididevice.AbstractMidiChannelStatus;
public VirtualMidiDevice midiDevice = new AbstractVirtualMidiDevice() {
class MyInfo extends Info {
protected MyInfo() {
- super("Virtual MIDI Keyboard","Unknown vendor","Software MIDI keyboard","");
+ super(ChordHelperApplet.VersionInfo.NAME,
+ ChordHelperApplet.VersionInfo.AUTHER,
+ "Software MIDI keyboard with indicator",
+ ChordHelperApplet.VersionInfo.VERSION);
}
}
/**