]> ruin.nu Git - moosique.git/commitdiff
Fixed recording!!!
authorEinar Pehrson <einarp@itstud.chalmers.se>
Mon, 19 May 2003 23:51:27 +0000 (23:51 +0000)
committerEinar Pehrson <einarp@itstud.chalmers.se>
Mon, 19 May 2003 23:51:27 +0000 (23:51 +0000)
..plus nested transpose popup menus and note-play on double-click etc.

MooKeyboard.java
MooNote.java
MooNoteElement.java
MooToolbar.java
MooTrackTitle.java
MooTrackView.java
MooView.java
Moosique.java
To Do.txt

index ef4785e67c5081e343983c06d411800dab2e1d1c..29ffeecd6207ea2b5ac1348178478528ca4c4a65 100644 (file)
@@ -9,14 +9,17 @@ import java.awt.event.*;
  
 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];
        }
 
@@ -34,9 +37,17 @@ public class MooKeyboard extends KeyAdapter {
                                // 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;
                        }
                }
@@ -51,16 +62,36 @@ public class MooKeyboard extends KeyAdapter {
                                // 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) {
@@ -69,7 +100,7 @@ public class MooKeyboard extends KeyAdapter {
        }
 
        /**
-        * 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) {
index fb73341e327f969ff51a50c23fbc5387d9f36b2b..57cf86c8529c9fef5ce0e59726b6c944f83ebc04 100644 (file)
@@ -44,6 +44,46 @@ public class MooNote extends MidiEvent implements Cloneable, Comparable {
                } 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)
@@ -102,38 +142,6 @@ public class MooNote extends MidiEvent implements Cloneable, Comparable {
                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.
@@ -167,7 +175,6 @@ public class MooNote extends MidiEvent implements Cloneable, Comparable {
         * @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());
        }
-
 }
index 60808898339361e3b70a53b21b6ac03c325713d7..beed5c416acb498a25a95ff46291e419d3733ddd 100644 (file)
@@ -14,7 +14,9 @@ public class MooNoteElement extends JPanel implements Comparable{
        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;
@@ -42,19 +44,12 @@ public class MooNoteElement extends JPanel implements Comparable{
 
                // 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");
        }
 
        /** 
@@ -178,11 +173,53 @@ public class MooNoteElement extends JPanel implements Comparable{
                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.
                 */
@@ -198,6 +235,7 @@ public class MooNoteElement extends JPanel implements Comparable{
                 */
                public void mouseExited(MouseEvent e) {
                        mouseIn = false;
+                       Moosique.getReceiver().send(note.getNoteOffEvent().getMessage(), -1);
                }
 
                /**
@@ -229,7 +267,6 @@ public class MooNoteElement extends JPanel implements Comparable{
                                }
                        } else {
                                select();
-                               // Play the note
                                maybeShowPopup(e);
                        }
                }
@@ -257,7 +294,7 @@ public class MooNoteElement extends JPanel implements Comparable{
        }
 
        /**
-        * 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) {
@@ -267,13 +304,18 @@ public class MooNoteElement extends JPanel implements Comparable{
                                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);
+                               }
                        }
                }
        }
index 50aaf4dafbfae93daf83e778a0a357d9a49ebfbb..1ea47ab08f5e3af9becb759089bc58889cdda5ef 100644 (file)
@@ -102,11 +102,12 @@ public class MooToolbar extends JToolBar {
        }
 
        /**
-        * 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;
        }
@@ -133,20 +134,29 @@ public class MooToolbar extends JToolBar {
        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) {
index 979aed2139208e234f4124871b34b955fe536aef..6c629d90522651f4743fa765e1fb114b9083dc98 100644 (file)
@@ -15,12 +15,14 @@ public class MooTrackTitle extends JPanel {
        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;
@@ -63,6 +65,7 @@ public class MooTrackTitle extends JPanel {
                // 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);
@@ -84,19 +87,7 @@ public class MooTrackTitle extends JPanel {
 
                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();
@@ -106,33 +97,21 @@ public class MooTrackTitle extends 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);
        }
        
@@ -144,6 +123,14 @@ public class MooTrackTitle extends JPanel {
                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.
         */
@@ -152,4 +139,55 @@ public class MooTrackTitle extends JPanel {
                        // 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();
+                               }
+                       }
+               }
+       }
 }
index c1d8b5878cdb66b4f4b0d1ceef38a3f62c499f83..f7e8335bf365748478972feff97c7ce4fb879f53 100644 (file)
@@ -15,16 +15,18 @@ public class MooTrackView extends JPanel {
 
        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;
@@ -38,26 +40,58 @@ public class MooTrackView extends JPanel {
         */
        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);
@@ -69,45 +103,8 @@ public class MooTrackView extends JPanel {
                                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.
@@ -264,12 +261,13 @@ public class MooTrackView extends JPanel {
         * 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);
        }
 
        /**
@@ -286,12 +284,14 @@ public class MooTrackView extends JPanel {
        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);
                        }
                }
@@ -324,8 +324,8 @@ public class MooTrackView extends JPanel {
         * @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();
@@ -333,7 +333,7 @@ public class MooTrackView extends JPanel {
                                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()) {
@@ -352,6 +352,54 @@ public class MooTrackView extends JPanel {
                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
@@ -434,7 +482,7 @@ public class MooTrackView extends JPanel {
        }
 
        /**
-        * 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) {
@@ -451,10 +499,15 @@ public class MooTrackView extends JPanel {
                                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);
+                               }
                        }
                }
        }
index c97a4a46239b745124a0cdbafe8a023121879c2b..a5ebf903d95a35537e84c409329cbbe95a27b4eb 100644 (file)
@@ -60,7 +60,9 @@ public class MooView extends JScrollPane {
                        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.
@@ -85,7 +87,9 @@ public class MooView extends JScrollPane {
                                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 {
index 8de399fc3f2f11c884a4cffd4a5facd4144a756c..9089a2fc7c722234f3f29fedf7f57b73f217297d 100644 (file)
@@ -22,7 +22,7 @@ public class Moosique {
        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;
@@ -141,6 +141,14 @@ public class Moosique {
                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
@@ -290,6 +298,14 @@ public class Moosique {
                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
@@ -466,10 +482,65 @@ public class Moosique {
                        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.
@@ -491,6 +562,7 @@ public class Moosique {
                emptyTracks = new ArrayList();
                trackMute = new HashMap();
                trackSolo = new HashMap();
+               copyBuffer = new ArrayList();
 
                // Searches track 0 for changes in tempo and time signature.
                MidiEvent event;
@@ -509,56 +581,9 @@ public class Moosique {
                // 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);
index 321bd186d2e55c1e1b2f099d06aebc8e3d9189c0..f53632ac97fb4d38fcb9d6898ed40e3f51e0e4f7 100644 (file)
--- a/To Do.txt
+++ b/To Do.txt
@@ -1,6 +1,6 @@
 
 \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
@@ -23,12 +23,11 @@ Kopiera/flytta sp
 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.