interactivespaces.util.sampling.SampledDataSequencePlayer.java Source code

Java tutorial

Introduction

Here is the source code for interactivespaces.util.sampling.SampledDataSequencePlayer.java

Source

/*
 * Copyright (C) 2014 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package interactivespaces.util.sampling;

import interactivespaces.util.resource.ManagedResource;
import interactivespaces.util.sampling.SampledDataSequence.SampledDataFrame;

import org.apache.commons.logging.Log;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;

/**
 * Send a sampled data sequence out as a series of frames.
 *
 * @author Keith M. Hughes
 */
public class SampledDataSequencePlayer implements ManagedResource {

    /**
     * The data to be sent.
     */
    private final SampledDataSequence sequence;

    /**
     * The object which will actually transmit the samples.
     */
    private final SampledDataSequenceSampleSender sender;

    /**
     * The executor service for sending the data.
     */
    private final ScheduledExecutorService executorService;

    /**
     * The future for the sending task.
     */
    private Future<?> runningFuture;

    /**
     * The logger to use.
     */
    private final Log log;

    /**
     * Construct a sampled data sequence player.
     *
     * @param sequence
     *          the sequence to play
     * @param sender
     *          the player of the data
     * @param executorService
     *          the executor service to get a thread for the player
     * @param log
     *          the logger to use
     */
    public SampledDataSequencePlayer(SampledDataSequence sequence, SampledDataSequenceSampleSender sender,
            ScheduledExecutorService executorService, Log log) {
        this.sequence = sequence;
        this.sender = sender;
        this.executorService = executorService;
        this.log = log;
    }

    @Override
    public void startup() {
        // Nothing to do during startup as this should be started manually.
    }

    @Override
    public void shutdown() {
        stopPlayback();
    }

    /**
     * Play the frames in sequence.
     *
     * @throws InterruptedException
     *           the player has been interrupted
     */
    private void play() throws InterruptedException {

        List<SampledDataFrame> frames = sequence.getFrames();
        int maxFrames = frames.size() - 1;

        while (!Thread.interrupted()) {
            log.info("Starting playback of sampled data");
            SampledDataFrame currentFrame = frames.get(0);
            int[] samples = currentFrame.getSamples();
            sender.sendSampledData(currentFrame.getSource(), Arrays.copyOf(samples, samples.length));
            SampledDataFrame previousFrame;
            for (int frame = 1; !Thread.interrupted() && frame < maxFrames; frame++) {
                previousFrame = currentFrame;
                currentFrame = frames.get(frame);

                long delay = currentFrame.getTimestamp() - previousFrame.getTimestamp();
                if (delay > 0) {
                    Thread.sleep(delay);
                }

                samples = currentFrame.getSamples();
                sender.sendSampledData(currentFrame.getSource(), Arrays.copyOf(samples, samples.length));
            }
            log.info("Ending playback of sampled data");
        }
    }

    /**
     * Start playing the data.
     *
     * <p>
     * Can be called more than once, only the first time will start sending.
     */
    public synchronized void startPlayback() {
        if (runningFuture == null) {
            runningFuture = executorService.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        play();
                    } catch (InterruptedException e) {
                        log.info("Playback of sample data frames interrupted");
                    } catch (Exception e) {
                        log.error("Error while sending sampled data frame", e);
                    }
                }
            });
        }
    }

    /**
     * Stop sending data.
     *
     * <p>
     * Can be called multiple times.
     */
    public synchronized void stopPlayback() {
        if (runningFuture != null) {
            runningFuture.cancel(true);
            runningFuture = null;
        }
    }

    /**
     * The data sender.
     *
     * @author Keith M. Hughes
     */
    public interface SampledDataSequenceSampleSender {

        /**
         * Send data from a source.
         *
         * @param source
         *          name of the source
         * @param samples
         *          the samples for the source in the current frame
         */
        void sendSampledData(String source, int[] samples);
    }
}