+++ /dev/null
-/*\r
- * Copyright 2010 Fred Sauer\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client;\r
-\r
-import com.allen_sauer.gwt.voices.client.handler.SoundHandler;\r
-import com.allen_sauer.gwt.voices.client.handler.SoundHandlerCollection;\r
-import com.allen_sauer.gwt.voices.client.handler.SoundLoadStateChangeEvent;\r
-\r
-abstract class AbstractSound implements Sound {\r
- private static final LoadState INITIAL_LOAD_STATE = LoadState.LOAD_STATE_UNINITIALIZED;\r
- protected final SoundHandlerCollection soundHandlerCollection = new SoundHandlerCollection();\r
-\r
- private final boolean crossOrigin;\r
- private LoadState loadState = INITIAL_LOAD_STATE;\r
- private final String mimeType;\r
- private final boolean streaming;\r
- private final String url;\r
-\r
- public AbstractSound(String mimeType, String url, boolean streaming, boolean crossOrigin) {\r
- this.mimeType = mimeType;\r
- this.url = url;\r
- this.streaming = streaming;\r
- this.crossOrigin = crossOrigin;\r
- }\r
-\r
- @Override\r
- public final void addEventHandler(SoundHandler handler) {\r
- soundHandlerCollection.add(handler);\r
- if (loadState != INITIAL_LOAD_STATE) {\r
- handler.onSoundLoadStateChange(new SoundLoadStateChangeEvent(this));\r
- }\r
- }\r
-\r
- @Override\r
- public final LoadState getLoadState() {\r
- return loadState;\r
- }\r
-\r
- @Override\r
- public final String getMimeType() {\r
- return mimeType;\r
- }\r
-\r
- @Override\r
- public abstract SoundType getSoundType();\r
-\r
- @Override\r
- public final String getUrl() {\r
- return url;\r
- }\r
-\r
- public boolean isCrossOrigin() {\r
- return crossOrigin;\r
- }\r
-\r
- public final boolean isStreaming() {\r
- return streaming;\r
- }\r
-\r
- @Override\r
- public final void removeEventHandler(SoundHandler handler) {\r
- soundHandlerCollection.remove(handler);\r
- }\r
-\r
- public final void setLoadState(LoadState loadState) {\r
- if (loadState != this.loadState) {\r
- this.loadState = loadState;\r
- if (loadState != INITIAL_LOAD_STATE) {\r
- soundHandlerCollection.fireOnSoundLoadStateChange(this);\r
- }\r
- }\r
- }\r
-\r
- @Override\r
- public final String toString() {\r
- return getSoundType() + "(\"" + mimeType + "\", \"" + url + "\", "\r
- + (isStreaming() ? "streaming" : "not streaming") + ", "\r
- + (isCrossOrigin() ? "cross origin" : "same origin") + ")";\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client;\r
-\r
-import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_SUPPORTED_AND_READY;\r
-\r
-import com.google.gwt.core.client.Scheduler;\r
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;\r
-\r
-import com.allen_sauer.gwt.voices.client.ui.VoicesMovie;\r
-\r
-import java.util.ArrayList;\r
-\r
-/**\r
- * <a href= 'http://www.adobe.com/products/flashplayer/'>Adobe Flash Player</a> based\r
- * sound.\r
- */\r
-public class FlashSound extends AbstractSound {\r
- // CHECKSTYLE_JAVADOC_OFF\r
-\r
- private static ArrayList<FlashSound> soundList = new ArrayList<FlashSound>();\r
-\r
- @SuppressWarnings("unused")\r
- private static void playbackCompleted(final int index) {\r
- Scheduler.get().scheduleDeferred(new ScheduledCommand() {\r
- @Override\r
- public void execute() {\r
- soundList.get(index).playbackCompleted();\r
- }\r
- });\r
- }\r
-\r
- @SuppressWarnings("unused")\r
- private static void soundLoaded(final int index) {\r
- Scheduler.get().scheduleDeferred(new ScheduledCommand() {\r
- @Override\r
- public void execute() {\r
- soundList.get(index).soundLoaded();\r
- }\r
- });\r
- }\r
-\r
- private int balance = SoundController.DEFAULT_BALANCE;\r
- private boolean looping = SoundController.DEFAULT_LOOPING;\r
- private final int soundNumber;\r
- private boolean soundRegistered = false;\r
- private final VoicesMovie voicesMovie;\r
- private int volume = SoundController.DEFAULT_VOLUME;\r
-\r
- public FlashSound(String mimeType, String url, boolean streaming, boolean crossOrigin,\r
- VoicesMovie voicesMovie) {\r
- super(mimeType, url, streaming, crossOrigin);\r
- this.voicesMovie = voicesMovie;\r
- soundNumber = soundList.size();\r
- soundList.add(this);\r
- if (streaming) {\r
- setLoadState(LOAD_STATE_SUPPORTED_AND_READY);\r
- } else {\r
- registerSound();\r
- }\r
- }\r
-\r
- @Override\r
- public int getBalance() {\r
- return balance;\r
- }\r
-\r
- @Override\r
- public boolean getLooping() {\r
- return looping;\r
- }\r
-\r
- public int getSoundNumber() {\r
- return soundNumber;\r
- }\r
-\r
- @Override\r
- public SoundType getSoundType() {\r
- return SoundType.FLASH;\r
- }\r
-\r
- @Override\r
- public int getVolume() {\r
- return volume;\r
- }\r
-\r
- @Override\r
- public boolean play() {\r
- registerSound();\r
- if (getLoadState() == LOAD_STATE_SUPPORTED_AND_READY) {\r
- // true indicates the sound was played\r
- return voicesMovie.playSound(soundNumber);\r
- }\r
- // sound was not played, return false\r
- return false;\r
- }\r
-\r
- @Override\r
- public void setBalance(int balance) {\r
- assert balance >= -100;\r
- assert balance <= 100;\r
- this.balance = balance;\r
- if (getLoadState() == LOAD_STATE_SUPPORTED_AND_READY) {\r
- voicesMovie.setBalance(soundNumber, balance);\r
- }\r
- }\r
-\r
- @Override\r
- public void setLooping(boolean looping) {\r
- this.looping = looping;\r
- if (getLoadState() == LOAD_STATE_SUPPORTED_AND_READY) {\r
- voicesMovie.setLooping(soundNumber, looping);\r
- }\r
- }\r
-\r
- @Override\r
- public void setVolume(int volume) {\r
- assert volume >= 0;\r
- assert volume <= 100;\r
- this.volume = volume;\r
- if (getLoadState() == LOAD_STATE_SUPPORTED_AND_READY) {\r
- voicesMovie.setVolume(soundNumber, volume);\r
- }\r
- }\r
-\r
- @Override\r
- public void stop() {\r
- if (getLoadState() == LOAD_STATE_SUPPORTED_AND_READY) {\r
- voicesMovie.stopSound(soundNumber);\r
- }\r
- }\r
-\r
- protected void playbackCompleted() {\r
- soundHandlerCollection.fireOnPlaybackComplete(this);\r
- }\r
-\r
- protected void soundLoaded() {\r
- setLoadState(LOAD_STATE_SUPPORTED_AND_READY);\r
- if (volume != SoundController.DEFAULT_VOLUME) {\r
- voicesMovie.setVolume(soundNumber, volume);\r
- }\r
- if (balance != SoundController.DEFAULT_BALANCE) {\r
- voicesMovie.setBalance(soundNumber, balance);\r
- }\r
- if (looping != SoundController.DEFAULT_LOOPING) {\r
- voicesMovie.setLooping(soundNumber, looping);\r
- }\r
- }\r
-\r
- private void registerSound() {\r
- if (!soundRegistered) {\r
- voicesMovie.registerSound(this);\r
- soundRegistered = true;\r
- }\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2010 Fred Sauer\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client;\r
-\r
-import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_NOT_SUPPORTED;\r
-import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_SUPPORTED_MAYBE_READY;\r
-import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_SUPPORT_NOT_KNOWN;\r
-\r
-import com.google.gwt.dom.client.AudioElement;\r
-import com.google.gwt.event.dom.client.EndedEvent;\r
-import com.google.gwt.event.dom.client.EndedHandler;\r
-import com.google.gwt.event.shared.HandlerRegistration;\r
-import com.google.gwt.media.client.Audio;\r
-import com.google.gwt.user.client.ui.RootPanel;\r
-\r
-import com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport;\r
-\r
-/**\r
- * Sound object representing sounds which can be played back via HTML5 audio.\r
- */\r
-public class Html5Sound extends AbstractSound {\r
- // CHECKSTYLE_JAVADOC_OFF\r
-\r
- /**\r
- * @param mimeType the requested MIME type and optional codec according to RFC 4281\r
- * @return the level of support for the provided MIME type\r
- */\r
- public static MimeTypeSupport getMimeTypeSupport(String mimeType) {\r
- if (!Audio.isSupported()) {\r
- return MimeTypeSupport.MIME_TYPE_NOT_SUPPORTED;\r
- }\r
- String support = Audio.createIfSupported().getAudioElement().canPlayType(mimeType);\r
- assert support != null;\r
- if (AudioElement.CAN_PLAY_PROBABLY.equals(support)) {\r
- return MimeTypeSupport.MIME_TYPE_SUPPORT_READY;\r
- }\r
- if (AudioElement.CAN_PLAY_MAYBE.equals(support)) {\r
- return MimeTypeSupport.MIME_TYPE_SUPPORT_READY;\r
- }\r
- return MimeTypeSupport.MIME_TYPE_SUPPORT_UNKNOWN;\r
- }\r
-\r
- private Audio audio;\r
-\r
- private EndedHandler endedHandler = new EndedHandler() {\r
- @Override\r
- public void onEnded(EndedEvent event) {\r
- soundHandlerCollection.fireOnPlaybackComplete(Html5Sound.this);\r
- }\r
- };\r
-\r
- private HandlerRegistration endedRegistration;\r
-\r
- /**\r
- * @param mimeType the requested MIME type and optional codec according to RFC 4281\r
- * @param url the URL of the audio resource\r
- * @param streaming whether or not to stream the content, although currently ignored\r
- * @param crossOrigin whether or not the content is to be accessed from a different origin\r
- */\r
- public Html5Sound(String mimeType, String url, boolean streaming, boolean crossOrigin) {\r
- super(mimeType, url, streaming, crossOrigin);\r
-\r
- createAudioElement();\r
-\r
- MimeTypeSupport mimeTypeSupport = getMimeTypeSupport(mimeType);\r
- switch (mimeTypeSupport) {\r
- case MIME_TYPE_SUPPORT_READY:\r
- setLoadState(LOAD_STATE_SUPPORTED_MAYBE_READY);\r
- break;\r
- case MIME_TYPE_NOT_SUPPORTED:\r
- setLoadState(LOAD_STATE_NOT_SUPPORTED);\r
- break;\r
- case MIME_TYPE_SUPPORT_UNKNOWN:\r
- setLoadState(LOAD_STATE_SUPPORT_NOT_KNOWN);\r
- throw new IllegalArgumentException("unexpected MIME type support " + mimeTypeSupport);\r
- default:\r
- throw new IllegalArgumentException("unknown MIME type support " + mimeTypeSupport);\r
- }\r
- }\r
-\r
- @Override\r
- public int getBalance() {\r
- // not implemented\r
- return SoundController.DEFAULT_BALANCE;\r
- }\r
-\r
- @Override\r
- public boolean getLooping() {\r
- return audio.getAudioElement().isLoop();\r
- }\r
-\r
- @Override\r
- public SoundType getSoundType() {\r
- return SoundType.HTML5;\r
- }\r
-\r
- @Override\r
- public int getVolume() {\r
- return (int) (audio.getAudioElement().getVolume() * 100d);\r
- }\r
-\r
- @Override\r
- public boolean play() {\r
- AudioElement elem = audio.getAudioElement();\r
- elem.pause();\r
- try {\r
- // IE9 has been seen to throw an exception here\r
- elem.setCurrentTime(0);\r
- } catch (Exception ignore) {\r
- }\r
- if (elem.getCurrentTime() != 0) {\r
- /*\r
- * Workaround Chrome's inability to play the same audio twice:\r
- * http://code.google.com/p/chromium/issues/detail?id=71323\r
- * http://code.google.com/p/chromium/issues/detail?id=75725\r
- */\r
- createAudioElement();\r
- }\r
- elem.play();\r
- // best guess is that the sound played, so return true\r
- return true;\r
- }\r
-\r
- @Override\r
- public void setBalance(int balance) {\r
- // not implemented\r
- }\r
-\r
- @Override\r
- public void setLooping(boolean looping) {\r
- audio.getAudioElement().setLoop(looping);\r
- }\r
-\r
- @Override\r
- public void setVolume(int volume) {\r
- assert volume >= 0;\r
- assert volume <= 100;\r
- audio.getAudioElement().setVolume(volume / 100d);\r
- }\r
-\r
- @Override\r
- public void stop() {\r
- audio.getAudioElement().pause();\r
- }\r
-\r
- private void createAudioElement() {\r
- if (endedRegistration != null) {\r
- endedRegistration.removeHandler();\r
- }\r
- if (audio != null) {\r
- // TODO: remove, once DOM attachment no longer required to sink (bitless) events\r
- audio.removeFromParent();\r
- }\r
- assert Audio.isSupported();\r
- audio = Audio.createIfSupported();\r
- assert audio != null;\r
- AudioElement elem = audio.getAudioElement();\r
- assert elem != null;\r
-\r
- endedRegistration = audio.addEndedHandler(endedHandler);\r
-\r
- // TODO: remove, once DOM attachment no longer required to sink (bitless) events\r
- RootPanel.get().add(audio);\r
-\r
- if (isCrossOrigin()) {\r
- elem.setAttribute("crossOrigin", "anonymous");\r
- }\r
- elem.setSrc(getUrl());\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2010 Fred Sauer\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client;\r
-\r
-import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_NOT_SUPPORTED;\r
-import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_SUPPORTED_MAYBE_READY;\r
-import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_SUPPORTED_NOT_READY;\r
-import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_SUPPORT_NOT_KNOWN;\r
-\r
-import com.google.gwt.core.client.GWT;\r
-import com.google.gwt.dom.client.Element;\r
-\r
-import com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport;\r
-import com.allen_sauer.gwt.voices.client.ui.impl.NativeSoundImpl;\r
-\r
-/**\r
- * Sound object representing sounds which can be played back natively by the browser, i.e. without\r
- * additional plugins.\r
- */\r
-public class NativeSound extends AbstractSound {\r
- // CHECKSTYLE_JAVADOC_OFF\r
-\r
- protected static NativeSoundImpl impl;\r
- static {\r
- impl = (NativeSoundImpl) GWT.create(NativeSoundImpl.class);\r
- }\r
-\r
- public static MimeTypeSupport getMimeTypeSupport(String mimeType) {\r
- return impl.getMimeTypeSupport(mimeType);\r
- }\r
-\r
- private int balance = SoundController.DEFAULT_BALANCE;\r
-\r
- private Element element;\r
-\r
- private final String mimeType;\r
-\r
- private final Element soundControllerElement;\r
-\r
- private int volume = SoundController.DEFAULT_VOLUME;\r
-\r
- public NativeSound(String mimeType, String url, boolean streaming, boolean crossOrigin,\r
- Element soundControllerElement) {\r
- super(mimeType, url, streaming, crossOrigin);\r
-\r
- this.soundControllerElement = soundControllerElement;\r
- this.mimeType = mimeType;\r
- // TODO: determine whether requests can be cross origin\r
- impl.preload(soundControllerElement, mimeType, url);\r
- element = impl.createElement(url);\r
-\r
- MimeTypeSupport mimeTypeSupport = getMimeTypeSupport(mimeType);\r
- switch (mimeTypeSupport) {\r
- case MIME_TYPE_SUPPORT_READY:\r
- setLoadState(LOAD_STATE_SUPPORTED_MAYBE_READY);\r
- break;\r
- case MIME_TYPE_NOT_SUPPORTED:\r
- setLoadState(LOAD_STATE_NOT_SUPPORTED);\r
- break;\r
- case MIME_TYPE_SUPPORT_UNKNOWN:\r
- setLoadState(LOAD_STATE_SUPPORT_NOT_KNOWN);\r
- break;\r
- case MIME_TYPE_SUPPORT_NOT_READY:\r
- setLoadState(LOAD_STATE_SUPPORTED_NOT_READY);\r
- break;\r
- default:\r
- throw new IllegalArgumentException("unknown MIME type support " + mimeTypeSupport);\r
- }\r
- }\r
-\r
- @Override\r
- public int getBalance() {\r
- return balance;\r
- }\r
-\r
- @Override\r
- public boolean getLooping() {\r
- return impl.getLooping(element);\r
- }\r
-\r
- @Override\r
- public SoundType getSoundType() {\r
- return SoundType.NATIVE;\r
- }\r
-\r
- @Override\r
- public int getVolume() {\r
- return volume;\r
- }\r
-\r
- @Override\r
- public boolean play() {\r
- return impl.play(soundControllerElement, element, mimeType);\r
- }\r
-\r
- @Override\r
- public void setBalance(int balance) {\r
- assert balance >= -100;\r
- assert balance <= 100;\r
- this.balance = balance;\r
- impl.setBalance(element, balance);\r
- }\r
-\r
- @Override\r
- public void setLooping(boolean looping) {\r
- impl.setLooping(element, looping);\r
- }\r
-\r
- @Override\r
- public void setVolume(int volume) {\r
- assert volume >= 0;\r
- assert volume <= 100;\r
- this.volume = volume;\r
- impl.setVolume(element, volume);\r
- }\r
-\r
- @Override\r
- public void stop() {\r
- impl.stop(element);\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2010 Fred Sauer\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client;\r
-\r
-import com.allen_sauer.gwt.voices.client.handler.FiresSoundEvents;\r
-\r
-/**\r
- * Common interface for all concrete supported sound implementations.\r
- */\r
-public interface Sound extends FiresSoundEvents {\r
- /**\r
- * Enumeration of sound load states.\r
- */\r
- enum LoadState {\r
- /**\r
- * Play back of this sound's MIME type is known NOT to be supported. Calling\r
- * {@link Sound#play()} may in rare occasions still work.\r
- */\r
- LOAD_STATE_NOT_SUPPORTED,\r
-\r
- /**\r
- * The sound load state is unknown, and cannot be determined. Hope for the best. Calling\r
- * {@link Sound#play()} may or may not work.\r
- */\r
- LOAD_STATE_SUPPORT_NOT_KNOWN,\r
-\r
- /**\r
- * Play back of this sound's MIME type is supported and this sound object is ready for immediate\r
- * play back. This means that the sound file has either been downloaded by the client (when not\r
- * streaming), or is ready for streaming.\r
- */\r
- LOAD_STATE_SUPPORTED_AND_READY,\r
-\r
- /**\r
- * Play back of this sound's MIME type is known to be supported, however the client browser is\r
- * unable to provide load notification events. It cannot be programmatically determined when the\r
- * client has downloaded the sound. When possible, an attempt will be made to begin downloading\r
- * the sound file in the background. The load state will NOT change to\r
- * {@link LoadState#LOAD_STATE_SUPPORTED_AND_READY}, or indeed to any other state.\r
- */\r
- LOAD_STATE_SUPPORTED_MAYBE_READY,\r
-\r
- /**\r
- * Play back of this sound's MIME type is known to be supported, however the sound file has not\r
- * yet been loaded. The load state is at some point expected to change to\r
- * {@link LoadState#LOAD_STATE_SUPPORTED_AND_READY}.\r
- */\r
- LOAD_STATE_SUPPORTED_NOT_READY,\r
-\r
- /**\r
- * All new sounds start in this load state, after which they will transition at least once to a\r
- * new load state.\r
- */\r
- LOAD_STATE_UNINITIALIZED,\r
- }\r
-\r
- /**\r
- * IANA assigned media type {@value}, from RFC 2045/2046. Typical filename\r
- * extensions include {@literal .au} and {@literal .snd}.\r
- */\r
- String MIME_TYPE_AUDIO_BASIC = "audio/basic";\r
-\r
- /**\r
- * IANA assigned media type {@value}, from RFC 4337. Typical filename extension\r
- * {@literal .mp4}.\r
- *\r
- * @deprecated Use a more specific MIME Type which includes an appropriate {@literal codecs} parameter\r
- */\r
- @Deprecated\r
- String MIME_TYPE_AUDIO_MP4 = "audio/mp4";\r
-\r
- /**\r
- * MIME Type {@value}, for AAC low complexity MP4 as described in\r
- * RFC 4281. Typical filename extension {@literal .mp4}.\r
- */\r
- String MIME_TYPE_AUDIO_MP4_MP4A_40_2 = "audio/mp4; codecs=mp4a.40.2";\r
-\r
- /**\r
- * IANA assigned media type {@value}, from RFC 3003. Typical filename extensions\r
- * include {@literal .mp1}, {@literal .mp2} and {@literal .mp3}.\r
- *\r
- * @deprecated Use a more specific MIME Type which includes an appropriate {@literal codecs} parameter\r
- */\r
- @Deprecated\r
- String MIME_TYPE_AUDIO_MPEG = "audio/mpeg";\r
-\r
- /**\r
- * Non-standard MIME type {@value} for MP3 audio.\r
- * Typical filename extension {@literal .mp3}.\r
- */\r
- String MIME_TYPE_AUDIO_MPEG_MP3 = "audio/mpeg; codecs=MP3";\r
-\r
- /**\r
- * IANA assigned media type {@value}, from RFC 5334. Typical filename\r
- * extensions include {@literal .ogg}.\r
- *\r
- * @deprecated Use a more specific MIME Type which includes an appropriate {@literal codecs} parameter\r
- */\r
- @Deprecated\r
- String MIME_TYPE_AUDIO_OGG = "audio/ogg";\r
-\r
- /**\r
- * IANA assigned media type {@value}, from RFC 5334. Typical filename\r
- * extensions include {@literal .ogg}.\r
- */\r
- String MIME_TYPE_AUDIO_OGG_FLAC = "audio/ogg; codecs=flac";\r
-\r
- /**\r
- * IANA assigned media type {@value}, from RFC 5334. Typical filename\r
- * extensions include {@literal .ogg}.\r
- */\r
- String MIME_TYPE_AUDIO_OGG_SPEEX = "audio/ogg; codecs=speex";\r
-\r
- /**\r
- * IANA assigned media type {@value}, from RFC 5334. Typical filename\r
- * extensions include {@literal .ogg}.\r
- */\r
- String MIME_TYPE_AUDIO_OGG_VORBIS = "audio/ogg; codecs=vorbis";\r
-\r
- /**\r
- * MIME Type {@value} for WAVE audio in Microsoft ADPCM format.\r
- * See RFC 2361 (WAVE and AVI Codec Registries).\r
- * Typical filename extension is {@literal .wav}.\r
- */\r
- String MIME_TYPE_AUDIO_WAV_ADPCM = "audio/wav; codecs=2";\r
-\r
- /**\r
- * MIME Type {@value} for WAVE audio in Microsoft PCM format.\r
- * See RFC 2361 (WAVE and AVI Codec Registries).\r
- * Typical filename extension is {@literal .wav}.\r
- */\r
- String MIME_TYPE_AUDIO_WAV_PCM = "audio/wav; codecs=1";\r
-\r
- /**\r
- * MIME Type {@value} for WAVE audio in unknown format.\r
- * See RFC 2361 (WAVE and AVI Codec Registries).\r
- * Typical filename extension is {@literal .wav}.\r
- */\r
- String MIME_TYPE_AUDIO_WAV_UNKNOWN = "audio/wav; codecs=0";\r
-\r
- /**\r
- * Using {@value} instead of the more popular, but unregistered,\r
- * {@literal audio/aiff}. Typical filename extension is {@literal .aif}.\r
- */\r
- String MIME_TYPE_AUDIO_X_AIFF = "audio/x-aiff";\r
-\r
- /**\r
- * Using {@value} instead of the more popular, but unregistered,\r
- * {@literal audio/midi}. Typical filename extensions include {@literal .mid}. and\r
- * {@literal .midi}.\r
- */\r
- String MIME_TYPE_AUDIO_X_MIDI = "audio/x-midi";\r
-\r
- /**\r
- * Using {@value} instead of the more popular, but\r
- * unregistered, {@literal audio/wav}. Typical filename extension is\r
- * {@literal .wav}.\r
- *\r
- * @deprecated Prefer {@literal audio/wav} over {@literal audio/x-wav}, due\r
- * to better MAC Safari support. Also use a more specific MIME\r
- * Type which includes an appropriate {@literal codecs}\r
- * parameter\r
- */\r
- @Deprecated\r
- String MIME_TYPE_AUDIO_X_WAV = "audio/x-wav";\r
-\r
- /**\r
- * Determine this sound's play back balance (range {@literal 1--}..{@literal 100}).\r
- *\r
- * @return this sound's current play back balance (range {@literal -100}..{@literal 100})\r
- */\r
- int getBalance();\r
-\r
- /**\r
- * Determine the current {@link LoadState} of this sound.\r
- *\r
- * @return current {@link LoadState}\r
- */\r
- LoadState getLoadState();\r
-\r
- /**\r
- * Determine whether this sound is to be played in a loop.\r
- *\r
- * @return true if this sounds is to be played in a loop\r
- */\r
- boolean getLooping();\r
-\r
- /**\r
- * Determine this sound's MIME type.\r
- *\r
- * @return this sound's MIME type\r
- */\r
- String getMimeType();\r
-\r
- /**\r
- * Determine the sound type being used for playback.\r
- *\r
- * @return the sound type\r
- */\r
- SoundType getSoundType();\r
-\r
- /**\r
- * Determine the URL for this sound.\r
- *\r
- * @return this sound's URL\r
- */\r
- String getUrl();\r
-\r
- /**\r
- * Determine this soound's play back volume (range {@literal 0}..{@literal 100}).\r
- *\r
- * @return this sound's current play back volume (range {@literal 0}..{@literal 100})\r
- */\r
- int getVolume();\r
-\r
- /**\r
- * Play (or restart) this sound. This methods returns {@literal false} when the sound could not be\r
- * played. This could happen because the sound system has not yet been initialized, there are no\r
- * available sound channels, or any number of other reasons. A return value of {@literal true}\r
- * indicates that the sound probably played. However, this cannot be known with certainty.\r
- *\r
- * @return {@literal false} if the sound could not be played, {@literal true} otherwise\r
- */\r
- boolean play();\r
-\r
- /**\r
- * Set the left/right speaker balance (range {@literal -100}..{@literal 100}).\r
- *\r
- * @param balance new balance (range {@literal -100}..{@literal 100})\r
- */\r
- void setBalance(int balance);\r
-\r
- /**\r
- * Set whether this sound should be played in a loop.\r
- *\r
- * @param looping true if the sound is to be looped\r
- */\r
- void setLooping(boolean looping);\r
-\r
- /**\r
- * Set this sound's volume (range {@literal 0}..{@literal 100}).\r
- *\r
- * @param volume new volume (range <{@literal 0}..{@literal 100})\r
- */\r
- void setVolume(int volume);\r
-\r
- /**\r
- * Stop play back of this sound.\r
- */\r
- void stop();\r
-}
\ No newline at end of file
+++ /dev/null
-/*\r
- * Copyright 2010 Fred Sauer\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client;\r
-\r
-import com.google.gwt.core.client.GWT;\r
-import com.google.gwt.dom.client.Style;\r
-import com.google.gwt.dom.client.Style.Overflow;\r
-import com.google.gwt.dom.client.Style.Position;\r
-import com.google.gwt.dom.client.Style.Unit;\r
-import com.google.gwt.user.client.DOM;\r
-import com.google.gwt.user.client.Element;\r
-import com.google.gwt.user.client.Window;\r
-import com.google.gwt.user.client.ui.RootPanel;\r
-\r
-import com.allen_sauer.gwt.voices.client.ui.FlashMovie;\r
-import com.allen_sauer.gwt.voices.client.ui.VoicesMovie;\r
-import com.allen_sauer.gwt.voices.client.util.DOMUtil;\r
-\r
-/**\r
- * Main class with which client code interact in order to create {@link Sound}\r
- * objects, which can be played. In addition, each SoundController defines its\r
- * own default volume and provides the ability to prioritize Flash based sound.\r
- *\r
- * <p>\r
- * For the time being do not create 16 or more SoundControllers as that would\r
- * result in 16+ Flash Players, which triggers an Adobe bug, mentioned <a\r
- * href="http://bugzilla.mozilla.org/show_bug.cgi?id=289873#c41">here</a>.\r
- */\r
-public class SoundController {\r
- /**\r
- * Enumeration for varying levels of MIME type support.\r
- */\r
- public enum MimeTypeSupport {\r
- /**\r
- * Play back of the MIME type is known to NOT be supported in this browser,\r
- * based on known capabilities of browsers with the same user agent and\r
- * installed plugins.\r
- */\r
- MIME_TYPE_NOT_SUPPORTED,\r
-\r
- /**\r
- * Play back of the MIME type is known to be supported in this browser,\r
- * based on known capabilities of browsers with the same user agent and\r
- * installed plugins, but this capability has not yet been initialized.\r
- * Usually this is due to a browser plugin, such as <a href=\r
- * 'http://www.adobe.com/products/flashplayer/'>Adobe Flash Player\r
- * < / a > , <a href=\r
- * 'http://www.apple.com/quicktime/download/'>Apple QuickTime</a> or <a\r
- * href=\r
- * 'http://www.microsoft.com/windows/windowsmedia/'>Windows Media Playe\r
- * r < / a > .\r
- */\r
- MIME_TYPE_SUPPORT_NOT_READY,\r
-\r
- /**\r
- * Play back of the MIME type is known to be supported in this browser,\r
- * based on known capabilities of browsers with the same user agent and\r
- * installed plugins.\r
- */\r
- MIME_TYPE_SUPPORT_READY,\r
-\r
- /**\r
- * It is unknown (cannot be determined) whether play back of the MIME type\r
- * is supported in this browser, based on known capabilities of browsers\r
- * with the same user agent and installed plugins.\r
- */\r
- MIME_TYPE_SUPPORT_UNKNOWN,\r
- }\r
-\r
- static final int DEFAULT_BALANCE = 0;\r
- static final boolean DEFAULT_LOOPING = false;\r
- static final int DEFAULT_VOLUME = 100;\r
-\r
- static {\r
- setVersion();\r
- }\r
-\r
- private static native void setVersion()\r
- /*-{\r
- $wnd.$GWT_VOICES_VERSION = "@GWT_VOICES_VERSION@";\r
- }-*/;\r
-\r
- /**\r
- * Our DOM sound container which is positioned off screen.\r
- */\r
- protected final Element soundContainer = DOM.createDiv();\r
- private int defaultVolume = DEFAULT_VOLUME;\r
- private SoundType[] preferredSoundTypes;\r
- private VoicesMovie voicesWrapper;\r
-\r
- /**\r
- * We avoid using the usual, module relative {@link GWT#getModuleBaseURL()} to\r
- * force {@literal gwt-voices.swf} to be loaded from the same domain as the\r
- * host page. This avoids cross origin issues when the page contains a\r
- * {@code <base href="http://...">} tag. To override the base URL in your\r
- * code, use {@link SoundController#setGwtVoicesSwfLocation(String)}.\r
- */\r
- private String gwtVoicesSwfBaseUrl = GWT.getHostPageBaseURL() + GWT.getModuleName() + "/";\r
-\r
- /**\r
- * Default constructor to be used by client code.\r
- */\r
- public SoundController() {\r
- initSoundContainer();\r
- }\r
-\r
- /**\r
- * Create a new Sound object using the provided MIME type and URL. To enable\r
- * streaming, or for cross origin content, use {@link #createSound(String, String, boolean, boolean)}.\r
- *\r
- * @param mimeType MIME type of the new Sound object\r
- * @param url location of the new Sound object\r
- * @return a new Sound object\r
- */\r
- public Sound createSound(String mimeType, String url) {\r
- return createSound(mimeType, url, false, false);\r
- }\r
-\r
- /**\r
- * Create a new Sound object using the provided MIME type and URL.\r
- *\r
- * @param mimeType MIME type of the new Sound object\r
- * @param url location of the new Sound object\r
- * @param streaming whether or not to allow play back to start before sound\r
- * has been fully downloaded\r
- * @param crossOrigin true of the resource is cross origin, false for same origin\r
- * @return a new Sound object\r
- */\r
- public Sound createSound(String mimeType, String url, boolean streaming, boolean crossOrigin) {\r
- Sound sound = createSoundImpl(mimeType, url, streaming, crossOrigin);\r
- sound.setVolume(defaultVolume);\r
- return sound;\r
- }\r
-\r
- /**\r
- * Determine the current preferred sound types for new sounds.\r
- *\r
- * @return the current preferred sound types\r
- *\r
- * @deprecated this method will be removed in a future release\r
- */\r
- @Deprecated\r
- public SoundType[] getPreferredSoundTypes() {\r
- return preferredSoundTypes;\r
- }\r
-\r
- /**\r
- * Set the default volume (range <code>0-100</code>) for new sound.\r
- *\r
- * @param defaultVolume the default volume (range <code>0-100</code>) to be\r
- * used for new sounds\r
- */\r
- public void setDefaultVolume(int defaultVolume) {\r
- this.defaultVolume = defaultVolume;\r
- }\r
-\r
- /**\r
- * Set preferred {@link Sound} class: {@link Html5Sound}, {@link FlashSound},\r
- * {@link NativeSound}.\r
- *\r
- * @param soundTypes the preferred sound types\r
- *\r
- * @deprecated this method is a temporary stop-gap, may be retired at any\r
- * time, and may be made to do nothing at all without warning\r
- */\r
- @Deprecated\r
- public void setPreferredSoundTypes(SoundType... soundTypes) {\r
- for (SoundType s : soundTypes) {\r
- assert s != null;\r
- }\r
- preferredSoundTypes = soundTypes;\r
- }\r
-\r
- /**\r
- * Provides a way to set the base URL for the {@literal gwt-voices.swf} file.\r
- * The provided base URL must ends with a trailing {@literal /}.\r
- *\r
- * @param gwtVoicesSwfBaseUrl base URL relative to which\r
- * {@literal gwt-voices.swf} can be found\r
- */\r
- public void setGwtVoicesSwfLocation(String gwtVoicesSwfBaseUrl) {\r
- assert gwtVoicesSwfBaseUrl.endsWith("/");\r
- this.gwtVoicesSwfBaseUrl = gwtVoicesSwfBaseUrl;\r
- }\r
-\r
- /**\r
- * Lazily instantiate Flash Movie so browser plug-in is not unnecessarily\r
- * triggered.\r
- *\r
- * @return the new movie widget\r
- */\r
- protected VoicesMovie getVoicesMovie() {\r
- if (voicesWrapper == null) {\r
- voicesWrapper = new VoicesMovie(DOMUtil.getUniqueId(), gwtVoicesSwfBaseUrl);\r
- DOM.appendChild(soundContainer, voicesWrapper.getElement());\r
- }\r
- return voicesWrapper;\r
- }\r
-\r
- private Sound createSoundImplHtml5(String mimeType, String url, boolean streaming,\r
- boolean crossOrigin) {\r
- if (Html5Sound.getMimeTypeSupport(mimeType) == MimeTypeSupport.MIME_TYPE_SUPPORT_READY) {\r
- return new Html5Sound(mimeType, url, streaming, crossOrigin);\r
- }\r
- return null;\r
- }\r
-\r
- private Sound createSoundImpl(String mimeType, String url, boolean streaming, boolean crossOrigin) {\r
- Sound sound = null;\r
- for (SoundType c : preferredSoundTypes) {\r
- switch(c) {\r
- case HTML5:\r
- sound = createSoundImplHtml5(mimeType, url, streaming, crossOrigin);\r
- break;\r
- case FLASH:\r
- sound = createSoundImplFlash(mimeType, url, streaming, crossOrigin);\r
- break;\r
- case NATIVE:\r
- sound = createSoundImplWebAudio(mimeType, url, streaming, crossOrigin);\r
- break;\r
- case WEB_AUDIO:\r
- sound = createSoundImplWebAudio(mimeType, url, streaming, crossOrigin);\r
- break;\r
- }\r
- if (sound != null) {\r
- return sound;\r
- }\r
- }\r
-\r
- // Web Audio rocks\r
- sound = createSoundImplWebAudio(mimeType, url, streaming, crossOrigin);\r
- if (sound != null) {\r
- return sound;\r
- }\r
-\r
- sound = createSoundImplFlash(mimeType, url, streaming, crossOrigin);\r
- if (sound != null) {\r
- return sound;\r
- }\r
-\r
- sound = createSoundImplHtml5(mimeType, url, streaming, crossOrigin);\r
- if (sound != null) {\r
- return sound;\r
- }\r
-\r
- // Fallback to native browser audio\r
- sound = new NativeSound(mimeType, url, streaming, crossOrigin, soundContainer);\r
- return sound;\r
- }\r
-\r
- private Sound createSoundImplWebAudio(String mimeType, String url, boolean streaming,\r
- boolean crossOrigin) {\r
- if (WebAudioSound.getMimeTypeSupport(mimeType) == MimeTypeSupport.MIME_TYPE_SUPPORT_READY) {\r
- return new WebAudioSound(mimeType, url, streaming, crossOrigin);\r
- }\r
- return null;\r
- }\r
-\r
- private FlashSound createSoundImplFlash(String mimeType, String url, boolean streaming,\r
- boolean crossOrigin) {\r
- if (url.startsWith("data:")) {\r
- return null;\r
- }\r
- if (FlashMovie.isExternalInterfaceSupported()) {\r
- VoicesMovie vm = getVoicesMovie();\r
- MimeTypeSupport mimeTypeSupport = vm.getMimeTypeSupport(mimeType);\r
- if (mimeTypeSupport == MimeTypeSupport.MIME_TYPE_SUPPORT_READY\r
- || mimeTypeSupport == MimeTypeSupport.MIME_TYPE_SUPPORT_NOT_READY) {\r
- FlashSound sound = new FlashSound(mimeType, url, streaming, crossOrigin, vm);\r
- return sound;\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- private void initSoundContainer() {\r
- String gwtVoices = Window.Location.getParameter(SoundType.QUERY_PARAMETER_NAME);\r
- if (SoundType.FLASH.getQueryParameterValue().equals(gwtVoices)) {\r
- setPreferredSoundTypes(SoundType.FLASH);\r
- } else if (SoundType.HTML5.getQueryParameterValue().equals(gwtVoices)) {\r
- setPreferredSoundTypes(SoundType.HTML5);\r
- } else if (SoundType.WEB_AUDIO.getQueryParameterValue().equals(gwtVoices)) {\r
- setPreferredSoundTypes(SoundType.WEB_AUDIO);\r
- } else if (SoundType.NATIVE.getQueryParameterValue().equals(gwtVoices)) {\r
- setPreferredSoundTypes(SoundType.NATIVE);\r
- } else {\r
- // For now, prefer Flash over HTML5\r
- setPreferredSoundTypes(SoundType.WEB_AUDIO, SoundType.FLASH, SoundType.HTML5);\r
- }\r
-\r
- // place off screen with fixed dimensions and overflow:hidden\r
- RootPanel.getBodyElement().appendChild(soundContainer);\r
- Style style = soundContainer.getStyle();\r
- style.setPosition(Position.ABSOLUTE);\r
- style.setOverflow(Overflow.HIDDEN);\r
- style.setLeft(-500, Unit.PX);\r
- style.setTop(-500, Unit.PX);\r
- style.setWidth(0, Unit.PX);\r
- style.setHeight(0, Unit.PX);\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2012 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client;\r
-\r
-/**\r
- * Sound type implementations.\r
- */\r
-public enum SoundType {\r
- /**\r
- * Flash Audio.\r
- */\r
- FLASH("flash"),\r
-\r
- /**\r
- * HTML5 Audio.\r
- */\r
- HTML5("html5"),\r
-\r
- /**\r
- * Native browser audio, e.g. <code><BGSOUND></code> and <code><OBJECT></code>.\r
- */\r
- NATIVE("native"),\r
-\r
- /**\r
- * Modern Web Audio API.\r
- */\r
- WEB_AUDIO("webaudio");\r
- \r
- /**\r
- * Query parameter name, which can be used to request a specific audio implementation\r
- * at runtime.\r
- */\r
- public static final String QUERY_PARAMETER_NAME = "gwt-voices";\r
-\r
- private final String queryParameterValue;\r
-\r
- private SoundType(String queryParameterValue) {\r
- this.queryParameterValue = queryParameterValue;\r
- }\r
-\r
- /**\r
- * Get the query parameter value which may be assigned to the {@literal gwt-voices} URL query\r
- * parameter.\r
- * \r
- * @return value which may be used with the {@literal gwt-voices} URL query parameter\r
- */\r
- public String getQueryParameterValue() {\r
- return queryParameterValue;\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2010 Fred Sauer\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client;\r
-\r
-import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_NOT_SUPPORTED;\r
-import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_SUPPORTED_NOT_READY;\r
-import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_SUPPORT_NOT_KNOWN;\r
-\r
-import com.google.gwt.core.client.JavaScriptObject;\r
-import com.google.gwt.dom.client.Element;\r
-\r
-import com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport;\r
-\r
-/**\r
- * Sound object using the Web Audio API.\r
- */\r
-public class WebAudioSound extends AbstractSound {\r
- // CHECKSTYLE_JAVADOC_OFF\r
-\r
- private String mimeType;\r
- private Element voice;\r
- private static Element audioContext;\r
- private JavaScriptObject buffer;\r
- private int volume;\r
- private boolean looping;\r
-\r
- public static MimeTypeSupport getMimeTypeSupport(String mimeType) {\r
- if (audioContext == null) {\r
- return MimeTypeSupport.MIME_TYPE_NOT_SUPPORTED;\r
- }\r
- return Html5Sound.getMimeTypeSupport(mimeType);\r
- }\r
-\r
- public WebAudioSound(String mimeType, String url, boolean streaming, boolean crossOrigin) {\r
- super(mimeType, url, streaming, crossOrigin);\r
-\r
- this.mimeType = mimeType;\r
-\r
- try {\r
- createVoice(url, crossOrigin);\r
- } catch (Throwable e) {\r
- setLoadState(LOAD_STATE_NOT_SUPPORTED);\r
- }\r
-\r
- MimeTypeSupport mimeTypeSupport = getMimeTypeSupport(mimeType);\r
- switch (mimeTypeSupport) {\r
- case MIME_TYPE_SUPPORT_READY:\r
- setLoadState(LOAD_STATE_SUPPORTED_NOT_READY);\r
- break;\r
- case MIME_TYPE_NOT_SUPPORTED:\r
- setLoadState(LOAD_STATE_NOT_SUPPORTED);\r
- break;\r
- case MIME_TYPE_SUPPORT_UNKNOWN:\r
- setLoadState(LOAD_STATE_SUPPORT_NOT_KNOWN);\r
- break;\r
- case MIME_TYPE_SUPPORT_NOT_READY:\r
- setLoadState(LOAD_STATE_SUPPORTED_NOT_READY);\r
- break;\r
- default:\r
- throw new IllegalArgumentException("unknown MIME type support " + mimeTypeSupport);\r
- }\r
- }\r
-\r
- static {\r
- audioContext = createAudioContext();\r
- }\r
-\r
- private static native Element createAudioContext() /*-{\r
- try {\r
- return new AudioContext();\r
- } catch (ignore) {\r
- }\r
-\r
- try {\r
- return new webkitAudioContext();\r
- } catch (ignore) {\r
- }\r
-\r
- return null;\r
- }-*/;\r
-\r
- private native void createVoice(String url, boolean crossOrigin) /*-{\r
- var context = @com.allen_sauer.gwt.voices.client.WebAudioSound::audioContext;\r
-\r
- // TODO: Implement XDomainRequest for IE\r
- var request = new $wnd.XMLHttpRequest();\r
- request.open("GET", url, true);\r
- request.responseType = "arraybuffer";\r
-\r
- var self = this;\r
- request.onload = function() {\r
- try {\r
- self.@com.allen_sauer.gwt.voices.client.WebAudioSound::buffer = context\r
- .createBuffer(request.response, false);\r
- self.@com.allen_sauer.gwt.voices.client.WebAudioSound::soundLoaded()();\r
- } catch(e) {\r
- self.@com.allen_sauer.gwt.voices.client.WebAudioSound::soundLoadFailed()();\r
- }\r
- }\r
-\r
- request.send();\r
- }-*/;\r
-\r
- private void soundLoadFailed() {\r
- setLoadState(LoadState.LOAD_STATE_NOT_SUPPORTED);\r
- }\r
-\r
- private void soundLoaded() {\r
- setLoadState(LoadState.LOAD_STATE_SUPPORTED_AND_READY);\r
- }\r
- \r
- @Override\r
- public int getBalance() {\r
- // TODO(fredsa): Auto-generated method stub\r
- return 0;\r
- }\r
-\r
- @Override\r
- public boolean getLooping() {\r
- return looping;\r
- }\r
-\r
- @Override\r
- public int getVolume() {\r
- return volume;\r
- }\r
-\r
- @Override\r
- public native boolean play() /*-{\r
- var buffer = this.@com.allen_sauer.gwt.voices.client.WebAudioSound::buffer;\r
-\r
- if (buffer == null) {\r
- // XHR has not yet returned\r
- return false;\r
- }\r
- this.@com.allen_sauer.gwt.voices.client.WebAudioSound::stop()();\r
- var context = @com.allen_sauer.gwt.voices.client.WebAudioSound::audioContext;\r
-\r
- var voice = context.createBufferSource();\r
- this.@com.allen_sauer.gwt.voices.client.WebAudioSound::voice = voice;\r
-\r
- if (this.@com.allen_sauer.gwt.voices.client.WebAudioSound::looping) {\r
- voice.loop = true;\r
- }\r
-\r
- var node = voice;\r
-\r
- var volume = this.@com.allen_sauer.gwt.voices.client.WebAudioSound::volume;\r
- if (volume != @com.allen_sauer.gwt.voices.client.SoundController::DEFAULT_VOLUME) {\r
- var gainNode = context.createGainNode();\r
- gainNode.gain.value = volume\r
- / @com.allen_sauer.gwt.voices.client.SoundController::DEFAULT_VOLUME;\r
- node.connect(gainNode);\r
- node = gainNode;\r
- }\r
-\r
- node.connect(context.destination);\r
-\r
- voice.buffer = buffer;\r
-\r
- voice.noteOn(context.currentTime);\r
-\r
- // TODO Replace setTimeout() once https://bugs.webkit.org/show_bug.cgi?id=71942 is fixed\r
- if (!voice.loop) {\r
- var self = this;\r
- setTimeout(\r
- function() {\r
- self.@com.allen_sauer.gwt.voices.client.WebAudioSound::plackbackCompleted()();\r
- }, voice.buffer.duration * 1000);\r
- }\r
-\r
- return true;\r
- }-*/;\r
-\r
- private void plackbackCompleted() {\r
- soundHandlerCollection.fireOnPlaybackComplete(this);\r
- }\r
- \r
- @Override\r
- public void setBalance(int balance) {\r
- // TODO(fredsa): Auto-generated method stub\r
- }\r
-\r
- @Override\r
- public void setLooping(boolean looping) {\r
- this.looping = looping;\r
- }\r
-\r
- @Override\r
- public void setVolume(int volume) {\r
- this.volume = volume;\r
- }\r
-\r
- @Override\r
- public native void stop() /*-{\r
- var context = @com.allen_sauer.gwt.voices.client.WebAudioSound::audioContext;\r
- var voice = this.@com.allen_sauer.gwt.voices.client.WebAudioSound::voice;\r
- if (voice == null) {\r
- return;\r
- }\r
- voice.noteOff(context.currentTime);\r
- this.@com.allen_sauer.gwt.voices.client.WebAudioSound::voice = null;\r
- }-*/;\r
-\r
- @Override\r
- public SoundType getSoundType() {\r
- return SoundType.WEB_AUDIO;\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.handler;\r
-\r
-/**\r
- * Interface for classes wishing to fire sound events.\r
- */\r
-public interface FiresSoundEvents {\r
- /**\r
- * Register a new sound handler.\r
- * \r
- * @param handler sound handler to register\r
- */\r
- void addEventHandler(SoundHandler handler);\r
-\r
- /**\r
- * Remove a previously registered sound handler.\r
- * \r
- * @param handler sound handler to unregister\r
- */\r
- void removeEventHandler(SoundHandler handler);\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.handler;\r
-\r
-import com.allen_sauer.gwt.voices.client.Sound;\r
-import com.allen_sauer.gwt.voices.client.util.StringUtil;\r
-\r
-import java.util.EventObject;\r
-\r
-/**\r
- * Event object when play back of a sound completes.\r
- */\r
-@SuppressWarnings("serial")\r
-public class PlaybackCompleteEvent extends EventObject {\r
- /**\r
- * Constructor, used by {@link SoundHandlerCollection}.\r
- * \r
- * @param source the {@link Sound} object which completed play back\r
- */\r
- public PlaybackCompleteEvent(Object source) {\r
- super(source);\r
- }\r
-\r
- /**\r
- * Returns the string <code>"PlaybackCompleteEvent: "</code> followed by\r
- * <code>sound.toString()</code>, whereby <code>sound</code> is the <code>source</code> of this\r
- * {@link EventObject}.\r
- * \r
- * @return the string representation of this event\r
- */\r
- @Override\r
- public String toString() {\r
- Sound sound = (Sound) getSource();\r
- return StringUtil.getSimpleName(PlaybackCompleteEvent.class) + ": " + sound;\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.handler;\r
-\r
-import java.util.EventListener;\r
-\r
-/**\r
- * Implement this interface to receive events related to sound load states sound playback.\r
- */\r
-public interface SoundHandler extends EventListener {\r
- /**\r
- * Fired when playback of a sound completes.\r
- * \r
- * @param event the completion event\r
- */\r
- void onPlaybackComplete(PlaybackCompleteEvent event);\r
-\r
- /**\r
- * Fired when the load state changes.\r
- * \r
- * @param event the load state completion event\r
- */\r
- void onSoundLoadStateChange(SoundLoadStateChangeEvent event);\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.handler;\r
-\r
-import java.util.ArrayList;\r
-\r
-/**\r
- * Utility collection class used by AbstractSound.\r
- */\r
-@SuppressWarnings("serial")\r
-public class SoundHandlerCollection extends ArrayList<SoundHandler> {\r
- /**\r
- * Fires when playback of a sound completes.\r
- * \r
- * @param sender the sound which finished playing\r
- */\r
- public void fireOnPlaybackComplete(Object sender) {\r
- PlaybackCompleteEvent event = new PlaybackCompleteEvent(sender);\r
-\r
- for (SoundHandler handler : this) {\r
- handler.onPlaybackComplete(event);\r
- }\r
- }\r
-\r
- /**\r
- * Fires when a sound's load state changes.\r
- * \r
- * @param sender the sound who's load state changed\r
- */\r
- public void fireOnSoundLoadStateChange(Object sender) {\r
- SoundLoadStateChangeEvent event = new SoundLoadStateChangeEvent(sender);\r
-\r
- for (SoundHandler handler : this) {\r
- handler.onSoundLoadStateChange(event);\r
- }\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.handler;\r
-\r
-import com.allen_sauer.gwt.voices.client.Sound;\r
-import com.allen_sauer.gwt.voices.client.Sound.LoadState;\r
-import com.allen_sauer.gwt.voices.client.util.StringUtil;\r
-\r
-import java.util.EventObject;\r
-\r
-/**\r
- * Event object representing a load state change.\r
- */\r
-@SuppressWarnings("serial")\r
-public class SoundLoadStateChangeEvent extends EventObject {\r
- private final LoadState loadState;\r
-\r
- /**\r
- * Event constructor.\r
- * \r
- * @param source the sound object\r
- */\r
- public SoundLoadStateChangeEvent(Object source) {\r
- super(source);\r
- Sound sound = (Sound) source;\r
- loadState = sound.getLoadState();\r
- }\r
-\r
- /**\r
- * Determine the load state for this event.\r
- * \r
- * @return this event's load state\r
- */\r
- public LoadState getLoadState() {\r
- return loadState;\r
- }\r
-\r
- /**\r
- * Get a string representation of this event object.\r
- * \r
- * @return a string representation of this event object\r
- */\r
- @Override\r
- public String toString() {\r
- Sound sound = (Sound) getSource();\r
- return StringUtil.getSimpleName(SoundLoadStateChangeEvent.class) + ": " + sound + "; "\r
- + loadState.name();\r
- }\r
-}\r
+++ /dev/null
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN" "http://www.w3.org/TR/html4/strict.dtd">\r
-<html>\r
-<head>\r
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\r
-</head>\r
-<body>\r
-This package contains sound event handler related classes.\r
-</body>\r
-</html>
\ No newline at end of file
+++ /dev/null
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN" "http://www.w3.org/TR/html4/strict.dtd">\r
-<html>\r
-<head>\r
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\r
-</head>\r
-<body>\r
-This package contains the main classes used in client application code.\r
-</body>\r
-</html>
\ No newline at end of file
+++ /dev/null
-/*\r
- * Copyright 2010 Fred Sauer\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui;\r
-\r
-import com.google.gwt.core.client.GWT;\r
-import com.google.gwt.user.client.Element;\r
-\r
-import com.allen_sauer.gwt.voices.client.ui.impl.FlashMovieImpl;\r
-\r
-/**\r
- * Flash movie.\r
- */\r
-public class FlashMovie {\r
- // CHECKSTYLE_JAVADOC_OFF\r
-\r
- /**\r
- * Flash movie MIME type (<code>{@value}</code>). Typical filename extension is <code>.swf</code>.\r
- */\r
- public static final String MIME_TYPE_APPLICATION_X_SHOCKWAVE_FLASH = "application/x-shockwave-flash";\r
-\r
- private static FlashMovieImpl impl;\r
-\r
- /**\r
- * We require at least Flash version ({@value}), since it provides 32 audio channels. We\r
- * previously required Flash version 8, which provides support for <code>ExternalInterface</code>.\r
- */\r
- private static final int MINIMUM_MAJOR_VERSION = 9;\r
-\r
- static {\r
- impl = (FlashMovieImpl) GWT.create(FlashMovieImpl.class);\r
- }\r
-\r
- public static int getMajorVersion() {\r
- return impl.getMajorVersion();\r
- }\r
-\r
- public static boolean isExternalInterfaceSupported() {\r
- return getMajorVersion() >= MINIMUM_MAJOR_VERSION;\r
- }\r
-\r
- private Element element;\r
-\r
- public FlashMovie(String id, String url) {\r
- element = impl.createElementMaybeSetURL(id, url);\r
- }\r
-\r
- public Element getElement() {\r
- return element;\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2010 Fred Sauer\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui;\r
-\r
-import static com.allen_sauer.gwt.voices.client.Sound.LoadState.LOAD_STATE_NOT_SUPPORTED;\r
-import static com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport.MIME_TYPE_NOT_SUPPORTED;\r
-import static com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport.MIME_TYPE_SUPPORT_NOT_READY;\r
-import static com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport.MIME_TYPE_SUPPORT_READY;\r
-import static com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport.MIME_TYPE_SUPPORT_UNKNOWN;\r
-\r
-import com.google.gwt.core.client.GWT;\r
-import com.google.gwt.core.client.Scheduler;\r
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;\r
-\r
-import com.allen_sauer.gwt.voices.client.FlashSound;\r
-import com.allen_sauer.gwt.voices.client.Sound;\r
-import com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport;\r
-import com.allen_sauer.gwt.voices.client.util.StringUtil;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-\r
-// CHECKSTYLE_JAVADOC_OFF\r
-public class VoicesMovie extends FlashMovie {\r
-\r
- @SuppressWarnings("deprecation")\r
- private static final String[] FLASH_SUPPORTED_MIME_TYPES = {\r
- Sound.MIME_TYPE_AUDIO_MPEG, Sound.MIME_TYPE_AUDIO_MPEG_MP3,};\r
- private static final String GWT_VOICES_SWF = "gwt-voices.swf";\r
-\r
-\r
- private MimeTypeSupport flashSupport = MIME_TYPE_SUPPORT_UNKNOWN;\r
- private final ArrayList<FlashSound> unitializedSoundList = new ArrayList<FlashSound>();\r
-\r
- public VoicesMovie(String id, String gwtVoicesSwfBaseUrl) {\r
- super(id, gwtVoicesSwfBaseUrl + GWT_VOICES_SWF);\r
- installFlashCallbackHooks(id);\r
-\r
- // Flash Player version check for ExternalInterface support\r
- if (isExternalInterfaceSupported()) {\r
- flashSupport = MIME_TYPE_SUPPORT_NOT_READY;\r
- } else {\r
- flashSupport = MIME_TYPE_NOT_SUPPORTED;\r
- Scheduler.get().scheduleDeferred(new ScheduledCommand() {\r
- @Override\r
- public void execute() {\r
- movieUnsupported();\r
- }\r
- });\r
- }\r
- }\r
-\r
- public MimeTypeSupport getMimeTypeSupport(String mimeType) {\r
- switch (flashSupport) {\r
- case MIME_TYPE_SUPPORT_READY:\r
- case MIME_TYPE_SUPPORT_NOT_READY:\r
- return StringUtil.contains(FLASH_SUPPORTED_MIME_TYPES, mimeType) ? MIME_TYPE_SUPPORT_READY\r
- : MIME_TYPE_NOT_SUPPORTED;\r
- case MIME_TYPE_SUPPORT_UNKNOWN:\r
- case MIME_TYPE_NOT_SUPPORTED:\r
- return flashSupport;\r
- default:\r
- throw new RuntimeException("Unhandled flash support value " + flashSupport);\r
- }\r
- }\r
-\r
- public boolean playSound(int id) {\r
- if (flashSupport == MIME_TYPE_SUPPORT_READY) {\r
- return callPlaySound(id);\r
- }\r
- // the sound was not played, return false\r
- return false;\r
- }\r
-\r
- public void registerSound(FlashSound flashSound) {\r
- if (flashSupport == MIME_TYPE_SUPPORT_READY) {\r
- doCreateSound(flashSound);\r
- } else {\r
- unitializedSoundList.add(flashSound);\r
- }\r
- }\r
-\r
- public void setBalance(int id, int balance) {\r
- assert balance >= -100;\r
- assert balance <= 100;\r
- if (flashSupport == MIME_TYPE_SUPPORT_READY) {\r
- callSetPanning(id, balance / 100f);\r
- }\r
- }\r
-\r
- public void setLooping(int id, boolean looping) {\r
- if (flashSupport == MIME_TYPE_SUPPORT_READY) {\r
- callSetLooping(id, looping ? Integer.MAX_VALUE : 0);\r
- }\r
- }\r
-\r
- public void setVolume(int id, int volume) {\r
- assert volume >= 0;\r
- assert volume <= 100;\r
- if (flashSupport == MIME_TYPE_SUPPORT_READY) {\r
- callSetVolume(id, volume / 100f);\r
- }\r
- }\r
-\r
- public void stopSound(int id) {\r
- if (flashSupport == MIME_TYPE_SUPPORT_READY) {\r
- callStopSound(id);\r
- }\r
- }\r
-\r
- protected void debug(String text) {\r
- System.out.println(text);\r
- if (!GWT.isProdMode()) {\r
- consoleDebug(text);\r
- }\r
- }\r
-\r
- private native void callCreateSound(int id, String soundURL, boolean checkPolicyFile) /*-{\r
- var elem = this.@com.allen_sauer.gwt.voices.client.ui.FlashMovie::element;\r
- elem.createSound(id, soundURL, checkPolicyFile);\r
- }-*/;\r
-\r
- private native boolean callPlaySound(int id) /*-{\r
- var elem = this.@com.allen_sauer.gwt.voices.client.ui.FlashMovie::element;\r
- return elem.playSound(id);\r
- }-*/;\r
-\r
- private native void callSetLooping(int id, int looping) /*-{\r
- var elem = this.@com.allen_sauer.gwt.voices.client.ui.FlashMovie::element;\r
- elem.setLooping(id, looping);\r
- }-*/;\r
-\r
- private native void callSetPanning(int id, float panning) /*-{\r
- var elem = this.@com.allen_sauer.gwt.voices.client.ui.FlashMovie::element;\r
- elem.setPanning(id, panning);\r
- }-*/;\r
-\r
- private native void callSetVolume(int id, float volume) /*-{\r
- var elem = this.@com.allen_sauer.gwt.voices.client.ui.FlashMovie::element;\r
- elem.setVolume(id, volume);\r
- }-*/;\r
-\r
- private native void callStopSound(int id) /*-{\r
- var elem = this.@com.allen_sauer.gwt.voices.client.ui.FlashMovie::element;\r
- elem.stopSound(id);\r
- }-*/;\r
-\r
- private native void consoleDebug(String text) /*-{\r
- console.log(text);\r
- }-*/;\r
-\r
- private void doCreateSound(FlashSound flashSound) {\r
- callCreateSound(flashSound.getSoundNumber(), flashSound.getUrl(), flashSound.isCrossOrigin());\r
- }\r
-\r
- private native void installFlashCallbackHooks(String id) /*-{\r
- if ($doc.VoicesMovie === undefined) {\r
- $doc.VoicesMovie = {};\r
- }\r
- var self = this;\r
- $doc.VoicesMovie[id] = {};\r
-\r
- $doc.VoicesMovie[id].ready = function() {\r
- self.@com.allen_sauer.gwt.voices.client.ui.VoicesMovie::movieReady()();\r
- }\r
-\r
- $doc.VoicesMovie[id].soundLoaded = function(id) {\r
- @com.allen_sauer.gwt.voices.client.FlashSound::soundLoaded(I)(id);\r
- return true;\r
- }\r
-\r
- $doc.VoicesMovie[id].playbackCompleted = function(id) {\r
- @com.allen_sauer.gwt.voices.client.FlashSound::playbackCompleted(I)(id);\r
- }\r
-\r
- $doc.VoicesMovie[id].log = function(text) {\r
- self.@com.allen_sauer.gwt.voices.client.ui.VoicesMovie::debug(Ljava/lang/String;)("FLASH[" + id + "]: " + text);\r
- }\r
- }-*/;\r
-\r
- private void movieReady() {\r
- flashSupport = MIME_TYPE_SUPPORT_READY;\r
- for (Iterator<FlashSound> iterator = unitializedSoundList.iterator(); iterator.hasNext();) {\r
- FlashSound flashSound = iterator.next();\r
- doCreateSound(flashSound);\r
- iterator.remove();\r
- }\r
- }\r
-\r
- private void movieUnsupported() {\r
- for (FlashSound flashSound : unitializedSoundList) {\r
- flashSound.setLoadState(LOAD_STATE_NOT_SUPPORTED);\r
- // Flash plug-in may become available later; do not call iterator.remove()\r
- }\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui.impl;\r
-\r
-import com.google.gwt.user.client.Element;\r
-\r
-/**\r
- * {@link com.allen_sauer.gwt.voices.client.ui.FlashMovie} default cross-browser\r
- * implementation.\r
- */\r
-public abstract class FlashMovieImpl {\r
- // CHECKSTYLE_JAVADOC_OFF\r
-\r
- public abstract Element createElementMaybeSetURL(String id, String url);\r
-\r
- /**\r
- * Returns a major version number, starting with Flash Players version 3 or 4, depending on the\r
- * browser. Earlier versions are not currently detected and result in <code>0</code> being\r
- * returned.\r
- * \r
- * @return major version number for the installed Flash Player, or <code>0</code> if version\r
- * cannot be determined, or Flash Player is not installed\r
- */\r
- public int getMajorVersion() {\r
- String versionString = getVersionString();\r
- return versionString == null ? 0 : Integer.parseInt(versionString.replaceFirst(",.*", ""));\r
- }\r
-\r
- /**\r
- * Returns a generic string of comma delimited version numbers, e.g. <code>9,0,47,0</code> or\r
- * <code>9,0,47</code>, starting with Flash Players version 3 or 4, depending on the browser.\r
- * Earlier versions are not currently detected and result in <code>null</code> being returned.\r
- * \r
- * @return generic version string or <code>null</code> if version could not be determined, or\r
- * plug-in is unavailable\r
- */\r
- public String getVersionString() {\r
- String rawVersionString = getRawVersionString();\r
- return rawVersionString == null ? null\r
- : rawVersionString.replaceAll("\\D*(\\d+)", "$1,").replaceFirst(",$", "");\r
- }\r
-\r
- /**\r
- * Returns a browser specific version string such as <code>WIN 9,0,47,0</code> or\r
- * <code>Shockwave Flash 9.0 r47</code>, starting with Flash Player version\r
- * 3. Earlier versions are not currently detected and result in <code>null</code> being returned.\r
- * \r
- * @return non-IE Flash plug-in version string or <code>null</code> if version could not be\r
- * determined, or plug-in is unavailable\r
- */\r
- protected abstract String getRawVersionString();\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui.impl;\r
-\r
-import com.google.gwt.user.client.Element;\r
-\r
-/**\r
- * {@link com.allen_sauer.gwt.voices.client.ui.FlashMovie} implementation for IE.\r
- */\r
-public class FlashMovieImplIE6 extends FlashMovieImpl {\r
- // CHECKSTYLE_JAVADOC_OFF\r
-\r
- @Override\r
- public native Element createElementMaybeSetURL(String id, String url)\r
- /*-{\r
- var elem = $doc.createElement("object");\r
- elem.tabIndex = -1;\r
- elem.id = id;\r
- elem.classid = "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000";\r
- elem.codebase = "http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0";\r
- // elem.Quality = 1; // 0=Low, 1=High, 2=AutoLow, 3=AutoHigh\r
- // elem.ScaleMode = 2; //0=ShowAll, 1=NoBorder, 2=ExactFit\r
-\r
- // Must be set after the classid\r
- elem.FlashVars = "id=" + id;\r
- elem.Movie = url;\r
- return elem;\r
- }-*/;\r
-\r
- /**\r
- * Returns an IE specific version string such as {@literal WIN 9,0,47,0} or\r
- * {@literal UNIX 9,0,47,0}, starting with Flash Player version 4,0,11,0. Earlier versions\r
- * are not currently detected and result in <code>null</code> being returned.\r
- *\r
- * @return IE specific Flash plug-in version string or <code>null</code> if version could not be\r
- * determined, or plug-in is unavailable\r
- */\r
- @Override\r
- protected native String getRawVersionString()\r
- /*-{\r
- try {\r
- return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version");\r
- } catch (e) {\r
- return null;\r
- }\r
- }-*/;\r
-}
\ No newline at end of file
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui.impl;\r
-\r
-/**\r
- * {@link com.allen_sauer.gwt.voices.client.ui.FlashMovie} implementation for Mozilla.\r
- */\r
-public class FlashMovieImplMozilla extends FlashMovieImplStandard {\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui.impl;\r
-\r
-/**\r
- * {@link com.allen_sauer.gwt.voices.client.ui.FlashMovie} implementation for older Mozillae.\r
- */\r
-public class FlashMovieImplMozillaOld extends FlashMovieImplMozilla {\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui.impl;\r
-\r
-/**\r
- * {@link com.allen_sauer.gwt.voices.client.ui.FlashMovie} implementation for Opera.\r
- */\r
-public class FlashMovieImplOpera extends FlashMovieImplStandard {\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui.impl;\r
-\r
-/**\r
- * {@link com.allen_sauer.gwt.voices.client.ui.FlashMovie} implementation for Webkit/Safari.\r
- */\r
-public class FlashMovieImplSafari extends FlashMovieImplStandard {\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui.impl;\r
-\r
-import com.google.gwt.user.client.Element;\r
-\r
-/**\r
- * {@link com.allen_sauer.gwt.voices.client.ui.FlashMovie} implementation for standard\r
- * browsers.\r
- */\r
-public abstract class FlashMovieImplStandard extends FlashMovieImpl {\r
- // CHECKSTYLE_JAVADOC_OFF\r
-\r
- @Override\r
- public native Element createElementMaybeSetURL(String id, String url)\r
- /*-{\r
- var elem = $doc.createElement("object");\r
- elem.setAttribute("id", id);\r
- elem.setAttribute("type", "application/x-shockwave-flash");\r
- elem.setAttribute("data", url);\r
-\r
- var param = $doc.createElement("param");\r
- param.setAttribute("name", "FlashVars");\r
- param.setAttribute("value", "id=" + id);\r
- elem.appendChild(param);\r
-\r
- return elem;\r
- }-*/;\r
-\r
- @Override\r
- protected native String getRawVersionString()\r
- /*-{\r
- var p = navigator.plugins["Shockwave Flash"];\r
- return p == null ? null : p.description;\r
- }-*/;\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2010 Fred Sauer\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui.impl;\r
-\r
-import com.google.gwt.dom.client.Element;\r
-\r
-import com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport;\r
-\r
-/**\r
- * {@link com.allen_sauer.gwt.voices.client.NativeSound} default cross-browser\r
- * implementation.\r
- */\r
-public abstract class NativeSoundImpl {\r
- // CHECKSTYLE_JAVADOC_OFF\r
-\r
- public abstract Element createElement(String url);\r
-\r
- public boolean getLooping(Element element) {\r
- return element.hasAttribute("loop");\r
- }\r
-\r
- public abstract MimeTypeSupport getMimeTypeSupport(String mimeType);\r
-\r
- public native boolean play(Element soundControllerElement, Element elem, String mimeType)\r
- /*-{\r
- soundControllerElement.appendChild(elem);\r
- // best guess is that the sound played, so return true\r
- return true;\r
- }-*/;\r
-\r
- public void preload(Element soundControllerElement, String mimeType, String url) {\r
- if (mimeTypeSupportsVolume(mimeType)) {\r
- Element elem = createElement(url);\r
- setVolume(elem, 0);\r
- play(soundControllerElement, elem, mimeType);\r
- }\r
- }\r
-\r
- public abstract void setBalance(Element elem, int balancePercentage);\r
-\r
- public void setLooping(Element element, boolean looping) {\r
- element.setAttribute("loop", "infinite");\r
- }\r
-\r
- public abstract void setVolume(Element elem, int volume);\r
-\r
- public native void stop(Element elem)\r
- /*-{\r
- var parent = elem.parentNode;\r
- if (parent != null) {\r
- parent.removeChild(elem);\r
- }\r
- }-*/;\r
-\r
- protected boolean mimeTypeSupportsVolume(String mimeType) {\r
- return true;\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2010 Fred Sauer\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui.impl;\r
-\r
-import static com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport.MIME_TYPE_NOT_SUPPORTED;\r
-import static com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport.MIME_TYPE_SUPPORT_READY;\r
-\r
-import com.google.gwt.dom.client.Element;\r
-\r
-import com.allen_sauer.gwt.voices.client.Sound;\r
-import com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport;\r
-import com.allen_sauer.gwt.voices.client.util.StringUtil;\r
-\r
-import java.util.HashMap;\r
-\r
-/**\r
- * {@link com.allen_sauer.gwt.voices.client.NativeSound} implementation for IE.\r
- */\r
-public class NativeSoundImplIE6 extends NativeSoundImpl {\r
- /**\r
- * List based on <a href='http://support.microsoft.com/kb/297477'>How to apply a background sound\r
- * to a Web page in FrontPage</a> knowledge base article.\r
- */\r
- @SuppressWarnings("deprecation")\r
- private static final String[] BGSOUND_SUPPORTED_MIME_TYPES = {\r
- Sound.MIME_TYPE_AUDIO_X_AIFF, Sound.MIME_TYPE_AUDIO_BASIC, Sound.MIME_TYPE_AUDIO_X_MIDI,\r
- Sound.MIME_TYPE_AUDIO_MPEG, Sound.MIME_TYPE_AUDIO_X_WAV,};\r
-\r
- // CHECKSTYLE_JAVADOC_OFF\r
- private static final String[] MIME_TYPES_BGSOUND_NO_VOLUME_CONTROL = {Sound.MIME_TYPE_AUDIO_X_MIDI,};\r
-\r
- private static final String[] MIME_TYPES_ONE_AT_ATIME = {Sound.MIME_TYPE_AUDIO_X_MIDI,};\r
-\r
- private static final HashMap<String, Element> oneAtATimeElements = new HashMap<String, Element>();\r
-\r
- @Override\r
- public native Element createElement(String url)\r
- /*-{\r
- var elem = $doc.createElement("bgsound");\r
- elem.src = url;\r
- // elem.loop = 1; // -1 = infinitely, 0 = one time, n = number of times\r
- return elem;\r
- }-*/;\r
-\r
- @Override\r
- public MimeTypeSupport getMimeTypeSupport(String mimeType) {\r
- return StringUtil.contains(BGSOUND_SUPPORTED_MIME_TYPES, mimeType) ? MIME_TYPE_SUPPORT_READY\r
- : MIME_TYPE_NOT_SUPPORTED;\r
- }\r
-\r
- @Override\r
- public boolean play(Element soundControllerElement, Element elem, String mimeType) {\r
- Element currentElement = oneAtATimeElements.remove(mimeType);\r
- if (currentElement != null) {\r
- stop(currentElement);\r
- }\r
- if (StringUtil.contains(MIME_TYPES_ONE_AT_ATIME, mimeType)) {\r
- oneAtATimeElements.put(mimeType, elem);\r
- }\r
- return super.play(soundControllerElement, elem, mimeType);\r
- }\r
-\r
- @Override\r
- public void preload(Element soundControllerElement, String mimeType, String url) {\r
- if (!StringUtil.contains(MIME_TYPES_BGSOUND_NO_VOLUME_CONTROL, mimeType)) {\r
- super.preload(soundControllerElement, mimeType, url);\r
- }\r
- }\r
-\r
- /**\r
- * Best guess at conversion formula from standard -100 .. 100 range to -10000 .. 10000 range used\r
- * by IE.\r
- *\r
- * TODO location documentation for IE\r
- */\r
- @Override\r
- public native void setBalance(Element elem, int balance)\r
- /*-{\r
- if (balance == -100) {\r
- balance = -10000;\r
- } else if (balance == 100) {\r
- balance = 10000;\r
- } else if (balance < 0) {\r
- balance = 100 - 10000 / (100 + balance);\r
- } else {\r
- balance = 10000 / (100 - balance) - 100;\r
- }\r
- elem.balance = "" + balance; // -10000 .. 10000\r
- }-*/;\r
-\r
- /**\r
- * Best guess at conversion formula from standard 0 .. 100 range to -10000 .. 0 range used by IE.\r
- *\r
- * TODO location documentation for IE\r
- */\r
- @Override\r
- public native void setVolume(Element elem, int volume)\r
- /*-{\r
- elem.volume = volume == 0 ? -10000 : (-10000 / volume); // -10000 .. 0\r
- }-*/;\r
-}
\ No newline at end of file
+++ /dev/null
-/*\r
- * Copyright 2010 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui.impl;\r
-\r
-/**\r
- * {@link com.allen_sauer.gwt.voices.client.NativeSound} implementation for Mozilla.\r
- */\r
-public class NativeSoundImplMozilla extends NativeSoundImplStandard {\r
-\r
- /**\r
- * Determine whether volume control is supported for the provided MIME type.\r
- *\r
- * Returns <code>false</code> if <code>navigator.mimeTypes[mimeType].enabledPlugin.filename</code>\r
- * ends with <code>wmp.so</code>, indicating the mplayer plugin on Linux, which does not support\r
- * volume control. Known strings to date are <code>gecko-mediaplayer-wmp.so</code> and\r
- * <code>mplayerplug-in-wmp.so</code>.\r
- *\r
- * @param mimeType the MIME type to test\r
- * @return true if the MIME type and enabled plugin is believed to provide volume support\r
- */\r
- @Override\r
- protected native boolean mimeTypeSupportsVolume(String mimeType)\r
- /*-{\r
- if (mimeType = @com.allen_sauer.gwt.voices.client.Sound::MIME_TYPE_AUDIO_X_MIDI) {\r
- // No MIDI volume support in Firefox 3.6\r
- // (Tested on OSX)\r
- return false;\r
- }\r
- var m = navigator.mimeTypes[mimeType];\r
- if (m != null && m.enabledPlugin != null && m.enabledPlugin.filename.search(/wmp.so$/) != -1) {\r
- return false;\r
- }\r
- return true;\r
- }-*/;\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui.impl;\r
-\r
-/**\r
- * {@link com.allen_sauer.gwt.voices.client.NativeSound} implementation for older Mozillae.\r
- */\r
-public class NativeSoundImplMozillaOld extends NativeSoundImplMozilla {\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2010 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui.impl;\r
-\r
-import static com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport.MIME_TYPE_SUPPORT_READY;\r
-\r
-import com.google.gwt.dom.client.Element;\r
-\r
-import com.allen_sauer.gwt.voices.client.Sound;\r
-import com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport;\r
-import com.allen_sauer.gwt.voices.client.util.StringUtil;\r
-\r
-/**\r
- * {@link com.allen_sauer.gwt.voices.client.NativeSound} implementation for Opera.\r
- */\r
-public class NativeSoundImplOpera extends NativeSoundImplStandard {\r
- // CHECKSTYLE_JAVADOC_OFF\r
-\r
- @SuppressWarnings("deprecation")\r
- private static final String[] SUPPORTED_WITHOUT_PLUGINS_MIME_TYPES = {Sound.MIME_TYPE_AUDIO_X_WAV,};\r
-\r
- @Override\r
- public MimeTypeSupport getMimeTypeSupport(String mimeType) {\r
- if (StringUtil.contains(SUPPORTED_WITHOUT_PLUGINS_MIME_TYPES, mimeType)) {\r
- return MIME_TYPE_SUPPORT_READY;\r
- }\r
- return operaGetMimeTypeSupport(mimeType);\r
- }\r
-\r
- @Override\r
- public native void preload(Element soundControllerElement, String mimeType, String url) /*-{\r
- new Audio(url);\r
- }-*/;\r
-\r
- private native MimeTypeSupport operaGetMimeTypeSupport(String mimeType) /*-{\r
- var m = navigator.mimeTypes[mimeType];\r
- // Note, m != null occurs in many browsers for well known MIME types\r
- // even though the MIME type is not supported without a plug-in\r
- return (m != null && m.description && m.description.length > 0)\r
- ? @com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport::MIME_TYPE_SUPPORT_READY\r
- : @com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport::MIME_TYPE_NOT_SUPPORTED;\r
- }-*/;\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2010 Fred Sauer\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui.impl;\r
-\r
-import com.google.gwt.dom.client.Element;\r
-\r
-import com.allen_sauer.gwt.voices.client.Sound;\r
-\r
-/**\r
- * {@link com.allen_sauer.gwt.voices.client.NativeSound} implementation for Webkit/Safari.\r
- */\r
-public class NativeSoundImplSafari extends NativeSoundImplStandard {\r
- // CHECKSTYLE_JAVADOC_OFF\r
-\r
- @Override\r
- public native boolean play(Element soundControllerElement, Element elem, String mimeType)\r
- /*-{\r
- var parent = elem.parentNode;\r
- if (parent != null) {\r
- parent.removeChild(elem);\r
- }\r
- soundControllerElement.appendChild(elem);\r
- // best guess is that the sound played, so return true\r
- return true;\r
- }-*/;\r
-\r
- @Override\r
- protected boolean mimeTypeSupportsVolume(String mimeType) {\r
- if (Sound.MIME_TYPE_AUDIO_X_MIDI.equals(mimeType)) {\r
- // No MIDI volume support in Safari 4 and Chrome 5\r
- // (Tested on OSX)\r
- return false;\r
- }\r
- return true;\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2010 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.ui.impl;\r
-\r
-import com.google.gwt.dom.client.Element;\r
-\r
-import com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport;\r
-\r
-/**\r
- * {@link com.allen_sauer.gwt.voices.client.NativeSound} implementation for standard browsers.\r
- */\r
-public abstract class NativeSoundImplStandard extends NativeSoundImpl {\r
- // CHECKSTYLE_JAVADOC_OFF\r
-\r
- @Override\r
- public native Element createElement(String url)\r
- /*-{\r
- var elem = $doc.createElement("object");\r
- elem.setAttribute("data", url);\r
- elem.setAttribute("autostart", "true");\r
- // setting hidden property prevents MIDI playback\r
- // elem.setAttribute("hidden", "true");\r
- return elem;\r
- }-*/;\r
-\r
- @Override\r
- public native MimeTypeSupport getMimeTypeSupport(String mimeType)\r
- /*-{\r
- var m = navigator.mimeTypes[mimeType];\r
- // Note, m != null occurs in many browsers for well known MIME types\r
- // even though the MIME type is not supported without a plug-in\r
- return (m != null && m.enabledPlugin != null)\r
- ? @com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport::MIME_TYPE_SUPPORT_READY\r
- : @com.allen_sauer.gwt.voices.client.SoundController.MimeTypeSupport::MIME_TYPE_NOT_SUPPORTED;\r
- }-*/;\r
-\r
- @Override\r
- public native void setBalance(Element elem, int balance)\r
- /*-{\r
- // did not find any browsers actually supporting this\r
- elem.setAttribute("balance", "" + balance);\r
- }-*/;\r
-\r
- @Override\r
- public native void setVolume(Element elem, int volume)\r
- /*-{\r
- elem.setAttribute("volume", "" + volume);\r
- }-*/;\r
-}\r
+++ /dev/null
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN" "http://www.w3.org/TR/html4/strict.dtd">\r
-<html>\r
-<head>\r
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\r
-</head>\r
-<body>\r
-This package contains deferred binding implementations.\r
-</body>\r
-</html>
\ No newline at end of file
+++ /dev/null
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN" "http://www.w3.org/TR/html4/strict.dtd">\r
-<html>\r
-<head>\r
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\r
-</head>\r
-<body>\r
-This package contains widgets.\r
-</body>\r
-</html>
\ No newline at end of file
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.util;\r
-\r
-import com.google.gwt.user.client.Element;\r
-\r
-// CHECKSTYLE_JAVADOC_OFF\r
-public class DOMUtil {\r
- private static int uniqueId = 1000;\r
-\r
- public static native String getNodeName(Element elem)\r
- /*-{\r
- return elem.nodeName;\r
- }-*/;\r
-\r
- public static String getUniqueId() {\r
- return "gwtVoices" + uniqueId++;\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright 2009 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
- * in compliance with the License. You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software distributed under the License\r
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
- * or implied. See the License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.allen_sauer.gwt.voices.client.util;\r
-\r
-// CHECKSTYLE_JAVADOC_OFF\r
-public class StringUtil {\r
- public static boolean contains(String[] arr, String text) {\r
- for (String element : arr) {\r
- if (element.equals(text)) {\r
- return true;\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- public static String getSimpleName(Class<?> clazz) {\r
- String name = clazz.getName();\r
- return name.substring(name.lastIndexOf('.') + 1);\r
- }\r
-}\r
+++ /dev/null
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN" "http://www.w3.org/TR/html4/strict.dtd">\r
-<html>\r
-<head>\r
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\r
-</head>\r
-<body>\r
-This package contains library utility classes.\r
-</body>\r
-</html>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">\r
- <!--\r
- Copyright 2007 Fred Sauer Licensed under the Apache License, Version 2.0 (the "License"); you\r
- may not use this file except in compliance with the License. You may obtain a copy of the\r
- License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or\r
- agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the\r
- specific language governing permissions and limitations under the License.\r
- -->\r
-<module>\r
-\r
- <!-- Inherit the core Web Toolkit stuff. -->\r
- <inherits name='com.google.gwt.user.User' />\r
-\r
- <source path="client" />\r
-\r
- <public path="public">\r
- <exclude name="**/*.as" />\r
- </public>\r
-\r
- <replace-with class="com.allen_sauer.gwt.voices.client.ui.impl.FlashMovieImplOpera">\r
- <when-type-is class="com.allen_sauer.gwt.voices.client.ui.impl.FlashMovieImpl" />\r
- <when-property-is name="user.agent" value="opera" />\r
- </replace-with>\r
-\r
- <replace-with class="com.allen_sauer.gwt.voices.client.ui.impl.FlashMovieImplSafari">\r
- <when-type-is class="com.allen_sauer.gwt.voices.client.ui.impl.FlashMovieImpl" />\r
- <when-property-is name="user.agent" value="safari" />\r
- </replace-with>\r
-\r
- <replace-with class="com.allen_sauer.gwt.voices.client.ui.impl.FlashMovieImplIE6">\r
- <when-type-is class="com.allen_sauer.gwt.voices.client.ui.impl.FlashMovieImpl" />\r
- <any>\r
- <when-property-is name="user.agent" value="ie6" />\r
- <when-property-is name="user.agent" value="ie8" />\r
- <when-property-is name="user.agent" value="ie9" />\r
- </any>\r
- </replace-with>\r
-\r
- <replace-with class="com.allen_sauer.gwt.voices.client.ui.impl.FlashMovieImplMozilla">\r
- <when-type-is class="com.allen_sauer.gwt.voices.client.ui.impl.FlashMovieImpl" />\r
- <when-property-is name="user.agent" value="gecko1_8" />\r
- </replace-with>\r
-\r
- <replace-with class="com.allen_sauer.gwt.voices.client.ui.impl.FlashMovieImplMozillaOld">\r
- <when-type-is class="com.allen_sauer.gwt.voices.client.ui.impl.FlashMovieImpl" />\r
- <when-property-is name="user.agent" value="gecko" />\r
- </replace-with>\r
-\r
-\r
- <replace-with class="com.allen_sauer.gwt.voices.client.ui.impl.NativeSoundImplOpera">\r
- <when-type-is class="com.allen_sauer.gwt.voices.client.ui.impl.NativeSoundImpl" />\r
- <when-property-is name="user.agent" value="opera" />\r
- </replace-with>\r
-\r
- <replace-with class="com.allen_sauer.gwt.voices.client.ui.impl.NativeSoundImplSafari">\r
- <when-type-is class="com.allen_sauer.gwt.voices.client.ui.impl.NativeSoundImpl" />\r
- <when-property-is name="user.agent" value="safari" />\r
- </replace-with>\r
-\r
- <replace-with class="com.allen_sauer.gwt.voices.client.ui.impl.NativeSoundImplIE6">\r
- <when-type-is class="com.allen_sauer.gwt.voices.client.ui.impl.NativeSoundImpl" />\r
- <any>\r
- <when-property-is name="user.agent" value="ie6" />\r
- <when-property-is name="user.agent" value="ie8" />\r
- <when-property-is name="user.agent" value="ie9" />\r
- </any>\r
- </replace-with>\r
-\r
- <replace-with class="com.allen_sauer.gwt.voices.client.ui.impl.NativeSoundImplMozilla">\r
- <when-type-is class="com.allen_sauer.gwt.voices.client.ui.impl.NativeSoundImpl" />\r
- <when-property-is name="user.agent" value="gecko1_8" />\r
- </replace-with>\r
-\r
- <replace-with class="com.allen_sauer.gwt.voices.client.ui.impl.NativeSoundImplMozillaOld">\r
- <when-type-is class="com.allen_sauer.gwt.voices.client.ui.impl.NativeSoundImpl" />\r
- <when-property-is name="user.agent" value="gecko" />\r
- </replace-with>\r
-\r
-</module>\r
+++ /dev/null
-/*\r
- * Copyright 2011 Fred Sauer\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
- \r
- // See http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/Sound.html\r
-\r
- package {\r
- import flash.external.ExternalInterface;\r
- import flash.media.Sound;\r
- import flash.display.Sprite;\r
- import flash.events.Event;\r
- import flash.events.IOErrorEvent;\r
- import flash.media.SoundChannel;\r
- import flash.media.SoundLoaderContext;\r
- import flash.net.URLRequest;\r
- import flash.media.SoundTransform;\r
- \r
- public class Voices extends Sprite\r
- {\r
- private var sounds:Array = [];\r
- private var volume:Array = [];\r
- private var panning:Array = [];\r
- private var channel:Array = [];\r
- private var loop:Array = [];\r
- private var domId:String;\r
- \r
- public function Voices() {\r
- ExternalInterface.marshallExceptions = true;\r
- \r
- domId = this.root.loaderInfo.parameters.id;\r
- log("***************************************************************************************************");\r
- log("Creating Voices '" + domId + "' ...");\r
- \r
- log("ExternalInterface.available = " + ExternalInterface.available);\r
- log("ExternalInterface.objectID = " + ExternalInterface.objectID);\r
- \r
- var result:Object;\r
- \r
- ExternalInterface.addCallback("createSound", createSound);\r
- log("addCallback(createSound) -> done");\r
- \r
- ExternalInterface.addCallback("playSound", playSound);\r
- log("addCallback(playSound) -> done");\r
- \r
- ExternalInterface.addCallback("stopSound", stopSound);\r
- log("addCallback(stopSound) -> done");\r
- \r
- ExternalInterface.addCallback("setLooping", setLooping);\r
- log("addCallback(setLooping) -> done");\r
- \r
- ExternalInterface.addCallback("setVolume", setVolume);\r
- log("addCallback(setVolume) -> done");\r
- \r
- ExternalInterface.addCallback("setPanning", setPanning);\r
- log("addCallback(setPanning) -> done");\r
- \r
- log("Voices created.");\r
- \r
- // notify JavaScript that we are ready\r
- result = ExternalInterface.call("document.VoicesMovie['" + domId + "'].ready");\r
- log("document.VoicesMovie['" + domId + "'].ready() -> " + result);\r
- }\r
-\r
- private function createSound(id:Number, url:String, checkPolicyFile:Boolean):void {\r
- var func:String = "createSound(id=" + id + ", url='" + url + "')";\r
- logStart(func);\r
-\r
- // default to false\r
- loop[id] = 0;\r
-\r
- var bufferTime:Number = 1000; // default\r
- var context:SoundLoaderContext = new SoundLoaderContext(bufferTime, checkPolicyFile);\r
-\r
- sounds[id] = new Sound();\r
- volume[id] = 1;\r
- panning[id] = 0;\r
- sounds[id].addEventListener(Event.COMPLETE, function(event:Event):void {\r
- var func:String = "Event.COMPLETE (=Sound Loaded) id=" + id;\r
- logStart(func);\r
- try {\r
- var result:Object = ExternalInterface.call("document.VoicesMovie['" + domId + "'].soundLoaded", id);\r
- } catch(e:Error) {\r
- logError(func, e);\r
- }\r
- log("document.VoicesMovie['" + domId + "'].soundLoaded(" + id + ") -> " + result + " // " + typeof result);\r
- logEnd(func);\r
- });\r
- // TODO handle IO_ERROR\r
-// sounds[id].addEventListener(IOErrorEvent.IO_ERROR, function(event:Event):void {\r
-// log("IOErrorEvent.IO_ERROR id=" + id);\r
-// var result:Object = ExternalInterface.call("document.VoicesMovie['" + domId + "'].soundLoaded", id);\r
-// log("document.VoicesMovie['" + domId + "'].soundLoaded(" + id + ") -> " + result);\r
-// });\r
- sounds[id].load(new URLRequest(url), context);\r
- logEnd(func);\r
- }\r
- \r
- private function playSound(id:Number):Boolean {\r
- var func:String = "playSound(id=" + id + ")";\r
- logStart(func);\r
- var success:Boolean;\r
- \r
- if (channel[id] != null) {\r
- channel[id].stop();\r
- }\r
- var transform:SoundTransform = new SoundTransform(volume[id], panning[id]);\r
- /*\r
- * Sound#play() returns null if there is no sound card, or if the maximum number of sound channels (32) has been reached.\r
- * See http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#play()\r
- */\r
- channel[id] = sounds[id].play(0, loop[id], transform);\r
- if (channel[id] == null) {\r
- log("No (more) channel(s) available to play sound id " + id);\r
- success = false;\r
- } else {\r
- channel[id].addEventListener(Event.SOUND_COMPLETE, function(event:Event):void {\r
- var func:String = "Event.SOUND_COMPLETE (=Playback Completed) id=" + id;\r
- logStart(func);\r
- var method:String = "document.VoicesMovie['" + domId + "'].playbackCompleted";\r
- try {\r
- var result:Object = ExternalInterface.call(method, id);\r
- logResult(method, result);\r
- } catch(e:Error) {\r
- logError(method, e)\r
- }\r
- });\r
- success = true;\r
- }\r
- logEnd(func);\r
- return success;\r
- }\r
- \r
- private function stopSound(id:Number):void {\r
- var func:String = "stopSound(id=" + id + ")";\r
- logStart(func);\r
- channel[id].stop();\r
- logEnd(func);\r
- }\r
-\r
- private function setLooping(id:Number, loopCount:Number):void {\r
- var func:String = "setLooping(id=" + id + ", loopCount=" + loopCount + ")";\r
- logStart(func);\r
- loop[id] = loopCount;\r
- logEnd(func);\r
- }\r
- \r
- private function setVolume(id:Number, volume:Number):void {\r
- var func:String = "setVolume(id=" + id + ", volume=" + volume + "%)";\r
- logStart(func);\r
- this.volume[id] = volume;\r
- logEnd(func);\r
- }\r
- \r
- private function setPanning(id:Number, panning:Number):void {\r
- var func:String = "setPanning(id=" + id + ", panning=" + panning + ")";\r
- logStart(func);\r
- this.panning[id] = panning;\r
- logEnd(func);\r
- }\r
-\r
- private function logStart(func:String):void {\r
- log(">> " + func);\r
- }\r
-\r
- private function logEnd(func:String):void {\r
- log("<< " + func);\r
- }\r
-\r
- private function logResult(method:String, result:Object):void {\r
- log(method + " -> " + (typeof result) + ": " + result);\r
- }\r
- \r
- private function logError(func:String, e:Error):void {\r
- log(func + " -> ERROR(" + e + "): " + e.getStackTrace());\r
- }\r
- \r
- private function log(text:String):void {\r
- //ExternalInterface.call("document.VoicesMovie['" + this.root.loaderInfo.parameters.id + "'].log", text);\r
- }\r
- }\r
-}
\ No newline at end of file
<module rename-to='com.badlogic.gdx.backends.gwt'>\r
<inherits name='com.google.gwt.user.User' />\r
<inherits name="com.badlogic.gdx" />\r
- <inherits name='com.allen_sauer.gwt.voices.gwt-voices' />\r
<inherits name="com.google.gwt.typedarrays.TypedArrays" />\r
<inherits name="com.google.gwt.webgl.WebGL" />\r
<inherits name="com.badlogic.gwtref.GwtReflect"/>\r
\r
+ <script src="soundmanager2-jsmin.js"/>\r
+ <public path="gwt/resources"/>\r
<super-source path="gwt/emu" />\r
<source path="gwt">\r
<exclude name="**/emu/**" />\r
package com.badlogic.gdx.backends.gwt;\r
\r
-import com.allen_sauer.gwt.voices.client.SoundController;\r
import com.badlogic.gdx.Audio;\r
-import com.badlogic.gdx.Gdx;\r
import com.badlogic.gdx.audio.AudioDevice;\r
import com.badlogic.gdx.audio.AudioRecorder;\r
import com.badlogic.gdx.audio.Music;\r
import com.badlogic.gdx.utils.GdxRuntimeException;\r
\r
public class GwtAudio implements Audio {\r
- SoundController soundController;\r
- \r
public GwtAudio() {\r
- soundController = new SoundController();\r
- soundController.setGwtVoicesSwfLocation(((GwtApplication)Gdx.app).getBaseUrl());\r
}\r
\r
@Override\r
\r
@Override\r
public Sound newSound (FileHandle fileHandle) {\r
- return new GwtSound(soundController, fileHandle);\r
+ return new GwtSound(fileHandle);\r
}\r
\r
@Override\r
public Music newMusic (FileHandle file) {\r
- return new GwtMusic(soundController, file);\r
+ return new GwtMusic(file);\r
}\r
}\r
package com.badlogic.gdx.backends.gwt;\r
\r
-import com.allen_sauer.gwt.voices.client.Sound;\r
-import com.allen_sauer.gwt.voices.client.SoundController;\r
-import com.allen_sauer.gwt.voices.client.handler.PlaybackCompleteEvent;\r
-import com.allen_sauer.gwt.voices.client.handler.SoundHandler;\r
-import com.allen_sauer.gwt.voices.client.handler.SoundLoadStateChangeEvent;\r
import com.badlogic.gdx.Gdx;\r
import com.badlogic.gdx.audio.Music;\r
import com.badlogic.gdx.files.FileHandle;\r
\r
public class GwtMusic implements Music {\r
- Sound sound;\r
boolean isPlaying = false;\r
boolean isLooping = false;\r
\r
- public GwtMusic (SoundController soundController, FileHandle file) {\r
+ public GwtMusic (FileHandle file) {\r
String url = ((GwtApplication)Gdx.app).getBaseUrl() + file.path();\r
- String mimeType = getMimeType(file.extension());\r
- sound = soundController.createSound(mimeType, url, true, false);\r
- sound.addEventHandler(new SoundHandler() {\r
- @Override\r
- public void onSoundLoadStateChange (SoundLoadStateChangeEvent event) {\r
- if(isPlaying) sound.play();\r
- }\r
- \r
- @Override\r
- public void onPlaybackComplete (PlaybackCompleteEvent event) {\r
- isPlaying = false;\r
- }\r
- });\r
}\r
\r
- private String getMimeType(String extension) {\r
- if(extension.toLowerCase().equals("wav")) return Sound.MIME_TYPE_AUDIO_WAV_PCM;\r
- if(extension.toLowerCase().equals("ogg")) return Sound.MIME_TYPE_AUDIO_OGG_VORBIS;\r
- if(extension.toLowerCase().equals("mp3")) return Sound.MIME_TYPE_AUDIO_MPEG_MP3;\r
- return Sound.MIME_TYPE_AUDIO_WAV_UNKNOWN; // FIXME not really possible...\r
- }\r
-\r
@Override\r
public void play () {\r
if(isPlaying) return;\r
- sound.play();\r
isPlaying = true;\r
}\r
\r
@Override\r
public void pause () {\r
- sound.stop();\r
isPlaying = false;\r
}\r
\r
@Override\r
public void stop () {\r
- sound.stop();\r
isPlaying = false;\r
}\r
\r
\r
@Override\r
public void setLooping (boolean isLooping) {\r
- sound.setLooping(isLooping);\r
this.isLooping = isLooping;\r
}\r
\r
\r
@Override\r
public void setVolume (float volume) {\r
- sound.setVolume((int)(100 * volume));\r
}\r
\r
@Override\r
package com.badlogic.gdx.backends.gwt;\r
\r
-import com.allen_sauer.gwt.voices.client.SoundController;\r
import com.badlogic.gdx.Gdx;\r
import com.badlogic.gdx.audio.Sound;\r
import com.badlogic.gdx.files.FileHandle;\r
\r
public class GwtSound implements Sound {\r
- com.allen_sauer.gwt.voices.client.Sound sound;\r
\r
- public GwtSound (SoundController soundController, FileHandle file) {\r
+ public GwtSound (FileHandle file) {\r
String url = ((GwtApplication)Gdx.app).getBaseUrl() + file.path();\r
- String mimeType = getMimeType(file.extension());\r
- sound = soundController.createSound(mimeType, url, false, false);\r
}\r
\r
- private String getMimeType(String extension) {\r
- if(extension.toLowerCase().equals("wav")) return com.allen_sauer.gwt.voices.client.Sound.MIME_TYPE_AUDIO_WAV_PCM;\r
- if(extension.toLowerCase().equals("ogg")) return com.allen_sauer.gwt.voices.client.Sound.MIME_TYPE_AUDIO_OGG_VORBIS;\r
- if(extension.toLowerCase().equals("mp3")) return com.allen_sauer.gwt.voices.client.Sound.MIME_TYPE_AUDIO_MPEG_MP3;\r
- return com.allen_sauer.gwt.voices.client.Sound.MIME_TYPE_AUDIO_WAV_UNKNOWN; // FIXME not really possible...\r
- }\r
-\r
@Override\r
public long play () {\r
- sound.play();\r
return 0;\r
}\r
\r
@Override\r
public long play (float volume) {\r
- sound.play();\r
- sound.setVolume(((int)volume * 100));\r
return 0;\r
}\r
\r
@Override\r
public long loop () {\r
- // TODO Auto-generated method stub\r
return 0;\r
}\r
\r
@Override\r
public long loop (float volume) {\r
- // TODO Auto-generated method stub\r
return 0;\r
}\r
\r
@Override\r
public void stop () {\r
- // TODO Auto-generated method stub\r
-\r
}\r
\r
@Override\r
\r
@Override\r
public void stop (long soundId) {\r
- // TODO Auto-generated method stub\r
-\r
}\r
\r
@Override\r
public void setLooping (long soundId, boolean looping) {\r
- // TODO Auto-generated method stub\r
}\r
-\r
+ \r
@Override\r
public void setPitch (long soundId, float pitch) {\r
- // TODO Auto-generated method stub\r
-\r
}\r
\r
@Override\r
public void setVolume (long soundId, float volume) {\r
- // TODO Auto-generated method stub\r
-\r
}\r
\r
@Override\r
public void setPan (long soundId, float pan, float volume) {\r
- // TODO Auto-generated method stub\r
}\r
}\r
--- /dev/null
+/** @license
+
+
+ SoundManager 2: JavaScript Sound for the Web
+ ----------------------------------------------
+ http://schillmania.com/projects/soundmanager2/
+
+ Copyright (c) 2007, Scott Schiller. All rights reserved.
+ Code provided under the BSD License:
+ http://schillmania.com/projects/soundmanager2/license.txt
+
+ V2.97a.20120318
+*/
+(function(F){function W(W,la){function n(a){return function(d){var e=this._t;return!e||!e._a?(e&&e.sID?c._wD(m+"ignoring "+d.type+": "+e.sID):c._wD(m+"ignoring "+d.type),null):a.call(this,d)}}this.flashVersion=8;this.debugMode=!0;this.debugFlash=!1;this.consoleOnly=this.useConsole=!0;this.waitForWindowLoad=!1;this.bgColor="#ffffff";this.useHighPerformance=!1;this.html5PollingInterval=this.flashPollingInterval=null;this.flashLoadTimeout=1E3;this.wmode=null;this.allowScriptAccess="always";this.useFlashBlock=
+!1;this.useHTML5Audio=!0;this.html5Test=/^(probably|maybe)$/i;this.preferFlash=!0;this.noSWFCache=!1;this.audioFormats={mp3:{type:['audio/mpeg; codecs="mp3"',"audio/mpeg","audio/mp3","audio/MPA","audio/mpa-robust"],required:!0},mp4:{related:["aac","m4a"],type:['audio/mp4; codecs="mp4a.40.2"',"audio/aac","audio/x-m4a","audio/MP4A-LATM","audio/mpeg4-generic"],required:!1},ogg:{type:["audio/ogg; codecs=vorbis"],required:!1},wav:{type:['audio/wav; codecs="1"',"audio/wav","audio/wave","audio/x-wav"],required:!1}};
+this.defaultOptions={autoLoad:!1,autoPlay:!1,from:null,loops:1,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onposition:null,onstop:null,onfailure:null,onfinish:null,multiShot:!0,multiShotEvents:!1,position:null,pan:0,stream:!0,to:null,type:null,usePolicyFile:!1,volume:100};this.flash9Options={isMovieStar:null,usePeakData:!1,useWaveformData:!1,useEQData:!1,onbufferchange:null,ondataerror:null};this.movieStarOptions={bufferTime:3,serverURL:null,onconnect:null,
+duration:null};this.movieID="sm2-container";this.id=la||"sm2movie";this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.versionNumber="V2.97a.20120318";this.movieURL=this.version=null;this.url=W||null;this.altURL=null;this.enabled=this.swfLoaded=!1;this.oMC=null;this.sounds={};this.soundIDs=[];this.didFlashBlock=this.muted=!1;this.filePattern=null;this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.features={buffering:!1,peakData:!1,waveformData:!1,eqData:!1,
+movieStar:!1};this.sandbox={type:null,types:{remote:"remote (domain-based) rules",localWithFile:"local with file access (no internet access)",localWithNetwork:"local with network (internet access only, no local access)",localTrusted:"local, trusted (local+internet access)"},description:null,noRemote:null,noLocal:null};var ma;try{ma="undefined"!==typeof Audio&&"undefined"!==typeof(new Audio).canPlayType}catch(fb){ma=!1}this.hasHTML5=ma;this.html5={usingFlash:null};this.flash={};this.ignoreFlash=this.html5Only=
+!1;var Ea,c=this,g=null,m="HTML5::",r,t=navigator.userAgent,i=F,O=i.location.href.toString(),k=document,na,X,j,A=[],oa=!0,w,P=!1,Q=!1,p=!1,x=!1,Y=!1,o,Za=0,R,v,pa,G,H,Z,Fa,qa,D,$,aa,I,ra,sa,ba,ca,J,Ga,ta,$a=["log","info","warn","error"],Ha,da,Ia,S=null,ua=null,q,va,K,Ja,ea,fa,wa,s,ga=!1,xa=!1,Ka,La,Ma,ha=0,T=null,ia,y=null,Na,ja,U,B,ya,za,Oa,l,Pa=Array.prototype.slice,E=!1,u,ka,Qa,z,Ra,Aa=t.match(/(ipad|iphone|ipod)/i),ab=t.match(/firefox/i),bb=t.match(/droid/i),C=t.match(/msie/i),cb=t.match(/webkit/i),
+V=t.match(/safari/i)&&!t.match(/chrome/i),db=t.match(/opera/i),Ba=t.match(/(mobile|pre\/|xoom)/i)||Aa,Ca=!O.match(/usehtml5audio/i)&&!O.match(/sm2\-ignorebadua/i)&&V&&!t.match(/silk/i)&&t.match(/OS X 10_6_([3-7])/i),Sa="undefined"!==typeof console&&"undefined"!==typeof console.log,Da="undefined"!==typeof k.hasFocus?k.hasFocus():null,L=V&&"undefined"===typeof k.hasFocus,Ta=!L,Ua=/(mp3|mp4|mpa)/i,M=k.location?k.location.protocol.match(/http/i):null,Va=!M?"http://":"",Wa=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|mp4v|3gp|3g2)\s*(?:$|;)/i,
+Xa="mpeg4,aac,flv,mov,mp4,m4v,f4v,m4a,mp4v,3gp,3g2".split(","),eb=RegExp("\\.("+Xa.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL=!M;this._global_a=null;if(Ba&&(c.useHTML5Audio=!0,c.preferFlash=!1,Aa))E=c.ignoreFlash=!0;this.supported=this.ok=function(){return y?p&&!x:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(c){return r(c)||k[c]||i[c]};this.createSound=function(a){function d(){b=ea(b);c.sounds[f.id]=new Ea(f);c.soundIDs.push(f.id);
+return c.sounds[f.id]}var e,b=null,f=e=null;e="soundManager.createSound(): "+q(!p?"notReady":"notOK");if(!p||!c.ok())return wa(e),!1;2===arguments.length&&(a={id:arguments[0],url:arguments[1]});b=v(a);b.url=ia(b.url);f=b;f.id.toString().charAt(0).match(/^[0-9]$/)&&c._wD("soundManager.createSound(): "+q("badID",f.id),2);c._wD("soundManager.createSound(): "+f.id+" ("+f.url+")",1);if(s(f.id,!0))return c._wD("soundManager.createSound(): "+f.id+" exists",1),c.sounds[f.id];if(ja(f))e=d(),c._wD("Loading sound "+
+f.id+" via HTML5"),e._setup_html5(f);else{if(8<j){if(null===f.isMovieStar)f.isMovieStar=f.serverURL||(f.type?f.type.match(Wa):!1)||f.url.match(eb);f.isMovieStar&&c._wD("soundManager.createSound(): using MovieStar handling");if(f.isMovieStar){if(f.usePeakData)o("noPeak"),f.usePeakData=!1;1<f.loops&&o("noNSLoop")}}f=fa(f,"soundManager.createSound(): ");e=d();if(8===j)g._createSound(f.id,f.loops||1,f.usePolicyFile);else if(g._createSound(f.id,f.url,f.usePeakData,f.useWaveformData,f.useEQData,f.isMovieStar,
+f.isMovieStar?f.bufferTime:!1,f.loops||1,f.serverURL,f.duration||null,f.autoPlay,!0,f.autoLoad,f.usePolicyFile),!f.serverURL)e.connected=!0,f.onconnect&&f.onconnect.apply(e);!f.serverURL&&(f.autoLoad||f.autoPlay)&&e.load(f)}!f.serverURL&&f.autoPlay&&e.play();return e};this.destroySound=function(a,d){if(!s(a))return!1;var e=c.sounds[a],b;e._iO={};e.stop();e.unload();for(b=0;b<c.soundIDs.length;b++)if(c.soundIDs[b]===a){c.soundIDs.splice(b,1);break}d||e.destruct(!0);delete c.sounds[a];return!0};this.load=
+function(a,d){return!s(a)?!1:c.sounds[a].load(d)};this.unload=function(a){return!s(a)?!1:c.sounds[a].unload()};this.onposition=this.onPosition=function(a,d,e,b){return!s(a)?!1:c.sounds[a].onposition(d,e,b)};this.clearOnPosition=function(a,d,e){return!s(a)?!1:c.sounds[a].clearOnPosition(d,e)};this.start=this.play=function(a,d){if(!p||!c.ok())return wa("soundManager.play(): "+q(!p?"notReady":"notOK")),!1;if(!s(a)){d instanceof Object||(d={url:d});return d&&d.url?(c._wD('soundManager.play(): attempting to create "'+
+a+'"',1),d.id=a,c.createSound(d).play()):!1}return c.sounds[a].play(d)};this.setPosition=function(a,d){return!s(a)?!1:c.sounds[a].setPosition(d)};this.stop=function(a){if(!s(a))return!1;c._wD("soundManager.stop("+a+")",1);return c.sounds[a].stop()};this.stopAll=function(){var a;c._wD("soundManager.stopAll()",1);for(a in c.sounds)c.sounds.hasOwnProperty(a)&&c.sounds[a].stop()};this.pause=function(a){return!s(a)?!1:c.sounds[a].pause()};this.pauseAll=function(){var a;for(a=c.soundIDs.length-1;0<=a;a--)c.sounds[c.soundIDs[a]].pause()};
+this.resume=function(a){return!s(a)?!1:c.sounds[a].resume()};this.resumeAll=function(){var a;for(a=c.soundIDs.length-1;0<=a;a--)c.sounds[c.soundIDs[a]].resume()};this.togglePause=function(a){return!s(a)?!1:c.sounds[a].togglePause()};this.setPan=function(a,d){return!s(a)?!1:c.sounds[a].setPan(d)};this.setVolume=function(a,d){return!s(a)?!1:c.sounds[a].setVolume(d)};this.mute=function(a){var d=0;"string"!==typeof a&&(a=null);if(a){if(!s(a))return!1;c._wD('soundManager.mute(): Muting "'+a+'"');return c.sounds[a].mute()}c._wD("soundManager.mute(): Muting all sounds");
+for(d=c.soundIDs.length-1;0<=d;d--)c.sounds[c.soundIDs[d]].mute();return c.muted=!0};this.muteAll=function(){c.mute()};this.unmute=function(a){"string"!==typeof a&&(a=null);if(a){if(!s(a))return!1;c._wD('soundManager.unmute(): Unmuting "'+a+'"');return c.sounds[a].unmute()}c._wD("soundManager.unmute(): Unmuting all sounds");for(a=c.soundIDs.length-1;0<=a;a--)c.sounds[c.soundIDs[a]].unmute();c.muted=!1;return!0};this.unmuteAll=function(){c.unmute()};this.toggleMute=function(a){return!s(a)?!1:c.sounds[a].toggleMute()};
+this.getMemoryUse=function(){var c=0;g&&8!==j&&(c=parseInt(g._getMemoryUse(),10));return c};this.disable=function(a){var d;"undefined"===typeof a&&(a=!1);if(x)return!1;x=!0;o("shutdown",1);for(d=c.soundIDs.length-1;0<=d;d--)Ha(c.sounds[c.soundIDs[d]]);R(a);l.remove(i,"load",H);return!0};this.canPlayMIME=function(a){var d;c.hasHTML5&&(d=U({type:a}));return!y||d?d:a&&c.ok()?!!(8<j&&a.match(Wa)||a.match(c.mimePattern)):null};this.canPlayURL=function(a){var d;c.hasHTML5&&(d=U({url:a}));return!y||d?d:
+a&&c.ok()?!!a.match(c.filePattern):null};this.canPlayLink=function(a){return"undefined"!==typeof a.type&&a.type&&c.canPlayMIME(a.type)?!0:c.canPlayURL(a.href)};this.getSoundById=function(a,d){if(!a)throw Error("soundManager.getSoundById(): sID is null/undefined");var e=c.sounds[a];!e&&!d&&c._wD('"'+a+'" is an invalid sound ID.',2);return e};this.onready=function(a,d){if(a&&a instanceof Function)return p&&c._wD(q("queue","onready")),d||(d=i),pa("onready",a,d),G(),!0;throw q("needFunction","onready");
+};this.ontimeout=function(a,d){if(a&&a instanceof Function)return p&&c._wD(q("queue","ontimeout")),d||(d=i),pa("ontimeout",a,d),G({type:"ontimeout"}),!0;throw q("needFunction","ontimeout");};this._wD=this._writeDebug=function(a,d,e){var b,f;if(!c.debugMode)return!1;"undefined"!==typeof e&&e&&(a=a+" | "+(new Date).getTime());if(Sa&&c.useConsole){e=$a[d];if("undefined"!==typeof console[e])console[e](a);else console.log(a);if(c.consoleOnly)return!0}try{b=r("soundmanager-debug");if(!b)return!1;f=k.createElement("div");
+if(0===++Za%2)f.className="sm2-alt";d="undefined"===typeof d?0:parseInt(d,10);f.appendChild(k.createTextNode(a));if(d){if(2<=d)f.style.fontWeight="bold";if(3===d)f.style.color="#ff3333"}b.insertBefore(f,b.firstChild)}catch(g){}return!0};this._debug=function(){var a,d;o("currentObj",1);for(a=0,d=c.soundIDs.length;a<d;a++)c.sounds[c.soundIDs[a]]._debug()};this.reboot=function(){c._wD("soundManager.reboot()");c.soundIDs.length&&c._wD("Destroying "+c.soundIDs.length+" SMSound objects...");var a,d;for(a=
+c.soundIDs.length-1;0<=a;a--)c.sounds[c.soundIDs[a]].destruct();try{if(C)ua=g.innerHTML;S=g.parentNode.removeChild(g);c._wD("Flash movie removed.")}catch(e){o("badRemove",2)}ua=S=y=null;c.enabled=sa=p=ga=xa=P=Q=x=c.swfLoaded=!1;c.soundIDs=[];c.sounds={};g=null;for(a in A)if(A.hasOwnProperty(a))for(d=A[a].length-1;0<=d;d--)A[a][d].fired=!1;c._wD("soundManager: Rebooting...");i.setTimeout(c.beginDelayedInit,20)};this.getMoviePercent=function(){return g&&"undefined"!==typeof g.PercentLoaded?g.PercentLoaded():
+null};this.beginDelayedInit=function(){Y=!0;I();setTimeout(function(){if(xa)return!1;ca();aa();return xa=!0},20);Z()};this.destruct=function(){c._wD("soundManager.destruct()");c.disable(!0)};Ea=function(a){var d,e,b=this,f,k,h,N,i,Ya,p=!1,l=[],n=0,t,u,r=null;d=null;e=null;this.sID=a.id;this.url=a.url;this._iO=this.instanceOptions=this.options=v(a);this.pan=this.options.pan;this.volume=this.options.volume;this.isHTML5=!1;this._a=null;this.id3={};this._debug=function(){if(c.debugMode){var a=null,d=
+[],f,e;for(a in b.options)null!==b.options[a]&&(b.options[a]instanceof Function?(f=b.options[a].toString(),f=f.replace(/\s\s+/g," "),e=f.indexOf("{"),d.push(" "+a+": {"+f.substr(e+1,Math.min(Math.max(f.indexOf("\n")-1,64),64)).replace(/\n/g,"")+"... }")):d.push(" "+a+": "+b.options[a]));c._wD("SMSound() merged options: {\n"+d.join(", \n")+"\n}")}};this._debug();this.load=function(a){var d=null;if("undefined"!==typeof a)b._iO=v(a,b.options),b.instanceOptions=b._iO;else if(a=b.options,b._iO=a,b.instanceOptions=
+b._iO,r&&r!==b.url)o("manURL"),b._iO.url=b.url,b.url=null;if(!b._iO.url)b._iO.url=b.url;b._iO.url=ia(b._iO.url);c._wD("SMSound.load(): "+b._iO.url,1);if(b._iO.url===b.url&&0!==b.readyState&&2!==b.readyState)return o("onURL",1),3===b.readyState&&b._iO.onload&&b._iO.onload.apply(b,[!!b.duration]),b;a=b._iO;r=b.url;b.loaded=!1;b.readyState=1;b.playState=0;if(ja(a))d=b._setup_html5(a),d._called_load?c._wD(m+"ignoring request to load again: "+b.sID):(c._wD(m+"load: "+b.sID),b._html5_canplay=!1,b._a.autobuffer=
+"auto",b._a.preload="auto",d.load(),d._called_load=!0,a.autoPlay&&b.play());else try{b.isHTML5=!1,b._iO=fa(ea(a)),a=b._iO,8===j?g._load(b.sID,a.url,a.stream,a.autoPlay,a.whileloading?1:0,a.loops||1,a.usePolicyFile):g._load(b.sID,a.url,!!a.stream,!!a.autoPlay,a.loops||1,!!a.autoLoad,a.usePolicyFile)}catch(f){o("smError",2),w("onload",!1),J({type:"SMSOUND_LOAD_JS_EXCEPTION",fatal:!0})}return b};this.unload=function(){0!==b.readyState&&(c._wD('SMSound.unload(): "'+b.sID+'"'),b.isHTML5?(N(),b._a&&(b._a.pause(),
+ya(b._a))):8===j?g._unload(b.sID,"about:blank"):g._unload(b.sID),f());return b};this.destruct=function(a){c._wD('SMSound.destruct(): "'+b.sID+'"');if(b.isHTML5){if(N(),b._a)b._a.pause(),ya(b._a),E||h(),b._a._t=null,b._a=null}else b._iO.onfailure=null,g._destroySound(b.sID);a||c.destroySound(b.sID,!0)};this.start=this.play=function(a,d){var f,d=void 0===d?!0:d;a||(a={});b._iO=v(a,b._iO);b._iO=v(b._iO,b.options);b._iO.url=ia(b._iO.url);b.instanceOptions=b._iO;if(b._iO.serverURL&&!b.connected)return b.getAutoPlay()||
+(c._wD("SMSound.play(): Netstream not connected yet - setting autoPlay"),b.setAutoPlay(!0)),b;ja(b._iO)&&(b._setup_html5(b._iO),i());if(1===b.playState&&!b.paused)if(f=b._iO.multiShot)c._wD('SMSound.play(): "'+b.sID+'" already playing (multi-shot)',1);else return c._wD('SMSound.play(): "'+b.sID+'" already playing (one-shot)',1),b;if(b.loaded)c._wD('SMSound.play(): "'+b.sID+'"');else if(0===b.readyState){c._wD('SMSound.play(): Attempting to load "'+b.sID+'"',1);if(!b.isHTML5)b._iO.autoPlay=!0;b.load(b._iO)}else{if(2===
+b.readyState)return c._wD('SMSound.play(): Could not load "'+b.sID+'" - exiting',2),b;c._wD('SMSound.play(): "'+b.sID+'" is loading - attempting to play..',1)}if(!b.isHTML5&&9===j&&0<b.position&&b.position===b.duration)c._wD('SMSound.play(): "'+b.sID+'": Sound at end, resetting to position:0'),a.position=0;if(b.paused&&b.position&&0<b.position)c._wD('SMSound.play(): "'+b.sID+'" is resuming from paused state',1),b.resume();else{b._iO=v(a,b._iO);if(null!==b._iO.from&&null!==b._iO.to&&0===b.instanceCount&&
+0===b.playState&&!b._iO.serverURL){f=function(){b._iO=v(a,b._iO);b.play(b._iO)};if(b.isHTML5&&!b._html5_canplay)return c._wD('SMSound.play(): Beginning load of "'+b.sID+'" for from/to case'),b.load({_oncanplay:f}),!1;if(!b.isHTML5&&!b.loaded&&(!b.readyState||2!==b.readyState))return c._wD('SMSound.play(): Preloading "'+b.sID+'" for from/to case'),b.load({onload:f}),!1;b._iO=u()}c._wD('SMSound.play(): "'+b.sID+'" is starting to play');(!b.instanceCount||b._iO.multiShotEvents||!b.isHTML5&&8<j&&!b.getAutoPlay())&&
+b.instanceCount++;0===b.playState&&b._iO.onposition&&Ya(b);b.playState=1;b.paused=!1;b.position="undefined"!==typeof b._iO.position&&!isNaN(b._iO.position)?b._iO.position:0;if(!b.isHTML5)b._iO=fa(ea(b._iO));b._iO.onplay&&d&&(b._iO.onplay.apply(b),p=!0);b.setVolume(b._iO.volume,!0);b.setPan(b._iO.pan,!0);b.isHTML5?(i(),f=b._setup_html5(),b.setPosition(b._iO.position),f.play()):g._start(b.sID,b._iO.loops||1,9===j?b._iO.position:b._iO.position/1E3)}return b};this.stop=function(c){var a=b._iO;if(1===
+b.playState){b._onbufferchange(0);b._resetOnPosition(0);b.paused=!1;if(!b.isHTML5)b.playState=0;t();a.to&&b.clearOnPosition(a.to);if(b.isHTML5){if(b._a)c=b.position,b.setPosition(0),b.position=c,b._a.pause(),b.playState=0,b._onTimer(),N()}else g._stop(b.sID,c),a.serverURL&&b.unload();b.instanceCount=0;b._iO={};a.onstop&&a.onstop.apply(b)}return b};this.setAutoPlay=function(a){c._wD("sound "+b.sID+" turned autoplay "+(a?"on":"off"));b._iO.autoPlay=a;b.isHTML5||(g._setAutoPlay(b.sID,a),a&&!b.instanceCount&&
+1===b.readyState&&(b.instanceCount++,c._wD("sound "+b.sID+" incremented instance count to "+b.instanceCount)))};this.getAutoPlay=function(){return b._iO.autoPlay};this.setPosition=function(a){void 0===a&&(a=0);var d=b.isHTML5?Math.max(a,0):Math.min(b.duration||b._iO.duration,Math.max(a,0));b.position=d;a=b.position/1E3;b._resetOnPosition(b.position);b._iO.position=d;if(b.isHTML5){if(b._a)if(b._html5_canplay){if(b._a.currentTime!==a){c._wD("setPosition("+a+"): setting position");try{b._a.currentTime=
+a,(0===b.playState||b.paused)&&b._a.pause()}catch(f){c._wD("setPosition("+a+"): setting position failed: "+f.message,2)}}}else c._wD("setPosition("+a+"): delaying, sound not ready")}else a=9===j?b.position:a,b.readyState&&2!==b.readyState&&g._setPosition(b.sID,a,b.paused||!b.playState);b.isHTML5&&b.paused&&b._onTimer(!0);return b};this.pause=function(a){if(b.paused||0===b.playState&&1!==b.readyState)return b;c._wD("SMSound.pause()");b.paused=!0;b.isHTML5?(b._setup_html5().pause(),N()):(a||void 0===
+a)&&g._pause(b.sID);b._iO.onpause&&b._iO.onpause.apply(b);return b};this.resume=function(){var a=b._iO;if(!b.paused)return b;c._wD("SMSound.resume()");b.paused=!1;b.playState=1;b.isHTML5?(b._setup_html5().play(),i()):(a.isMovieStar&&!a.serverURL&&b.setPosition(b.position),g._pause(b.sID));!p&&a.onplay?(a.onplay.apply(b),p=!0):a.onresume&&a.onresume.apply(b);return b};this.togglePause=function(){c._wD("SMSound.togglePause()");if(0===b.playState)return b.play({position:9===j&&!b.isHTML5?b.position:
+b.position/1E3}),b;b.paused?b.resume():b.pause();return b};this.setPan=function(a,c){"undefined"===typeof a&&(a=0);"undefined"===typeof c&&(c=!1);b.isHTML5||g._setPan(b.sID,a);b._iO.pan=a;if(!c)b.pan=a,b.options.pan=a;return b};this.setVolume=function(a,d){"undefined"===typeof a&&(a=100);"undefined"===typeof d&&(d=!1);if(b.isHTML5){if(b._a)b._a.volume=Math.max(0,Math.min(1,a/100))}else g._setVolume(b.sID,c.muted&&!b.muted||b.muted?0:a);b._iO.volume=a;if(!d)b.volume=a,b.options.volume=a;return b};
+this.mute=function(){b.muted=!0;if(b.isHTML5){if(b._a)b._a.muted=!0}else g._setVolume(b.sID,0);return b};this.unmute=function(){b.muted=!1;var a="undefined"!==typeof b._iO.volume;if(b.isHTML5){if(b._a)b._a.muted=!1}else g._setVolume(b.sID,a?b._iO.volume:b.options.volume);return b};this.toggleMute=function(){return b.muted?b.unmute():b.mute()};this.onposition=this.onPosition=function(a,c,d){l.push({position:parseInt(a,10),method:c,scope:"undefined"!==typeof d?d:b,fired:!1});return b};this.clearOnPosition=
+function(b,a){var c,b=parseInt(b,10);if(isNaN(b))return!1;for(c=0;c<l.length;c++)if(b===l[c].position&&(!a||a===l[c].method))l[c].fired&&n--,l.splice(c,1)};this._processOnPosition=function(){var a,c;a=l.length;if(!a||!b.playState||n>=a)return!1;for(a-=1;0<=a;a--)if(c=l[a],!c.fired&&b.position>=c.position)c.fired=!0,n++,c.method.apply(c.scope,[c.position]);return!0};this._resetOnPosition=function(b){var a,c;a=l.length;if(!a)return!1;for(a-=1;0<=a;a--)if(c=l[a],c.fired&&b<=c.position)c.fired=!1,n--;
+return!0};u=function(){var a=b._iO,d=a.from,f=a.to,e,h;h=function(){c._wD(b.sID+': "to" time of '+f+" reached.");b.clearOnPosition(f,h);b.stop()};e=function(){c._wD(b.sID+': playing "from" '+d);if(null!==f&&!isNaN(f))b.onPosition(f,h)};if(null!==d&&!isNaN(d))a.position=d,a.multiShot=!1,e();return a};Ya=function(){var a,c=b._iO.onposition;if(c)for(a in c)if(c.hasOwnProperty(a))b.onPosition(parseInt(a,10),c[a])};t=function(){var a,c=b._iO.onposition;if(c)for(a in c)c.hasOwnProperty(a)&&b.clearOnPosition(parseInt(a,
+10))};i=function(){b.isHTML5&&Ka(b)};N=function(){b.isHTML5&&La(b)};f=function(){l=[];n=0;p=!1;b._hasTimer=null;b._a=null;b._html5_canplay=!1;b.bytesLoaded=null;b.bytesTotal=null;b.duration=b._iO&&b._iO.duration?b._iO.duration:null;b.durationEstimate=null;b.eqData=[];b.eqData.left=[];b.eqData.right=[];b.failures=0;b.isBuffering=!1;b.instanceOptions={};b.instanceCount=0;b.loaded=!1;b.metadata={};b.readyState=0;b.muted=!1;b.paused=!1;b.peakData={left:0,right:0};b.waveformData={left:[],right:[]};b.playState=
+0;b.position=null};f();this._onTimer=function(a){var c,f=!1,h={};if(b._hasTimer||a){if(b._a&&(a||(0<b.playState||1===b.readyState)&&!b.paused)){c=b._get_html5_duration();if(c!==d)d=c,b.duration=c,f=!0;b.durationEstimate=b.duration;c=1E3*b._a.currentTime||0;c!==e&&(e=c,f=!0);(f||a)&&b._whileplaying(c,h,h,h,h);return f}return!1}};this._get_html5_duration=function(){var a=b._iO,c=b._a?1E3*b._a.duration:a?a.duration:void 0;return c&&!isNaN(c)&&Infinity!==c?c:a?a.duration:null};this._setup_html5=function(a){var a=
+v(b._iO,a),d=decodeURI,e=E?c._global_a:b._a,h=d(a.url),g=e&&e._t?e._t.instanceOptions:null;if(e){if(e._t&&(!E&&h===d(r)||E&&g.url===a.url&&(!r||r===g.url)))return e;c._wD("setting new URL on existing object: "+h+(r?", old URL: "+r:""));E&&e._t&&e._t.playState&&a.url!==g.url&&e._t.stop();f();e.src=a.url;r=b.url=a.url;e._called_load=!1}else{c._wD("creating HTML5 Audio() element with URL: "+h);e=new Audio(a.url);e._called_load=!1;if(bb)e._called_load=!0;if(E)c._global_a=e}b.isHTML5=!0;b._a=e;e._t=b;
+k();e.loop=1<a.loops?"loop":"";a.autoLoad||a.autoPlay?b.load():(e.autobuffer=!1,e.preload="none");e.loop=1<a.loops?"loop":"";return e};k=function(){if(b._a._added_events)return!1;var a;c._wD(m+"adding event listeners: "+b.sID);b._a._added_events=!0;for(a in z)z.hasOwnProperty(a)&&b._a&&b._a.addEventListener(a,z[a],!1);return!0};h=function(){var a;c._wD(m+"removing event listeners: "+b.sID);b._a._added_events=!1;for(a in z)z.hasOwnProperty(a)&&b._a&&b._a.removeEventListener(a,z[a],!1)};this._onload=
+function(a){a=!!a;c._wD('SMSound._onload(): "'+b.sID+'"'+(a?" loaded.":" failed to load? - "+b.url),a?1:2);!a&&!b.isHTML5&&(!0===c.sandbox.noRemote&&c._wD("SMSound._onload(): "+q("noNet"),1),!0===c.sandbox.noLocal&&c._wD("SMSound._onload(): "+q("noLocal"),1));b.loaded=a;b.readyState=a?3:2;b._onbufferchange(0);b._iO.onload&&b._iO.onload.apply(b,[a]);return!0};this._onbufferchange=function(a){if(0===b.playState||a&&b.isBuffering||!a&&!b.isBuffering)return!1;b.isBuffering=1===a;b._iO.onbufferchange&&
+(c._wD("SMSound._onbufferchange(): "+a),b._iO.onbufferchange.apply(b));return!0};this._onsuspend=function(){b._iO.onsuspend&&(c._wD("SMSound._onsuspend()"),b._iO.onsuspend.apply(b));return!0};this._onfailure=function(a,d,f){b.failures++;c._wD('SMSound._onfailure(): "'+b.sID+'" count '+b.failures);if(b._iO.onfailure&&1===b.failures)b._iO.onfailure(b,a,d,f);else c._wD("SMSound._onfailure(): ignoring")};this._onfinish=function(){var a=b._iO.onfinish;b._onbufferchange(0);b._resetOnPosition(0);if(b.instanceCount){b.instanceCount--;
+if(!b.instanceCount)t(),b.playState=0,b.paused=!1,b.instanceCount=0,b.instanceOptions={},b._iO={},N();if((!b.instanceCount||b._iO.multiShotEvents)&&a)c._wD('SMSound._onfinish(): "'+b.sID+'"'),a.apply(b)}};this._whileloading=function(a,c,d,f){var e=b._iO;b.bytesLoaded=a;b.bytesTotal=c;b.duration=Math.floor(d);b.bufferLength=f;if(e.isMovieStar)b.durationEstimate=b.duration;else if(b.durationEstimate=e.duration?b.duration>e.duration?b.duration:e.duration:parseInt(b.bytesTotal/b.bytesLoaded*b.duration,
+10),void 0===b.durationEstimate)b.durationEstimate=b.duration;3!==b.readyState&&e.whileloading&&e.whileloading.apply(b)};this._whileplaying=function(a,c,d,f,e){var h=b._iO;if(isNaN(a)||null===a)return!1;b.position=a;b._processOnPosition();if(!b.isHTML5&&8<j){if(h.usePeakData&&"undefined"!==typeof c&&c)b.peakData={left:c.leftPeak,right:c.rightPeak};if(h.useWaveformData&&"undefined"!==typeof d&&d)b.waveformData={left:d.split(","),right:f.split(",")};if(h.useEQData&&"undefined"!==typeof e&&e&&e.leftEQ&&
+(a=e.leftEQ.split(","),b.eqData=a,b.eqData.left=a,"undefined"!==typeof e.rightEQ&&e.rightEQ))b.eqData.right=e.rightEQ.split(",")}1===b.playState&&(!b.isHTML5&&8===j&&!b.position&&b.isBuffering&&b._onbufferchange(0),h.whileplaying&&h.whileplaying.apply(b));return!0};this._onmetadata=function(a,d){c._wD('SMSound._onmetadata(): "'+this.sID+'" metadata received.');var e={},f,h;for(f=0,h=a.length;f<h;f++)e[a[f]]=d[f];b.metadata=e;b._iO.onmetadata&&b._iO.onmetadata.apply(b)};this._onid3=function(a,d){c._wD('SMSound._onid3(): "'+
+this.sID+'" ID3 data received.');var e=[],f,h;for(f=0,h=a.length;f<h;f++)e[a[f]]=d[f];b.id3=v(b.id3,e);b._iO.onid3&&b._iO.onid3.apply(b)};this._onconnect=function(a){a=1===a;c._wD('SMSound._onconnect(): "'+b.sID+'"'+(a?" connected.":" failed to connect? - "+b.url),a?1:2);if(b.connected=a)b.failures=0,s(b.sID)&&(b.getAutoPlay()?b.play(void 0,b.getAutoPlay()):b._iO.autoLoad&&b.load()),b._iO.onconnect&&b._iO.onconnect.apply(b,[a])};this._ondataerror=function(a){0<b.playState&&(c._wD("SMSound._ondataerror(): "+
+a),b._iO.ondataerror&&b._iO.ondataerror.apply(b))}};ba=function(){return k.body||k._docElement||k.getElementsByTagName("div")[0]};r=function(a){return k.getElementById(a)};v=function(a,d){var e={},b,f;for(b in a)a.hasOwnProperty(b)&&(e[b]=a[b]);b="undefined"===typeof d?c.defaultOptions:d;for(f in b)b.hasOwnProperty(f)&&"undefined"===typeof e[f]&&(e[f]=b[f]);return e};l=function(){function a(a){var a=Pa.call(a),b=a.length;e?(a[1]="on"+a[1],3<b&&a.pop()):3===b&&a.push(!1);return a}function c(a,d){var h=
+a.shift(),g=[b[d]];if(e)h[g](a[0],a[1]);else h[g].apply(h,a)}var e=i.attachEvent,b={add:e?"attachEvent":"addEventListener",remove:e?"detachEvent":"removeEventListener"};return{add:function(){c(a(arguments),"add")},remove:function(){c(a(arguments),"remove")}}}();z={abort:n(function(){c._wD(m+"abort: "+this._t.sID)}),canplay:n(function(){var a=this._t,d;if(a._html5_canplay)return!0;a._html5_canplay=!0;c._wD(m+"canplay: "+a.sID+", "+a.url);a._onbufferchange(0);d=!isNaN(a.position)?a.position/1E3:null;
+if(a.position&&this.currentTime!==d){c._wD(m+"canplay: setting position to "+d);try{this.currentTime=d}catch(e){c._wD(m+"setting position failed: "+e.message,2)}}a._iO._oncanplay&&a._iO._oncanplay()}),load:n(function(){var a=this._t;a.loaded||(a._onbufferchange(0),a._whileloading(a.bytesTotal,a.bytesTotal,a._get_html5_duration()),a._onload(!0))}),ended:n(function(){var a=this._t;c._wD(m+"ended: "+a.sID);a._onfinish()}),error:n(function(){c._wD(m+"error: "+this.error.code);this._t._onload(!1)}),loadeddata:n(function(){var a=
+this._t,d=a.bytesTotal||1;c._wD(m+"loadeddata: "+this._t.sID);if(!a._loaded&&!V)a.duration=a._get_html5_duration(),a._whileloading(d,d,a._get_html5_duration()),a._onload(!0)}),loadedmetadata:n(function(){c._wD(m+"loadedmetadata: "+this._t.sID)}),loadstart:n(function(){c._wD(m+"loadstart: "+this._t.sID);this._t._onbufferchange(1)}),play:n(function(){c._wD(m+"play: "+this._t.sID+", "+this._t.url);this._t._onbufferchange(0)}),playing:n(function(){c._wD(m+"playing: "+this._t.sID);this._t._onbufferchange(0)}),
+progress:n(function(a){var d=this._t,e,b,f;f=0;var g="progress"===a.type;b=a.target.buffered;var h=a.loaded||0,k=a.total||1;if(d.loaded)return!1;if(b&&b.length){for(e=b.length-1;0<=e;e--)f=b.end(e)-b.start(e);h=f/a.target.duration;if(g&&1<b.length){f=[];b=b.length;for(e=0;e<b;e++)f.push(a.target.buffered.start(e)+"-"+a.target.buffered.end(e));c._wD(m+"progress: timeRanges: "+f.join(", "))}g&&!isNaN(h)&&c._wD(m+"progress: "+d.sID+": "+Math.floor(100*h)+"% loaded")}isNaN(h)||(d._onbufferchange(0),d._whileloading(h,
+k,d._get_html5_duration()),h&&k&&h===k&&z.load.call(this,a))}),ratechange:n(function(){c._wD(m+"ratechange: "+this._t.sID)}),suspend:n(function(a){var d=this._t;c._wD(m+"suspend: "+d.sID);z.progress.call(this,a);d._onsuspend()}),stalled:n(function(){c._wD(m+"stalled: "+this._t.sID)}),timeupdate:n(function(){this._t._onTimer()}),waiting:n(function(){var a=this._t;c._wD(m+"waiting: "+a.sID);a._onbufferchange(1)})};ja=function(a){return!a.serverURL&&(a.type?U({type:a.type}):U({url:a.url})||c.html5Only)};
+ya=function(a){if(a)a.src=ab?"":"about:blank"};U=function(a){function d(a){return c.preferFlash&&u&&!c.ignoreFlash&&"undefined"!==typeof c.flash[a]&&c.flash[a]}if(!c.useHTML5Audio||!c.hasHTML5)return!1;var e=a.url||null,a=a.type||null,b=c.audioFormats,f;if(a&&"undefined"!==typeof c.html5[a])return c.html5[a]&&!d(a);if(!B){B=[];for(f in b)b.hasOwnProperty(f)&&(B.push(f),b[f].related&&(B=B.concat(b[f].related)));B=RegExp("\\.("+B.join("|")+")(\\?.*)?$","i")}f=e?e.toLowerCase().match(B):null;if(!f||
+!f.length)if(a)e=a.indexOf(";"),f=(-1!==e?a.substr(0,e):a).substr(6);else return!1;else f=f[1];if(f&&"undefined"!==typeof c.html5[f])return c.html5[f]&&!d(f);a="audio/"+f;e=c.html5.canPlayType({type:a});return(c.html5[f]=e)&&c.html5[a]&&!d(a)};Oa=function(){function a(a){var b,e,f=!1;if(!d||"function"!==typeof d.canPlayType)return!1;if(a instanceof Array){for(b=0,e=a.length;b<e&&!f;b++)if(c.html5[a[b]]||d.canPlayType(a[b]).match(c.html5Test))f=!0,c.html5[a[b]]=!0,c.flash[a[b]]=!(!c.preferFlash||!u||
+!a[b].match(Ua));return f}a=d&&"function"===typeof d.canPlayType?d.canPlayType(a):!1;return!(!a||!a.match(c.html5Test))}if(!c.useHTML5Audio||"undefined"===typeof Audio)return!1;var d="undefined"!==typeof Audio?db?new Audio(null):new Audio:null,e,b={},f,g;f=c.audioFormats;for(e in f)if(f.hasOwnProperty(e)&&(b[e]=a(f[e].type),b["audio/"+e]=b[e],c.flash[e]=c.preferFlash&&!c.ignoreFlash&&e.match(Ua)?!0:!1,f[e]&&f[e].related))for(g=f[e].related.length-1;0<=g;g--)b["audio/"+f[e].related[g]]=b[e],c.html5[f[e].related[g]]=
+b[e],c.flash[f[e].related[g]]=b[e];b.canPlayType=d?a:null;c.html5=v(c.html5,b);return!0};$={notReady:"Not loaded yet - wait for soundManager.onload()/onready()",notOK:"Audio support is not available.",domError:"soundManager::createMovie(): appendChild/innerHTML call failed. DOM not ready or other error.",spcWmode:"soundManager::createMovie(): Removing wmode, preventing known SWF loading issue(s)",swf404:"soundManager: Verify that %s is a valid path.",tryDebug:"Try soundManager.debugFlash = true for more security details (output goes to SWF.)",
+checkSWF:"See SWF output for more debug info.",localFail:"soundManager: Non-HTTP page ("+k.location.protocol+" URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/",waitFocus:"soundManager: Special case: Waiting for focus-related event..",waitImpatient:"soundManager: Getting impatient, still waiting for Flash%s...",waitForever:"soundManager: Waiting indefinitely for Flash (will recover if unblocked)...",
+needFunction:"soundManager: Function object expected for %s",badID:'Warning: Sound ID "%s" should be a string, starting with a non-numeric character',currentObj:"--- soundManager._debug(): Current sound objects ---",waitEI:"soundManager::initMovie(): Waiting for ExternalInterface call from Flash..",waitOnload:"soundManager: Waiting for window.onload()",docLoaded:"soundManager: Document already loaded",onload:"soundManager::initComplete(): calling soundManager.onload()",onloadOK:"soundManager.onload() complete",
+init:"soundManager::init()",didInit:"soundManager::init(): Already called?",flashJS:"soundManager: Attempting to call Flash from JS..",secNote:"Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html",badRemove:"Warning: Failed to remove flash movie.",noPeak:"Warning: peakData features unsupported for movieStar formats",
+shutdown:"soundManager.disable(): Shutting down",queue:"soundManager: Queueing %s handler",smFail:"soundManager: Failed to initialise.",smError:"SMSound.load(): Exception: JS-Flash communication failed, or JS error.",fbTimeout:"No flash response, applying .swf_timedout CSS..",fbLoaded:"Flash loaded",fbHandler:"soundManager::flashBlockHandler()",manURL:"SMSound.load(): Using manually-assigned URL",onURL:"soundManager.load(): current URL already assigned.",badFV:'soundManager.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.',
+as2loop:"Note: Setting stream:false so looping can work (flash 8 limitation)",noNSLoop:"Note: Looping not implemented for MovieStar formats",needfl9:"Note: Switching to flash 9, required for MP4 formats.",mfTimeout:"Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case",mfOn:"mobileFlash::enabling on-screen flash repositioning",policy:"Enabling usePolicyFile for data access"};q=function(){var a=Pa.call(arguments),c=a.shift(),c=$&&$[c]?$[c]:"",e,b;if(c&&a&&a.length)for(e=0,b=a.length;e<
+b;e++)c=c.replace("%s",a[e]);return c};ea=function(a){if(8===j&&1<a.loops&&a.stream)o("as2loop"),a.stream=!1;return a};fa=function(a,d){if(a&&!a.usePolicyFile&&(a.onid3||a.usePeakData||a.useWaveformData||a.useEQData))c._wD((d||"")+q("policy")),a.usePolicyFile=!0;return a};wa=function(a){"undefined"!==typeof console&&"undefined"!==typeof console.warn?console.warn(a):c._wD(a)};na=function(){return!1};Ha=function(a){for(var c in a)a.hasOwnProperty(c)&&"function"===typeof a[c]&&(a[c]=na)};da=function(a){"undefined"===
+typeof a&&(a=!1);if(x||a)o("smFail",2),c.disable(a)};Ia=function(a){var d=null;if(a)if(a.match(/\.swf(\?.*)?$/i)){if(d=a.substr(a.toLowerCase().lastIndexOf(".swf?")+4))return a}else a.lastIndexOf("/")!==a.length-1&&(a+="/");a=(a&&-1!==a.lastIndexOf("/")?a.substr(0,a.lastIndexOf("/")+1):"./")+c.movieURL;c.noSWFCache&&(a+="?ts="+(new Date).getTime());return a};qa=function(){j=parseInt(c.flashVersion,10);if(8!==j&&9!==j)c._wD(q("badFV",j,8)),c.flashVersion=j=8;var a=c.debugMode||c.debugFlash?"_debug.swf":
+".swf";if(c.useHTML5Audio&&!c.html5Only&&c.audioFormats.mp4.required&&9>j)c._wD(q("needfl9")),c.flashVersion=j=9;c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":9===j?" (AS3/Flash 9)":" (AS2/Flash 8)");8<j?(c.defaultOptions=v(c.defaultOptions,c.flash9Options),c.features.buffering=!0,c.defaultOptions=v(c.defaultOptions,c.movieStarOptions),c.filePatterns.flash9=RegExp("\\.(mp3|"+Xa.join("|")+")(\\?.*)?$","i"),c.features.movieStar=!0):c.features.movieStar=!1;c.filePattern=c.filePatterns[8!==
+j?"flash9":"flash8"];c.movieURL=(8===j?"soundmanager2.swf":"soundmanager2_flash9.swf").replace(".swf",a);c.features.peakData=c.features.waveformData=c.features.eqData=8<j};Ga=function(a,c){if(!g)return!1;g._setPolling(a,c)};ta=function(){if(c.debugURLParam.test(O))c.debugMode=!0;if(r(c.debugID))return!1;var a,d,e,b;if(c.debugMode&&!r(c.debugID)&&(!Sa||!c.useConsole||!c.consoleOnly)){a=k.createElement("div");a.id=c.debugID+"-toggle";d={position:"fixed",bottom:"0px",right:"0px",width:"1.2em",height:"1.2em",
+lineHeight:"1.2em",margin:"2px",textAlign:"center",border:"1px solid #999",cursor:"pointer",background:"#fff",color:"#333",zIndex:10001};a.appendChild(k.createTextNode("-"));a.onclick=Ja;a.title="Toggle SM2 debug console";if(t.match(/msie 6/i))a.style.position="absolute",a.style.cursor="hand";for(b in d)d.hasOwnProperty(b)&&(a.style[b]=d[b]);d=k.createElement("div");d.id=c.debugID;d.style.display=c.debugMode?"block":"none";if(c.debugMode&&!r(a.id)){try{e=ba(),e.appendChild(a)}catch(f){throw Error(q("domError")+
+" \n"+f.toString());}e.appendChild(d)}}};s=this.getSoundById;o=function(a,d){return a?c._wD(q(a),d):""};if(O.indexOf("sm2-debug=alert")+1&&c.debugMode)c._wD=function(a){F.alert(a)};Ja=function(){var a=r(c.debugID),d=r(c.debugID+"-toggle");if(!a)return!1;oa?(d.innerHTML="+",a.style.display="none"):(d.innerHTML="-",a.style.display="block");oa=!oa};w=function(a,c,e){if("undefined"!==typeof sm2Debugger)try{sm2Debugger.handleEvent(a,c,e)}catch(b){}return!0};K=function(){var a=[];c.debugMode&&a.push("sm2_debug");
+c.debugFlash&&a.push("flash_debug");c.useHighPerformance&&a.push("high_performance");return a.join(" ")};va=function(){var a=q("fbHandler"),d=c.getMoviePercent(),e={type:"FLASHBLOCK"};if(c.html5Only)return!1;if(c.ok()){if(c.didFlashBlock&&c._wD(a+": Unblocked"),c.oMC)c.oMC.className=[K(),"movieContainer","swf_loaded"+(c.didFlashBlock?" swf_unblocked":"")].join(" ")}else{if(y)c.oMC.className=K()+" movieContainer "+(null===d?"swf_timedout":"swf_error"),c._wD(a+": "+q("fbTimeout")+(d?" ("+q("fbLoaded")+
+")":""));c.didFlashBlock=!0;G({type:"ontimeout",ignoreInit:!0,error:e});J(e)}};pa=function(a,c,e){"undefined"===typeof A[a]&&(A[a]=[]);A[a].push({method:c,scope:e||null,fired:!1})};G=function(a){a||(a={type:"onready"});if(!p&&a&&!a.ignoreInit||"ontimeout"===a.type&&c.ok())return!1;var d={success:a&&a.ignoreInit?c.ok():!x},e=a&&a.type?A[a.type]||[]:[],b=[],f,g=[d],h=y&&c.useFlashBlock&&!c.ok();if(a.error)g[0].error=a.error;for(d=0,f=e.length;d<f;d++)!0!==e[d].fired&&b.push(e[d]);if(b.length){c._wD("soundManager: Firing "+
+b.length+" "+a.type+"() item"+(1===b.length?"":"s"));for(d=0,f=b.length;d<f;d++)if(b[d].scope?b[d].method.apply(b[d].scope,g):b[d].method.apply(this,g),!h)b[d].fired=!0}return!0};H=function(){i.setTimeout(function(){c.useFlashBlock&&va();G();c.onload instanceof Function&&(o("onload",1),c.onload.apply(i),o("onloadOK",1));c.waitForWindowLoad&&l.add(i,"load",H)},1)};ka=function(){if(void 0!==u)return u;var a=!1,c=navigator,e=c.plugins,b,f=i.ActiveXObject;if(e&&e.length)(c=c.mimeTypes)&&c["application/x-shockwave-flash"]&&
+c["application/x-shockwave-flash"].enabledPlugin&&c["application/x-shockwave-flash"].enabledPlugin.description&&(a=!0);else if("undefined"!==typeof f){try{b=new f("ShockwaveFlash.ShockwaveFlash")}catch(g){}a=!!b}return u=a};Na=function(){var a,d;if(Aa&&t.match(/os (1|2|3_0|3_1)/i)){c.hasHTML5=!1;c.html5Only=!0;if(c.oMC)c.oMC.style.display="none";return!1}if(c.useHTML5Audio){if(!c.html5||!c.html5.canPlayType)return c._wD("SoundManager: No HTML5 Audio() support detected."),c.hasHTML5=!1,!0;c.hasHTML5=
+!0;if(Ca&&(c._wD("soundManager::Note: Buggy HTML5 Audio in Safari on this OS X release, see https://bugs.webkit.org/show_bug.cgi?id=32159 - "+(!u?" would use flash fallback for MP3/MP4, but none detected.":"will use flash fallback for MP3/MP4, if available"),1),ka()))return!0}else return!0;for(d in c.audioFormats)if(c.audioFormats.hasOwnProperty(d)&&(c.audioFormats[d].required&&!c.html5.canPlayType(c.audioFormats[d].type)||c.flash[d]||c.flash[c.audioFormats[d].type]))a=!0;c.ignoreFlash&&(a=!1);c.html5Only=
+c.hasHTML5&&c.useHTML5Audio&&!a;return!c.html5Only};ia=function(a){var d,e,b=0;if(a instanceof Array){for(d=0,e=a.length;d<e;d++)if(a[d]instanceof Object){if(c.canPlayMIME(a[d].type)){b=d;break}}else if(c.canPlayURL(a[d])){b=d;break}if(a[b].url)a[b]=a[b].url;return a[b]}return a};Ka=function(a){if(!a._hasTimer)a._hasTimer=!0,!Ba&&c.html5PollingInterval&&(null===T&&0===ha&&(T=F.setInterval(Ma,c.html5PollingInterval)),ha++)};La=function(a){if(a._hasTimer)a._hasTimer=!1,!Ba&&c.html5PollingInterval&&
+ha--};Ma=function(){var a;if(null!==T&&!ha)return F.clearInterval(T),T=null,!1;for(a=c.soundIDs.length-1;0<=a;a--)c.sounds[c.soundIDs[a]].isHTML5&&c.sounds[c.soundIDs[a]]._hasTimer&&c.sounds[c.soundIDs[a]]._onTimer()};J=function(a){a="undefined"!==typeof a?a:{};c.onerror instanceof Function&&c.onerror.apply(i,[{type:"undefined"!==typeof a.type?a.type:null}]);"undefined"!==typeof a.fatal&&a.fatal&&c.disable()};Qa=function(){if(!Ca||!ka())return!1;var a=c.audioFormats,d,e;for(e in a)if(a.hasOwnProperty(e)&&
+("mp3"===e||"mp4"===e))if(c._wD("soundManager: Using flash fallback for "+e+" format"),c.html5[e]=!1,a[e]&&a[e].related)for(d=a[e].related.length-1;0<=d;d--)c.html5[a[e].related[d]]=!1};this._setSandboxType=function(a){var d=c.sandbox;d.type=a;d.description=d.types["undefined"!==typeof d.types[a]?a:"unknown"];c._wD("Flash security sandbox type: "+d.type);if("localWithFile"===d.type)d.noRemote=!0,d.noLocal=!1,o("secNote",2);else if("localWithNetwork"===d.type)d.noRemote=!1,d.noLocal=!0;else if("localTrusted"===
+d.type)d.noRemote=!1,d.noLocal=!1};this._externalInterfaceOK=function(a,d){if(c.swfLoaded)return!1;var e,b=(new Date).getTime();c._wD("soundManager::externalInterfaceOK()"+(a?" (~"+(b-a)+" ms)":""));w("swf",!0);w("flashtojs",!0);c.swfLoaded=!0;L=!1;Ca&&Qa();if(!d||d.replace(/\+dev/i,"")!==c.versionNumber.replace(/\+dev/i,""))return e='soundManager: Fatal: JavaScript file build "'+c.versionNumber+'" does not match Flash SWF build "'+d+'" at '+c.url+". Ensure both are up-to-date.",setTimeout(function(){throw Error(e);
+},0),!1;C?setTimeout(X,100):X()};ca=function(a,d){function e(){c._wD("-- SoundManager 2 "+c.version+(!c.html5Only&&c.useHTML5Audio?c.hasHTML5?" + HTML5 audio":", no HTML5 audio support":"")+(!c.html5Only?(c.useHighPerformance?", high performance mode, ":", ")+((c.flashPollingInterval?"custom ("+c.flashPollingInterval+"ms)":"normal")+" polling")+(c.wmode?", wmode: "+c.wmode:"")+(c.debugFlash?", flash debug mode":"")+(c.useFlashBlock?", flashBlock mode":""):"")+" --",1)}function b(a,b){return'<param name="'+
+a+'" value="'+b+'" />'}if(P&&Q)return!1;if(c.html5Only)return qa(),e(),c.oMC=r(c.movieID),X(),Q=P=!0,!1;var f=d||c.url,g=c.altURL||f,h;h=ba();var i,l,j=K(),m,n=null,n=(n=k.getElementsByTagName("html")[0])&&n.dir&&n.dir.match(/rtl/i),a="undefined"===typeof a?c.id:a;qa();c.url=Ia(M?f:g);d=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;if(null!==c.wmode&&(t.match(/msie 8/i)||!C&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i))o("spcWmode"),c.wmode=null;h={name:a,
+id:a,src:d,quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:Va+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};if(c.debugFlash)h.FlashVars="debug=1";c.wmode||delete h.wmode;if(C)f=k.createElement("div"),l=['<object id="'+a+'" data="'+d+'" type="'+h.type+'" title="'+h.title+'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="'+Va+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" width="'+
+h.width+'" height="'+h.height+'">',b("movie",d),b("AllowScriptAccess",c.allowScriptAccess),b("quality",h.quality),c.wmode?b("wmode",c.wmode):"",b("bgcolor",c.bgColor),b("hasPriority","true"),c.debugFlash?b("FlashVars",h.FlashVars):"","</object>"].join("");else for(i in f=k.createElement("embed"),h)h.hasOwnProperty(i)&&f.setAttribute(i,h[i]);ta();j=K();if(h=ba())if(c.oMC=r(c.movieID)||k.createElement("div"),c.oMC.id){m=c.oMC.className;c.oMC.className=(m?m+" ":"movieContainer")+(j?" "+j:"");c.oMC.appendChild(f);
+if(C)i=c.oMC.appendChild(k.createElement("div")),i.className="sm2-object-box",i.innerHTML=l;Q=!0}else{c.oMC.id=c.movieID;c.oMC.className="movieContainer "+j;i=j=null;if(!c.useFlashBlock)if(c.useHighPerformance)j={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"};else if(j={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},n)j.left=Math.abs(parseInt(j.left,10))+"px";if(cb)c.oMC.style.zIndex=1E4;if(!c.debugFlash)for(m in j)j.hasOwnProperty(m)&&
+(c.oMC.style[m]=j[m]);try{C||c.oMC.appendChild(f);h.appendChild(c.oMC);if(C)i=c.oMC.appendChild(k.createElement("div")),i.className="sm2-object-box",i.innerHTML=l;Q=!0}catch(p){throw Error(q("domError")+" \n"+p.toString());}}P=!0;e();c._wD("soundManager::createMovie(): Trying to load "+d+(!M&&c.altURL?" (alternate URL)":""),1);return!0};aa=function(){if(c.html5Only)return ca(),!1;if(g)return!1;g=c.getMovie(c.id);if(!g)S?(C?c.oMC.innerHTML=ua:c.oMC.appendChild(S),S=null,P=!0):ca(c.id,c.url),g=c.getMovie(c.id);
+g&&o("waitEI");c.oninitmovie instanceof Function&&setTimeout(c.oninitmovie,1);return!0};Z=function(){setTimeout(Fa,1E3)};Fa=function(){if(ga)return!1;ga=!0;l.remove(i,"load",Z);if(L&&!Da)return o("waitFocus"),!1;var a;p||(a=c.getMoviePercent(),c._wD(q("waitImpatient",100===a?" (SWF loaded)":0<a?" (SWF "+a+"% loaded)":"")));setTimeout(function(){a=c.getMoviePercent();p||(c._wD("soundManager: No Flash response within expected time.\nLikely causes: "+(0===a?"Loading "+c.movieURL+" may have failed (and/or Flash "+
+j+"+ not present?), ":"")+"Flash blocked or JS-Flash security error."+(c.debugFlash?" "+q("checkSWF"):""),2),!M&&a&&(o("localFail",2),c.debugFlash||o("tryDebug",2)),0===a&&c._wD(q("swf404",c.url)),w("flashtojs",!1,": Timed out"+M?" (Check flash security or flash blockers)":" (No plugin/missing SWF?)"));!p&&Ta&&(null===a?c.useFlashBlock||0===c.flashLoadTimeout?(c.useFlashBlock&&va(),o("waitForever")):da(!0):0===c.flashLoadTimeout?o("waitForever"):da(!0))},c.flashLoadTimeout)};D=function(){function a(){l.remove(i,
+"focus",D);l.remove(i,"load",D)}if(Da||!L)return a(),!0;Da=Ta=!0;c._wD("soundManager::handleFocus()");V&&L&&l.remove(i,"mousemove",D);ga=!1;a();return!0};Ra=function(){var a,d=[];if(c.useHTML5Audio&&c.hasHTML5){for(a in c.audioFormats)c.audioFormats.hasOwnProperty(a)&&d.push(a+": "+c.html5[a]+(!c.html5[a]&&u&&c.flash[a]?" (using flash)":c.preferFlash&&c.flash[a]&&u?" (preferring flash)":!c.html5[a]?" ("+(c.audioFormats[a].required?"required, ":"")+"and no flash support)":""));c._wD("-- SoundManager 2: HTML5 support tests ("+
+c.html5Test+"): "+d.join(", ")+" --",1)}};R=function(a){if(p)return!1;if(c.html5Only)return c._wD("-- SoundManager 2: loaded --"),p=!0,H(),w("onload",!0),!0;var d;if(!c.useFlashBlock||!c.flashLoadTimeout||c.getMoviePercent())p=!0,x&&(d={type:!u&&y?"NO_FLASH":"INIT_TIMEOUT"});c._wD("-- SoundManager 2 "+(x?"failed to load":"loaded")+" ("+(x?"security/load error":"OK")+") --",1);if(x||a){if(c.useFlashBlock&&c.oMC)c.oMC.className=K()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error");G({type:"ontimeout",
+error:d});w("onload",!1);J(d);return!1}w("onload",!0);if(c.waitForWindowLoad&&!Y)return o("waitOnload"),l.add(i,"load",H),!1;c.waitForWindowLoad&&Y&&o("docLoaded");H();return!0};X=function(){o("init");if(p)return o("didInit"),!1;if(c.html5Only){if(!p)l.remove(i,"load",c.beginDelayedInit),c.enabled=!0,R();return!0}aa();try{o("flashJS"),g._externalInterfaceTest(!1),Ga(!0,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||g._disableDebug(),c.enabled=!0,w("jstoflash",!0),c.html5Only||
+l.add(i,"unload",na)}catch(a){return c._wD("js/flash exception: "+a.toString()),w("jstoflash",!1),J({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),da(!0),R(),!1}R();l.remove(i,"load",c.beginDelayedInit);return!0};I=function(){if(sa)return!1;sa=!0;ta();var a=O.toLowerCase(),d=null,d=null,e="undefined"!==typeof console&&"undefined"!==typeof console.log;if(-1!==a.indexOf("sm2-usehtml5audio="))d="1"===a.charAt(a.indexOf("sm2-usehtml5audio=")+18),e&&console.log((d?"Enabling ":"Disabling ")+"useHTML5Audio via URL parameter"),
+c.useHTML5Audio=d;if(-1!==a.indexOf("sm2-preferflash="))d="1"===a.charAt(a.indexOf("sm2-preferflash=")+16),e&&console.log((d?"Enabling ":"Disabling ")+"preferFlash via URL parameter"),c.preferFlash=d;if(!u&&c.hasHTML5)c._wD("SoundManager: No Flash detected"+(!c.useHTML5Audio?", enabling HTML5.":". Trying HTML5-only mode.")),c.useHTML5Audio=!0,c.preferFlash=!1;Oa();c.html5.usingFlash=Na();y=c.html5.usingFlash;Ra();if(!u&&y)c._wD("SoundManager: Fatal error: Flash is needed to play some required formats, but is not available."),
+c.flashLoadTimeout=1;k.removeEventListener&&k.removeEventListener("DOMContentLoaded",I,!1);aa();return!0};za=function(){"complete"===k.readyState&&(I(),k.detachEvent("onreadystatechange",za));return!0};ra=function(){Y=!0;l.remove(i,"load",ra)};ka();l.add(i,"focus",D);l.add(i,"load",D);l.add(i,"load",Z);l.add(i,"load",ra);V&&L&&l.add(i,"mousemove",D);k.addEventListener?k.addEventListener("DOMContentLoaded",I,!1):k.attachEvent?k.attachEvent("onreadystatechange",za):(w("onload",!1),J({type:"NO_DOM2_EVENTS",
+fatal:!0}));"complete"===k.readyState&&setTimeout(I,100)}var la=null;if("undefined"===typeof SM2_DEFER||!SM2_DEFER)la=new W;F.SoundManager=W;F.soundManager=la})(window);
\ No newline at end of file