I'm writing a java app that's trying to copy a midi file into the Mac OSX clipboard (and eventually Windows). I've tried using the DataFlavor.javaFileListFlavor with getSystemClipboard().setContents but the data that's copied to the clipboard is unable to be read by the Mac OSX system, which uses a UTI (https://alastairs-place.net/blog/2012/06/06/utis-are-better-than-you-think-and-heres-why/) similar to a MimeType to determine the data type. Is there some custom DataFlavor code for a binary file (specifically Midi file) that will allow me to put a file on the Mac OS clipboard, similar to if I did a cmd-c on a file from finder?
Here's a snippet of what i'm currently doing.
import javax.sound.midi.*;
import java.awt.Toolkit;
import java.util.List;
import java.awt.datatransfer.*;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
/**
* Created by vincentcimo on 12/22/16.
*/
public class WriteMidi {
public static byte[] longToBytes(long x) {
ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
buffer.putLong(x);
return buffer.array();
}
public static void writeFile(String path, ArrayList<LoopNote> notes, double bpm, long loop_length) {
try {
long midiTempo = (long) (60000000 / bpm);
double tickMS = (60 / (bpm * 24)) * 1000;
/*
* 24 ticks / beat --- 100 beats / minute
* tick length = 60 / 100 bpm * 24 pulses per beat
* */
//**** Create a new MIDI sequence with 24 ticks per beat ****
Sequence s = new Sequence(javax.sound.midi.Sequence.PPQ, 24);
//**** Obtain a MIDI track from the sequence ****
Track t = s.createTrack();
//**** General MIDI sysex -- turn on General MIDI sound set ****
byte[] b = {(byte) 0xF0, 0x7E, 0x7F, 0x09, 0x01, (byte) 0xF7};
SysexMessage sm = new SysexMessage();
sm.setMessage(b, 6);
MidiEvent me = new MidiEvent(sm, (long) 0);
t.add(me);
//**** set tempo (meta event) ****
MetaMessage mt = new MetaMessage();
byte[] bt = longToBytes(midiTempo);
mt.setMessage(0x51, bt, 3);
me = new MidiEvent(mt, (long) 0);
t.add(me);
//**** set track name (meta event) ****
mt = new MetaMessage();
String TrackName = new String("midifile track");
mt.setMessage(0x03, TrackName.getBytes(), TrackName.length());
me = new MidiEvent(mt, (long) 0);
t.add(me);
//**** set omni on ****
ShortMessage mm = new ShortMessage();
mm.setMessage(0xB0, 0x7D, 0x00);
me = new MidiEvent(mm, (long) 0);
t.add(me);
//**** set poly on ****
mm = new ShortMessage();
mm.setMessage(0xB0, 0x7F, 0x00);
me = new MidiEvent(mm, (long) 0);
t.add(me);
//**** set instrument to Piano ****
mm = new ShortMessage();
mm.setMessage(0xC0, 0x00, 0x00);
me = new MidiEvent(mm, (long) 0);
t.add(me);
for (LoopNote note : notes) {
mm = new ShortMessage();
if (note.getVelocity() != 0) {
mm.setMessage(ShortMessage.NOTE_ON, 1, note.getNote(), note.getVelocity());
} else {
mm.setMessage(ShortMessage.NOTE_OFF, 1, note.getNote(), note.getVelocity());
}
me = new MidiEvent(mm, (long) (note.getStartTime() / tickMS));
t.add(me);
}
//**** set end of track (meta event) 19 ticks later ****
mt = new MetaMessage();
byte[] bet = {}; // empty array
mt.setMessage(0x2F, bet, 0);
me = new MidiEvent(mt, (long) (loop_length / tickMS));
t.add(me);
//**** write the MIDI sequence to a MIDI file ****
File f = new File(path);
if (!f.exists()) {
f.createNewFile();
MidiSystem.write(s, 1, f);
List listOfFiles = new ArrayList();
listOfFiles.add(f);
FileTransferable ft = new FileTransferable(listOfFiles);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ft, new ClipboardOwner() {
@Override
public void lostOwnership(Clipboard clipboard, Transferable contents) {
System.out.println("Lost ownership");
}
});
}
} //try
catch (Exception e) {
System.out.println("Exception caught " + e.toString());
} //catch
System.out.println("midifile end ");
}
public static class FileTransferable implements Transferable {
private List listOfFiles;
public FileTransferable(List listOfFiles) {
this.listOfFiles = listOfFiles;
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{DataFlavor.javaFileListFlavor};
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return DataFlavor.javaFileListFlavor.equals(flavor);
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
return listOfFiles;
}
}
}
Here's a similar post which was never answered:
I had the same problem and after hours and hours of search I came up with the following simple workaround. In Java you call a Terminal Command, that runs an apple script, telling Finder to put the file to the clilboard:
you can then paste the file by cmd + v just as if you copied it in finder.