com.bramosystems.oss.player.provider.sample.client.Capsule.java Source code

Java tutorial

Introduction

Here is the source code for com.bramosystems.oss.player.provider.sample.client.Capsule.java

Source

/*
 * Copyright 2009 Sikirulai Braheem
 *
 * 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 com.bramosystems.oss.player.provider.sample.client;

import com.bramosystems.oss.player.core.client.*;
import com.bramosystems.oss.player.core.client.skin.*;
import com.bramosystems.oss.player.core.client.spi.Player;
import com.bramosystems.oss.player.core.event.client.*;
import com.bramosystems.oss.player.provider.sample.client.impl.SamplePlayersProvider;
import com.bramosystems.oss.player.provider.sample.client.skin.CapsuleResourcePack;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.*;
import java.util.ArrayList;

/**
 * Sample custom sound player.
 *
 * <h3>Usage Example</h3>
 *
 * <p>
 * <code><pre>
 * SimplePanel panel = new SimplePanel();   // create panel to hold the player
 * Widget player = null;
 * try {
 *      // create the player
 *      player = new Capsule("www.example.com/mediafile.wma");
 * } catch(PluginVersionException e) {
 *      // catch plugin version exception and alert user, possibly providing a link
 *      // to the plugin download page.
 *      player = new HTML(".. some nice message telling the user to download plugin first ..");
 * } catch(PluginNotFoundException e) {
 *      // catch PluginNotFoundException and tell user to download plugin, possibly providing
 *      // a link to the plugin download page.
 *      player = new HTML(".. another kind of message telling the user to download plugin..");
 * }
 *
 * panel.setWidget(player); // add player to panel.
 * </pre></code>
 *
 * @author Sikirulai Braheem
 */
@Player(name = "Capsule", providerFactory = SamplePlayersProvider.class, minPluginVersion = "1.0.0")
public class Capsule extends CustomAudioPlayer {

    private CapsuleUIResource uiRes;
    private ProgressBar progress;
    private Button play, stop;
    private Timer playTimer, infoTimer;
    private PlayState playState;
    private VolumeControl vc;
    private MediaInfo mInfo;
    private ArrayList<MediaInfo.MediaInfoKey> mItems;
    private int infoIndex;

    /**
     * Constructs <code>Capsule</code> player to automatically playback the
     * media located at {@code mediaURL}.
     *
     * @param mediaURL the URL of the media to playback
     *
     * @throws PluginVersionException if the required plugin version is not installed on the client.
     * @throws PluginNotFoundException if the plugin is not installed on the client.
     */
    public Capsule(String mediaURL) throws PluginNotFoundException, PluginVersionException, LoadException {
        this(mediaURL, true);
    }

    /**
     * Constructs <code>Capsule</code> player to automatically playback the
     * media located at {@code mediaURL}, if {@code autoplay} is {@code true}.
     *
     * @param mediaURL the URL of the media to playback
     * @param autoplay {@code true} to start playing automatically, {@code false} otherwise
     *
     * @throws PluginVersionException if the required plugin version is not installed on the client.
     * @throws PluginNotFoundException if the plugin is not installed on the client.
     */
    public Capsule(String mediaURL, boolean autoplay)
            throws PluginNotFoundException, PluginVersionException, LoadException {
        this(Plugin.Auto, mediaURL, autoplay);
    }

    /**
     * Constructs <code>Capsule</code> player to automatically playback the
     * media located at {@code mediaURL}, if {@code autoplay} is {@code true} using
     * the specified {@code plugin}.
     *
     * <p>
     * This constructor uses the default {@link CapsuleResourcePack} to build the UI controls.
     * </p>
     *
     * @param plugin plugin to use for playback.
     * @param mediaURL the URL of the media to playback
     * @param autoplay {@code true} to start playing automatically, {@code false} otherwise
     *
     * @throws PluginVersionException if the required plugin version is not installed on the client.
     * @throws PluginNotFoundException if the plugin is not installed on the client.
     *
     * @see Plugin
     */
    public Capsule(Plugin plugin, String mediaURL, boolean autoplay)
            throws PluginNotFoundException, PluginVersionException, LoadException {
        this(plugin, mediaURL, autoplay,
                ((CapsuleResourcePack) GWT.create(CapsuleResourcePack.class)).uiResource());
    }

    /**
     * Constructs <code>Capsule</code> player to automatically playback the
     * media located at {@code mediaURL}, if {@code autoplay} is {@code true} using
     * the specified {@code plugin}.
     *
     * @param plugin plugin to use for playback.
     * @param mediaURL the URL of the media to playback
     * @param autoplay {@code true} to start playing automatically, {@code false} otherwise
     * @param uiResource the CSS resource to use for the UI
     *
     * @throws PluginVersionException if the required plugin version is not installed on the client.
     * @throws PluginNotFoundException if the plugin is not installed on the client.
     *
     * @see Plugin
     * @since 1.2
     */
    public Capsule(Plugin plugin, String mediaURL, boolean autoplay, CapsuleUIResource uiResource)
            throws PluginNotFoundException, PluginVersionException, LoadException { // TODO: remove LoadEx on API 2.0.3 release ...
        super(plugin, mediaURL, autoplay, "64px", "100%");
        uiRes = uiResource;
        uiRes.ensureInjected();
        playState = PlayState.Stop;
        mItems = new ArrayList<MediaInfo.MediaInfoKey>();

        progress = new ProgressBar();
        progress.setWidth("95%");

        playTimer = new Timer() {

            @Override
            public void run() {
                progress.setTime(getPlayPosition(), getMediaDuration());
            }
        };
        infoTimer = new Timer() {

            @Override
            public void run() {
                if (mItems.size() > 0) {
                    MediaInfo.MediaInfoKey item = mItems.get(infoIndex);
                    progress.setInfo(item.toString() + ": " + mInfo.getItem(item));
                    infoIndex++;
                    infoIndex %= mItems.size();
                } else {
                    cancel();
                }
            }

            @Override
            public void cancel() {
                super.cancel();
                progress.setInfo("");
            }
        };

        play = new CButton(uiRes.pauseDisabled(), new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                switch (playState) {
                case Stop:
                case Pause:
                    try { // play media...
                        play.setEnabled(false);
                        playMedia();
                    } catch (PlayException ex) {
                        fireError(ex.getMessage());
                    }
                    break;
                case Playing:
                    pauseMedia();
                }
            }
        });
        play.setStyleName(uiRes.play());
        play.setEnabled(false);

        stop = new CButton(uiRes.stopDisabled(), new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                stopMedia();
            }
        });
        stop.setStyleName(uiRes.stop());
        stop.setEnabled(false);

        vc = new VolumeControl(5);
        vc.setStyleName(uiRes.volume());
        vc.addVolumeChangeHandler(new VolumeChangeHandler() {

            @Override
            public void onVolumeChanged(VolumeChangeEvent event) {
                setVolume(event.getNewVolume());
            }
        });
        vc.setPopupStyleName("player-Capsule-volumeControl");

        addLoadingProgressHandler(new LoadingProgressHandler() {

            @Override
            public void onLoadingProgress(LoadingProgressEvent event) {
                double prog = event.getProgress();
                progress.setLoadingProgress(prog);
                if (prog == 1.0) {
                    progress.setTime(0, getMediaDuration());
                    vc.setVolume(getVolume());
                }
            }
        });
        addPlayStateHandler(new PlayStateHandler() {

            @Override
            public void onPlayStateChanged(PlayStateEvent event) {
                switch (event.getPlayState()) {
                case Stopped:
                case Finished:
                    toPlayState(PlayState.Stop);
                    break;
                case Paused:
                    toPlayState(PlayState.Pause);
                    break;
                case Started:
                    toPlayState(PlayState.Playing);
                    break;
                }
            }
        });
        addPlayerStateHandler(new PlayerStateHandler() {

            @Override
            public void onPlayerStateChanged(PlayerStateEvent event) {
                switch (event.getPlayerState()) {
                case BufferingFinished:
                case BufferingStarted:
                    break;
                case Ready:
                    play.setEnabled(true);
                    vc.setVolume(getVolume());
                }
            }
        });

        // build the UI...
        DockPanel main = new DockPanel();
        main.setStyleName("player-Capsule");
        main.setSpacing(0);
        main.setVerticalAlignment(DockPanel.ALIGN_MIDDLE);
        main.setSize("100%", "64px");

        main.add(new CEdge(uiRes.leftEdge()), DockPanel.WEST);
        main.add(play, DockPanel.WEST);
        main.add(stop, DockPanel.WEST);
        main.add(new CEdge(uiRes.rightEdge()), DockPanel.EAST);
        main.add(vc, DockPanel.EAST);
        main.add(progress, DockPanel.CENTER);
        main.setCellWidth(progress, "100%");
        main.setCellHorizontalAlignment(progress, DockPanel.ALIGN_CENTER);
        setPlayerControlWidget(main);
        setWidth("100%");
    }

    /**
     * Overridden to release resources.
     */
    @Override
    protected void onUnload() {
        playTimer.cancel();
        infoTimer.cancel();
    }

    private void toPlayState(PlayState state) {
        switch (state) {
        case Playing:
            play.setEnabled(true);
            stop.setEnabled(true);
            vc.setVolume(getVolume());
            playTimer.scheduleRepeating(1000);
            infoTimer.scheduleRepeating(3000);

            play.setStylePrimaryName(uiRes.pause());
            break;
        case Stop:
            progress.setTime(0, getMediaDuration());
            progress.setFinishedState();
            stop.setEnabled(false);
            playTimer.cancel();
            infoTimer.cancel();
        case Pause:
            play.setStylePrimaryName(uiRes.play());
            break;
        }
        playState = state;
    }

    private class ProgressBar extends Composite {

        private MediaSeekBar seekBar;
        private Label timeLabel, infoLabel;

        public ProgressBar() {
            timeLabel = new Label("--:-- / --:--");
            timeLabel.setStyleName("player-Capsule-info");
            timeLabel.setWordWrap(false);
            timeLabel.setHorizontalAlignment(Label.ALIGN_RIGHT);

            infoLabel = new Label();
            infoLabel.setStyleName("player-Capsule-info");
            infoLabel.setWordWrap(false);

            DockPanel dp = new DockPanel();
            dp.setVerticalAlignment(DockPanel.ALIGN_MIDDLE);
            dp.setWidth("100%");

            dp.add(timeLabel, DockPanel.EAST);
            dp.add(infoLabel, DockPanel.CENTER);

            seekBar = new CSSSeekBar(5);
            seekBar.setStylePrimaryName("player-Capsule-seekbar");
            seekBar.setWidth("100%");
            seekBar.addSeekChangeHandler(new SeekChangeHandler() {

                @Override
                public void onSeekChanged(SeekChangeEvent event) {
                    setPlayPosition(event.getSeekPosition() * getMediaDuration());
                }
            });

            VerticalPanel main = new VerticalPanel();
            main.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
            main.setVerticalAlignment(VerticalPanel.ALIGN_MIDDLE);
            main.setSpacing(2);
            main.setWidth("80%");
            main.add(dp);
            main.add(seekBar);
            initWidget(main);
        }

        public void setTime(double timeInMS, double duration) {
            timeLabel.setText(PlayerUtil.formatMediaTime((long) timeInMS) + " / "
                    + PlayerUtil.formatMediaTime((long) duration));
            seekBar.setPlayingProgress(timeInMS / duration);
        }

        public void setLoadingProgress(double progress) {
            seekBar.setLoadingProgress(progress);
        }

        public void setInfo(String info) {
            infoLabel.setText(info);
        }

        public void setFinishedState() {
            setTime(0, getMediaDuration());
            seekBar.setPlayingProgress(0);
        }
    }

    private enum PlayState {

        Playing, Pause, Stop;
    }

    /**
    * Defines the CSS class names used by the {@linkplain Capsule} widget.
    * These class names should be defined in a stylesheet and linked as required by
    * GWT's ClientBundle
    *
    * @since 1.2
    * @author Sikiru Braheem
    */
    public static interface CapsuleUIResource extends CssResource {

        public String leftEdge();

        public String rightEdge();

        public String pauseDisabled();

        public String pause();

        public String play();

        public String playDisabled();

        public String stop();

        public String stopDisabled();

        public String volume();
    }

    private class CButton extends Button {

        private String disabledStyle = "disabled";

        public CButton(String disabledStyleName, ClickHandler handler) {
            super();
            addClickHandler(handler);
            disabledStyle = disabledStyleName;
        }

        @Override
        public void setEnabled(boolean enabled) {
            super.setEnabled(enabled);
            if (enabled) {
                removeStyleName(disabledStyle);
            } else {
                addStyleName(disabledStyle);
            }
        }
    }

    private class CEdge extends Label {

        public CEdge(String styleName) {
            super();
            setStyleName(styleName);
        }

    }
}