*/
public static class VersionInfo {
public static final String NAME = "MIDI Chord Helper";
- public static final String VERSION = "Ver.20160605.1";
+ public static final String VERSION = "Ver.20160612.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/";
dataText.setVisible(false);
}
else {
- dataText.setTitle(MIDISpec.hasMetaText(msgType)?"Text:":"Data:");
+ dataText.setTitle(MIDISpec.hasMetaMessageText(msgType)?"Text:":"Data:");
}
}
else {
int msgType = data1Text.getValue();
if( msgType < 0 ) return null;
byte msgData[];
- if( MIDISpec.hasMetaText(msgType) ) {
+ if( MIDISpec.hasMetaMessageText(msgType) ) {
msgData = dataText.getString().getBytes(charset);
}
else if( msgType == 0x2F ) { // EOT
case 0x59: keysigSelecter.setKey(new Key(data)); break;
default: break;
}
- if( MIDISpec.hasMetaText(msgType) ) {
+ if( MIDISpec.hasMetaMessageText(msgType) ) {
dataText.setString(new String(data,charset));
}
else {
) {
@Override
public void actionPerformed(ActionEvent event) {
- SequenceTrackListTableModel sequenceModel = getModel().getSelectedSequenceModel();
+ PlaylistTableModel playlistModel = getModel();
+ SequenceTrackListTableModel sequenceModel = playlistModel.getSelectedSequenceModel();
String fn = sequenceModel.getFilename();
if( fn != null && ! fn.isEmpty() ) setSelectedFile(new File(fn));
if( showSaveDialog((Component)event.getSource()) != JFileChooser.APPROVE_OPTION ) return;
try ( FileOutputStream out = new FileOutputStream(f) ) {
out.write(sequenceModel.getMIDIdata());
sequenceModel.setModified(false);
+ playlistModel.fireSequenceModified(sequenceModel, false);
}
catch( IOException ex ) {
showError( ex.getMessage() );
scrollToEventAt(tick);
// ペーストで曲の長さが変わったことをプレイリストに通知
SequenceTrackListTableModel seqModel = trackModel.getParent();
- seqModel.getParent().fireSequenceModified(seqModel);
+ seqModel.getParent().fireSequenceModified(seqModel, true);
eventDialog.setVisible(false);
trackModel = null;
}
scrollToEventAt(partnerTick > tick ? partnerTick : tick);
}
}
- seqModel.getParent().fireSequenceModified(seqModel);
+ seqModel.getParent().fireSequenceModified(seqModel, true);
eventDialog.setVisible(false);
return true;
}
return sequenceList.get(selectedIndex);
}
/**
- * æ\8c\87å®\9aã\81\95ã\82\8cã\81\9fã\82·ã\83¼ã\82±ã\83³ã\82¹ã\81\8cä¿®æ£ã\81\95ã\82\8cã\81\9fã\81\93ã\81¨ã\82\92é\80\9aç\9f¥します。
+ * æ\8c\87å®\9aã\81\95ã\82\8cã\81\9fã\82·ã\83¼ã\82±ã\83³ã\82¹ã\81®æ\9b´æ\96°æ¸\88ã\81¿ã\83\95ã\83©ã\82°ã\82\92å¤\89æ\9b´ã\81\97ã\81¦å\85¨ã\81¦ã\81®å\88\97ã\82\92å\86\8d表示します。
* @param sequenceTableModel MIDIシーケンスモデル
+ * @param isModified 更新済みフラグ
*/
- public void fireSequenceModified(SequenceTrackListTableModel sequenceTableModel) {
+ public void fireSequenceModified(SequenceTrackListTableModel sequenceTableModel, boolean isModified) {
int index = sequenceList.indexOf(sequenceTableModel);
if( index < 0 ) return;
- sequenceTableModel.setModified(true);
+ sequenceTableModel.setModified(isModified);
fireTableRowsUpdated(index, index);
}
/**
- * æ\8c\87å®\9aã\81\95ã\82\8cã\81¦ã\81\84ã\82\8bé\81¸æ\8a\9eç¯\84å\9b²ã\81®ã\82·ã\83¼ã\82±ã\83³ã\82¹ã\81\8cå¤\89æ\9b´ã\81\95ã\82\8cã\81\9fã\81\93ã\81¨ã\82\92é\80\9aç\9f¥します。
- * 更新済みフラグをセットし、選択されたシーケンスの全ての列を再表示します。
+ * æ\8c\87å®\9aã\81\95ã\82\8cã\81¦ã\81\84ã\82\8bé\81¸æ\8a\9eç¯\84å\9b²ã\81®ã\82·ã\83¼ã\82±ã\83³ã\82¹ã\81«ã\81¤ã\81\84ã\81¦ã\80\81æ\9b´æ\96°æ¸\88ã\81¿ã\83\95ã\83©ã\82°ã\82\92å¤\89æ\9b´ã\81\97ã\81¦å\85¨ã\81¦ã\81®å\88\97ã\82\92å\86\8d表示します。
+ * @param isModified 更新済みフラグ
*/
- public void fireSelectedSequenceModified() {
+ public void fireSelectedSequenceModified(boolean isModified) {
if( sequenceListSelectionModel.isSelectionEmpty() ) return;
int minIndex = sequenceListSelectionModel.getMinSelectionIndex();
int maxIndex = sequenceListSelectionModel.getMaxSelectionIndex();
for( int index = minIndex; index <= maxIndex; index++ ) {
- sequenceList.get(index).setModified(true);
+ sequenceList.get(index).setModified(isModified);
}
fireTableRowsUpdated(minIndex, maxIndex);
}
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
* シーケンスtickインデックスを返します。
* @return シーケンスtickインデックス
*/
- public SequenceTickIndex getSequenceTickIndex() {
- return sequenceTickIndex;
- }
+ public SequenceTickIndex getSequenceTickIndex() { return sequenceTickIndex; }
/**
* MIDIシーケンスを設定します。
* @param sequence MIDIシーケンス(nullを指定するとトラックリストが空になる)
trackModelList.add(new TrackEventListTableModel(this, track));
}
// 文字コードの判定
- byte b[] = MIDISpec.getNameBytesOf(sequence);
- if( b != null && b.length > 0 ) {
- try {
- String autoDetectedName = new String(b, "JISAutoDetect");
- Set<Map.Entry<String,Charset>> entrySet;
- entrySet = Charset.availableCharsets().entrySet();
- for( Map.Entry<String,Charset> entry : entrySet ) {
- Charset cs = entry.getValue();
- if( ! autoDetectedName.equals(new String(b, cs)) )
- continue;
- charset = cs;
- break;
- }
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- }
+ Charset cs = MIDISpec.getCharsetOf(sequence);
+ charset = cs==null ? Charset.defaultCharset() : cs;
+ //
// トラックが挿入されたことを通知
fireTableRowsInserted(0, tracks.length-1);
}
* @return 成功したらtrue
*/
public boolean setName(String name) {
- if( name.equals(toString()) )
- return false;
- byte b[] = name.getBytes(charset);
- if( ! MIDISpec.setNameBytesOf(sequence, b) )
- return false;
+ if( name.equals(toString()) ) return false;
+ if( ! MIDISpec.setNameBytesOf(sequence, name.getBytes(charset)) ) return false;
setModified(true);
fireTableDataChanged();
return true;
int row = indexOf(track);
if( row < 0 ) return;
fireTableRowsUpdated(row, row);
- sequenceListTableModel.fireSequenceModified(this);
+ sequenceListTableModel.fireSequenceModified(this, true);
}
/**
* 選択されているトラックモデルを返します。
trackModelList.add(new TrackEventListTableModel(this, newTrack));
int lastRow = getRowCount() - 1;
fireTableRowsInserted(lastRow, lastRow);
- sequenceListTableModel.fireSelectedSequenceModified();
+ sequenceListTableModel.fireSelectedSequenceModified(true);
trackListSelectionModel.setSelectionInterval(lastRow, lastRow);
return lastRow;
}
trackModelList.remove(i);
}
fireTableRowsDeleted(minIndex, maxIndex);
- sequenceListTableModel.fireSelectedSequenceModified();
+ sequenceListTableModel.fireSelectedSequenceModified(true);
}
/**
* このシーケンスモデルのシーケンスをシーケンサーが操作しているか調べます。
fireTableDataChanged();
if( MIDISpec.isEOT(msg) ) {
// EOTの場所が変わると曲の長さが変わるので、親モデルへ通知する。
- sequenceTrackListTableModel.getParent().fireSequenceModified(sequenceTrackListTableModel);
+ sequenceTrackListTableModel.getParent().fireSequenceModified(sequenceTrackListTableModel, true);
}
}
/**
if( ! MIDISpec.setNameBytesOf(track, b) )
return false;
sequenceTrackListTableModel.setModified(true);
- sequenceTrackListTableModel.getParent().fireSequenceModified(sequenceTrackListTableModel);
+ sequenceTrackListTableModel.getParent().fireSequenceModified(sequenceTrackListTableModel, true);
fireTableDataChanged();
return true;
}
int oldLastIndex = lastIndex + midiEvents.length;
if(lastIndex < 0) lastIndex = 0;
fireTableRowsDeleted(oldLastIndex, lastIndex);
- sequenceTrackListTableModel.getParent().fireSelectedSequenceModified();
+ sequenceTrackListTableModel.getParent().fireSelectedSequenceModified(true);
}
/**
* 引数の選択内容が示すMIDIイベントを除去します。
package camidion.chordhelper.music;
+import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MetaMessage;
* @param metaMessageType メタメッセージタイプ
* @return テキストがつくときtrue
*/
- public static boolean hasMetaText(int metaMessageType) {
+ public static boolean hasMetaMessageText(int metaMessageType) {
return (metaMessageType > 0 && metaMessageType < 10);
}
/**
* @return 拍子記号ならtrue
*/
public static boolean isTimeSignature(MidiMessage midiMessage) {
- if ( !(midiMessage instanceof MetaMessage) )
- return false;
+ if ( !(midiMessage instanceof MetaMessage) ) return false;
return isTimeSignature( ((MetaMessage)midiMessage).getType() );
}
/**
* @param metaMessageType メタメッセージタイプ
* @return EOTならtrue
*/
- public static boolean isEOT(int metaMessageType) {
- return metaMessageType == 0x2F;
- }
+ public static boolean isEOT(int metaMessageType) { return metaMessageType == 0x2F; }
/**
* MIDIメッセージが EOT (End Of Track) か調べます。
* @param midiMessage MIDIメッセージ
* @return EOTならtrue
*/
public static boolean isEOT(MidiMessage midiMessage) {
- if ( !(midiMessage instanceof MetaMessage) )
- return false;
+ if ( !(midiMessage instanceof MetaMessage) ) return false;
return isEOT( ((MetaMessage)midiMessage).getType() );
}
/**
* @return テンポ[QPM]
*/
public static int byteArrayToQpmTempo(byte[] b) {
- int tempoInUsPerQuarter
- = ((b[0] & 0xFF) << 16) | ((b[1] & 0xFF) << 8) | (b[2] & 0xFF);
+ int tempoInUsPerQuarter = ((b[0] & 0xFF) << 16) | ((b[1] & 0xFF) << 8) | (b[2] & 0xFF);
return MICROSECOND_PER_MINUTE / tempoInUsPerQuarter;
}
/**
//
Track tracks[] = seq.getTracks();
byte b[];
- for( Track track : tracks )
- if( (b = getNameBytesOf(track)) != null ) return b;
+ for( Track track : tracks ) if( (b = getNameBytesOf(track)) != null ) return b;
return null;
}
/**
*/
public static boolean setNameBytesOf(Sequence seq, byte[] name) {
Track tracks[] = seq.getTracks();
- for( Track track : tracks )
- if( setNameBytesOf(track,name) ) return true;
+ for( Track track : tracks ) if( setNameBytesOf(track,name) ) return true;
return false;
}
+ /**
+ * シーケンスの名前や歌詞など、メタイベントのテキストをもとに文字コードを判定します。
+ * 判定できなかった場合はnullを返します。
+ * @param seq MIDIシーケンス
+ * @return 文字コード判定結果(またはnull)
+ */
+ public static Charset getCharsetOf(Sequence seq) {
+ Track tracks[] = seq.getTracks();
+ byte[] b = new byte[0];
+ for( Track track : tracks ) {
+ MidiMessage message;
+ MetaMessage metaMessage;
+ for( int i=0; i<track.size(); i++ ) {
+ message = track.get(i).getMessage();
+ if( ! (message instanceof MetaMessage) ) continue;
+ metaMessage = (MetaMessage)message;
+ if( ! hasMetaMessageText(metaMessage.getType()) ) continue;
+ byte[] additional = metaMessage.getData();
+ byte[] concated = new byte[b.length + additional.length];
+ System.arraycopy(b, 0, concated, 0, b.length);
+ System.arraycopy(additional, 0, concated, b.length, additional.length);
+ b = concated;
+ }
+ }
+ if( b.length > 0 ) {
+ try {
+ String autoDetectedName = new String(b, "JISAutoDetect");
+ Set<Map.Entry<String,Charset>> entrySet;
+ entrySet = Charset.availableCharsets().entrySet();
+ for( Map.Entry<String,Charset> entry : entrySet ) {
+ Charset cs = entry.getValue();
+ if( autoDetectedName.equals(new String(b, cs)) ) return cs;
+ }
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
///////////////////////////////////////////////////////////////////
//
// Channel Message / System Message
str += meta_name;
//
// Add the text data
- if( hasMetaText(msgtype) ) {
+ if( hasMetaMessageText(msgtype) ) {
str +=" ["+(new String(msgdata,charset))+"]";
return str;
}