001package org.intellimate.izou.sdk.frameworks.permanentSoundOutput.output;
002
003import org.intellimate.izou.events.EventModel;
004import org.intellimate.izou.identification.Identification;
005import org.intellimate.izou.resource.ResourceModel;
006import org.intellimate.izou.sdk.Context;
007import org.intellimate.izou.sdk.frameworks.common.resources.SelectorResource;
008import org.intellimate.izou.sdk.frameworks.permanentSoundOutput.events.MuteEvent;
009import org.intellimate.izou.sdk.frameworks.permanentSoundOutput.events.StopEvent;
010import org.intellimate.izou.sdk.frameworks.permanentSoundOutput.events.UnMuteEvent;
011import org.intellimate.izou.sdk.output.OutputPlugin;
012
013import java.util.List;
014import java.util.Objects;
015import java.util.Optional;
016import java.util.concurrent.CompletableFuture;
017
018/**
019 * extend this class to use the framework
020 * @author LeanderK
021 * @version 1.0
022 */
023public abstract class SimplePermanentSoundOutputPlugin<T> extends OutputPlugin<T> implements PermanentSoundUsed,
024        PermanentSoundHelper, PermanentSoundResources {
025    private boolean isCurrentlyPlayingSound = false;
026    public final boolean isUsingJava;
027
028    /**
029     * creates a new output-plugin with a new id
030     *
031     * @param context context
032     * @param id the id of the new output-plugin
033     */
034    public SimplePermanentSoundOutputPlugin(Context context, String id, boolean isUsingJava) {
035        super(context, id);
036        resourcesInit(context);
037        this.isUsingJava = isUsingJava;
038    }
039
040    /**
041     * Default implementation waits until a new Event has been received and then processes it.
042     * <p>
043     * This method is made to be overwritten as seen fit by the developer
044     *
045     * @return the recently added Event-instance to be processed by the outputPlugin
046     * @throws InterruptedException if interrupted while waiting
047     */
048    @Override
049    public EventModel blockingQueueHandling() throws InterruptedException {
050        EventModel eventModel = super.blockingQueueHandling();
051        if (eventModel.containsDescriptor(MuteEvent.ID)) {
052            List<ResourceModel> resourceModels =
053                    eventModel.getListResourceContainer().provideResource(SelectorResource.RESOURCE_ID);
054            if (resourceModels.isEmpty()) {
055                mute();
056            } else {
057                resourceModels.stream()
058                        .map(resourceModel -> resourceModel.getResource() instanceof Identification ?
059                                ((Identification) resourceModel.getResource()) : null)
060                        .filter(Objects::nonNull)
061                        .filter(this::isOwner)
062                        .findAny()
063                        .ifPresent(id -> mute());
064            }
065        }
066        if (eventModel.containsDescriptor(UnMuteEvent.ID)) {
067            List<ResourceModel> resourceModels =
068                    eventModel.getListResourceContainer().provideResource(SelectorResource.RESOURCE_ID);
069            if (resourceModels.isEmpty()) {
070                unMute();
071            } else {
072                resourceModels.stream()
073                        .map(resourceModel -> resourceModel.getResource() instanceof Identification ?
074                                ((Identification) resourceModel.getResource()) : null)
075                        .filter(Objects::nonNull)
076                        .filter(this::isOwner)
077                        .findAny()
078                        .ifPresent(id -> unMute());
079            }
080        }
081        if (eventModel.containsDescriptor(StopEvent.ID)) {
082            List<ResourceModel> resourceModels =
083                    eventModel.getListResourceContainer().provideResource(SelectorResource.RESOURCE_ID);
084            if (resourceModels.isEmpty()) {
085                stopSound();
086            } else {
087                resourceModels.stream()
088                        .map(resourceModel -> resourceModel.getResource() instanceof Identification ?
089                                ((Identification) resourceModel.getResource()) : null)
090                        .filter(Objects::nonNull)
091                        .filter(this::isOwner)
092                        .findAny()
093                        .ifPresent(id -> stopSound());
094            }
095        }
096        return eventModel;
097    }
098
099
100
101    /**
102     * retruns true if playing and false if not
103     *
104     * @return tre if playing
105     */
106    @Override
107    public boolean isOutputRunning() {
108        return isCurrentlyPlayingSound;
109    }
110
111    /**
112     * true if using java, false if not (and for example a C-library)
113     *
114     * @return true if using java
115     */
116    @Override
117    public boolean isUsingJava() {
118        return isUsingJava;
119    }
120
121    /**
122     * use this method to start playing sound (only plays sound if it is not already playing)
123     * @param function the function which plays the sound
124     * @return the Future
125     */
126    public Optional<CompletableFuture<Void>> startPlaying(Runnable function) {
127        if (isCurrentlyPlayingSound)
128            return Optional.empty();
129        CompletableFuture<Void> voidCompletableFuture = submit((Runnable) () -> startedSound(isUsingJava))
130                .thenRun(() -> {
131                    try {
132                        isCurrentlyPlayingSound = true;
133                        function.run();
134                    } finally {
135                        submit((Runnable) this::endedSound);
136                        isCurrentlyPlayingSound = false;
137                    }
138                });
139        return Optional.of(voidCompletableFuture);
140    }
141
142    /**
143     * this method call must mute the plugin
144     */
145    public abstract void mute();
146
147    /**
148     * this method call must un-mute the plugin
149     */
150    public abstract void unMute();
151
152    /**
153     * this method call must stop the sound
154     */
155    public abstract void stopSound();
156}