..plus nested transpose popup menus and note-play on double-click etc.
public class MooKeyboard extends KeyAdapter {
- private boolean[] isOn;
private static int startNote;
private static int[] keyToNote = new int[120];
+ private boolean[] isOn;
+ private boolean recording;
+ private MooTrackTitle title;
/**
* Sets up the synthesizer emulation.
*/
- public MooKeyboard() {
+ public MooKeyboard(MooTrackTitle mtt) {
+ title = mtt;
isOn = new boolean[120];
}
// Retrieves the notenumber from the conversion array.
int noteNumber = keyToNote[e.getKeyCode()];
// If note is not already on and the key is mapped to a note, sends the NoteOn event.
- if (!isOn[noteNumber] && noteNumber > 0) Moosique.getActiveChannel().noteOn(noteNumber, 127);
+ if (!isOn[noteNumber] && noteNumber > 0) {
+ if (recording) {
+ ShortMessage msg = new ShortMessage();
+ msg.setMessage(ShortMessage.NOTE_ON, title.getChannel(), noteNumber, 100);
+ Moosique.getSequencer().getReceiver().send(msg, -1);
+ } else {
+ Moosique.getActiveChannel().noteOn(noteNumber, 127);
+ }
+ }
isOn[noteNumber] = true;
- } catch (ArrayIndexOutOfBoundsException x) {
+ } catch (Exception x) {
return;
}
}
// Retrieves the notenumber from the conversion array.
int noteNumber = keyToNote[e.getKeyCode()];
// Sends the NoteOff event.
- Moosique.getActiveChannel().noteOff(noteNumber);
+ if (recording) {
+ ShortMessage msg = new ShortMessage();
+ msg.setMessage(ShortMessage.NOTE_OFF, title.getChannel(), noteNumber, 0);
+ Moosique.getSequencer().getReceiver().send(msg, -1);
+ } else {
+ Moosique.getActiveChannel().noteOff(noteNumber);
+ }
isOn[noteNumber] = false;
- } catch (ArrayIndexOutOfBoundsException x) {
+ } catch (Exception x) {
return;
}
}
}
/**
- * Sets the octave of the lower part of the keyboard (default = 4)
+ * Prepares the keyboard for recording on the current channel.
+ */
+ public void recordEnable() {
+ recording = true;
+ }
+
+ /**
+ * Disables recording and returns to keyjazz mode.
+ */
+ public void recordDisable() {
+ recording = false;
+ }
+
+ /**
+ * Sets the octave of the lower part of the keyboard (default = 4).
* @param n the octave to start at
*/
public static void setOctave(int n) {
}
/**
- * Increases or decreases the octave of the lower part of the keyboard (default = 4)
+ * Increases or decreases the octave of the lower part of the keyboard (default = 4).
* @param increase true for increase, false for decrease
*/
public static void setRelativeOctave(boolean increase) {
} catch (InvalidMidiDataException e) {System.out.println("Invalid data!");}
}
+ /**
+ * Returns the note off event of this note.
+ * @return the note off event
+ */
+ public MidiEvent getNoteOffEvent() {
+ return noteOffEvent;
+ }
+
+ /**
+ * Returns the channel of the current note.
+ * @return the channel of the note (1-16)
+ */
+ public int getChannel() {
+ return noteOnMsg.getChannel();
+ }
+
+ /**
+ * Returns the pitch of the current note.
+ * @return the pitch of the note (0-127)
+ */
+ public int getPitch() {
+ return noteOnMsg.getData1();
+ }
+
+ /**
+ * Returns the velocity of the current note.
+ * @return the velocity of the note (0-127)
+ */
+ public int getVelocity() {
+ return noteOnMsg.getData2();
+ }
+
+ /**
+ * Returns the duration of the current note.
+ * @return the duration of the note (in ticks)
+ */
+ public int getDuration() {
+ return (int)(noteOffEvent.getTick() - getTick());
+ }
+
/**
* Sets the channel of the current note.
* @param channel the channel of the note (1-16)
setPitch(getPitch() + halftones);
}
- /**
- * Returns the channel of the current note.
- * @return the channel of the note (1-16)
- */
- public int getChannel() {
- return noteOnMsg.getChannel();
- }
-
- /**
- * Returns the pitch of the current note.
- * @return the pitch of the note (0-127)
- */
- public int getPitch() {
- return noteOnMsg.getData1();
- }
-
- /**
- * Returns the velocity of the current note.
- * @return the velocity of the note (0-127)
- */
- public int getVelocity() {
- return noteOnMsg.getData2();
- }
-
- /**
- * Returns the duration of the current note.
- * @return the duration of the note (in ticks)
- */
- public int getDuration() {
- return (int)(noteOffEvent.getTick() - getTick());
- }
-
/**
* Adds this note (both noteOn and noteOffEvents) to a track.
* @param track the track it'll be added to.
* @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object
*/
public int compareTo(Object o) {
- return (int)(((MidiEvent)o).getTick() - getTick());
+ return (int)(getTick() - ((MidiEvent)o).getTick());
}
-
}
private MooTrackView mtv;
private MooNote note;
private JPopupMenu popup;
- private JMenuItem popupRemove, popupProp, popupTranspOctUp, popupTranspOctDown;
+ private JMenu popupTranspUp, popupTranspDown;
+ private JMenuItem popupRemove, popupProp;
+ private JMenuItem[] popupTranspUpItems, popupTranspDownItems;
private Rectangle pitchRect, veloRect;
private String notePitch, noteVelocity;
private boolean selected = false, leftMouseButtonPressed = false, mouseIn = false;
// Creates pop-up menu.
popup = new JPopupMenu();
- PopupListener pList = new PopupListener();
- popupProp = new JMenuItem("Preferences...");
- popupProp.addActionListener(pList);
- popup.add(popupProp);
- popupRemove = new JMenuItem("Remove");
- popupRemove.addActionListener(pList);
- popup.add(popupRemove);
- popupTranspOctUp = new JMenuItem("Transpose one octave up");
- popupTranspOctUp.addActionListener(pList);
- popup.add(popupTranspOctUp);
- popupTranspOctDown = new JMenuItem("Transpose one octave down");
- popupTranspOctDown.addActionListener(pList);
- popup.add(popupTranspOctDown);
+ popupProp = addMenuItem(popup, "Preferences...");
+ popupRemove = addMenuItem(popup, "Remove");
+ popupTranspUpItems = new JMenuItem[12];
+ popupTranspDownItems = new JMenuItem[12];
+ popupTranspUp = createTransposeMenu(popup, popupTranspUpItems, "note up");
+ popupTranspDown = createTransposeMenu(popup, popupTranspDownItems, "note down");
}
/**
mtv.layoutElement(this,true);
}
+ /**
+ * Adds a menu item with the given command to the given popup menu.
+ */
+ private JMenuItem addMenuItem(JPopupMenu menu, String command) {
+ JMenuItem item = new JMenuItem(command);
+ item.addActionListener(new PopupListener());
+ menu.add(item);
+ return item;
+ }
+
+ /**
+ * Adds a menu item with the given command to the given menu.
+ */
+ private JMenuItem addMenuItem(JMenu menu, String command) {
+ JMenuItem item = new JMenuItem(command);
+ item.addActionListener(new PopupListener());
+ menu.add(item);
+ return item;
+ }
+
+ /**
+ * Creates a transpose sub menu with the given title in the given popup menu,
+ * inserting the items into the given array.
+ */
+ private JMenu createTransposeMenu(JPopupMenu menu, JMenuItem[] items, String title) {
+ JMenu trans = new JMenu("Transpose " + title);
+ menu.add(trans);
+ items[0] = addMenuItem(trans, "One octave");
+ for (int i = 1; i < 12; i++) {
+ items[i] = addMenuItem(trans, (i) + " halftones");
+ }
+ return trans;
+ }
+
/**
* Listener that checks the mouse actions on this element.
*/
class MAdapter extends MouseAdapter {
+ /**
+ * Plays the note on double-click.
+ */
+ public void mouseClicked(MouseEvent e) {
+ if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2)
+ Moosique.getReceiver().send(note.getMessage(), -1);
+ }
+
/**
* Selects the note if mouse entered with the left mouse button pressed.
*/
*/
public void mouseExited(MouseEvent e) {
mouseIn = false;
+ Moosique.getReceiver().send(note.getNoteOffEvent().getMessage(), -1);
}
/**
}
} else {
select();
- // Play the note
maybeShowPopup(e);
}
}
}
/**
- * Listens on the actions made to the popupmenu.
+ * Takes the appropriate action when a user selects an item on the popup menu.
*/
class PopupListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
new MooDialog(note);
System.out.println("Duration: " + note.getDuration());
newLayout();
- repaint();
+ update();
} else if (source == popupRemove) {
remove();
- } else if (source == popupTranspOctUp) {
+ } else if (source == popupTranspUpItems[0]) {
transpose(12);
- } else if (source == popupTranspOctDown) {
+ } else if (source == popupTranspDownItems[0]) {
transpose(-12);
+ } else {
+ for (int i = 1; i < 12; i++) {
+ if (source == popupTranspUpItems[i]) transpose(i);
+ else if (source == popupTranspDownItems[i]) transpose(-i);
+ }
}
}
}
}
/**
- * Creates a button with the specified image and tooltip.
+ * Creates a button with the specified image and action command / tooltip.
*/
- private JButton createButton(String imagelocation, String tooltip) {
+ private JButton createButton(String imagelocation, String command) {
JButton button = new JButton (new ImageIcon(imagelocation));
- button.setToolTipText(tooltip);
+ button.setToolTipText(command);
+ button.setActionCommand(command);
button.addMouseListener(mouseAdapter);
return button;
}
class MAdapter extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
if (e.getSource() instanceof JButton) {
- String toolTip = ((JButton)e.getSource()).getToolTipText();
- if (toolTip == "Play") {
+ String command = ((JButton)e.getSource()).getActionCommand();
+ if (command == "Play") {
playpause.setIcon(pauseIcon);
+ playpause.setActionCommand("Pause");
playpause.setToolTipText("Pause");
Moosique.play();
- } else if (toolTip == "Pause") {
+ } else if (command == "Pause") {
playpause.setIcon(playIcon);
+ playpause.setActionCommand("Resume");
playpause.setToolTipText("Resume");
Moosique.pause();
- } else if (toolTip == "Resume") {
+ } else if (command == "Resume") {
playpause.setIcon(pauseIcon);
+ playpause.setActionCommand("Pause");
playpause.setToolTipText("Pause");
Moosique.resume();
- } else if (toolTip == "Stop") {
+ } else if (command == "Rewind") {
+ // Different implementation, perhaps?
+ Moosique.setEditPosition(0);
+ Moosique.stop();
+ } else if (command == "Fast forward") {
+
+ } else if (command == "Stop") {
Moosique.stop();
}
} else if (e.getSource() instanceof JLabel) {
private Track track;
private MetaMessage trackNameMessage;
private ShortMessage programChangeMessage;
+ private MooTrackView mtv;
private JTextField title;
private MooInstrumentList instruments;
private JComboBox channelBox;
private JCheckBox mute;
private JCheckBox solo;
+ private JButton record;
private String trackName = "";
private int channel = 0;
// Creates and places components.
setLayout(new GridLayout(4,1));
setBorder(BorderFactory.createLineBorder(Color.black));
+ TitleListener tl = new TitleListener();
setPreferredSize(new Dimension(MooTrackView.VIEW_WIDTH,70));
title = new JTextField(trackName);
channelBox.setSelectedIndex(channel);
- channelBox.addActionListener(new ActionListener(){
- public void actionPerformed(ActionEvent e){
- channel = channelBox.getSelectedIndex();
- MidiEvent me;
- MooNote mn;
- instruments.setChannel(channel);
- for (int j = 0; j < track.size(); j++) {
- me = track.get(j);
- if (me instanceof MooNote){
- mn = (MooNote)me;
- mn.setChannel(channel);
- }
- }}});
+ channelBox.addActionListener(tl);
add(channelBox);
JPanel checkboxes = new JPanel();
mute.setSelected(false);
Moosique.setTrackMute(track, false);
mute.setFont(Moosique.getGUI().FONT);
- mute.addActionListener(new ActionListener(){
- public void actionPerformed(ActionEvent event){
- boolean selected = mute.isSelected();
- if (selected){
- solo.setSelected(false);
- Moosique.setTrackSolo(track, false);
- }
- Moosique.setTrackMute(track, selected);
-
- }});
+ mute.addActionListener(tl);
checkboxes.add(mute);
solo = new JCheckBox("Solo");
solo.setSelected(false);
Moosique.setTrackSolo(track, false);
solo.setFont(Moosique.getGUI().FONT);
- solo.addActionListener(new ActionListener(){
- public void actionPerformed(ActionEvent event){
- //setSolo
- boolean selected = solo.isSelected();
- if (selected){
- mute.setSelected(false);
- Moosique.setTrackMute(track, false);
- }
- Moosique.setTrackSolo(track, selected);
- }});
+ solo.addActionListener(tl);
checkboxes.add(solo);
+
+ record = new JButton("Record");
+ record.setFont(Moosique.getGUI().FONT);
+ record.addActionListener(tl);
+ checkboxes.add(record);
+
add(checkboxes);
}
return channel;
}
+ /**
+ * Sets the track view this title should update after recording.
+ * @param the track view
+ */
+ public void setTrackView(MooTrackView tv) {
+ mtv = tv;
+ }
+
/**
* Checks if the focus is lost.
*/
// Update the MidiEvent containing the title of this track
}
}
+
+ /**
+ * Takes the appropriate action when a user selects an item on the popup menu.
+ */
+ class TitleListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ Object source = e.getSource();
+ if (source == channelBox) {
+ channel = channelBox.getSelectedIndex();
+ MidiEvent me;
+ MooNote mn;
+ instruments.setChannel(channel);
+ // Query the user before rechannelling???
+ for (int j = 0; j < track.size(); j++) {
+ me = track.get(j);
+ if (me instanceof MooNote){
+ mn = (MooNote)me;
+ mn.setChannel(channel);
+ }
+ }
+ } else if (source == solo) {
+ boolean selected = mute.isSelected();
+ if (selected){
+ solo.setSelected(false);
+ Moosique.setTrackSolo(track, false);
+ }
+ Moosique.setTrackMute(track, selected);
+ } else if (source == mute) {
+ boolean selected = solo.isSelected();
+ if (selected){
+ mute.setSelected(false);
+ Moosique.setTrackMute(track, false);
+ }
+ Moosique.setTrackSolo(track, selected);
+ } else if (source == record) {
+ Sequencer sequencer = Moosique.getSequencer();
+ if (record.getText() == "Record") {
+ record.setText("Stop");
+ mtv.enableKeyboardRecording();
+ sequencer.recordEnable(track, channel);
+ sequencer.startRecording();
+ } else {
+ record.setText("Record");
+ mtv.disableKeyboardRecording();
+ sequencer.stopRecording();
+ sequencer.recordDisable(track);
+ mtv.placeNoteElements();
+ }
+ }
+ }
+ }
}
private Track track;
private MooTrackTitle title;
- private Rectangle box;
+ private MooKeyboard keyboard;
private JPopupMenu popup, selPopup;
private JMenu selPopupTranspUp, selPopupTranspDown;
private JMenuItem popupAdd, popupPaste;
- private JMenuItem selPopupCopy, selPopupCut, selPopupRemove, selPopupTranspUpOct, selPopupTranspDownOct;
+ private JMenuItem selPopupCopy, selPopupCut, selPopupRemove;
+ private JMenuItem[] selPopupTranspUpItems, selPopupTranspDownItems;
- private ArrayList coords, copyBuffer;
+ private ArrayList coords;
private TreeSet selection;
private Insets insets;
+ private Rectangle box;
private int ticksPerSixteenth, popupY = 0;
private boolean leftMouseButtonPressed = false;
protected static int viewLength = 0;
*/
public MooTrackView (Track track, MooTrackTitle title) {
super(true);
+
+ // Defines instance variables
this.track = track;
this.title = title;
-
- // Creates instance variables
insets = getInsets();
+
+ // Configures panel
+ setBackground(Color.white);
+ setBorder(BorderFactory.createLineBorder(Color.black));
+ setLayout(null);
+ setPreferredSize(new Dimension(VIEW_WIDTH, 140 * NOTE_HEIGHT));
+
+ placeNoteElements();
+
+ // Creates panel pop-up menu.
+ popup = new JPopupMenu();
+ popupAdd = addMenuItem(popup, "Add note...");
+ popupPaste = addMenuItem(popup, "Paste");
+
+ // Creates selection pop-up menu.
+ selPopup = new JPopupMenu();
+ selPopupCopy = addMenuItem(selPopup, "Copy selection");
+ selPopupCut = addMenuItem(selPopup, "Cut selection");
+ selPopupRemove = addMenuItem(selPopup, "Remove selection");
+ selPopupTranspUpItems = new JMenuItem[12];
+ selPopupTranspDownItems = new JMenuItem[12];
+ selPopupTranspUp = createTransposeMenu(selPopup, selPopupTranspUpItems, "selection up");
+ selPopupTranspDown = createTransposeMenu(selPopup, selPopupTranspDownItems, "selection down");
+
+ // Adds listeners for popup menu and keyboard synthesizer.
+ addMouseListener(new MAdapter());
+ keyboard = new MooKeyboard(title);
+ addKeyListener(keyboard);
+ }
+
+ /**
+ * Creates note elements for all MooNotes in the track, and places them in the appropriate place.
+ */
+ public void placeNoteElements() {
+ // Converts the track.
+ Moosique.convertTrack(track);
+
+ // Empties the container
+ removeAll();
coords = new ArrayList(track.size() / 2);
selection = new TreeSet();
- copyBuffer = new ArrayList();
// Creates temporary variables
MidiEvent note;
MooNoteElement elem;
extraHeight = Toolkit.getDefaultToolkit().getScreenSize().height - 150;
- // Configures panel
- setBackground(Color.white);
- setBorder(BorderFactory.createLineBorder(Color.black));
- setLayout(null);
- setPreferredSize(new Dimension(VIEW_WIDTH, 140 * NOTE_HEIGHT));
-
// Places note elements
for (int i = 0; i < track.size(); i++) {
note = track.get(i);
layoutElement(elem, false);
}
setPreferredSize(new Dimension(VIEW_WIDTH, viewLength + extraHeight));
-
}
-
- // Creates panel pop-up menu.
- popup = new JPopupMenu();
- PopupListener pList = new PopupListener();
- popupAdd = new JMenuItem("Add note...");
- popupAdd.addActionListener(pList);
- popup.add(popupAdd);
- popupPaste = new JMenuItem("Paste");
- popupPaste.addActionListener(pList);
- popup.add(popupPaste);
-
- // Creates selection pop-up menu.
- selPopup = new JPopupMenu();
- selPopupCopy = new JMenuItem("Copy selection");
- selPopupCopy.addActionListener(pList);
- selPopup.add(selPopupCopy);
- selPopupCut = new JMenuItem("Cut selection");
- selPopupCut.addActionListener(pList);
- selPopup.add(selPopupCut);
- selPopupRemove = new JMenuItem("Remove selection");
- selPopupRemove.addActionListener(pList);
- selPopup.add(selPopupRemove);
- selPopupTranspUp = new JMenu("Transpose selection up");
- selPopup.add(selPopupTranspUp);
- selPopupTranspUpOct = new JMenuItem("One octave");
- selPopupTranspUpOct.addActionListener(pList);
- selPopupTranspUp.add(selPopupTranspUpOct);
- selPopupTranspDown = new JMenu("Transpose selection down");
- selPopup.add(selPopupTranspDown);
- selPopupTranspDownOct = new JMenuItem("One octave");
- selPopupTranspDownOct.addActionListener(pList);
- selPopupTranspDown.add(selPopupTranspDownOct);
-
- // Adds listeners for popup menu and keyboard synthesizer.
- addMouseListener(new MAdapter());
- addKeyListener(new MooKeyboard());
- }
+ }
/**
* Layouts the element to the right place.
* Copies the current selection.
*/
public void copySelectedNotes() {
- copyBuffer = new ArrayList(selection.size());
+ ArrayList copyBuffer = new ArrayList(selection.size());
Iterator it = selection.iterator();
while(it.hasNext()) {
copyBuffer.add(((MooNoteElement)it.next()).getNote().clone());
}
Collections.sort(copyBuffer);
+ Moosique.setCopyBuffer(copyBuffer);
}
/**
public void pasteCopiedNotes() {
int row = (popupY - insets.top) / NOTE_HEIGHT;
long timestamp = (long)(ticksPerSixteenth * row);
+ ArrayList copyBuffer = Moosique.getCopyBuffer();
if (copyBuffer.size() > 0) {
long startTime = ((MooNote)copyBuffer.get(0)).getTick();
Iterator it = copyBuffer.iterator();
while(it.hasNext()) {
MooNote mn = (MooNote)((MooNote)it.next()).clone();
mn.setTick(mn.getTick() - startTime + timestamp);
+ mn.setChannel(title.getChannel());
addNote(mn);
}
}
* @param ticks the number of ticks to move the selection.
*/
public void moveSelectedNotes(int ticks) {
- if (ticks > 0) {
- // If the selection should be moved downwards, traverses the list in the natural order.
+ if (ticks < 0) {
+ // If the selection should be moved upwards, traverses the list in the natural order.
Iterator it = selection.iterator();
while(it.hasNext()) {
MooNoteElement elem = (MooNoteElement)it.next();
layoutElement(elem, true);
}
} else {
- // If the selection should be moved upwards, traverses the list in the opposite order.
+ // If the selection should be moved downwards, traverses the list in the opposite order.
ArrayList selectedList = new ArrayList(selection);
ListIterator it = selectedList.listIterator(selectedList.size());
while(it.hasPrevious()) {
moveSelectedNotes(ticksPerSixteenth * (y / NOTE_HEIGHT));
}
+ /**
+ * Enables keyboard recording.
+ */
+ public void enableKeyboardRecording() {
+ keyboard.recordEnable();
+ }
+
+ /**
+ * Disables keyboard recording.
+ */
+ public void disableKeyboardRecording() {
+ keyboard.recordDisable();
+ }
+
+ /**
+ * Adds a menu item with the given command to the given popup menu.
+ */
+ private JMenuItem addMenuItem(JPopupMenu menu, String command) {
+ JMenuItem item = new JMenuItem(command);
+ item.addActionListener(new PopupListener());
+ menu.add(item);
+ return item;
+ }
+
+ /**
+ * Adds a menu item with the given command to the given menu.
+ */
+ private JMenuItem addMenuItem(JMenu menu, String command) {
+ JMenuItem item = new JMenuItem(command);
+ item.addActionListener(new PopupListener());
+ menu.add(item);
+ return item;
+ }
+
+ /**
+ * Creates a transpose sub menu with the given title in the given popup menu,
+ * inserting the items into the given array.
+ */
+ private JMenu createTransposeMenu(JPopupMenu menu, JMenuItem[] items, String title) {
+ JMenu trans = new JMenu("Transpose " + title);
+ menu.add(trans);
+ items[0] = addMenuItem(trans, "One octave");
+ for (int i = 1; i < 12; i++) {
+ items[i] = addMenuItem(trans, (i) + " halftones");
+ }
+ return trans;
+ }
+
/**
* Shows a popup-menu with options for the current selection of note elements.
* @param c the component over which to display the menu
}
/**
- * Listens on actions on the popup menu and executes the appropriate action.
+ * Takes the appropriate action when a user selects an item on the popup menu.
*/
class PopupListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
cutSelectedNotes();
} else if (source == selPopupRemove) {
removeSelectedNotes();
- } else if (source == selPopupTranspUpOct) {
+ } else if (source == selPopupTranspUpItems[0]) {
transposeSelectedNotes(12);
- } else if (source == selPopupTranspDownOct) {
+ } else if (source == selPopupTranspDownItems[0]) {
transposeSelectedNotes(-12);
+ } else {
+ for (int i = 1; i < 12; i++) {
+ if (source == selPopupTranspUpItems[i]) transposeSelectedNotes(i);
+ else if (source == selPopupTranspDownItems[i]) transposeSelectedNotes(-i);
+ }
}
}
}
trackPanel.setLayout(new FlowLayout());
MooTrackTitle title = new MooTrackTitle(tracks[0]);
titlePanel.add(title);
- trackPanel.add(new MooTrackView(tracks[0], title));
+ MooTrackView mtv = new MooTrackView(tracks[0], title);
+ trackPanel.add(mtv);
+ title.setTrackView(mtv);
} else {
if (showProgress) {
// Creates dialog for progress bar.
if (Moosique.shouldBeDrawn(tracks[i])) {
MooTrackTitle title = new MooTrackTitle(tracks[i]);
titlePanel.add(title);
- trackPanel.add(new MooTrackView(tracks[i], title));
+ MooTrackView mtv = new MooTrackView(tracks[i], title);
+ trackPanel.add(mtv);
+ title.setTrackView(mtv);
if (showProgress) progressBar.setValue(i);
else System.out.print(".");
} else {
private static MidiChannel activeChannel;
private static MidiEvent[] timeSignatures, tempoChanges;
- private static ArrayList emptyTracks;
+ private static ArrayList copyBuffer, emptyTracks;
private static Map trackMute = new HashMap();
private static Map trackSolo = new HashMap();
private static Thread player;
return channels;
}
+ /**
+ * Returns the current copy buffer.
+ * @return the current copy buffer
+ */
+ public static ArrayList getCopyBuffer() {
+ return copyBuffer;
+ }
+
/**
* Returns the current editing position of the sequencer.
* @return the tick position
activeChannel = channels[channel];
}
+ /**
+ * Sets the current copy buffer.
+ * @param the copy buffer
+ */
+ public static void setCopyBuffer(ArrayList buffer) {
+ copyBuffer = buffer;
+ }
+
/**
* Sets whether empty tracks should be drawn
* @param state true if empty tracks should be drawn
emptyTracks = new ArrayList();
trackSolo = new HashMap();
trackMute = new HashMap();
+ copyBuffer = new ArrayList();
} catch (InvalidMidiDataException e) {}
// Sends sequence to GUI.
if (gui != null) gui.setSequence(seq);
}
+
+ /**
+ * Wraps each NoteOn event in the track with its NoteOff event in a MooNote.
+ */
+ public static void convertTrack(Track track) {
+ // Searches the track for NoteOn and NoteOff events
+ ArrayList noteOns = new ArrayList(track.size() / 2);
+ ArrayList noteOffs = new ArrayList(track.size() / 2);
+ MidiEvent event;
+ for (int j = 0; j < track.size(); j++) {
+ event = track.get(j);
+ if (event.getMessage().getStatus() >= 144 &&
+ event.getMessage().getStatus() < 160) noteOns.add(event);
+ if (event.getMessage().getStatus() >= 128 &&
+ event.getMessage().getStatus() < 144) noteOffs.add(event);
+ }
+ noteOns.trimToSize();
+ noteOffs.trimToSize();
+ if (noteOns.size() == 0) emptyTracks.add(track);
+
+ // Sorts the note lists by tick position.
+ Comparator c = new MidiEventComparator();
+ Collections.sort(noteOns, c);
+ Collections.sort(noteOffs, c);
+
+ // Replaces each NoteOn event it with a MooNote containing a reference to the NoteOff event.
+ Iterator iOn = noteOns.iterator(), iOff;
+ MidiEvent on, off = null, nextOff;
+ ShortMessage onMsg, nextOffMsg;
+ while(iOn.hasNext()) {
+ on = (MidiEvent)iOn.next();
+ onMsg = (ShortMessage)on.getMessage();
+ iOff = noteOffs.iterator();
+ while(iOff.hasNext()) {
+ nextOff = (MidiEvent)iOff.next();
+ nextOffMsg = (ShortMessage)nextOff.getMessage();
+ if(onMsg.getChannel() == nextOffMsg.getChannel() &&
+ onMsg.getData1() == nextOffMsg.getData1() &&
+ c.compare(nextOff, on) > 0) {
+ off = nextOff;
+ iOff.remove();
+ break;
+ }
+
+ }
+ track.remove(on);
+ if (off != null) {
+ track.add(new MooNote(on, off));
+ } else {
+ track.add(new MooNote(on, new MidiEvent((ShortMessage)on.getMessage().clone(), on.getTick() + 48)));
+ }
+ iOn.remove();
+ }
+ }
/**
* Loads a MIDI sequence from the given file.
emptyTracks = new ArrayList();
trackMute = new HashMap();
trackSolo = new HashMap();
+ copyBuffer = new ArrayList();
// Searches track 0 for changes in tempo and time signature.
MidiEvent event;
// timeSignatures = ts.toArray(timeSignatures);
// tempoChanges = tc.toArray(tempoChanges);
- // Wraps each NoteOn event with its NoteOff event in a MooNote
- ArrayList noteOns, noteOffs;
+ // Converts tracks.
for (int i = 0; i < tracks.length; i++) {
- // Searches the sequence for NoteOn and NoteOff events
- noteOns = new ArrayList(tracks[i].size() / 2);
- noteOffs = new ArrayList(tracks[i].size() / 2);
- for (int j = 0; j < tracks[i].size(); j++) {
- event = tracks[i].get(j);
- if (event.getMessage().getStatus() >= 144 &&
- event.getMessage().getStatus() < 160) noteOns.add(event);
- if (event.getMessage().getStatus() >= 128 &&
- event.getMessage().getStatus() < 144) noteOffs.add(event);
- }
- noteOns.trimToSize();
- noteOffs.trimToSize();
- if (noteOns.size() == 0) emptyTracks.add(tracks[i]);
-
- // Sorts the note lists by tick position.
- Comparator c = new MidiEventComparator();
- Collections.sort(noteOns, c);
- Collections.sort(noteOffs, c);
-
- // Replaces each NoteOn event it with a MooNote containing a reference to the NoteOff event.
- Iterator iOn = noteOns.iterator(), iOff;
- MidiEvent on, off = null, nextOff;
- ShortMessage onMsg, nextOffMsg;
- while(iOn.hasNext()) {
- on = (MidiEvent)iOn.next();
- onMsg = (ShortMessage)on.getMessage();
- iOff = noteOffs.iterator();
- while(iOff.hasNext()) {
- nextOff = (MidiEvent)iOff.next();
- nextOffMsg = (ShortMessage)nextOff.getMessage();
- if(onMsg.getChannel() == nextOffMsg.getChannel() &&
- onMsg.getData1() == nextOffMsg.getData1() &&
- c.compare(nextOff, on) > 0) {
- off = nextOff;
- iOff.remove();
- break;
- }
-
- }
- tracks[i].remove(on);
- if (off != null) {
- tracks[i].add(new MooNote(on, off));
- } else {
- tracks[i].add(new MooNote(on, new MidiEvent((ShortMessage)on.getMessage().clone(), on.getTick() + 48)));
- }
- iOn.remove();
- }
+ convertTrack(tracks[i]);
}
// Sends sequence to GUI and sequencer, then returns
if (gui != null) gui.setSequence(seq);
\f
-jar cmf manif Moosique.jar *.class
+jar cmf manif Moosique.jar *.class *.java midi\*.mid images\*.gif Manual.txt
manif: Main-Class: Moosique
\f
IO
x Implementera ljudlös körning med -m.
x Lägg till alla metameddelanden i filerna vi skapar. Annars är det lite dumt.
-x Play hänger sig om man ändrar duration på en not.. \f
+x Play hänger sig om man ändrar duration på en not.
x Spara konfiguration?
Arbetskatalog
Fem senast öppnade filerna
Valda MIDI-enheter
-x Inspelning!
TEMPO / TAKTART
x Räkna ut tempo och taktart. Skicka (på nåt sätt) tempovektorn till MooToolbar.