Java tutorial
/* * Copyright 2010 Fred Sauer * * 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.allen_sauer.gwt.voices.client; import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_NOT_SUPPORTED; import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_SUPPORTED_MAYBE_READY; import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_SUPPORT_NOT_KNOWN; import com.google.gwt.dom.client.AudioElement; import com.google.gwt.event.dom.client.EndedEvent; import com.google.gwt.event.dom.client.EndedHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.media.client.Audio; import com.google.gwt.user.client.ui.RootPanel; import com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport; /** * Sound object representing sounds which can be played back via HTML5 audio. */ public class Html5Sound extends AbstractSound { // CHECKSTYLE_JAVADOC_OFF /** * @param mimeType the requested MIME type and optional codec according to RFC 4281 * @return the level of support for the provided MIME type */ public static MimeTypeSupport getMimeTypeSupport(String mimeType) { if (!Audio.isSupported()) { return MimeTypeSupport.MIME_TYPE_NOT_SUPPORTED; } String support = Audio.createIfSupported().getAudioElement().canPlayType(mimeType); assert support != null; if (AudioElement.CAN_PLAY_PROBABLY.equals(support)) { return MimeTypeSupport.MIME_TYPE_SUPPORT_READY; } if (AudioElement.CAN_PLAY_MAYBE.equals(support)) { return MimeTypeSupport.MIME_TYPE_SUPPORT_READY; } return MimeTypeSupport.MIME_TYPE_SUPPORT_UNKNOWN; } private Audio audio; private EndedHandler endedHandler = new EndedHandler() { @Override public void onEnded(EndedEvent event) { soundHandlerCollection.fireOnPlaybackComplete(Html5Sound.this); } }; private HandlerRegistration endedRegistration; /** * @param mimeType the requested MIME type and optional codec according to RFC 4281 * @param url the URL of the audio resource * @param streaming whether or not to stream the content, although currently ignored * @param crossOrigin whether or not the content is to be accessed from a different origin */ public Html5Sound(String mimeType, String url, boolean streaming, boolean crossOrigin) { super(mimeType, url, streaming, crossOrigin); createAudioElement(); MimeTypeSupport mimeTypeSupport = getMimeTypeSupport(mimeType); switch (mimeTypeSupport) { case MIME_TYPE_SUPPORT_READY: setLoadState(LOAD_STATE_SUPPORTED_MAYBE_READY); break; case MIME_TYPE_NOT_SUPPORTED: setLoadState(LOAD_STATE_NOT_SUPPORTED); break; case MIME_TYPE_SUPPORT_UNKNOWN: setLoadState(LOAD_STATE_SUPPORT_NOT_KNOWN); throw new IllegalArgumentException("unexpected MIME type support " + mimeTypeSupport); default: throw new IllegalArgumentException("unknown MIME type support " + mimeTypeSupport); } } @Override public int getBalance() { // not implemented return SoundController.DEFAULT_BALANCE; } @Override public boolean getLooping() { return audio.getAudioElement().isLoop(); } @Override public SoundType getSoundType() { return SoundType.HTML5; } @Override public int getVolume() { return (int) (audio.getAudioElement().getVolume() * 100d); } @Override public boolean play() { AudioElement elem = audio.getAudioElement(); elem.pause(); try { // IE9 has been seen to throw an exception here elem.setCurrentTime(0); } catch (Exception ignore) { } if (elem.getCurrentTime() != 0) { /* * Workaround Chrome's inability to play the same audio twice: * http://code.google.com/p/chromium/issues/detail?id=71323 * http://code.google.com/p/chromium/issues/detail?id=75725 */ createAudioElement(); } elem.play(); // best guess is that the sound played, so return true return true; } @Override public void setBalance(int balance) { // not implemented } @Override public void setLooping(boolean looping) { audio.getAudioElement().setLoop(looping); } @Override public void setVolume(int volume) { assert volume >= 0; assert volume <= 100; audio.getAudioElement().setVolume(volume / 100d); } @Override public void stop() { audio.getAudioElement().pause(); } private void createAudioElement() { if (endedRegistration != null) { endedRegistration.removeHandler(); } if (audio != null) { // TODO: remove, once DOM attachment no longer required to sink (bitless) events audio.removeFromParent(); } assert Audio.isSupported(); audio = Audio.createIfSupported(); assert audio != null; AudioElement elem = audio.getAudioElement(); assert elem != null; endedRegistration = audio.addEndedHandler(endedHandler); // TODO: remove, once DOM attachment no longer required to sink (bitless) events RootPanel.get().add(audio); if (isCrossOrigin()) { elem.setAttribute("crossOrigin", "anonymous"); } elem.setSrc(getUrl()); } }