OSDN Git Service

[added] rudimentary sound support. add gwt-voices.swf to the folder containing assets...
authorbadlogicgames <badlogicgames@6c4fd544-2939-11df-bb46-9574ba5d0bfa>
Wed, 14 Mar 2012 10:50:44 +0000 (10:50 +0000)
committerbadlogicgames <badlogicgames@6c4fd544-2939-11df-bb46-9574ba5d0bfa>
Wed, 14 Mar 2012 10:50:44 +0000 (10:50 +0000)
44 files changed:
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/AbstractSound.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/FlashSound.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/Html5Sound.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/NativeSound.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/Sound.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/SoundController.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/SoundType.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/WebAudioSound.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/FiresSoundEvents.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/PlaybackCompleteEvent.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/SoundHandler.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/SoundHandlerCollection.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/SoundLoadStateChangeEvent.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/package.html [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/package.html [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/FlashMovie.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/VoicesMovie.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImpl.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplIE6.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplMozilla.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplMozillaOld.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplOpera.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplSafari.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplStandard.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImpl.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplIE6.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplMozilla.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplMozillaOld.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplOpera.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplSafari.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplStandard.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/package.html [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/package.html [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/util/DOMUtil.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/util/StringUtil.java [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/util/package.html [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/gwt-voices.gwt.xml [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/public/Voices.as [new file with mode: 0644]
backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gdx_backends_gwt.gwt.xml
backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/GwtApplication.java
backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/GwtAudio.java
backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/GwtMusic.java
backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/GwtSound.java
backends/gdx-backends-gwt/src/com/badlogic/gdx/backends/gwt/preloader/Preloader.java

diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/AbstractSound.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/AbstractSound.java
new file mode 100644 (file)
index 0000000..c8d4982
--- /dev/null
@@ -0,0 +1,93 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/FlashSound.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/FlashSound.java
new file mode 100644 (file)
index 0000000..4fe47d7
--- /dev/null
@@ -0,0 +1,167 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/Html5Sound.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/Html5Sound.java
new file mode 100644 (file)
index 0000000..887e2e0
--- /dev/null
@@ -0,0 +1,184 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/NativeSound.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/NativeSound.java
new file mode 100644 (file)
index 0000000..c17dddd
--- /dev/null
@@ -0,0 +1,135 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/Sound.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/Sound.java
new file mode 100644 (file)
index 0000000..9ad6e9c
--- /dev/null
@@ -0,0 +1,264 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/SoundController.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/SoundController.java
new file mode 100644 (file)
index 0000000..c9569df
--- /dev/null
@@ -0,0 +1,314 @@
+/*\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&nbsp;Flash&nbsp;Player\r
+     * < / a > , <a href=\r
+     * 'http://www.apple.com/quicktime/download/'>Apple&nbsp;QuickTime</a> or <a\r
+     * href=\r
+     * 'http://www.microsoft.com/windows/windowsmedia/'>Windows&nbsp;Media&nbsp;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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/SoundType.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/SoundType.java
new file mode 100644 (file)
index 0000000..e320da5
--- /dev/null
@@ -0,0 +1,61 @@
+/*\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>&lt;BGSOUND&gt;</code> and <code>&lt;OBJECT&gt;</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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/WebAudioSound.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/WebAudioSound.java
new file mode 100644 (file)
index 0000000..341a485
--- /dev/null
@@ -0,0 +1,221 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/FiresSoundEvents.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/FiresSoundEvents.java
new file mode 100644 (file)
index 0000000..df0726f
--- /dev/null
@@ -0,0 +1,33 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/PlaybackCompleteEvent.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/PlaybackCompleteEvent.java
new file mode 100644 (file)
index 0000000..a04458d
--- /dev/null
@@ -0,0 +1,47 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/SoundHandler.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/SoundHandler.java
new file mode 100644 (file)
index 0000000..f489400
--- /dev/null
@@ -0,0 +1,35 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/SoundHandlerCollection.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/SoundHandlerCollection.java
new file mode 100644 (file)
index 0000000..cae59fc
--- /dev/null
@@ -0,0 +1,48 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/SoundLoadStateChangeEvent.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/SoundLoadStateChangeEvent.java
new file mode 100644 (file)
index 0000000..d741a0b
--- /dev/null
@@ -0,0 +1,60 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/package.html b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/handler/package.html
new file mode 100644 (file)
index 0000000..36a6ecd
--- /dev/null
@@ -0,0 +1,9 @@
+<!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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/package.html b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/package.html
new file mode 100644 (file)
index 0000000..6c1f6db
--- /dev/null
@@ -0,0 +1,9 @@
+<!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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/FlashMovie.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/FlashMovie.java
new file mode 100644 (file)
index 0000000..76de4ac
--- /dev/null
@@ -0,0 +1,64 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/VoicesMovie.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/VoicesMovie.java
new file mode 100644 (file)
index 0000000..f1b1062
--- /dev/null
@@ -0,0 +1,210 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImpl.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImpl.java
new file mode 100644 (file)
index 0000000..d55c6b4
--- /dev/null
@@ -0,0 +1,63 @@
+/*\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&nbsp;9,0,47,0</code> or\r
+   * <code>Shockwave&nbsp;Flash&nbsp;9.0&nbsp;&nbsp;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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplIE6.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplIE6.java
new file mode 100644 (file)
index 0000000..9eaad13
--- /dev/null
@@ -0,0 +1,58 @@
+/*\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&nbsp;9,0,47,0} or\r
+   * {@literal UNIX&nbsp;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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplMozilla.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplMozilla.java
new file mode 100644 (file)
index 0000000..dc9deb0
--- /dev/null
@@ -0,0 +1,20 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplMozillaOld.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplMozillaOld.java
new file mode 100644 (file)
index 0000000..e073e99
--- /dev/null
@@ -0,0 +1,20 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplOpera.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplOpera.java
new file mode 100644 (file)
index 0000000..419eba2
--- /dev/null
@@ -0,0 +1,20 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplSafari.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplSafari.java
new file mode 100644 (file)
index 0000000..50e0cfc
--- /dev/null
@@ -0,0 +1,20 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplStandard.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/FlashMovieImplStandard.java
new file mode 100644 (file)
index 0000000..9a44a08
--- /dev/null
@@ -0,0 +1,47 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImpl.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImpl.java
new file mode 100644 (file)
index 0000000..f22fe46
--- /dev/null
@@ -0,0 +1,71 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplIE6.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplIE6.java
new file mode 100644 (file)
index 0000000..f46a7cb
--- /dev/null
@@ -0,0 +1,114 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplMozilla.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplMozilla.java
new file mode 100644 (file)
index 0000000..c861ee9
--- /dev/null
@@ -0,0 +1,49 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplMozillaOld.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplMozillaOld.java
new file mode 100644 (file)
index 0000000..3b3a576
--- /dev/null
@@ -0,0 +1,20 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplOpera.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplOpera.java
new file mode 100644 (file)
index 0000000..ad6e072
--- /dev/null
@@ -0,0 +1,56 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplSafari.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplSafari.java
new file mode 100644 (file)
index 0000000..65c28db
--- /dev/null
@@ -0,0 +1,49 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplStandard.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/NativeSoundImplStandard.java
new file mode 100644 (file)
index 0000000..d6410bc
--- /dev/null
@@ -0,0 +1,62 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/package.html b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/impl/package.html
new file mode 100644 (file)
index 0000000..ea64032
--- /dev/null
@@ -0,0 +1,9 @@
+<!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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/package.html b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/ui/package.html
new file mode 100644 (file)
index 0000000..4e7084f
--- /dev/null
@@ -0,0 +1,9 @@
+<!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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/util/DOMUtil.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/util/DOMUtil.java
new file mode 100644 (file)
index 0000000..45a04b9
--- /dev/null
@@ -0,0 +1,30 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/util/StringUtil.java b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/util/StringUtil.java
new file mode 100644 (file)
index 0000000..5ffc482
--- /dev/null
@@ -0,0 +1,31 @@
+/*\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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/util/package.html b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/client/util/package.html
new file mode 100644 (file)
index 0000000..32fd939
--- /dev/null
@@ -0,0 +1,9 @@
+<!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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/gwt-voices.gwt.xml b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/gwt-voices.gwt.xml
new file mode 100644 (file)
index 0000000..77ffd7e
--- /dev/null
@@ -0,0 +1,81 @@
+<?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
diff --git a/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/public/Voices.as b/backends/gdx-backends-gwt/src/com/allen_sauer/gwt/voices/public/Voices.as
new file mode 100644 (file)
index 0000000..22a2ba1
--- /dev/null
@@ -0,0 +1,193 @@
+/*\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
index f469f4d..68601f7 100644 (file)
@@ -2,8 +2,9 @@
 <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.google.gwt.typedarrays.TypedArrays"/>\r
-       <inherits name="com.google.gwt.webgl.WebGL"/>\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
 \r
        <super-source path="gwt/emu" />\r
        <source path="gwt">\r
index 83c6a5a..241c06b 100644 (file)
@@ -124,8 +124,14 @@ public abstract class GwtApplication implements EntryPoint, Application {
                Gdx.audio = new GwtAudio();\r
 \r
                // tell listener about app creation\r
-               listener.create();\r
-               listener.resize(graphics.getWidth(), graphics.getHeight());\r
+               try {\r
+                       listener.create();\r
+                       listener.resize(graphics.getWidth(), graphics.getHeight());\r
+               } catch(Throwable t) {\r
+                       error("GwtApplication", "exception: " + t.getMessage(), t);\r
+                       t.printStackTrace();\r
+                       throw new RuntimeException(t);\r
+               }\r
 \r
                // add resize handler to canvas\r
                // FIXME\r
@@ -149,7 +155,7 @@ public abstract class GwtApplication implements EntryPoint, Application {
                                        ((GwtInput)Gdx.input).justTouched = false;\r
                                } catch (Throwable t) {\r
                                        error("GwtApplication", "exception: " + t.getMessage(), t);\r
-                                       t.printStackTrace();\r
+                                       throw new RuntimeException(t);\r
                                }\r
                        }\r
                }.scheduleRepeating((int)((1f / config.fps) * 1000));\r
@@ -401,4 +407,8 @@ public abstract class GwtApplication implements EntryPoint, Application {
                protected AgentInfo () {\r
                }\r
        }\r
+\r
+       public String getBaseUrl () {\r
+               return preloader.baseUrl;\r
+       }\r
 }\r
index 966e304..df12263 100644 (file)
@@ -1,6 +1,8 @@
 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
@@ -9,6 +11,13 @@ import com.badlogic.gdx.files.FileHandle;
 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
        public AudioDevice newAudioDevice (int samplingRate, boolean isMono) {\r
                throw new GdxRuntimeException("AudioDevice not supported by GWT backend");\r
@@ -21,11 +30,11 @@ public class GwtAudio implements Audio {
 \r
        @Override\r
        public Sound newSound (FileHandle fileHandle) {\r
-               return new GwtSound();\r
+               return new GwtSound(soundController, fileHandle);\r
        }\r
 \r
        @Override\r
        public Music newMusic (FileHandle file) {\r
-               return new GwtMusic();\r
+               return new GwtMusic(soundController, file);\r
        }\r
 }\r
index 06054a6..8751100 100644 (file)
@@ -1,59 +1,89 @@
 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
+               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
-               // TODO Auto-generated method stub\r
-\r
+               if(isPlaying) return;\r
+               sound.play();\r
+               isPlaying = true;\r
        }\r
 \r
        @Override\r
        public void pause () {\r
-               // TODO Auto-generated method stub\r
-\r
+               sound.stop();\r
+               isPlaying = false;\r
        }\r
 \r
        @Override\r
        public void stop () {\r
-               // TODO Auto-generated method stub\r
-\r
+               sound.stop();\r
+               isPlaying = false;\r
        }\r
 \r
        @Override\r
        public boolean isPlaying () {\r
-               // TODO Auto-generated method stub\r
-               return false;\r
+               return isPlaying;\r
        }\r
 \r
        @Override\r
        public void setLooping (boolean isLooping) {\r
-               // TODO Auto-generated method stub\r
-\r
+               sound.setLooping(isLooping);\r
+               this.isLooping = isLooping;\r
        }\r
 \r
        @Override\r
        public boolean isLooping () {\r
-               // TODO Auto-generated method stub\r
-               return false;\r
+               return isLooping;\r
        }\r
 \r
        @Override\r
        public void setVolume (float volume) {\r
-               // TODO Auto-generated method stub\r
-\r
+               sound.setVolume((int)(100 * volume));\r
        }\r
 \r
        @Override\r
        public float getPosition () {\r
-               // TODO Auto-generated method stub\r
                return 0;\r
        }\r
 \r
        @Override\r
        public void dispose () {\r
-               // TODO Auto-generated method stub\r
-\r
        }\r
 }\r
index f22b56d..ad27249 100644 (file)
@@ -1,17 +1,36 @@
 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
+               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
-               // TODO Auto-generated method stub\r
+               sound.play();\r
                return 0;\r
        }\r
 \r
        @Override\r
        public long play (float volume) {\r
-               // TODO Auto-generated method stub\r
+               sound.play();\r
+               sound.setVolume(((int)volume * 100));\r
                return 0;\r
        }\r
 \r
@@ -35,8 +54,6 @@ public class GwtSound implements Sound {
 \r
        @Override\r
        public void dispose () {\r
-               // TODO Auto-generated method stub\r
-\r
        }\r
 \r
        @Override\r
@@ -48,7 +65,6 @@ public class GwtSound implements Sound {
        @Override\r
        public void setLooping (long soundId, boolean looping) {\r
                // TODO Auto-generated method stub\r
-\r
        }\r
 \r
        @Override\r
@@ -66,7 +82,5 @@ public class GwtSound implements Sound {
        @Override\r
        public void setPan (long soundId, float pan, float volume) {\r
                // TODO Auto-generated method stub\r
-\r
        }\r
-\r
 }\r
index 44528d6..479c824 100644 (file)
@@ -39,7 +39,7 @@ public class Preloader {
                }\r
        }\r
        \r
-       final String baseUrl;\r
+       public final String baseUrl;\r
        \r
        public Preloader() {\r
                baseUrl = GWT.getModuleBaseURL().replace(GWT.getModuleName() + "/", "");\r