package de.tobias.playpad; import java.nio.file.Path; import java.util.ArrayList; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.List; import de.tobias.playpad.audio.AudioHandler; import de.tobias.playpad.pad.PadStatus; import de.tobias.playpad.pad.conntent.PadContent; import de.tobias.utils.util.Worker; import javafx.application.Platform; import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.util.Duration; public class NativeAudioMacHandler extends AudioHandler { private static final int SLEEP_TIME_POSITION = 100; private static int counter = 0; private final int id; private ObjectProperty<Duration> positionProperty; private ObjectProperty<Duration> durationProperty; private boolean isLoaded; private static Thread positionThread; private static List<NativeAudioMacHandler> playedHandlers = new ArrayList<>(); static { positionThread = new Thread(() -> { while (true) { try { if (playedHandlers.isEmpty()) { synchronized (positionThread) { positionThread.wait(); } } for (Iterator<NativeAudioMacHandler> iterator = playedHandlers.iterator(); iterator.hasNext();) { NativeAudioMacHandler handler = iterator.next(); Duration seconds = Duration.seconds(NativeAudio.getPosition(handler.id)); Platform.runLater(() -> handler.positionProperty.set(seconds)); } Thread.sleep(SLEEP_TIME_POSITION); } catch (InterruptedException e) { } catch (ConcurrentModificationException e) { } catch (Exception e) { e.printStackTrace(); } } }); positionThread.start(); } public NativeAudioMacHandler(PadContent content) { super(content); id = counter++; positionProperty = new SimpleObjectProperty<>(); durationProperty = new SimpleObjectProperty<>(); } @Override public void play() { NativeAudio.play(id); boolean start = false; if (playedHandlers.isEmpty()) { start = true; } if (!playedHandlers.contains(this)) playedHandlers.add(this); if (start) { synchronized (positionThread) { positionThread.notify(); } } } @Override public void pause() { NativeAudio.pause(id); if (playedHandlers.contains(this)) playedHandlers.remove(this); } @Override public void stop() { NativeAudio.stop(id); if (playedHandlers.contains(this)) playedHandlers.remove(this); } @Override public Duration getPosition() { return positionProperty.get(); } @Override public ReadOnlyObjectProperty<Duration> positionProperty() { return positionProperty; } @Override public Duration getDuration() { return durationProperty.get(); } @Override public ReadOnlyObjectProperty<Duration> durationProperty() { return durationProperty; } @Override public void setVolume(double volume, double masterVolume, double customVolume) { double vol = customVolume * volume * masterVolume; NativeAudio.setVolume(id, vol); } @Override public boolean isMediaLoaded() { return isLoaded; } @Override public void loadMedia(Path[] paths) { Platform.runLater(() -> { if (getContent().getPad().isPadVisible()) { getContent().getPad().getController().getView().showBusyView(true); } }); Worker.runLater(() -> { isLoaded = NativeAudio.load(id, paths[0].toString().replace(" ", "%20")); if (isLoaded) { Platform.runLater(() -> { durationProperty.set(Duration.seconds(NativeAudio.getDuration(id))); getContent().getPad().setStatus(PadStatus.READY); if (getContent().getPad().isPadVisible()) { getContent().getPad().getController().getView().showBusyView(false); } }); } }); } @Override public void unloadMedia() { NativeAudio.dispose(id); } }