Implementation of the AudioClip that uses HTML5 Audio tag sound
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 07 Aug 2013 15:29:42 +0200
branchsound
changeset 223ef2399c0fb9e
parent 222 63b36aba87c7
child 224 d76f680588ee
Implementation of the AudioClip that uses HTML5 Audio tag
sound/pom.xml
sound/src/main/java/net/java/html/sound/AudioClip.java
sound/src/main/java/org/apidesign/html/sound/impl/BrowserAudioEnv.java
sound/src/main/java/org/apidesign/html/sound/spi/AudioEnvironment.java
     1.1 --- a/sound/pom.xml	Wed Aug 07 14:28:21 2013 +0200
     1.2 +++ b/sound/pom.xml	Wed Aug 07 15:29:42 2013 +0200
     1.3 @@ -5,12 +5,12 @@
     1.4      <parent>
     1.5          <groupId>org.apidesign</groupId>
     1.6          <artifactId>html</artifactId>
     1.7 -        <version>0.4-SNAPSHOT</version>
     1.8 +        <version>0.5-SNAPSHOT</version>
     1.9      </parent>
    1.10 -    <groupId>net.java.html</groupId>
    1.11 -    <artifactId>sound</artifactId>
    1.12 -    <version>1.0-SNAPSHOT</version>
    1.13 -    <name>Sound API for Java</name>
    1.14 +    <groupId>org.apidesign.html</groupId>
    1.15 +    <artifactId>net.java.html.sound</artifactId>
    1.16 +    <version>0.5-SNAPSHOT</version>
    1.17 +    <name>Sound API via HTML</name>
    1.18      <url>http://maven.apache.org</url>
    1.19      <properties>
    1.20          <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    1.21 @@ -22,6 +22,7 @@
    1.22                  <artifactId>maven-javadoc-plugin</artifactId>
    1.23                  <configuration>
    1.24                      <skip>false</skip>
    1.25 +                    <subpackages>net.java.html.sound</subpackages>
    1.26                  </configuration>
    1.27              </plugin>
    1.28          </plugins>
    1.29 @@ -30,8 +31,18 @@
    1.30          <dependency>
    1.31              <groupId>org.testng</groupId>
    1.32              <artifactId>testng</artifactId>
    1.33 -            <version>6.5.2</version>
    1.34              <scope>test</scope>
    1.35          </dependency>
    1.36 +        <dependency>
    1.37 +            <groupId>org.apidesign.html</groupId>
    1.38 +            <artifactId>net.java.html.boot</artifactId>
    1.39 +            <version>0.5-SNAPSHOT</version>
    1.40 +            <type>jar</type>
    1.41 +        </dependency>
    1.42 +        <dependency>
    1.43 +          <groupId>org.netbeans.api</groupId>
    1.44 +          <artifactId>org-openide-util-lookup</artifactId>
    1.45 +          <scope>provided</scope>
    1.46 +        </dependency>
    1.47      </dependencies>
    1.48  </project>
     2.1 --- a/sound/src/main/java/net/java/html/sound/AudioClip.java	Wed Aug 07 14:28:21 2013 +0200
     2.2 +++ b/sound/src/main/java/net/java/html/sound/AudioClip.java	Wed Aug 07 15:29:42 2013 +0200
     2.3 @@ -1,106 +1,127 @@
     2.4  /**
     2.5 - * Back 2 Browser Bytecode Translator Copyright (C) 2012 Jaroslav Tulach
     2.6 - * <jaroslav.tulach@apidesign.org>
     2.7 + * HTML via Java(tm) Language Bindings
     2.8 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     2.9   *
    2.10 - * This program is free software: you can redistribute it and/or modify it under
    2.11 - * the terms of the GNU General Public License as published by the Free Software
    2.12 - * Foundation, version 2 of the License.
    2.13 + * This program is free software: you can redistribute it and/or modify
    2.14 + * it under the terms of the GNU General Public License as published by
    2.15 + * the Free Software Foundation, version 2 of the License.
    2.16   *
    2.17 - * This program is distributed in the hope that it will be useful, but WITHOUT
    2.18 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    2.19 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
    2.20 - * details.
    2.21 + * This program is distributed in the hope that it will be useful,
    2.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.24 + * GNU General Public License for more details. apidesign.org
    2.25 + * designates this particular file as subject to the
    2.26 + * "Classpath" exception as provided by apidesign.org
    2.27 + * in the License file that accompanied this code.
    2.28   *
    2.29 - * You should have received a copy of the GNU General Public License along with
    2.30 - * this program. Look for COPYING file in the top folder. If not, see
    2.31 - * http://opensource.org/licenses/GPL-2.0.
    2.32 + * You should have received a copy of the GNU General Public License
    2.33 + * along with this program. Look for COPYING file in the top folder.
    2.34 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    2.35   */
    2.36  package net.java.html.sound;
    2.37  
    2.38  import java.util.ServiceLoader;
    2.39  import org.apidesign.html.sound.spi.AudioEnvironment;
    2.40  
    2.41 -/**
    2.42 +/** Handle to an audio clip which can be {@link #play() played}, {@link #pause() paused}
    2.43 + * and etc. Obtain new instance via {@link #create(java.lang.String) create} factory 
    2.44 + * method and then use it when necessary.
    2.45   *
    2.46   * @author antonepple
    2.47   */
    2.48 -public final class AudioClip {
    2.49 -
    2.50 -    private Object cached;
    2.51 -    private int cacheHash;
    2.52 -    private final String src;
    2.53 -    private final AudioEnvironment audioEnvironment;
    2.54 -
    2.55 -    private AudioClip(String src) {
    2.56 -        this.src = src;
    2.57 -        ServiceLoader<AudioEnvironment> loader = ServiceLoader.load(AudioEnvironment.class);
    2.58 -        audioEnvironment = loader.iterator().next();
    2.59 +public abstract class AudioClip {
    2.60 +    private AudioClip() {
    2.61      }
    2.62  
    2.63 +    /** Creates new instance of an audio clip based on the provided URL.
    2.64 +     * 
    2.65 +     * @param src the URL where to find the audio clip
    2.66 +     * @return the audio clip handle
    2.67 +     * @throws NullPointerException if src is <code>null</code>
    2.68 +     */
    2.69      public static AudioClip create(String src) {
    2.70 -        return new AudioClip(src);
    2.71 +        src.getClass();
    2.72 +        for (AudioEnvironment<?> ae : ServiceLoader.load(AudioEnvironment.class)) {
    2.73 +            Impl handle = create(ae, src);
    2.74 +            if (handle != null) {
    2.75 +                return handle;
    2.76 +            }
    2.77 +        }
    2.78 +        throw new IllegalStateException();
    2.79      }
    2.80 +    
    2.81 +    /** Plays the clip from begining to the end.
    2.82 +     */
    2.83 +    public abstract void play();
    2.84  
    2.85 -    public void play() {
    2.86 -        Object nativeClip = audioEnvironment.play(this, cached);
    2.87 -        cache(nativeClip);
    2.88 +    /** Pauses playback of the clip
    2.89 +     */
    2.90 +    public abstract void pause();
    2.91 +
    2.92 +    /**
    2.93 +     * Specifies the volume of the audio. Must be a number between 0.0 and 1.0:
    2.94 +     * <ul>
    2.95 +     *   <li>1.0 - highest volume</li>
    2.96 +     *   <li>0.5 - 50% volume</li>
    2.97 +     *   <li>0.0 - silent</li>
    2.98 +     * </ul>
    2.99 +     * 
   2.100 +     * @param volume for the playback
   2.101 +     */
   2.102 +    public abstract void setVolume(double volume);
   2.103 +
   2.104 +//    public abstract void playFrom(int seconds);
   2.105 +
   2.106 +    //
   2.107 +    // Implementation
   2.108 +    //
   2.109 +    
   2.110 +    private static <Audio> Impl<Audio> create(AudioEnvironment<Audio> env, String src) {
   2.111 +        Audio a = env.create(src);
   2.112 +        if (a != null) {
   2.113 +            return new Impl<Audio>(env, src, a);
   2.114 +        } else {
   2.115 +            return null;
   2.116 +        }
   2.117      }
   2.118 +    
   2.119 +    private static final class Impl<Audio> extends AudioClip {
   2.120 +        private final String src;
   2.121 +        private final Audio clip;
   2.122 +        private final AudioEnvironment<Audio> env;
   2.123  
   2.124 -    public void pause() {
   2.125 -        Object nativeClip = audioEnvironment.pause(this, cached);
   2.126 -        cache(nativeClip);
   2.127 -    }
   2.128 +        public Impl(AudioEnvironment<Audio> env, String src, Audio clip) {
   2.129 +            this.clip = clip;
   2.130 +            this.env = env;
   2.131 +            this.src = src;
   2.132 +        }
   2.133  
   2.134 -    public void stop() {
   2.135 -        Object nativeClip = audioEnvironment.stop(this, cached);
   2.136 -        cache(nativeClip);
   2.137 -    }
   2.138 +        @Override
   2.139 +        public void play() {
   2.140 +            env.play(clip);
   2.141 +        }
   2.142  
   2.143 -    public void setVolume(int volume) {
   2.144 -        Object nativeClip = audioEnvironment.setVolume(this, volume, cached);
   2.145 -        cache(nativeClip);
   2.146 -    }
   2.147 +        @Override
   2.148 +        public void pause() {
   2.149 +            env.pause(clip);
   2.150 +        }
   2.151  
   2.152 -    public void playFrom(int seconds) {
   2.153 -        Object nativeClip = audioEnvironment.playFrom(this, seconds, cached);
   2.154 -        cache(nativeClip);
   2.155 -    }
   2.156 +        @Override
   2.157 +        public void setVolume(double volume) {
   2.158 +            env.setVolume(clip, volume);
   2.159 +        }
   2.160  
   2.161 -    void cache(Object toCache) {
   2.162 -        cacheHash = hashCode();
   2.163 -        this.cached = toCache;
   2.164 -    }
   2.165 +        @Override
   2.166 +        public int hashCode() {
   2.167 +            return 59 * src.hashCode();
   2.168 +        }
   2.169  
   2.170 -    private boolean isCached() {
   2.171 -        return cacheHash == hashCode();
   2.172 -    }
   2.173 -
   2.174 -    Object getCached() {
   2.175 -        return isCached() ? cached : null;
   2.176 -    }
   2.177 -
   2.178 -    @Override
   2.179 -    public int hashCode() {
   2.180 -        int hash = 5;
   2.181 -        hash = 59 * hash + (this.src != null ? this.src.hashCode() : 0) ^ (cached==null? 1231 : 1237);
   2.182 -        return hash;
   2.183 -    }
   2.184 -
   2.185 -    @Override
   2.186 -    public boolean equals(Object obj) {
   2.187 -        if (obj == null) {
   2.188 +        @Override
   2.189 +        public boolean equals(Object obj) {
   2.190 +            if (obj instanceof Impl) {
   2.191 +                return src.equals(((Impl)obj).src);
   2.192 +            }
   2.193              return false;
   2.194          }
   2.195 -        if (getClass() != obj.getClass()) {
   2.196 -            return false;
   2.197 -        }
   2.198 -        final AudioClip other = (AudioClip) obj;
   2.199 -        if ((this.src == null) ? (other.src != null) : !this.src.equals(other.src)) {
   2.200 -            return false;
   2.201 -        }
   2.202 -        if ((this.cached == null) != (other.cached == null)) {
   2.203 -            return false;
   2.204 -        }
   2.205 -        return true;
   2.206 -    }
   2.207 +    } // end of Impl
   2.208  }
   2.209 \ No newline at end of file
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/sound/src/main/java/org/apidesign/html/sound/impl/BrowserAudioEnv.java	Wed Aug 07 15:29:42 2013 +0200
     3.3 @@ -0,0 +1,53 @@
     3.4 +/**
     3.5 + * HTML via Java(tm) Language Bindings
     3.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.7 + *
     3.8 + * This program is free software: you can redistribute it and/or modify
     3.9 + * it under the terms of the GNU General Public License as published by
    3.10 + * the Free Software Foundation, version 2 of the License.
    3.11 + *
    3.12 + * This program is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU General Public License for more details. apidesign.org
    3.16 + * designates this particular file as subject to the
    3.17 + * "Classpath" exception as provided by apidesign.org
    3.18 + * in the License file that accompanied this code.
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License
    3.21 + * along with this program. Look for COPYING file in the top folder.
    3.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    3.23 + */
    3.24 +package org.apidesign.html.sound.impl;
    3.25 +
    3.26 +import net.java.html.js.JavaScriptBody;
    3.27 +import org.apidesign.html.sound.spi.AudioEnvironment;
    3.28 +import org.openide.util.lookup.ServiceProvider;
    3.29 +
    3.30 +/** Registers an audio provider that delegates to HTML5 Audio tag.
    3.31 + *
    3.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    3.33 + */
    3.34 +@ServiceProvider(service = AudioEnvironment.class, position = 100)
    3.35 +public final class BrowserAudioEnv implements AudioEnvironment<Object> {
    3.36 +    @Override
    3.37 +    @JavaScriptBody(args = { "src" }, body = ""
    3.38 +        + "if (!Audio) return null;"
    3.39 +        + "return new Audio(src);")
    3.40 +    public Object create(String src) {
    3.41 +        // null if not running in browser
    3.42 +        return null;
    3.43 +    }
    3.44 +
    3.45 +    @Override @JavaScriptBody(args = { "a" }, body = "a.play();")
    3.46 +    public void play(Object a) {
    3.47 +    }
    3.48 +
    3.49 +    @Override @JavaScriptBody(args = { "a" }, body = "a.pause();")
    3.50 +    public void pause(Object a) {
    3.51 +    }
    3.52 +
    3.53 +    @Override @JavaScriptBody(args = { "a", "volume" }, body = "a.setVolume(volume);")
    3.54 +    public void setVolume(Object a, double volume) {
    3.55 +    }
    3.56 +}
     4.1 --- a/sound/src/main/java/org/apidesign/html/sound/spi/AudioEnvironment.java	Wed Aug 07 14:28:21 2013 +0200
     4.2 +++ b/sound/src/main/java/org/apidesign/html/sound/spi/AudioEnvironment.java	Wed Aug 07 15:29:42 2013 +0200
     4.3 @@ -1,38 +1,36 @@
     4.4  /**
     4.5 - * Back 2 Browser Bytecode Translator Copyright (C) 2012 Jaroslav Tulach
     4.6 - * <jaroslav.tulach@apidesign.org>
     4.7 + * HTML via Java(tm) Language Bindings
     4.8 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4.9   *
    4.10 - * This program is free software: you can redistribute it and/or modify it under
    4.11 - * the terms of the GNU General Public License as published by the Free Software
    4.12 - * Foundation, version 2 of the License.
    4.13 + * This program is free software: you can redistribute it and/or modify
    4.14 + * it under the terms of the GNU General Public License as published by
    4.15 + * the Free Software Foundation, version 2 of the License.
    4.16   *
    4.17 - * This program is distributed in the hope that it will be useful, but WITHOUT
    4.18 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    4.19 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
    4.20 - * details.
    4.21 + * This program is distributed in the hope that it will be useful,
    4.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.24 + * GNU General Public License for more details. apidesign.org
    4.25 + * designates this particular file as subject to the
    4.26 + * "Classpath" exception as provided by apidesign.org
    4.27 + * in the License file that accompanied this code.
    4.28   *
    4.29 - * You should have received a copy of the GNU General Public License along with
    4.30 - * this program. Look for COPYING file in the top folder. If not, see
    4.31 - * http://opensource.org/licenses/GPL-2.0.
    4.32 + * You should have received a copy of the GNU General Public License
    4.33 + * along with this program. Look for COPYING file in the top folder.
    4.34 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    4.35   */
    4.36  package org.apidesign.html.sound.spi;
    4.37  
    4.38 -import net.java.html.sound.AudioClip;
    4.39 -
    4.40 -/**
    4.41 +/** Basic interface for sound playback providers.
    4.42   *
    4.43   * @author antonepple
    4.44 + * @param <Audio> the type representing an audio
    4.45   */
    4.46 -public interface AudioEnvironment {
    4.47 +public interface AudioEnvironment<Audio> {
    4.48 +    public Audio create(String src);
    4.49  
    4.50 -    public  Object play(AudioClip aThis, Object cached);
    4.51 +    public void play(Audio a);
    4.52  
    4.53 -    public  Object pause(AudioClip aThis, Object cached);
    4.54 +    public void pause(Audio a);
    4.55  
    4.56 -    public  Object stop(AudioClip aThis, Object cached);
    4.57 -
    4.58 -    public  Object setVolume(AudioClip aThis, int volume, Object cached);
    4.59 -
    4.60 -    public  Object playFrom(AudioClip aThis, int seconds, Object cached);
    4.61 -    
    4.62 +    public void setVolume(Audio a, double volume);
    4.63  }