1 /*
   2  * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.audio;
  27 
  28 import java.io.InputStream;
  29 import java.security.AccessController;
  30 import java.security.PrivilegedAction;
  31 
  32 
  33 /**
  34  * This class provides an interface to play audio streams.
  35  *
  36  * To play an audio stream use:
  37  * <pre>
  38  *      AudioPlayer.player.start(audiostream);
  39  * </pre>
  40  * To stop playing an audio stream use:
  41  * <pre>
  42  *      AudioPlayer.player.stop(audiostream);
  43  * </pre>
  44  * To play an audio stream from a URL use:
  45  * <pre>
  46  *      AudioStream audiostream = new AudioStream(url.openStream());
  47  *      AudioPlayer.player.start(audiostream);
  48  * </pre>
  49  * To play a continuous sound you first have to
  50  * create an AudioData instance and use it to construct a
  51  * ContinuousAudioDataStream.
  52  * For example:
  53  * <pre>
  54  *      AudioData data = new AudioStream(url.openStream()).getData();
  55  *      ContinuousAudioDataStream audiostream = new ContinuousAudioDataStream(data);
  56  *      AudioPlayer.player.start(audiostream);
  57  * </pre>
  58  *
  59  * @see AudioData
  60  * @see AudioDataStream
  61  * @see AudioDevice
  62  * @see AudioStream
  63  * @author Arthur van Hoff, Thomas Ball
  64  */
  65 
  66 public final class AudioPlayer extends Thread {
  67 
  68         private final AudioDevice devAudio;
  69         private final static boolean DEBUG = false /*true*/;
  70 
  71         /**
  72          * The default audio player. This audio player is initialized
  73          * automatically.
  74          */
  75         public static final AudioPlayer player = getAudioPlayer();
  76 
  77         private static ThreadGroup getAudioThreadGroup() {
  78 
  79             if(DEBUG) { System.out.println("AudioPlayer.getAudioThreadGroup()"); }
  80             ThreadGroup g = currentThread().getThreadGroup();
  81             while ((g.getParent() != null) &&
  82                    (g.getParent().getParent() != null)) {
  83                 g = g.getParent();
  84             }
  85             return g;
  86         }
  87 
  88         /**
  89          * Create an AudioPlayer thread in a privileged block.
  90          */
  91 
  92         private static AudioPlayer getAudioPlayer() {
  93 
  94             if(DEBUG) { System.out.println("> AudioPlayer.getAudioPlayer()"); }
  95             PrivilegedAction<AudioPlayer> action = new PrivilegedAction<AudioPlayer>() {
  96                     public AudioPlayer run() {
  97                         AudioPlayer t = new AudioPlayer();
  98                         t.setPriority(MAX_PRIORITY);
  99                         t.setDaemon(true);
 100                         t.start();
 101                         return t;
 102                     }
 103                 };
 104             return  AccessController.doPrivileged(action);
 105         }
 106 
 107         /**
 108          * Construct an AudioPlayer.
 109          */
 110         private AudioPlayer() {
 111 
 112             super(getAudioThreadGroup(), "Audio Player");
 113             if(DEBUG) { System.out.println("> AudioPlayer private constructor"); }
 114             devAudio = AudioDevice.device;
 115             devAudio.open();
 116             if(DEBUG) { System.out.println("< AudioPlayer private constructor completed"); }
 117         }
 118 
 119 
 120         /**
 121          * Start playing a stream. The stream will continue to play
 122          * until the stream runs out of data, or it is stopped.
 123          * @see AudioPlayer#stop
 124          */
 125         public synchronized void start(InputStream in) {
 126 
 127             if(DEBUG) {
 128                 System.out.println("> AudioPlayer.start");
 129                 System.out.println("  InputStream = " + in);
 130             }
 131             devAudio.openChannel(in);
 132             notify();
 133             if(DEBUG) {
 134                 System.out.println("< AudioPlayer.start completed");
 135             }
 136         }
 137 
 138         /**
 139          * Stop playing a stream. The stream will stop playing,
 140          * nothing happens if the stream wasn't playing in the
 141          * first place.
 142          * @see AudioPlayer#start
 143          */
 144         public synchronized void stop(InputStream in) {
 145 
 146             if(DEBUG) {
 147                 System.out.println("> AudioPlayer.stop");
 148             }
 149 
 150             devAudio.closeChannel(in);
 151             if(DEBUG) {
 152                 System.out.println("< AudioPlayer.stop completed");
 153             }
 154         }
 155 
 156         /**
 157          * Main mixing loop. This is called automatically when the AudioPlayer
 158          * is created.
 159          */
 160         public void run() {
 161 
 162             // $$jb: 06.24.99: With the JS API, mixing is no longer done by AudioPlayer
 163             // or AudioDevice ... it's done by the API itself, so this bit of legacy
 164             // code does nothing.
 165             // $$jb: 10.21.99: But it appears that some legacy applications
 166             // check to see if this thread is alive or not, so we need to spin here.
 167 
 168             devAudio.play();
 169             if(DEBUG) {
 170                 System.out.println("AudioPlayer mixing loop.");
 171             }
 172             while(true) {
 173                 try{
 174                     Thread.sleep(5000);
 175                     //wait();
 176                 } catch(Exception e) {
 177                     break;
 178                     // interrupted
 179                 }
 180             }
 181             if(DEBUG) {
 182                 System.out.println("AudioPlayer exited.");
 183             }
 184 
 185         }
 186     }