Commit 278cdee04a1413adc98d137837b0f5303da7f7b2

Authored by pfrison
1 parent a89c030d

VRGNYMusicLights timeline beginning

VRGNYMusicLights/Sources/AnimationPlayer.java
@@ -10,8 +10,7 @@ import javax.swing.JPanel; @@ -10,8 +10,7 @@ import javax.swing.JPanel;
10 public class AnimationPlayer extends JPanel implements ActionListener { 10 public class AnimationPlayer extends JPanel implements ActionListener {
11 private static final long serialVersionUID = 1L; 11 private static final long serialVersionUID = 1L;
12 12
13 - private LightCanvasJPanel lightCanvas;  
14 - private MusicList musicList; 13 + private Interface interf;
15 14
16 private JButton backward; 15 private JButton backward;
17 private JButton stop; 16 private JButton stop;
@@ -19,10 +18,9 @@ public class AnimationPlayer extends JPanel implements ActionListener { @@ -19,10 +18,9 @@ public class AnimationPlayer extends JPanel implements ActionListener {
19 private JButton pause; 18 private JButton pause;
20 private JButton forward; 19 private JButton forward;
21 20
22 - private long tick = 0;  
23 private boolean go = false; 21 private boolean go = false;
24 private boolean stopClock = false; 22 private boolean stopClock = false;
25 - private static final int TICK_JUMP = 20; 23 + private static final int TICK_JUMP = 10;
26 private Thread tickClock = new Thread(new Runnable() { 24 private Thread tickClock = new Thread(new Runnable() {
27 @Override 25 @Override
28 public void run() { 26 public void run() {
@@ -34,25 +32,24 @@ public class AnimationPlayer extends JPanel implements ActionListener { @@ -34,25 +32,24 @@ public class AnimationPlayer extends JPanel implements ActionListener {
34 } 32 }
35 33
36 long before = System.currentTimeMillis(); 34 long before = System.currentTimeMillis();
37 - lightCanvas.paintLights(musicList.render(tick));  
38 - tick += TICK_JUMP; 35 + interf.computeTick();
  36 + interf.tick += TICK_JUMP;
39 long after = System.currentTimeMillis(); 37 long after = System.currentTimeMillis();
40 38
41 if(after - before < TICK_JUMP) { 39 if(after - before < TICK_JUMP) {
42 - try { Thread.sleep(10 - after + before);} 40 + try { Thread.sleep(TICK_JUMP - after + before);}
43 catch (InterruptedException ignored) {} 41 catch (InterruptedException ignored) {}
44 } else if(after - before > TICK_JUMP) { 42 } else if(after - before > TICK_JUMP) {
45 - System.err.println("Animation were slowed down by " + String.valueOf(after - before - 10) + " ticks !"); 43 + System.err.println("Animation were slowed down by " + String.valueOf(after - before - TICK_JUMP) + " ticks !");
46 } 44 }
47 } 45 }
48 } 46 }
49 }); 47 });
50 public void stopTickClock() {stopClock = true;} 48 public void stopTickClock() {stopClock = true;}
51 49
52 - public AnimationPlayer(LightCanvasJPanel lightCanvas, MusicList musicList) { this(lightCanvas, musicList, BoxLayout.LINE_AXIS); }  
53 - public AnimationPlayer(LightCanvasJPanel lightCanvas, MusicList musicList, int direction) {  
54 - this.lightCanvas = lightCanvas;  
55 - this.musicList = musicList; 50 + public AnimationPlayer(Interface interf) { this(interf, BoxLayout.LINE_AXIS); }
  51 + public AnimationPlayer(Interface interf, int direction) {
  52 + this.interf = interf;
56 53
57 setLayout(new BoxLayout(this, direction)); 54 setLayout(new BoxLayout(this, direction));
58 55
@@ -90,20 +87,22 @@ public class AnimationPlayer extends JPanel implements ActionListener { @@ -90,20 +87,22 @@ public class AnimationPlayer extends JPanel implements ActionListener {
90 87
91 @Override 88 @Override
92 public void actionPerformed(ActionEvent e) { 89 public void actionPerformed(ActionEvent e) {
93 - // TODO player actions  
94 if(e.getSource() == backward) { 90 if(e.getSource() == backward) {
95 - tick -= 500;  
96 - if(tick < 0)  
97 - tick = 0; 91 + interf.tick -= 100;
  92 + if(interf.tick < 0)
  93 + interf.tick = 0;
  94 + interf.computeTick();
98 }else if(e.getSource() == stop) { 95 }else if(e.getSource() == stop) {
99 go = false; 96 go = false;
100 - tick = 0; 97 + interf.tick = 0;
  98 + interf.computeTick();
101 }else if(e.getSource() == play) { 99 }else if(e.getSource() == play) {
102 go = true; 100 go = true;
103 }else if(e.getSource() == pause) { 101 }else if(e.getSource() == pause) {
104 go = false; 102 go = false;
105 }else if(e.getSource() == forward) { 103 }else if(e.getSource() == forward) {
106 - tick += 500; 104 + interf.tick += 100;
  105 + interf.computeTick();
107 } 106 }
108 } 107 }
109 } 108 }
VRGNYMusicLights/Sources/Interface.java
1 import java.awt.BorderLayout; 1 import java.awt.BorderLayout;
2 -import java.awt.Font;  
3 import java.awt.event.WindowAdapter; 2 import java.awt.event.WindowAdapter;
4 import java.awt.event.WindowEvent; 3 import java.awt.event.WindowEvent;
5 4
6 import javax.swing.JFrame; 5 import javax.swing.JFrame;
7 -import javax.swing.JLabel;  
8 import javax.swing.JPanel; 6 import javax.swing.JPanel;
9 7
10 public class Interface extends JFrame{ 8 public class Interface extends JFrame{
11 private static final long serialVersionUID = 1L; 9 private static final long serialVersionUID = 1L;
12 - private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14);  
13 - private static final Font defaultFont = new Font(new JLabel().getFont().getName(), Font.PLAIN, new JLabel().getFont().getSize()); 10 + //private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14);
  11 + //private static final Font defaultFont = new Font(new JLabel().getFont().getName(), Font.PLAIN, new JLabel().getFont().getSize());
14 12
15 - private MusicList musicList;  
16 - private AnimationPlayer animPlayer; 13 + protected MusicList musicList;
  14 + protected AnimationPlayer animPlayer;
  15 + protected TimeLineJPanel timeLinePanel;
  16 + protected TimeLineJList timeLineList;
  17 + protected LightCanvasJPanel lightCanvas;
  18 + protected long tick = 0;
17 19
18 public Interface(MusicList musicList, final Runnable executeOnClose) { 20 public Interface(MusicList musicList, final Runnable executeOnClose) {
19 super("VRGNYMusicLights"); 21 super("VRGNYMusicLights");
@@ -22,6 +24,7 @@ public class Interface extends JFrame{ @@ -22,6 +24,7 @@ public class Interface extends JFrame{
22 populateWindow(); 24 populateWindow();
23 pack(); 25 pack();
24 setLocationRelativeTo(null); // center window 26 setLocationRelativeTo(null); // center window
  27 + getContentPane().requestFocus();
25 28
26 addWindowListener(new WindowAdapter() { 29 addWindowListener(new WindowAdapter() {
27 @Override 30 @Override
@@ -35,34 +38,18 @@ public class Interface extends JFrame{ @@ -35,34 +38,18 @@ public class Interface extends JFrame{
35 }); 38 });
36 } 39 }
37 40
  41 + protected void computeTick() {
  42 + lightCanvas.paintLights(musicList.render(tick));
  43 + timeLineList.repaint();
  44 + timeLinePanel.updateTick();
  45 + }
  46 +
38 private void populateWindow() { 47 private void populateWindow() {
39 JPanel mainPanel = new JPanel(new BorderLayout()); 48 JPanel mainPanel = new JPanel(new BorderLayout());
40 - addPlayPanel(mainPanel);  
41 - addTimeLine(mainPanel); 49 + timeLinePanel = new TimeLineJPanel(this, musicList);
  50 + mainPanel.add(timeLinePanel, BorderLayout.CENTER);
  51 + lightCanvas = new LightCanvasJPanel();
  52 + mainPanel.add(new PlayJPanel(this, lightCanvas), BorderLayout.SOUTH);
42 add(mainPanel); 53 add(mainPanel);
43 } 54 }
44 -  
45 - private void addPlayPanel(JPanel parent) {  
46 - JPanel playPanel = new JPanel(new BorderLayout());  
47 -  
48 - // title  
49 - JLabel title = new JLabel("Visualizer :");  
50 - title.setFont(titleFont);  
51 - playPanel.add(title, BorderLayout.NORTH);  
52 -  
53 - // lights  
54 - LightCanvasJPanel lightCanvas = new LightCanvasJPanel();  
55 - playPanel.add(lightCanvas, BorderLayout.CENTER);  
56 -  
57 - // controls  
58 - animPlayer = new AnimationPlayer(lightCanvas, musicList);  
59 - animPlayer.setAlignmentX(CENTER_ALIGNMENT);  
60 - playPanel.add(animPlayer, BorderLayout.SOUTH);  
61 -  
62 - parent.add(playPanel, BorderLayout.SOUTH);  
63 - }  
64 -  
65 - private void addTimeLine(JPanel parent) {  
66 - JPanel timeLine = new JPanel();  
67 - }  
68 } 55 }
VRGNYMusicLights/Sources/InvalidPatternException.java
@@ -3,6 +3,6 @@ public class InvalidPatternException extends RuntimeException { @@ -3,6 +3,6 @@ public class InvalidPatternException extends RuntimeException {
3 private static final long serialVersionUID = 1L; 3 private static final long serialVersionUID = 1L;
4 4
5 public InvalidPatternException() { 5 public InvalidPatternException() {
6 - super("Invalid pattern given. Length must be equal to 4."); 6 + super("Invalid pattern given. Length must be equal to 5.");
7 } 7 }
8 } 8 }
VRGNYMusicLights/Sources/Main.java
@@ -2,6 +2,7 @@ import javax.swing.JOptionPane; @@ -2,6 +2,7 @@ import javax.swing.JOptionPane;
2 2
3 /* TODO list : 3 /* TODO list :
4 * - keyboard listener for animation player (play / pause = space, forward = semicolon, backward = comma, stop = backspace) 4 * - keyboard listener for animation player (play / pause = space, forward = semicolon, backward = comma, stop = backspace)
  5 + * - pattern timeline info to follow scroll horizontal ?
5 */ 6 */
6 public class Main { 7 public class Main {
7 public static void main(String[] args) throws InterruptedException { 8 public static void main(String[] args) throws InterruptedException {
@@ -22,8 +23,13 @@ public class Main { @@ -22,8 +23,13 @@ public class Main {
22 MusicList musicList = new MusicList(null); 23 MusicList musicList = new MusicList(null);
23 musicList.addMusic( 24 musicList.addMusic(
24 new Music( 25 new Music(
25 - new MusicPattern(new int[] {1000, 0, 0, 1000}, 1000, 0),  
26 - new MusicPath(MusicPath.CENTER_IN, 1000), 26 + new MusicPattern(new int[] {0, 10, 100, 10, 100}, 100, 1000),
  27 + new MusicPath(MusicPath.CENTER_OUT, 1000),
  28 + 1));
  29 + musicList.addMusic(
  30 + new Music(
  31 + new MusicPattern(new int[] {0, 10, 100, 10, 100}, 1, 0),
  32 + new MusicPath(MusicPath.CENTER_OUT, 1000),
27 1)); 33 1));
28 34
29 Interface i = new Interface(musicList, new Runnable() { 35 Interface i = new Interface(musicList, new Runnable() {
VRGNYMusicLights/Sources/Music.java
@@ -10,6 +10,8 @@ public class Music { @@ -10,6 +10,8 @@ public class Music {
10 this.volume = volume; 10 this.volume = volume;
11 } 11 }
12 12
  13 + public MusicPattern getMusicPattern() { return pattern; }
  14 +
13 public double[] render(long tick) { 15 public double[] render(long tick) {
14 double[] lights = new double[lightTickDelais.length]; 16 double[] lights = new double[lightTickDelais.length];
15 for(int i=0; i<lights.length; i++) 17 for(int i=0; i<lights.length; i++)
VRGNYMusicLights/Sources/MusicList.java
@@ -9,6 +9,7 @@ public class MusicList { @@ -9,6 +9,7 @@ public class MusicList {
9 musics = new ArrayList<>(); 9 musics = new ArrayList<>();
10 } 10 }
11 11
  12 + public ArrayList<Music> getList() { return musics; }
12 public void addMusic(Music music) { musics.add(music); } 13 public void addMusic(Music music) { musics.add(music); }
13 public void deleteMusic(int index) { musics.remove(index); } 14 public void deleteMusic(int index) { musics.remove(index); }
14 15
VRGNYMusicLights/Sources/MusicPath.java
@@ -75,34 +75,34 @@ public class MusicPath { @@ -75,34 +75,34 @@ public class MusicPath {
75 || animation == CENTER_IN) { 75 || animation == CENTER_IN) {
76 switch (animation) { 76 switch (animation) {
77 case VERTICAL_DOWN: 77 case VERTICAL_DOWN:
78 - ticksDelais[i] += tickLateVerticalDown(LIGHT_COORDS[i][1]); 78 + ticksDelais[i] -= tickLateVerticalDown(LIGHT_COORDS[i][1]);
79 break; 79 break;
80 case VERTICAL_UP: 80 case VERTICAL_UP:
81 - ticksDelais[i] += tickLateVerticalUp(LIGHT_COORDS[i][1]); 81 + ticksDelais[i] -= tickLateVerticalUp(LIGHT_COORDS[i][1]);
82 break; 82 break;
83 case HORIZONTAL_TO_LEFT: 83 case HORIZONTAL_TO_LEFT:
84 - ticksDelais[i] += tickLateHorizontalToLeft(LIGHT_COORDS[i][0]); 84 + ticksDelais[i] -= tickLateHorizontalToLeft(LIGHT_COORDS[i][0]);
85 break; 85 break;
86 case HORIZONTAL_TO_RIGHT: 86 case HORIZONTAL_TO_RIGHT:
87 - ticksDelais[i] += tickLateHorizontalToRight(LIGHT_COORDS[i][0]); 87 + ticksDelais[i] -= tickLateHorizontalToRight(LIGHT_COORDS[i][0]);
88 break; 88 break;
89 case DIAGONAL_TOP_RIGHT_DOWN_LEFT: 89 case DIAGONAL_TOP_RIGHT_DOWN_LEFT:
90 - ticksDelais[i] += tickLateDiagTRDL(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]); 90 + ticksDelais[i] -= tickLateDiagTRDL(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
91 break; 91 break;
92 case DIAGONAL_DOWN_LEFT_TOP_RIGHT: 92 case DIAGONAL_DOWN_LEFT_TOP_RIGHT:
93 - ticksDelais[i] += tickLateDiagDLTR(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]); 93 + ticksDelais[i] -= tickLateDiagDLTR(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
94 break; 94 break;
95 case DIAGONAL_TOP_LEFT_DOWN_RIGHT: 95 case DIAGONAL_TOP_LEFT_DOWN_RIGHT:
96 - ticksDelais[i] += tickLateDiagTLDR(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]); 96 + ticksDelais[i] -= tickLateDiagTLDR(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
97 break; 97 break;
98 case DIAGONAL_DOWN_RIGHT_TOP_LEFT: 98 case DIAGONAL_DOWN_RIGHT_TOP_LEFT:
99 - ticksDelais[i] += tickLateDiagDRTL(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]); 99 + ticksDelais[i] -= tickLateDiagDRTL(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
100 break; 100 break;
101 case CENTER_OUT: 101 case CENTER_OUT:
102 - ticksDelais[i] += tickLateCenterOut(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]); 102 + ticksDelais[i] -= tickLateCenterOut(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
103 break; 103 break;
104 case CENTER_IN: 104 case CENTER_IN:
105 - ticksDelais[i] += tickLateCenterIn(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]); 105 + ticksDelais[i] -= tickLateCenterIn(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
106 break; 106 break;
107 } 107 }
108 } 108 }
@@ -111,16 +111,16 @@ public class MusicPath { @@ -111,16 +111,16 @@ public class MusicPath {
111 return ticksDelais; 111 return ticksDelais;
112 } 112 }
113 113
114 - private int tickLateVerticalDown(double y) {return (int) ((1-y) * effectDuration);}  
115 - private int tickLateVerticalUp(double y) {return (int) (y * effectDuration);}  
116 - private int tickLateHorizontalToRight(double x) {return (int) ((1-x) * effectDuration);}  
117 - private int tickLateHorizontalToLeft(double x) {return (int) (x * effectDuration);}  
118 - private int tickLateDiagTRDL(double x, double y) {return (int) ((x - y) / 2d * (double) effectDuration);}  
119 - private int tickLateDiagDLTR(double x, double y) {return (int) ((-x + y) / 2d * (double) effectDuration);}  
120 - private int tickLateDiagDRTL(double x, double y) {return (int) ((x + y) / 2d * (double) effectDuration);}  
121 - private int tickLateDiagTLDR(double x, double y) {return (int) ((-x - y) / 2d * (double) effectDuration);}  
122 - private int tickLateCenterOut(double x, double y) {return (int) ((1 - (x-0.5)*(x-0.5) - (y-0.5)*(y-0.5)) * 2 * (double) effectDuration);}  
123 - private int tickLateCenterIn(double x, double y) {return (int) (((x-0.5)*(x-0.5) + (y-0.5)*(y-0.5)) * 2 * (double) effectDuration);} 114 + private int tickLateVerticalDown(double y) {return (int) (y * effectDuration);}
  115 + private int tickLateVerticalUp(double y) {return (int) ((1-y) * effectDuration);}
  116 + private int tickLateHorizontalToRight(double x) {return (int) (x * effectDuration);}
  117 + private int tickLateHorizontalToLeft(double x) {return (int) ((1 - x) * effectDuration);}
  118 + private int tickLateDiagTRDL(double x, double y) {return (int) ((1 - x + y) / 2d * (double) effectDuration);}
  119 + private int tickLateDiagDLTR(double x, double y) {return (int) ((1 + x - y) / 2d * (double) effectDuration);}
  120 + private int tickLateDiagTLDR(double x, double y) {return (int) ((x + y) / 2d * (double) effectDuration);}
  121 + private int tickLateDiagDRTL(double x, double y) {return (int) ((2 - x - y) / 2d * (double) effectDuration);}
  122 + private int tickLateCenterOut(double x, double y) {return (int) (((x-0.5)*(x-0.5) + (y-0.5)*(y-0.5)) * 2 * (double) effectDuration);}
  123 + private int tickLateCenterIn(double x, double y) {return (int) ((0.5d - (x-0.5)*(x-0.5) - (y-0.5)*(y-0.5)) * 2 * (double) effectDuration);}
124 124
125 public int getNumberOfLights() { 125 public int getNumberOfLights() {
126 return this.lightsCoords.length; 126 return this.lightsCoords.length;
VRGNYMusicLights/Sources/MusicPattern.java
@@ -5,37 +5,48 @@ public class MusicPattern { @@ -5,37 +5,48 @@ public class MusicPattern {
5 * 1 : rise time 5 * 1 : rise time
6 * 2 : high time 6 * 2 : high time
7 * 3 : fall time 7 * 3 : fall time
  8 + * 4 : low time
8 */ 9 */
9 private int[] pattern; // in ms 10 private int[] pattern; // in ms
10 - private int totalLentgh;  
11 - private int[] patternTiming = new int[4]; // in ms 11 + private int totalLength;
  12 + private int[] patternTiming = new int[5]; // in ms
12 private long begin; // in ms 13 private long begin; // in ms
13 private long stop; // in ms 14 private long stop; // in ms
  15 + private int repeat;
14 16
15 public MusicPattern(int[] pattern, int repeat, long begin) { 17 public MusicPattern(int[] pattern, int repeat, long begin) {
16 - if(pattern.length != 4) 18 + if(pattern.length != 5)
17 throw new InvalidPatternException(); 19 throw new InvalidPatternException();
18 this.pattern = pattern; 20 this.pattern = pattern;
19 - this.totalLentgh = pattern[0] + pattern[1] + pattern[2] + pattern[3]; 21 + this.totalLength = pattern[0] + pattern[1] + pattern[2] + pattern[3] + pattern[4];
20 this.patternTiming[0] = pattern[0]; 22 this.patternTiming[0] = pattern[0];
21 - for(int i=1; i<4; i++) 23 + for(int i=1; i<5; i++)
22 this.patternTiming[i] = this.patternTiming[i-1] + pattern[i]; 24 this.patternTiming[i] = this.patternTiming[i-1] + pattern[i];
23 this.begin = begin; 25 this.begin = begin;
24 - this.stop = repeat * totalLentgh; 26 + this.stop = repeat * totalLength;
  27 + this.repeat = repeat;
25 } 28 }
  29 +
  30 + public int[] getPatternTiming() { return patternTiming; }
  31 + public long getStop() { return stop; }
  32 + public long getBegin() { return begin; }
  33 + public int getRepeat() { return repeat; }
  34 + public int getTotalLength () { return totalLength; }
26 35
27 public double render(long tick) { // tick in ms 36 public double render(long tick) { // tick in ms
28 if(tick <= begin) 37 if(tick <= begin)
29 return 0; 38 return 0;
30 if(tick >= stop) 39 if(tick >= stop)
31 return 0; 40 return 0;
32 - int tickMod = (int) (tick % totalLentgh); 41 + int tickMod = (int) (tick % totalLength);
33 if(tickMod < patternTiming[0]) 42 if(tickMod < patternTiming[0])
34 return 0; 43 return 0;
35 if(tickMod < patternTiming[1]) 44 if(tickMod < patternTiming[1])
36 return (double) (tickMod - patternTiming[0]) / (double) (pattern[1]); 45 return (double) (tickMod - patternTiming[0]) / (double) (pattern[1]);
37 if(tickMod < patternTiming[2]) 46 if(tickMod < patternTiming[2])
38 return 1; 47 return 1;
39 - return 1 - ((double) (tickMod - patternTiming[2]) / (double) (pattern[3])); 48 + if(tickMod < patternTiming[3])
  49 + return 1 - ((double) (tickMod - patternTiming[2]) / (double) (pattern[3]));
  50 + return 0;
40 } 51 }
41 } 52 }
VRGNYMusicLights/Sources/MusicRenderer.java 0 → 100644
@@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
  1 +import java.awt.Color;
  2 +import java.awt.Component;
  3 +import java.util.ArrayList;
  4 +
  5 +import javax.swing.Box;
  6 +import javax.swing.BoxLayout;
  7 +import javax.swing.JLabel;
  8 +import javax.swing.JList;
  9 +import javax.swing.JPanel;
  10 +import javax.swing.ListCellRenderer;
  11 +
  12 +public class MusicRenderer extends JPanel implements ListCellRenderer<Music> {
  13 + private static final long serialVersionUID = 1L;
  14 + private static final Color DEFAULT_BACKGROUND = new JPanel().getBackground();
  15 +
  16 + private TimeLineJPanel timeLine;
  17 +
  18 + public ArrayList<PatternJPanel> patterns;
  19 +
  20 + public MusicRenderer(TimeLineJPanel timeLine) {
  21 + this.timeLine = timeLine;
  22 + this.patterns = new ArrayList<>();
  23 + }
  24 +
  25 + @Override
  26 + public Component getListCellRendererComponent(JList<? extends Music> list, Music music, int index,
  27 + boolean isSelected, boolean cellHasFocus) {
  28 + removeAll();
  29 +
  30 + if(isSelected) {
  31 + setBackground(Color.LIGHT_GRAY);
  32 + } else {
  33 + setBackground(DEFAULT_BACKGROUND);
  34 + }
  35 +
  36 + setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
  37 +
  38 + JPanel infoPanel = new JPanel();
  39 + infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.LINE_AXIS));
  40 + infoPanel.add(new JLabel("Pattern " + String.valueOf(index) + " :"));
  41 + //TODO rigid area to follow scroll ?
  42 + infoPanel.add(Box.createHorizontalGlue());
  43 + add(infoPanel);
  44 +
  45 + PatternJPanel pattern = new PatternJPanel(music, timeLine);
  46 + if(patterns.size() > index)
  47 + patterns.set(index, pattern);
  48 + else
  49 + patterns.add(pattern);
  50 + add(pattern);
  51 +
  52 + return this;
  53 + }
  54 +}
VRGNYMusicLights/Sources/PatternJPanel.java 0 → 100644
@@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
  1 +import java.awt.Color;
  2 +import java.awt.Dimension;
  3 +import java.awt.Graphics;
  4 +
  5 +import javax.swing.JPanel;
  6 +
  7 +public class PatternJPanel extends JPanel {
  8 + private static final long serialVersionUID = 1L;
  9 + private static final int HEIGHT = 50;
  10 + private static final int PADDING = 2;
  11 + public static final int ZOOM_MULTIPLIER = 10;
  12 +
  13 + private Music music;
  14 + private TimeLineJPanel timeLine;
  15 + private int end;
  16 +
  17 + public PatternJPanel(Music music, TimeLineJPanel timeLine) {
  18 + this.music = music;
  19 + this.timeLine = timeLine;
  20 + end = transformZoon(music.getMusicPattern().getStop());
  21 + setPreferredSize(new Dimension((int) end, HEIGHT));
  22 + }
  23 +
  24 + public void refreshPreferedSize() {
  25 + end = transformZoon(music.getMusicPattern().getStop());
  26 + setPreferredSize(new Dimension((int) end, HEIGHT));
  27 + }
  28 +
  29 + public int getEnd() { return end; }
  30 + public Music getMusic() { return music; }
  31 +
  32 + @Override
  33 + protected void paintComponent(Graphics g) {
  34 + super.paintComponent(g);
  35 +
  36 + g.setColor(Color.WHITE);
  37 + int begin = transformZoon(music.getMusicPattern().getBegin());
  38 + g.fillRect(begin, 0, end, HEIGHT);
  39 +
  40 + MusicPattern pattern = music.getMusicPattern();
  41 + g.setColor(Color.BLACK);
  42 + for(int i=0; i<pattern.getRepeat(); i++) {
  43 + int repeatAddition = transformZoon(pattern.getTotalLength() * i) + begin;
  44 + g.drawLine(repeatAddition, HEIGHT - PADDING,
  45 + transformZoon(pattern.getPatternTiming()[0]) + repeatAddition, HEIGHT - PADDING);
  46 + g.drawLine(transformZoon(pattern.getPatternTiming()[0]) + repeatAddition, HEIGHT - PADDING,
  47 + transformZoon(pattern.getPatternTiming()[1]) + repeatAddition, PADDING);
  48 + g.drawLine(transformZoon(pattern.getPatternTiming()[1]) + repeatAddition, PADDING,
  49 + transformZoon(pattern.getPatternTiming()[2]) + repeatAddition, PADDING);
  50 + g.drawLine(transformZoon(pattern.getPatternTiming()[2]) + repeatAddition, PADDING,
  51 + transformZoon(pattern.getPatternTiming()[3]) + repeatAddition, HEIGHT - PADDING);
  52 + g.drawLine(transformZoon(pattern.getPatternTiming()[3]) + repeatAddition, HEIGHT - PADDING,
  53 + transformZoon(pattern.getPatternTiming()[4]) + repeatAddition, HEIGHT - PADDING);
  54 + }
  55 + }
  56 +
  57 + private int transformZoon(int n) {
  58 + return transformZoon((long) n);
  59 + }
  60 + private int transformZoon(long n) {
  61 + return (int) ((double) n / (double) ZOOM_MULTIPLIER * timeLine.getZoomLevel());
  62 + }
  63 +}
VRGNYMusicLights/Sources/PlayJPanel.java 0 → 100644
@@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
  1 +import java.awt.BorderLayout;
  2 +import java.awt.Font;
  3 +
  4 +import javax.swing.Box;
  5 +import javax.swing.BoxLayout;
  6 +import javax.swing.JLabel;
  7 +import javax.swing.JPanel;
  8 +
  9 +public class PlayJPanel extends JPanel {
  10 + private static final long serialVersionUID = 1L;
  11 + private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14);
  12 +
  13 + public PlayJPanel(Interface interf, LightCanvasJPanel lightCanvas) {
  14 + super(new BorderLayout());
  15 +
  16 + // title
  17 + JLabel title = new JLabel("Visualizer :");
  18 + title.setFont(titleFont);
  19 + add(title, BorderLayout.NORTH);
  20 +
  21 + // lights
  22 + JPanel centerPanel = new JPanel();
  23 + centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.LINE_AXIS));
  24 + centerPanel.add(Box.createHorizontalGlue());
  25 + centerPanel.add(lightCanvas);
  26 + add(centerPanel, BorderLayout.CENTER);
  27 +
  28 + // controls
  29 + interf.animPlayer = new AnimationPlayer(interf);
  30 + add(interf.animPlayer, BorderLayout.SOUTH);
  31 + }
  32 +}
VRGNYMusicLights/Sources/TimeLineJList.java 0 → 100644
@@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
  1 +import java.awt.Color;
  2 +import java.awt.Graphics;
  3 +
  4 +import javax.swing.JList;
  5 +import javax.swing.ListModel;
  6 +
  7 +public class TimeLineJList extends JList<Music> {
  8 + private static final long serialVersionUID = 1L;
  9 + private static final int MARK_WIDTH = 2;
  10 +
  11 + private Interface interf;
  12 +
  13 + public TimeLineJList(ListModel<Music> dataModel, Interface interf) {
  14 + super(dataModel);
  15 + this.interf = interf;
  16 + }
  17 +
  18 + @Override
  19 + protected void paintComponent(Graphics g) {
  20 + super.paintComponent(g);
  21 + g.setColor(Color.BLACK);
  22 +
  23 + int maxHeight = getPreferredSize().height;
  24 + int maxWidth = getPreferredSize().width;
  25 +
  26 + int mark = transformZoon(interf.tick);
  27 + if(mark > maxWidth)
  28 + mark = maxWidth;
  29 +
  30 + g.fillRect(mark, 0, MARK_WIDTH, maxHeight);
  31 + }
  32 +
  33 + private int transformZoon(long n) {
  34 + return (int) ((double) n / (double) PatternJPanel.ZOOM_MULTIPLIER * interf.timeLinePanel.getZoomLevel());
  35 + }
  36 +}
VRGNYMusicLights/Sources/TimeLineJPanel.java 0 → 100644
@@ -0,0 +1,146 @@ @@ -0,0 +1,146 @@
  1 +import java.awt.Dimension;
  2 +import java.awt.Font;
  3 +import java.awt.event.ActionEvent;
  4 +import java.awt.event.ActionListener;
  5 +import java.awt.event.FocusEvent;
  6 +import java.awt.event.FocusListener;
  7 +import java.awt.event.MouseWheelEvent;
  8 +import java.awt.event.MouseWheelListener;
  9 +
  10 +import javax.swing.Box;
  11 +import javax.swing.BoxLayout;
  12 +import javax.swing.DefaultListModel;
  13 +import javax.swing.JLabel;
  14 +import javax.swing.JPanel;
  15 +import javax.swing.JScrollBar;
  16 +import javax.swing.JScrollPane;
  17 +import javax.swing.JTextField;
  18 +import javax.swing.ListSelectionModel;
  19 +
  20 +public class TimeLineJPanel extends JPanel implements MouseWheelListener, FocusListener, ActionListener {
  21 + private static final long serialVersionUID = 1L;
  22 + private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14);
  23 +
  24 + private static final int SCROLL_SPEED_HORIZONTAL = 30;
  25 + private static final int SCROLL_SPEED_VERTICAL = 30;
  26 +
  27 + private DefaultListModel<Music> listModel;
  28 + private double zoomLevel = 1;
  29 +
  30 + private JScrollPane scrollPane;
  31 + private MusicRenderer musicRenderer;
  32 + private Interface interf;
  33 + private JTextField currentTick;
  34 + private JLabel maxTicks;
  35 +
  36 + public TimeLineJPanel(Interface interf, MusicList list) {
  37 + this.interf = interf;
  38 + setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
  39 +
  40 + // timing infos
  41 + JPanel timingPanel = new JPanel();
  42 + timingPanel.setLayout(new BoxLayout(timingPanel, BoxLayout.LINE_AXIS));
  43 +
  44 + JLabel title = new JLabel("Timeline : ");
  45 + title.setFont(titleFont);
  46 + timingPanel.add(title);
  47 +
  48 + currentTick = new JTextField("00:00.000", 8);
  49 + currentTick.setMaximumSize( currentTick.getPreferredSize() );
  50 + currentTick.addFocusListener(this);
  51 + currentTick.addActionListener(this);
  52 + timingPanel.add(currentTick);
  53 +
  54 + maxTicks = new JLabel(" / 00:00.0000 (MM:ss:ms)");
  55 + timingPanel.add(maxTicks);
  56 +
  57 + timingPanel.add(Box.createHorizontalGlue());
  58 +
  59 + add(timingPanel);
  60 +
  61 + // timeline
  62 +
  63 + listModel = new DefaultListModel<>();
  64 + for(Music music : list.getList())
  65 + listModel.addElement(music);
  66 +
  67 + interf.timeLineList = new TimeLineJList(listModel, interf);
  68 + musicRenderer = new MusicRenderer(this);
  69 + interf.timeLineList.setCellRenderer(musicRenderer);
  70 + interf.timeLineList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  71 + scrollPane = new JScrollPane(interf.timeLineList, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
  72 + scrollPane.addMouseWheelListener(this);
  73 + scrollPane.setWheelScrollingEnabled(false);
  74 + scrollPane.setPreferredSize(new Dimension(800, 400));
  75 + add(scrollPane);
  76 + }
  77 +
  78 + public double getZoomLevel() { return zoomLevel; }
  79 +
  80 + public void updateList(MusicList list) {
  81 + listModel.clear();
  82 + for(Music music : list.getList())
  83 + listModel.addElement(music);
  84 + }
  85 +
  86 + public void updateTick() {
  87 + currentTick.setText(Util.tickToText(interf.tick));
  88 + long maxTick = 0;
  89 + for(PatternJPanel pattern : musicRenderer.patterns) {
  90 + pattern.refreshPreferedSize();
  91 + long tick = pattern.getMusic().getMusicPattern().getStop();
  92 + if(tick > maxTick)
  93 + maxTick = tick;
  94 + }
  95 + maxTicks.setText(Util.tickToText(maxTick) + " (MM:ss:ms)");
  96 + }
  97 +
  98 + public void mouseWheelMoved(MouseWheelEvent e) {
  99 + if(e.getSource() == scrollPane) {
  100 + if (e.isControlDown()) {
  101 + if(e.getWheelRotation() < 0)
  102 + zoomLevel *= (double) e.getWheelRotation() * -1.1;
  103 + else
  104 + zoomLevel *= (double) e.getWheelRotation() / 1.1;
  105 +
  106 + int maxWidth = 0;
  107 + for(PatternJPanel pattern : musicRenderer.patterns) {
  108 + pattern.refreshPreferedSize();
  109 + int width = pattern.getEnd();
  110 + if(width > maxWidth)
  111 + maxWidth = width;
  112 + }
  113 +
  114 + interf.timeLineList.setPreferredSize(new Dimension(maxWidth, interf.getPreferredSize().height));
  115 + scrollPane.repaint();
  116 + scrollPane.getViewport().revalidate();
  117 + } else if(e.isShiftDown()) {
  118 + JScrollBar sb = scrollPane.getHorizontalScrollBar();
  119 + sb.setValue(sb.getValue() + e.getWheelRotation() * SCROLL_SPEED_HORIZONTAL);
  120 + } else {
  121 + JScrollBar sb = scrollPane.getVerticalScrollBar();
  122 + sb.setValue(sb.getValue() + e.getWheelRotation() * SCROLL_SPEED_VERTICAL);
  123 + }
  124 + }
  125 + }
  126 +
  127 + @Override
  128 + public void focusLost(FocusEvent e) {
  129 + if(e.getSource() == currentTick) {
  130 + interf.tick = Util.textToTick(currentTick.getText());
  131 + currentTick.setText(Util.tickToText(interf.tick));
  132 + interf.computeTick();
  133 + }
  134 + }
  135 + @Override
  136 + public void focusGained(FocusEvent e) {
  137 + if(e.getSource() == currentTick)
  138 + currentTick.setCaretPosition(currentTick.getDocument().getLength());
  139 + }
  140 +
  141 + @Override
  142 + public void actionPerformed(ActionEvent e) {
  143 + if(e.getSource() == currentTick)
  144 + interf.getContentPane().requestFocus();
  145 + }
  146 +}
VRGNYMusicLights/Sources/Util.java 0 → 100644
@@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
  1 +
  2 +public class Util {
  3 + public static long textToTick(String str) {
  4 + if(str == null || str.equals(""))
  5 + return 0;
  6 + String[] strs = str.split(":|\\.");
  7 + long ticks = 0;
  8 +
  9 + try {
  10 + switch (strs.length) {
  11 + case 1:
  12 + ticks += Integer.parseInt(strs[0]);
  13 + break;
  14 + case 2:
  15 + ticks += Integer.parseInt(strs[1]);
  16 + ticks += Integer.parseInt(strs[0]) * 1000;
  17 + break;
  18 + case 3:
  19 + ticks += Integer.parseInt(strs[2]);
  20 + ticks += Integer.parseInt(strs[1]) * 1000;
  21 + ticks += Integer.parseInt(strs[0]) * 60000;
  22 + break;
  23 + }
  24 + } catch (NumberFormatException e) {
  25 + return 0;
  26 + }
  27 + return ticks;
  28 + }
  29 +
  30 + public static String tickToText(long tick) {
  31 + String str = "";
  32 +
  33 + if(tick > 5900000)
  34 + str += "99:";
  35 + else
  36 + str += String.format("%02d", (int) ((double) tick / 60000d)) + ":";
  37 +
  38 + tick -= (int) ((double) tick / 60000d) * 60000;
  39 + str += String.format("%02d", (int) ((double) tick / 1000d)) + ".";
  40 +
  41 + tick -= (int) ((double) tick / 1000d) * 1000;
  42 + str += String.format("%03d", tick);
  43 +
  44 + return str;
  45 + }
  46 +}