diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/artifacts/LEDControl_jar.xml b/.idea/artifacts/LEDControl_jar.xml new file mode 100644 index 0000000..a2e19f5 --- /dev/null +++ b/.idea/artifacts/LEDControl_jar.xml @@ -0,0 +1,15 @@ + + + $PROJECT_DIR$/out/artifacts/LEDControl_jar + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..fdf34bc --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..712ab9d --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..e6ee860 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/LEDControl.iml b/LEDControl.iml new file mode 100644 index 0000000..78b2cc5 --- /dev/null +++ b/LEDControl.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..135b37e --- /dev/null +++ b/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + org.example + LEDControl + 1.0-SNAPSHOT + + + 15 + 15 + + + + + com.fazecast + jSerialComm + [2.0.0,3.0.0) + + + com.profesorfalken + jSensors + 2.2.1 + + + com.tagtraum + jipes + 0.9.17 + + + \ No newline at end of file diff --git a/src/main/java/de/zuim/ledcontrol/EffectManager.java b/src/main/java/de/zuim/ledcontrol/EffectManager.java new file mode 100644 index 0000000..3f007e2 --- /dev/null +++ b/src/main/java/de/zuim/ledcontrol/EffectManager.java @@ -0,0 +1,57 @@ +package de.zuim.ledcontrol; + +import de.zuim.ledcontrol.effects.*; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +public class EffectManager { + + int activeId=4; + private final LEDEffect[] effects = new LEDEffect[]{new TemperatureEffect(), new ClockEffect(), new SineEffect(), new AudioEffect(), new ColorSweep()}; + + public EffectManager(){ + + final SystemTray tray = SystemTray.getSystemTray(); + final TrayIcon trayIcon = new TrayIcon(new ImageIcon(getClass().getResource("/icon.png")).getImage(),"LEDEffects"); + + trayIcon.addMouseListener(new MouseListener() { + @Override + public void mouseClicked(MouseEvent e) { + if(e.getButton()!=MouseEvent.BUTTON1) + System.exit(0); + getActiveEffect().unload(); + activeId++; + if(activeId==effects.length) + activeId=0; + getActiveEffect().load(); + trayIcon.setToolTip("LEDEffects - " + getActiveEffect().getDescription()); + } + + @Override + public void mousePressed(MouseEvent e) {} + + @Override + public void mouseReleased(MouseEvent e) {} + + @Override + public void mouseEntered(MouseEvent e) {} + + @Override + public void mouseExited(MouseEvent e) {} + }); + try { + tray.add(trayIcon); + } catch (AWTException e) { + e.printStackTrace(); + } + + getActiveEffect().load(); + } + + public LEDEffect getActiveEffect() { + return effects[activeId]; + } +} diff --git a/src/main/java/de/zuim/ledcontrol/LEDControl.java b/src/main/java/de/zuim/ledcontrol/LEDControl.java new file mode 100644 index 0000000..f762618 --- /dev/null +++ b/src/main/java/de/zuim/ledcontrol/LEDControl.java @@ -0,0 +1,108 @@ +package de.zuim.ledcontrol; + +import com.fazecast.jSerialComm.SerialPort; + +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; + +public class LEDControl { + public static final int WIDTH=16; + public static final int HEIGHT=16; + public static final int LED_NUM = WIDTH*HEIGHT; + public static final int BAUD = 1000000; + + + private SerialPort port; + private byte[][][] leds = new byte[WIDTH][HEIGHT][3]; + private EffectManager eff; + private BufferedImage scaledImage; + + public LEDControl(){ + eff = new EffectManager(); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> port.closePort())); + + connect(); + + sendLoop(); + } + + private void sendLoop(){ + long time = System.nanoTime(); + long iteration = 0; + + while(true){ + if(port == null || !port.isOpen()){ + sleep(1000); + connect(); + continue; + } + + long timeDelta = System.nanoTime()-time; + time = System.nanoTime(); + + renderFrame(timeDelta); + + port.writeBytes(new byte[]{(byte) 255}, 1); //start of new frame + + for(int x=0;x>16)&0xff),254); + leds[x][y][1] = (byte) Math.min((col>>8)&0xff,254); + leds[x][y][2] = (byte) Math.min(((col)&0xff),254); + port.writeBytes(leds[x][y], 3); + } + } + + sleep(10); + + if(iteration%1000==1){ + System.out.println("Frametime: "+ (Math.round(timeDelta)/100000)/10.0 + "ms ("+iteration+" Frames)"); + } + iteration++; + } + } + + private void connect(){ + SerialPort[] ports = SerialPort.getCommPorts(); + if(ports.length > 0){ + port = SerialPort.getCommPorts()[0]; + System.out.println("Connect to " + port.getDescriptivePortName()+" "+port.getSystemPortName()+" "); + port.setComPortParameters(BAUD,8,1,0); + port.openPort(); + } + } + + private void sleep(int ms){ + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + private void renderFrame(long timeDelta) { + BufferedImage image = new BufferedImage(16*eff.getActiveEffect().getScale(),16*eff.getActiveEffect().getScale(),BufferedImage.TYPE_INT_ARGB); + Graphics g = image.getGraphics(); + eff.getActiveEffect().render(timeDelta, g); + g.dispose(); + + if(eff.getActiveEffect().getScale()==1){ + scaledImage = image; + }else{ + scaledImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB); + AffineTransform at = new AffineTransform(); + at.scale(1.0/eff.getActiveEffect().getScale(), 1.0/eff.getActiveEffect().getScale()); + AffineTransformOp scaleOp = + new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR); + scaledImage = scaleOp.filter(image, scaledImage); + } + } + + public static void main(String[] args) { + new LEDControl(); + } +} diff --git a/src/main/java/de/zuim/ledcontrol/LEDEffect.java b/src/main/java/de/zuim/ledcontrol/LEDEffect.java new file mode 100644 index 0000000..f79f228 --- /dev/null +++ b/src/main/java/de/zuim/ledcontrol/LEDEffect.java @@ -0,0 +1,12 @@ +package de.zuim.ledcontrol; + +import java.awt.*; + +public interface LEDEffect { + + String getDescription(); + default int getScale() {return 1; } + default void load() {} + default void unload() {} + void render(long timeDelta, Graphics g); +} diff --git a/src/main/java/de/zuim/ledcontrol/effects/AudioEffect.java b/src/main/java/de/zuim/ledcontrol/effects/AudioEffect.java new file mode 100644 index 0000000..996b183 --- /dev/null +++ b/src/main/java/de/zuim/ledcontrol/effects/AudioEffect.java @@ -0,0 +1,179 @@ +package de.zuim.ledcontrol.effects; + +import com.tagtraum.jipes.math.FFTFactory; +import com.tagtraum.jipes.math.Transform; +import de.zuim.ledcontrol.LEDControl; +import de.zuim.ledcontrol.LEDEffect; + +import javax.sound.sampled.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static de.zuim.ledcontrol.LEDControl.HEIGHT; +import static de.zuim.ledcontrol.LEDControl.WIDTH; + +public class AudioEffect implements LEDEffect { + @Override + public String getDescription() { + return "Audio Effect"; + } + + final static int BUFFERSIZE = 2048; + double[] magnitudes = null; + Thread audioThread = null; + + @Override + public void load() { + Runnable audioRunnable = () -> { + + + Mixer.Info[] mixers = AudioSystem.getMixerInfo(); + List availableTargetLines = new ArrayList<>(); + for (Mixer.Info mixerInfo : mixers){ + + Mixer m = AudioSystem.getMixer(mixerInfo); + + Line.Info[] lines = m.getTargetLineInfo(); + + for (Line.Info li : lines) + { + try + { + if(li instanceof DataLine.Info && mixerInfo.toString().contains("mix")) + { + m.open(); + System.out.println("("+availableTargetLines.size()+") Found target line: " + li+" "+mixerInfo + "("+li.getClass()+")"); + availableTargetLines.add(li); + m.close(); + } + } catch (LineUnavailableException e){ + System.out.println("Line unavailable."); + } + } + } + + DataLine.Info targetLineInfo = (DataLine.Info) availableTargetLines.get(0); + + System.out.println("SUPPORTED TARGET FORMATS: "); + AudioFormat[] formats = (targetLineInfo).getFormats(); + for(int i=0; i decode + + float[] fbuf = decode(buf,format); + + final float[][] transformed = fft.transform(fbuf); + final float[] realPart = transformed[0]; + final float[] imaginaryPart = transformed[1]; + magnitudes = toMagnitudes(realPart, imaginaryPart); + + //System.out.println("M"+ Arrays.toString(magnitudes)); + // do something with magnitudes... + int max = 0, avg = 0,min=11111111; + for(double m : magnitudes){ + avg += m; + if(m>max) + max= (int) m; + if(m 1) + step=0; + + gr.setColor(Color.getHSBColor(step,1f,15f/255f)); + gr.fillRect(0,0,WIDTH,HEIGHT); + } +} diff --git a/src/main/java/de/zuim/ledcontrol/effects/SineEffect.java b/src/main/java/de/zuim/ledcontrol/effects/SineEffect.java new file mode 100644 index 0000000..5c88498 --- /dev/null +++ b/src/main/java/de/zuim/ledcontrol/effects/SineEffect.java @@ -0,0 +1,53 @@ +package de.zuim.ledcontrol.effects; + +import de.zuim.ledcontrol.LEDEffect; + +import java.awt.*; +import java.util.Random; + +import static de.zuim.ledcontrol.LEDControl.HEIGHT; +import static de.zuim.ledcontrol.LEDControl.WIDTH; + +public class SineEffect implements LEDEffect { + + private Random r = new Random(); + private double[][] seeds = new double[10][7]; + + @Override + public void load() { + for(double[] seed : seeds){ + for(int i = 0; i < seed.length; i++){ + seed[i] = r.nextDouble(); + } + } + } + + double steps = 0; + @Override + public void render(long timeDelta, Graphics g) { + + steps += timeDelta*0.000000001; + + for(int i = 0; i < 6; i++){ + g.setColor(new Color((int) (15*seeds[i][0]), (int) (10*seeds[i][3]),(int)(4*seeds[i][4]))); + for (int x = 0; x < WIDTH*getScale(); x++){ + g.drawLine(x, calc(i, x),x+1,calc(i, x+1)); + } + } + } + + private int calc(int i, int x){ + return (int) (Math.sin(((x+2*seeds[i][2])*0.5*seeds[i][1])/getScale()+steps*seeds[i][6])*7*getScale()*(seeds[i][5]+0.2) + (getScale()*HEIGHT)/2); + } + + @Override + public String getDescription() { + return "SineEffect"; + } + + @Override + public int getScale() { + return 1; + } + +} diff --git a/src/main/java/de/zuim/ledcontrol/effects/TemperatureEffect.java b/src/main/java/de/zuim/ledcontrol/effects/TemperatureEffect.java new file mode 100644 index 0000000..786aa1a --- /dev/null +++ b/src/main/java/de/zuim/ledcontrol/effects/TemperatureEffect.java @@ -0,0 +1,58 @@ +package de.zuim.ledcontrol.effects; + +import com.profesorfalken.jsensors.JSensors; +import com.profesorfalken.jsensors.model.components.Component; +import com.profesorfalken.jsensors.model.components.Components; +import com.profesorfalken.jsensors.model.components.Cpu; +import com.profesorfalken.jsensors.model.sensors.Fan; +import com.profesorfalken.jsensors.model.sensors.Load; +import com.profesorfalken.jsensors.model.sensors.Temperature; +import de.zuim.ledcontrol.LEDEffect; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + + +public class TemperatureEffect implements LEDEffect { + @Override + public String getDescription() { + return "Temperatur Sensoren"; + } + + @Override + public void render(long timeDelta, Graphics g) { + /*Components components = JSensors.get.components(); + + List comps = new ArrayList<>(components.cpus); + comps.addAll(components.disks); + comps.addAll(components.gpus); + comps.addAll(components.mobos); + + if (comps != null) { + for (final Component c : comps) { + System.out.println("Found component: " + c.name); + if (c.sensors != null) { + System.out.println("Sensors: "); + + //Print temperatures + List temps = c.sensors.temperatures; + for (final Temperature temp : temps) { + System.out.println(temp.name + ": " + temp.value + " C"); + } + + //Print fan speed + List fans = c.sensors.fans; + for (final Fan fan : fans) { + System.out.println(fan.name + ": " + fan.value + " RPM"); + } + //Print fan speed + List loads = c.sensors.loads; + for (final Load load : loads) { + System.out.println(load.name + ": " + load.value + " %"); + } + } + } + }*/ + } +} diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 0000000..8f32fa0 --- /dev/null +++ b/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: de.zuim.ledcontrol.LEDControl + diff --git a/src/main/resources/icon.png b/src/main/resources/icon.png new file mode 100644 index 0000000..35cbec2 Binary files /dev/null and b/src/main/resources/icon.png differ