diff --git a/PlayWall/src/main/resources/lang/_de.properties b/PlayWall/src/main/resources/lang/_de.properties index 36d6216941a1dc5e4b9d951beaa656adf60078dc..89375f4cd298891b17d51dc0afa36aad00086b3f 100755 --- a/PlayWall/src/main/resources/lang/_de.properties +++ b/PlayWall/src/main/resources/lang/_de.properties @@ -215,6 +215,7 @@ Trigger.Volume.Name=Lautst\u00E4rke TriggerPoint.START=Start TriggerPoint.STOP=Stop TriggerPoint.EOF=Ende +TriggerPoint.PLAYLIST_NEXT=Playlist Next # Drag and Drop Mode DnDMode.Replace=Ersetzen diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/Pad.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/Pad.java index 8125b05854eaf41a28e2fbe7cb1760730bbafa64..833e52beb59f423a9c0c9c14b81d82ecb46df735 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/Pad.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/Pad.java @@ -4,6 +4,7 @@ import de.thecodelabs.utils.io.PathUtils; import de.tobias.playpad.PlayPadPlugin; import de.tobias.playpad.pad.content.PadContent; import de.tobias.playpad.pad.content.PadContentFactory; +import de.tobias.playpad.pad.content.Playlistable; import de.tobias.playpad.pad.content.play.Pauseable; import de.tobias.playpad.pad.fade.listener.PadFadeContentListener; import de.tobias.playpad.pad.fade.listener.PadFadeDurationListener; @@ -11,6 +12,7 @@ import de.tobias.playpad.pad.listener.PadStatusControlListener; import de.tobias.playpad.pad.listener.PadStatusNotFoundListener; import de.tobias.playpad.pad.listener.trigger.PadTriggerContentListener; import de.tobias.playpad.pad.listener.trigger.PadTriggerDurationListener; +import de.tobias.playpad.pad.listener.trigger.PadTriggerPlaylistListener; import de.tobias.playpad.pad.listener.trigger.PadTriggerStatusListener; import de.tobias.playpad.pad.mediapath.MediaPath; import de.tobias.playpad.pad.viewcontroller.AbstractPadViewController; @@ -74,6 +76,7 @@ public class Pad implements IPad { private transient PadTriggerStatusListener padTriggerStatusListener; private transient PadTriggerDurationListener padTriggerDurationListener; private transient PadTriggerContentListener padTriggerContentListener; + private transient PadTriggerPlaylistListener padTriggerPlaylistListener; private transient boolean ignoreTrigger = false; // Utils @@ -128,6 +131,11 @@ public class Pad implements IPad { contentProperty.removeListener(padTriggerContentListener); padTriggerContentListener.changed(contentProperty, getContent(), null); } + if (padTriggerPlaylistListener != null && contentProperty != null) { + if (getContent() instanceof Playlistable) { + ((Playlistable) getContent()).removePlaylistListener(padTriggerPlaylistListener); + } + } if (padFadeDurationListener != null && contentProperty != null) { contentProperty.removeListener(padFadeContentListener); @@ -161,6 +169,8 @@ public class Pad implements IPad { contentProperty.addListener(padTriggerContentListener); padTriggerContentListener.changed(contentProperty, null, getContent()); + padTriggerPlaylistListener = new PadTriggerPlaylistListener(); + // Pad Listener if (mediaPathUpdateListener != null) { mediaPaths.removeListener(mediaPathUpdateListener); @@ -610,6 +620,10 @@ public class Pad implements IPad { return padTriggerDurationListener; } + public PadTriggerPlaylistListener getPadTriggerPlaylistListener() { + return padTriggerPlaylistListener; + } + public PadFadeDurationListener getPadFadeDurationListener() { return padFadeDurationListener; } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PlaylistListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PlaylistListener.java new file mode 100644 index 0000000000000000000000000000000000000000..1402fe7ae96105fd8e563096d617dcfaf9f5aaba --- /dev/null +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/PlaylistListener.java @@ -0,0 +1,8 @@ +package de.tobias.playpad.pad.content; + +import de.tobias.playpad.pad.Pad; + +public interface PlaylistListener { + + void onNextItem(Pad pad, int next, int total); +} diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/Playlistable.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/Playlistable.java index aab735bcd3ea9d96b6109628a31833eced738598..b4b60ea6dc70853cfa768a90c9643c91bad8582c 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/Playlistable.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/content/Playlistable.java @@ -17,4 +17,8 @@ public interface Playlistable { void next(); boolean isLoaded(MediaPath mediaPath); + + void addPlaylistListener(PlaylistListener listener); + + void removePlaylistListener(PlaylistListener listener); } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusControlListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusControlListener.java index 3c6b86d4a99fd3cb992a8731d96b2c0952359c07..a791354a38462196371d63f1471273a9dfbdbe4f 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusControlListener.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/PadStatusControlListener.java @@ -17,7 +17,7 @@ import javafx.util.Duration; public class PadStatusControlListener implements ChangeListener<PadStatus> { - private Pad pad; + private final Pad pad; // Utils für Single Pad Playing private static Pad currentPlayingPad; // Nur wenn ProfileSettings.isMultiplePlayer == false diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerContentListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerContentListener.java index 09d08d491d8846561e33ac6dcfcfdf1fdff718fa..ae9789f26c4e97b356fe92452cdd8b8f25f1dd32 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerContentListener.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerContentListener.java @@ -2,6 +2,7 @@ package de.tobias.playpad.pad.listener.trigger; import de.tobias.playpad.pad.Pad; import de.tobias.playpad.pad.content.PadContent; +import de.tobias.playpad.pad.content.Playlistable; import de.tobias.playpad.pad.content.play.Durationable; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; @@ -9,7 +10,7 @@ import javafx.beans.value.ObservableValue; // Fügt Time Listener hinzu für neuen Content public class PadTriggerContentListener implements ChangeListener<PadContent> { - private Pad pad; + private final Pad pad; public PadTriggerContentListener(Pad pad) { this.pad = pad; @@ -21,12 +22,20 @@ public class PadTriggerContentListener implements ChangeListener<PadContent> { if (oldValue instanceof Durationable) { ((Durationable) oldValue).positionProperty().removeListener(pad.getPadTriggerDurationListener()); } + + if (oldValue instanceof Playlistable) { + ((Playlistable) oldValue).removePlaylistListener(pad.getPadTriggerPlaylistListener()); + } } if (newValue != null) { if (newValue instanceof Durationable) { ((Durationable) newValue).positionProperty().addListener(pad.getPadTriggerDurationListener()); } + + if (newValue instanceof Playlistable) { + ((Playlistable) newValue).addPlaylistListener(pad.getPadTriggerPlaylistListener()); + } } } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerPlaylistListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerPlaylistListener.java new file mode 100644 index 0000000000000000000000000000000000000000..eec30a0feaec27cb639cbe7ab76b5329f028981f --- /dev/null +++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/listener/trigger/PadTriggerPlaylistListener.java @@ -0,0 +1,30 @@ +package de.tobias.playpad.pad.listener.trigger; + +import de.tobias.playpad.PlayPadPlugin; +import de.tobias.playpad.pad.Pad; +import de.tobias.playpad.pad.PadSettings; +import de.tobias.playpad.pad.content.PlaylistListener; +import de.tobias.playpad.profile.Profile; +import de.tobias.playpad.tigger.Trigger; +import de.tobias.playpad.tigger.TriggerPoint; +import de.tobias.playpad.viewcontroller.main.IMainViewController; +import javafx.util.Duration; + +public class PadTriggerPlaylistListener implements PlaylistListener { + @Override + public void onNextItem(Pad pad, int next, int total) { + if (!pad.isIgnoreTrigger()) { + PadSettings padSettings = pad.getPadSettings(); + executeTrigger(pad, padSettings.getTriggers().get(TriggerPoint.PLAYLIST_NEXT)); + } else { + pad.setIgnoreTrigger(false); + } + } + + private void executeTrigger(Pad pad, Trigger trigger) { + IMainViewController mainViewController = PlayPadPlugin.getInstance().getMainViewController(); + Profile currentProfile = Profile.currentProfile(); + + trigger.handle(pad, Duration.ZERO, pad.getProject(), mainViewController, currentProfile); + } +} diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/Trigger.java b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/Trigger.java index 39ece8a9fd18f427d10d0d3067dc1184a1b8a681..f6d5fda76ac66f14a09bf7759e569b7ad9357bcb 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/Trigger.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/Trigger.java @@ -118,6 +118,8 @@ public class Trigger { } else { handleEndPoint(pad, currentDuration, project, mainViewController, currentProfile, item); } + } else if (triggerPoint == TriggerPoint.PLAYLIST_NEXT) { + item.performAction(pad, project, mainViewController, currentProfile); } } } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerPoint.java b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerPoint.java index ce08ec84067ac2b3cb2a89b44f7c17335558eba2..175f1517ebb0418ad0684ea6f2693853d1203fa3 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerPoint.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/tigger/TriggerPoint.java @@ -4,7 +4,8 @@ public enum TriggerPoint { START(true), STOP(false), - EOF(true); + EOF(true), + PLAYLIST_NEXT(false); /** * Defines if a trigger can be run after, before a certain event. diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerMediaContainer.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerMediaContainer.scala index 93d34c1c817b3a8b92fb62facc00b0b63729d5a0..7ee826dc53dd7a9c986999b31d9cb225e357e59f 100644 --- a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerMediaContainer.scala +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerMediaContainer.scala @@ -49,15 +49,16 @@ class ContentPlayerMediaContainer(val content: ContentPlayerPadContent, private[ } def next(): Unit = { - stop() - val players = content.getMediaContainers val currentIndex = players.indexOf(this) content.currentPlayingMediaIndexProperty().set(currentIndex) + if (currentIndex + 1 < players.length) { + content.listeners.forEach(listener => listener.onNextItem(content.pad, currentIndex + 1, players.length)) players(currentIndex + 1).play(false) } else if (content.getPad.getPadSettings.isLoop) { + content.listeners.forEach(listener => listener.onNextItem(content.pad, 0, players.length)) players.head.play(false) } else { content.getPad.setStatus(PadStatus.STOP) diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContent.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContent.scala index f18c5b622c33ee530c4dee590bf9917208aa2c08..94524b4c33bc1c535d9b9c094593b8b851fafb86 100644 --- a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContent.scala +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/pad/ContentPlayerPadContent.scala @@ -1,8 +1,7 @@ package de.tobias.playpad.plugin.content.pad -import de.thecodelabs.logger.Logger import de.tobias.playpad.pad.content.play.{Durationable, Pauseable} -import de.tobias.playpad.pad.content.{PadContent, Playlistable} +import de.tobias.playpad.pad.content.{PadContent, PlaylistListener, Playlistable} import de.tobias.playpad.pad.fade.{Fadeable, LinearFadeController} import de.tobias.playpad.pad.mediapath.MediaPath import de.tobias.playpad.pad.{Pad, PadStatus} @@ -20,8 +19,8 @@ import nativecontentplayerwindows.ContentPlayer import java.nio.file.Files import java.util -import java.util.{Collections, UUID} import java.util.stream.Collectors +import java.util.{Collections, UUID} import scala.jdk.CollectionConverters._ class ContentPlayerPadContent(val pad: Pad, val `type`: String) extends PadContent(pad) with Pauseable with Durationable with Playlistable with Fadeable { @@ -32,6 +31,8 @@ class ContentPlayerPadContent(val pad: Pad, val `type`: String) extends PadConte private[content] val _durationProperty = new SimpleObjectProperty[Duration] private[content] val _positionProperty = new SimpleObjectProperty[Duration] + private[content] val listeners: util.Set[PlaylistListener] = new util.HashSet[PlaylistListener]() + private var showingLastFrame: Boolean = false private var isPause: Boolean = false @@ -315,4 +316,12 @@ class ContentPlayerPadContent(val pad: Pad, val `type`: String) extends PadConte ).asInstanceOf[util.List[UUID]] zoneConfiguration.zones.asScala.filter(zone => selectedZoneIds.contains(zone.id)).toSeq } + + /* + Listener + */ + + override def addPlaylistListener(listener: PlaylistListener): Unit = listeners.add(listener) + + override def removePlaylistListener(listener: PlaylistListener): Unit = listeners.remove(listener) } diff --git a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/util/package.scala b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/util/package.scala index a03e9ed9cff725f64f68845f2b88fd7fd43b7cce..14526479256ffb973bc8fd278df46f82b2b82f32 100644 --- a/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/util/package.scala +++ b/PlayWallPlugins/PlayWallPluginContentPlayer/src/main/scala/de/tobias/playpad/plugin/content/util/package.scala @@ -17,7 +17,7 @@ package object util { def apply(index: Int): E = list.get(index) - def length: Long = list.size() + def length: Int = list.size() def isNotEmpty: Boolean = !list.isEmpty