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 }