From 57a6fab13f8ca7509394cf18ac20247777d9a878 Mon Sep 17 00:00:00 2001 From: overflowerror Date: Thu, 8 Sep 2016 21:32:39 +0200 Subject: [PATCH] a few more features --- src/main/java/net/persei/dionysus/Main.java | 73 ++++++----- .../net/persei/dionysus/commands/Command.java | 16 +++ .../dionysus/commands/MusicCommand.java | 70 +++++++++++ .../dionysus/commands/MusicCommandType.java | 5 + .../dionysus/commands/MusicPlayCommand.java | 18 +++ .../commands/ResetContextCommand.java | 13 ++ .../dionysus/commands/SetContextCommand.java | 30 +++++ .../dionysus/commands/SoundFXComanndType.java | 5 + .../dionysus/commands/SoundFXCommand.java | 56 +++++++++ .../dionysus/commands/VideoCommand.java | 69 +++++++++++ .../dionysus/commands/VideoCommandType.java | 5 + .../dionysus/commands/VideoPlayCommand.java | 11 ++ .../net/persei/dionysus/events/Event.java | 81 ++++++++++++ .../dionysus/events/LaunchpadEvent.java | 11 ++ .../dionysus/managers/CommandManager.java | 48 +++++++- .../net/persei/dionysus/managers/Context.java | 18 +++ .../persei/dionysus/managers/MidiManager.java | 111 +++++++++++++++-- .../dionysus/managers/MusicManager.java | 116 ++++++++++++++++++ .../persei/dionysus/managers/Sequence.java | 15 +++ .../dionysus/managers/SoundFXManager.java | 35 ++++++ .../dionysus/managers/VideoManager.java | 37 ++++++ .../persei/dionysus/players/AudioPlayer.java | 10 ++ .../net/persei/dionysus/players/Player.java | 2 + .../persei/dionysus/players/VideoPlayer.java | 10 ++ 24 files changed, 820 insertions(+), 45 deletions(-) create mode 100644 src/main/java/net/persei/dionysus/commands/Command.java create mode 100644 src/main/java/net/persei/dionysus/commands/MusicCommand.java create mode 100644 src/main/java/net/persei/dionysus/commands/MusicCommandType.java create mode 100644 src/main/java/net/persei/dionysus/commands/MusicPlayCommand.java create mode 100644 src/main/java/net/persei/dionysus/commands/ResetContextCommand.java create mode 100644 src/main/java/net/persei/dionysus/commands/SetContextCommand.java create mode 100644 src/main/java/net/persei/dionysus/commands/SoundFXComanndType.java create mode 100644 src/main/java/net/persei/dionysus/commands/SoundFXCommand.java create mode 100644 src/main/java/net/persei/dionysus/commands/VideoCommand.java create mode 100644 src/main/java/net/persei/dionysus/commands/VideoCommandType.java create mode 100644 src/main/java/net/persei/dionysus/commands/VideoPlayCommand.java create mode 100644 src/main/java/net/persei/dionysus/events/Event.java create mode 100644 src/main/java/net/persei/dionysus/events/LaunchpadEvent.java create mode 100644 src/main/java/net/persei/dionysus/managers/Context.java create mode 100644 src/main/java/net/persei/dionysus/managers/MusicManager.java create mode 100644 src/main/java/net/persei/dionysus/managers/SoundFXManager.java create mode 100644 src/main/java/net/persei/dionysus/managers/VideoManager.java diff --git a/src/main/java/net/persei/dionysus/Main.java b/src/main/java/net/persei/dionysus/Main.java index e783c77..7800dcd 100644 --- a/src/main/java/net/persei/dionysus/Main.java +++ b/src/main/java/net/persei/dionysus/Main.java @@ -2,14 +2,21 @@ package net.persei.dionysus; import javax.sound.midi.MidiUnavailableException; +import net.persei.dionysus.commands.Command; +import net.persei.dionysus.commands.MusicPlayCommand; +import net.persei.dionysus.commands.ResetContextCommand; +import net.persei.dionysus.commands.SetContextCommand; +import net.persei.dionysus.commands.VideoPlayCommand; +import net.persei.dionysus.events.Event; import net.persei.dionysus.exceptions.LibrariesNotFoundException; -import net.persei.dionysus.managers.Command; import net.persei.dionysus.managers.CommandManager; -import net.persei.dionysus.managers.Event; +import net.persei.dionysus.managers.Context; import net.persei.dionysus.managers.MidiManager; import net.persei.dionysus.managers.MidiSource; +import net.persei.dionysus.managers.MusicManager; import net.persei.dionysus.managers.PlayerManager; import net.persei.dionysus.managers.Sequence; +import net.persei.dionysus.managers.VideoManager; import net.persei.dionysus.players.PlayerType; import uk.co.caprica.vlcj.binding.LibVlc; import uk.co.caprica.vlcj.discovery.NativeDiscovery; @@ -24,43 +31,47 @@ public class Main { throw new LibrariesNotFoundException(); System.out.println(LibVlc.INSTANCE.libvlc_get_version()); - System.out.println("Adding players..."); - PlayerManager.getInstance().create(PlayerType.Video, "TestVideo", true); - PlayerManager.getInstance().create(PlayerType.Audio, "TestAudio", true); - + System.out.println("Instancing video manager..."); + VideoManager videoManager = new VideoManager("MainVideoManager"); + PlayerManager.getInstance().create(PlayerType.Video, "primary", true); + + System.out.println("Instancing music manager..."); + MusicManager musicManager = new MusicManager("MainMusicManager"); + System.out.println("Instancing command manager..."); CommandManager commandManager = new CommandManager(); System.out.println("Instancing midi manager..."); MidiManager midiManager = new MidiManager(commandManager); - + System.out.println("Adding commands..."); - commandManager.addCommand(new Sequence().append(new Event(MidiSource.LAUNCHPAD, true, 0, 0, 0, 0)), - new Command() { - @Override - public String getName() { - return "Test Command"; - } - @Override - public void execute() { - PlayerManager.getInstance().getByName("TestVideo").playFile("test.mp4"); - System.out.println("Hallo Welt"); - } - }); - commandManager.addCommand(new Sequence().append(new Event(MidiSource.LAUNCHPAD, true, 0, 1, 0, 0)) - .append(new Event(MidiSource.LAUNCHPAD, true, 0, 2, 0, 0)), new Command() { - @Override - public String getName() { - return "Test Sequence Command"; - } + Sequence contextSequence = new Sequence().append(new Event(MidiSource.LAUNCHPAD, true, 0, 8, 7, 0)); + Sequence resetContext = new Sequence().append(new Event(MidiSource.LAUNCHPAD, true, 0, 8, 6, 0)); - @Override - public void execute() { - PlayerManager.getInstance().getByName("TestAudio").playFile("test.mp3"); - System.out.println("Sequence Test"); - } - }); + Context musicContext = new Context().append(new Event(MidiSource.LAUNCHPAD, true, 0, 8, 0, 0)); + Context fxContext = new Context().append(new Event(MidiSource.LAUNCHPAD, true, 0, 8, 1, 0)); + Context videoContext = new Context().append(new Event(MidiSource.LAUNCHPAD, true, 0, 8, 2, 0)); + Context unusedContext = new Context().append(new Event(MidiSource.LAUNCHPAD, true, 0, 8, 3, 0)); + commandManager.addCommand(resetContext, new ResetContextCommand("ResetContext", commandManager)); + + commandManager.addCommand(new Sequence(contextSequence).append(musicContext), + new SetContextCommand("MusicContext", commandManager, musicContext)); + commandManager.addCommand(new Sequence(contextSequence).append(fxContext), + new SetContextCommand("FXContext", commandManager, fxContext)); + commandManager.addCommand(new Sequence(contextSequence).append(videoContext), + new SetContextCommand("VideoContext", commandManager, videoContext)); + commandManager.addCommand(new Sequence(contextSequence).append(unusedContext), + new SetContextCommand("UnusedContext", commandManager, unusedContext)); + + commandManager.addCommand(new Sequence(musicContext).append(new Event(MidiSource.LAUNCHPAD, true, 0, 0, 7, 0)), + new MusicPlayCommand("Play_Merlins's_Study", musicManager, + "resources/audio/camelot/Merlin's Study.mp3")); + + commandManager.addCommand(new Sequence(videoContext).append(new Event(MidiSource.LAUNCHPAD, true, 0, 0, 6, 0)), + new VideoPlayCommand("Show_Mountains", videoManager, "primary", + "resources/video/mountains.mp4", true)); + System.out.println("Adding shutdown hook..."); Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { diff --git a/src/main/java/net/persei/dionysus/commands/Command.java b/src/main/java/net/persei/dionysus/commands/Command.java new file mode 100644 index 0000000..e3c059d --- /dev/null +++ b/src/main/java/net/persei/dionysus/commands/Command.java @@ -0,0 +1,16 @@ +package net.persei.dionysus.commands; + +public abstract class Command { + public abstract void execute(); + public abstract String getName(); + public boolean equals(Object obj) { + if (obj == null) + return false; + if (!obj.getClass().equals(this.getClass())) + return false; + Command command = (Command) obj; + if (!command.getName().equals(this.getName())) + return false; + return true; + } +} diff --git a/src/main/java/net/persei/dionysus/commands/MusicCommand.java b/src/main/java/net/persei/dionysus/commands/MusicCommand.java new file mode 100644 index 0000000..954420e --- /dev/null +++ b/src/main/java/net/persei/dionysus/commands/MusicCommand.java @@ -0,0 +1,70 @@ +package net.persei.dionysus.commands; + +import net.persei.dionysus.managers.MusicManager; + +public class MusicCommand extends Command { + private String name; + private MusicCommandType type; + private MusicManager musicManager; + private String file; + private long duration; + private boolean loop; + + public MusicCommand(String name, MusicManager musicManager, MusicCommandType type, String file, long duration, boolean loop) { + this.name = name; + this.musicManager = musicManager; + this.type = type; + this.file = file; + this.duration = duration; + this.loop = loop; + } + + public MusicCommand(String name) { + this.name = name; + } + + @Override + public void execute() { + switch (type) { + case change: + musicManager.change(file, duration, loop); + break; + case pause: + musicManager.pause(); + break; + case play: + musicManager.play(file, duration, loop); + break; + case stop: + musicManager.stop(duration); + break; + default: + break; + } + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (!obj.getClass().equals(this.getClass())) + return false; + MusicCommand command = (MusicCommand) obj; + if (!command.getName().equals(this.getName())) + return false; + if (command.type != type) + return false; + if (command.duration != duration) + return false; + if (command.file != null && !command.file.equals(file)) + return false; + if (command.loop != loop) + return false; + return true; + } +} diff --git a/src/main/java/net/persei/dionysus/commands/MusicCommandType.java b/src/main/java/net/persei/dionysus/commands/MusicCommandType.java new file mode 100644 index 0000000..79dc55e --- /dev/null +++ b/src/main/java/net/persei/dionysus/commands/MusicCommandType.java @@ -0,0 +1,5 @@ +package net.persei.dionysus.commands; + +public enum MusicCommandType { + play, change, stop, pause +} diff --git a/src/main/java/net/persei/dionysus/commands/MusicPlayCommand.java b/src/main/java/net/persei/dionysus/commands/MusicPlayCommand.java new file mode 100644 index 0000000..29bff03 --- /dev/null +++ b/src/main/java/net/persei/dionysus/commands/MusicPlayCommand.java @@ -0,0 +1,18 @@ +package net.persei.dionysus.commands; + +import net.persei.dionysus.managers.MusicManager; + +public class MusicPlayCommand extends MusicCommand { + public MusicPlayCommand(String name, MusicManager musicManager, String file) { + this(name, musicManager, file, 0); + } + + public MusicPlayCommand(String name, MusicManager musicManager, String file, long duration) { + this(name, musicManager, file, duration, true); + } + + public MusicPlayCommand(String name, MusicManager musicManager, String file, long duration, + boolean loop) { + super(name, musicManager, MusicCommandType.play, file, duration, loop); + } +} diff --git a/src/main/java/net/persei/dionysus/commands/ResetContextCommand.java b/src/main/java/net/persei/dionysus/commands/ResetContextCommand.java new file mode 100644 index 0000000..464dde4 --- /dev/null +++ b/src/main/java/net/persei/dionysus/commands/ResetContextCommand.java @@ -0,0 +1,13 @@ +package net.persei.dionysus.commands; + +import net.persei.dionysus.managers.CommandManager; +import net.persei.dionysus.managers.Context; +import net.persei.dionysus.managers.Sequence; + +public class ResetContextCommand extends SetContextCommand { + + public ResetContextCommand(String name, CommandManager commandManager) { + super(name, commandManager, new Context()); + } + +} diff --git a/src/main/java/net/persei/dionysus/commands/SetContextCommand.java b/src/main/java/net/persei/dionysus/commands/SetContextCommand.java new file mode 100644 index 0000000..c3fea7b --- /dev/null +++ b/src/main/java/net/persei/dionysus/commands/SetContextCommand.java @@ -0,0 +1,30 @@ +package net.persei.dionysus.commands; + +import net.persei.dionysus.managers.CommandManager; +import net.persei.dionysus.managers.Context; +import net.persei.dionysus.managers.Sequence; + +public class SetContextCommand extends Command { + + private String name; + private CommandManager commandManager; + private Context context; + + public SetContextCommand(String name, CommandManager commandManager, Context context) { + this.name = name; + this.commandManager = commandManager; + this.context = context; + } + + @Override + public void execute() { + if (!commandManager.getContext().equals(context)) + commandManager.setContext(context); + } + + @Override + public String getName() { + return name; + } + +} diff --git a/src/main/java/net/persei/dionysus/commands/SoundFXComanndType.java b/src/main/java/net/persei/dionysus/commands/SoundFXComanndType.java new file mode 100644 index 0000000..76ea283 --- /dev/null +++ b/src/main/java/net/persei/dionysus/commands/SoundFXComanndType.java @@ -0,0 +1,5 @@ +package net.persei.dionysus.commands; + +public enum SoundFXComanndType { + play, stop +} diff --git a/src/main/java/net/persei/dionysus/commands/SoundFXCommand.java b/src/main/java/net/persei/dionysus/commands/SoundFXCommand.java new file mode 100644 index 0000000..7841ee2 --- /dev/null +++ b/src/main/java/net/persei/dionysus/commands/SoundFXCommand.java @@ -0,0 +1,56 @@ +package net.persei.dionysus.commands; + +import net.persei.dionysus.managers.MusicManager; +import net.persei.dionysus.managers.SoundFXManager; + +public class SoundFXCommand extends Command { + private String name; + private SoundFXComanndType type; + private SoundFXManager soundManager; + private String file; + + public SoundFXCommand(String name, SoundFXManager soundManager, MusicCommandType type, String file) { + this.name = name; + this.soundManager = soundManager; + this.file = file; + } + + public SoundFXCommand(String name) { + this.name = name; + } + + @Override + public void execute() { + switch (type) { + case play: + soundManager.play(file); + break; + case stop: + soundManager.stopAll(); + break; + default: + break; + } + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (!obj.getClass().equals(this.getClass())) + return false; + SoundFXCommand command = (SoundFXCommand) obj; + if (!command.getName().equals(this.getName())) + return false; + if (command.type != type) + return false; + if (command.file != null && !command.file.equals(file)) + return false; + return true; + } +} diff --git a/src/main/java/net/persei/dionysus/commands/VideoCommand.java b/src/main/java/net/persei/dionysus/commands/VideoCommand.java new file mode 100644 index 0000000..6957bcc --- /dev/null +++ b/src/main/java/net/persei/dionysus/commands/VideoCommand.java @@ -0,0 +1,69 @@ +package net.persei.dionysus.commands; + +import net.persei.dionysus.managers.VideoManager; + +public class VideoCommand extends Command { + private String name; + private VideoManager videoManager; + private VideoCommandType type; + private String playerName; + private String file; + private boolean loop; + + public VideoCommand(String name, VideoCommandType type, VideoManager videoManager, String playerName, String file, + boolean loop) { + this.name = name; + this.type = type; + this.videoManager = videoManager; + this.file = file; + this.playerName = playerName; + this.loop = loop; + } + + @Override + public void execute() { + switch (type) { + case pause: + videoManager.pause(playerName); + break; + case play: + if (file == null) + videoManager.play(playerName); + else + videoManager.play(playerName, file, loop); + break; + case stop: + videoManager.stop(playerName); + break; + default: + break; + + } + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) + return false; + if (!obj.getClass().equals(this.getClass())) + return false; + VideoCommand command = (VideoCommand) obj; + if (!command.getName().equals(this.getName())) + return false; + if (command.type != type) + return false; + if (command.file != null && !command.file.equals(file)) + return false; + if (command.loop != loop) + return false; + if (!command.playerName.equals(playerName)) + return false; + return true; + } + +} diff --git a/src/main/java/net/persei/dionysus/commands/VideoCommandType.java b/src/main/java/net/persei/dionysus/commands/VideoCommandType.java new file mode 100644 index 0000000..d0e9f80 --- /dev/null +++ b/src/main/java/net/persei/dionysus/commands/VideoCommandType.java @@ -0,0 +1,5 @@ +package net.persei.dionysus.commands; + +public enum VideoCommandType { + play, stop, pause +} diff --git a/src/main/java/net/persei/dionysus/commands/VideoPlayCommand.java b/src/main/java/net/persei/dionysus/commands/VideoPlayCommand.java new file mode 100644 index 0000000..840c99d --- /dev/null +++ b/src/main/java/net/persei/dionysus/commands/VideoPlayCommand.java @@ -0,0 +1,11 @@ +package net.persei.dionysus.commands; + +import net.persei.dionysus.managers.VideoManager; + +public class VideoPlayCommand extends VideoCommand { + public VideoPlayCommand(String name, VideoManager videoManager, String playerName, + String file, boolean loop) { + super(name, VideoCommandType.play, videoManager, playerName, file, loop); + } + +} diff --git a/src/main/java/net/persei/dionysus/events/Event.java b/src/main/java/net/persei/dionysus/events/Event.java new file mode 100644 index 0000000..6391096 --- /dev/null +++ b/src/main/java/net/persei/dionysus/events/Event.java @@ -0,0 +1,81 @@ +package net.persei.dionysus.events; + +import net.persei.dionysus.managers.MidiSource; + +public class Event { + static private boolean velocitySensitive = false; + + private MidiSource source; + private boolean press; + private int channel; + private int x; + public MidiSource getSource() { + return source; + } + + public boolean isPress() { + return press; + } + + public int getChannel() { + return channel; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getV() { + return v; + } + + private int y; + private int v; + + public Event(MidiSource source, boolean press, int channel, int x, int y, int v) { + this.source = source; + this.press = press; + this.channel = channel; + this.x = x; + this.y = y; + this.v = v; + } + + public static boolean isVelocitySensitive() { + return velocitySensitive; + } + + public static void setVelocitySensitive(boolean velocitySensitive) { + Event.velocitySensitive = velocitySensitive; + } + + public boolean equals(Object obj) { + if (obj == null) + return false; + if (!(obj instanceof Event)) + return false; + Event event = (Event) obj; + if (event.source != source) + return false; + if (event.press != press) + return false; + if (event.channel != channel) + return false; + if (event.x != x) + return false; + if (event.y != y) + return false; + if (velocitySensitive) + if (event.v != v) + return false; + return true; + } + + public String toString() { + return (press ? "press" : "release") + " on " + source + " x:" + x + ", y:" + y + ", v:" + v; + } +} \ No newline at end of file diff --git a/src/main/java/net/persei/dionysus/events/LaunchpadEvent.java b/src/main/java/net/persei/dionysus/events/LaunchpadEvent.java new file mode 100644 index 0000000..857f2c0 --- /dev/null +++ b/src/main/java/net/persei/dionysus/events/LaunchpadEvent.java @@ -0,0 +1,11 @@ +package net.persei.dionysus.events; + +import net.persei.dionysus.managers.MidiSource; + +public class LaunchpadEvent extends Event { + + public LaunchpadEvent(boolean press, int x, int y) { + super(MidiSource.LAUNCHPAD, press, 0, x, y, 0); + } + +} diff --git a/src/main/java/net/persei/dionysus/managers/CommandManager.java b/src/main/java/net/persei/dionysus/managers/CommandManager.java index 793d52c..4cb7d76 100644 --- a/src/main/java/net/persei/dionysus/managers/CommandManager.java +++ b/src/main/java/net/persei/dionysus/managers/CommandManager.java @@ -3,6 +3,9 @@ package net.persei.dionysus.managers; import java.util.LinkedList; import java.util.List; +import net.persei.dionysus.commands.Command; +import net.persei.dionysus.events.Event; + public class CommandManager { static private class CommandTuple { public final Sequence sequence; @@ -12,17 +15,50 @@ public class CommandManager { this.sequence = sequence; this.command = command; } + + public boolean equals(Object obj) { + if (!(obj instanceof CommandTuple)) + return false; + CommandTuple ct = (CommandTuple) obj; + if (!sequence.equals(ct.sequence)) + return false; + if (!command.equals(ct.command)) + return false; + return true; + } } private List commands = new LinkedList<>(); + private List executedCommands = new LinkedList<>(); private Sequence sequence = new Sequence(); + + public Sequence getSequence() { + return sequence; + } + + public Context getContext() { + return context; + } + + private Context context = new Context(); + private Context nextContext = null; private long lastChange = 0; - static private long maxInterval = 1 * 1000; + public long getLastChange() { + return lastChange; + } + + public void setContext(Context context) { + this.nextContext = context; + } + + static public long maxInterval = 1 * 1000; public boolean registerEvent(Event event) { - if (System.currentTimeMillis() - lastChange > maxInterval) - sequence = new Sequence(); + if (System.currentTimeMillis() - lastChange > maxInterval) { + sequence = new Sequence(context); + executedCommands = new LinkedList<>(); + } sequence.add(event); lastChange = System.currentTimeMillis(); return checkForCommand(); @@ -38,11 +74,17 @@ public class CommandManager { break; } if (check) { + if (executedCommands.contains(ct)) + continue; System.out.println("Executing " + ct.command.getName() + "..."); ct.command.execute(); + executedCommands.add(ct); result = true; } } + if (nextContext != null) + context = nextContext; + nextContext = null; return result; } diff --git a/src/main/java/net/persei/dionysus/managers/Context.java b/src/main/java/net/persei/dionysus/managers/Context.java new file mode 100644 index 0000000..ab798f7 --- /dev/null +++ b/src/main/java/net/persei/dionysus/managers/Context.java @@ -0,0 +1,18 @@ +package net.persei.dionysus.managers; + +import net.persei.dionysus.events.Event; + +public class Context extends Sequence { + public Context append(Event event) { + add(event); + return this; + } + public Context append(Context context) { + addAll(context); + return this; + } + public Context append(Sequence sequence) { + addAll(sequence); + return this; + } +} diff --git a/src/main/java/net/persei/dionysus/managers/MidiManager.java b/src/main/java/net/persei/dionysus/managers/MidiManager.java index 57cce13..69041fd 100644 --- a/src/main/java/net/persei/dionysus/managers/MidiManager.java +++ b/src/main/java/net/persei/dionysus/managers/MidiManager.java @@ -10,17 +10,20 @@ import java.util.Arrays; import java.util.LinkedList; import java.util.List; +import javax.sound.midi.InvalidMidiDataException; import javax.sound.midi.MidiDevice; import javax.sound.midi.MidiMessage; import javax.sound.midi.MidiDevice.Info; +import net.persei.dionysus.events.Event; + public class MidiManager { - + private CommandManager commandManager; public MidiManager(CommandManager cm) throws MidiUnavailableException { this.commandManager = cm; - + Info[] infos = MidiSystem.getMidiDeviceInfo(); System.out.println("Searching for midi devices..."); @@ -37,21 +40,30 @@ public class MidiManager { transmitter.setReceiver(new MPD18Listener()); continue; } - if (info.getName().contains("S")) { + if (info.getName().contains("S ")) { System.out.println("Found Launchpad: " + info.getName()); - if (device.getMaxTransmitters() == 0) + if (device.getMaxTransmitters() != 0) { + System.out.println("... transmitter"); + if (!device.isOpen()) + device.open(); + devices.add(device); + Transmitter transmitter = device.getTransmitter(); + transmitter.setReceiver(new LaunchpadListener()); continue; - if (!device.isOpen()) - device.open(); - devices.add(device); - Transmitter transmitter = device.getTransmitter(); - transmitter.setReceiver(new LaunchpadListener()); - continue; + } + if (device.getMaxReceivers() != 0) { + System.out.println("... receiver"); + if (!device.isOpen()) + device.open(); + devices.add(device); + continue; + } } System.out.println("Found nothing: " + info.getName()); } + feedbackSequence(); } - + public static final int MIDI_NOTE_OFF = 0x80; public static final int MIDI_NOTE_ON = 0x90; @@ -101,4 +113,81 @@ public class MidiManager { System.out.println(press + " on " + source + ": " + x + ", " + y + " - " + v); commandManager.registerEvent(new Event(source, press, channel, x, y, v)); } + + public void feedbackSequence() { + MidiDevice launchpadTmp = null; + for (MidiDevice device : devices) { + if (device.getDeviceInfo().getName().contains("S ")) { + if (device.getMaxReceivers() == 0) { + System.out.println("Launchpad found, but no receivers. " + device.getDeviceInfo().getName()); + continue; + } + launchpadTmp = device; + break; + } + } + if (launchpadTmp == null) + return; + final MidiDevice launchpad = launchpadTmp; + + Receiver receiver; + try { + receiver = launchpad.getReceiver(); + } catch (MidiUnavailableException e) { + e.printStackTrace(); + return; + } + new Thread() { + public void run() { + try { + while (true) { + List events = new Sequence(commandManager.getSequence()); + List context = commandManager.getContext(); + for (Event event : context) { + if (events.contains(event)) + events.remove(event); + } + + int intensity = 0x03 + - (int) ((3.0 * (System.currentTimeMillis() - commandManager.getLastChange()) + / CommandManager.maxInterval)); + + clearLaunchpad(launchpad); + for (Event event : context) { + setLaunchpad(launchpad, event.getX(), event.getY(), 0x00, 0x03); + } + if (intensity > 0) { + for (Event event : events) { + setLaunchpad(launchpad, event.getX(), event.getY(), intensity, 0x00); + } + } + Thread.sleep(100); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }.start(); + } + + private void clearLaunchpad(MidiDevice launchpad) { + for (int i = 0; i < 9; i++) { + for (int j = 0; j < 8; j++) { + setLaunchpad(launchpad, i, j, 0, 0); + } + } + } + + private void setLaunchpad(MidiDevice launchpad, int x, int y, int r, int g) { + ShortMessage message = new ShortMessage(); + try { + message.setMessage(((r | g) != 0) ? MIDI_NOTE_ON : MIDI_NOTE_OFF, 0, ((y & 0x07) << 4) | (x & 0x0F), + (r & 0x03) | ((g & 0x03) << 4)); + launchpad.getReceiver().send(message, System.currentTimeMillis()); + } catch (InvalidMidiDataException e) { + e.printStackTrace(); + } catch (MidiUnavailableException e) { + e.printStackTrace(); + } + } } \ No newline at end of file diff --git a/src/main/java/net/persei/dionysus/managers/MusicManager.java b/src/main/java/net/persei/dionysus/managers/MusicManager.java new file mode 100644 index 0000000..a559fdb --- /dev/null +++ b/src/main/java/net/persei/dionysus/managers/MusicManager.java @@ -0,0 +1,116 @@ +package net.persei.dionysus.managers; + +import net.persei.dionysus.players.AudioPlayer; +import net.persei.dionysus.players.PlayerType; +import uk.co.caprica.vlcj.player.MediaPlayer; + +public class MusicManager { + static private int BASE_VOLUME = 100; + + private String name; + + private AudioPlayer[] crossfadePlayers = new AudioPlayer[2]; + private boolean[] isPlaying = new boolean[2]; + + public MusicManager(String name) { + this.name = name; + PlayerManager playerManager = PlayerManager.getInstance(); + crossfadePlayers[0] = (AudioPlayer) playerManager.create(PlayerType.Audio, "MusicPlayer_" + name + "_fade0"); + crossfadePlayers[1] = (AudioPlayer) playerManager.create(PlayerType.Audio, "MusicPlayer_" + name + "_fade1"); + } + + public void play(String file, long fadeduration, boolean loop) { + change(file, fadeduration, loop); + } + + public void change(String file, long fadeduration, boolean loop) { + if (!isPlaying[0]) { + // use 0 + stopPlayer(1, fadeduration); + startPlayer(0, file, fadeduration, loop); + } else if (!isPlaying[1]) { + // use 2 + stopPlayer(0, fadeduration); + startPlayer(1, file, fadeduration, loop); + } else { + // no player is applicable + } + } + + public void stop(long fadeduration) { + for (int i = 0; i < crossfadePlayers.length; i++) + stopPlayer(i, fadeduration); + } + + public void pause() { + // TODO resume + for (AudioPlayer player : crossfadePlayers) + player.pause(); + } + + private void startPlayer(int playerId, String file, long fadeduration, boolean loop) { + new Thread() { + public void run() { + setPlaying(playerId, true); + MediaPlayer player = crossfadePlayers[playerId].getMediaPlayer(); + + crossfadePlayers[playerId].playFile(file); + crossfadePlayers[playerId].setLoop(loop); + if (fadeduration == 0) { + player.setVolume(BASE_VOLUME); + return; + } + player.setVolume(0); + + int targetVolume = BASE_VOLUME; + int sourceVolume = 0; + int stepsPerSecond = 10; + int numberOfSteps = (int) ((fadeduration * stepsPerSecond) / 1000); + int msPerStep = (int) (fadeduration / numberOfSteps); + int incrementPerStep = (sourceVolume - targetVolume) / numberOfSteps; + + try { + for (int i = 0; i < numberOfSteps; i++) { + player.setVolume(player.getVolume() + incrementPerStep); + Thread.sleep(msPerStep); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }.start(); + } + + private synchronized void setPlaying(int playerId, boolean playing) { + isPlaying[playerId] = playing; + } + + private void stopPlayer(int playerId, long fadeduration) { + new Thread() { + public void run() { + if (!crossfadePlayers[playerId].isPlaying()) + return; + MediaPlayer player = crossfadePlayers[playerId].getMediaPlayer(); + int targetVolume = 0; + int sourceVolume = player.getVolume(); + int stepsPerSecond = 10; + int numberOfSteps = (int) ((fadeduration * stepsPerSecond) / 1000); + int msPerStep = (int) (fadeduration / numberOfSteps); + int decrementPerStep = (sourceVolume - targetVolume) / numberOfSteps; + + try { + for (int i = 0; i < numberOfSteps; i++) { + player.setVolume(player.getVolume() - decrementPerStep); + Thread.sleep(msPerStep); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + + setPlaying(playerId, false); + crossfadePlayers[playerId].stop(); + } + }.start(); + } + +} diff --git a/src/main/java/net/persei/dionysus/managers/Sequence.java b/src/main/java/net/persei/dionysus/managers/Sequence.java index d786fac..ca8a96b 100644 --- a/src/main/java/net/persei/dionysus/managers/Sequence.java +++ b/src/main/java/net/persei/dionysus/managers/Sequence.java @@ -2,9 +2,24 @@ package net.persei.dionysus.managers; import java.util.LinkedList; +import net.persei.dionysus.events.Event; + public class Sequence extends LinkedList { + public Sequence(Sequence context) { + super(context); + } + + public Sequence() { + super(); + } + public Sequence append(Event event) { add(event); return this; } + + public Sequence append(Sequence sequence) { + addAll(sequence); + return this; + } } diff --git a/src/main/java/net/persei/dionysus/managers/SoundFXManager.java b/src/main/java/net/persei/dionysus/managers/SoundFXManager.java new file mode 100644 index 0000000..3175d57 --- /dev/null +++ b/src/main/java/net/persei/dionysus/managers/SoundFXManager.java @@ -0,0 +1,35 @@ +package net.persei.dionysus.managers; + +import java.util.LinkedList; +import java.util.List; + +import net.persei.dionysus.players.AudioPlayer; +import net.persei.dionysus.players.PlayerType; + +public class SoundFXManager { + private String name; + private List players = new LinkedList<>(); + + public SoundFXManager(String name) { + this.name = name; + } + + public void play(String file) { + for (AudioPlayer player : players) { + if (player.isPlaying()) + continue; + player.playFile(file); + return; + } + AudioPlayer player = (AudioPlayer) PlayerManager.getInstance().create(PlayerType.Audio, + "FXPlayer_" + name + "_" + players.size()); + players.add(player); + player.playFile(file); + } + + public void stopAll() { + for (AudioPlayer player : players) { + player.stop(); + } + } +} diff --git a/src/main/java/net/persei/dionysus/managers/VideoManager.java b/src/main/java/net/persei/dionysus/managers/VideoManager.java new file mode 100644 index 0000000..eff310c --- /dev/null +++ b/src/main/java/net/persei/dionysus/managers/VideoManager.java @@ -0,0 +1,37 @@ +package net.persei.dionysus.managers; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import net.persei.dionysus.players.VideoPlayer; + +public class VideoManager { + private String name; + private PlayerManager playerManager = PlayerManager.getInstance(); + + public VideoManager(String name) { + this.name = name; + } + + public VideoPlayer getVideoPlayer(String name) { + return (VideoPlayer) playerManager.getByName(name); + } + + public void play(String name, String file, boolean loop) { + getVideoPlayer(name).playFile(file); + getVideoPlayer(name).setLoop(loop); + } + + public void play(String name) { + getVideoPlayer(name).play(); + } + + public void stop(String name) { + getVideoPlayer(name).stop(); + } + + public void pause(String name) { + getVideoPlayer(name).pause(); + } +} diff --git a/src/main/java/net/persei/dionysus/players/AudioPlayer.java b/src/main/java/net/persei/dionysus/players/AudioPlayer.java index e90182d..d96d9d3 100644 --- a/src/main/java/net/persei/dionysus/players/AudioPlayer.java +++ b/src/main/java/net/persei/dionysus/players/AudioPlayer.java @@ -42,4 +42,14 @@ public class AudioPlayer implements Player { public String getName() { return name; } + + @Override + public void stop() { + getMediaPlayer().stop(); + } + + @Override + public boolean isPlaying() { + return getMediaPlayer().isPlaying(); + } } diff --git a/src/main/java/net/persei/dionysus/players/Player.java b/src/main/java/net/persei/dionysus/players/Player.java index 0640f7d..81c258e 100644 --- a/src/main/java/net/persei/dionysus/players/Player.java +++ b/src/main/java/net/persei/dionysus/players/Player.java @@ -6,6 +6,8 @@ public interface Player { boolean isLoop(); void playFile(String file); void play(); + boolean isPlaying(); + void stop(); void pause(); void setLoop(boolean loop); MediaPlayer getMediaPlayer(); diff --git a/src/main/java/net/persei/dionysus/players/VideoPlayer.java b/src/main/java/net/persei/dionysus/players/VideoPlayer.java index 9f3d19f..621f9e0 100644 --- a/src/main/java/net/persei/dionysus/players/VideoPlayer.java +++ b/src/main/java/net/persei/dionysus/players/VideoPlayer.java @@ -85,4 +85,14 @@ public class VideoPlayer extends JFrame implements Player { public String getName() { return name; } + + @Override + public void stop() { + getMediaPlayer().stop(); + } + + @Override + public boolean isPlaying() { + return getMediaPlayer().isPlaying(); + } }