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 AudioPlayer audioPlayer; 96 PrivilegedAction action = new PrivilegedAction() { 97 public Object run() { 98 Thread t = new AudioPlayer(); 99 t.setPriority(MAX_PRIORITY); 100 t.setDaemon(true); 101 t.start(); 102 return t; 103 } 104 }; 105 audioPlayer = (AudioPlayer) AccessController.doPrivileged(action); 106 return audioPlayer; 107 } 108 109 /** 110 * Construct an AudioPlayer. 111 */ 112 private AudioPlayer() { 113 114 super(getAudioThreadGroup(), "Audio Player"); 115 if(DEBUG) { System.out.println("> AudioPlayer private constructor"); } 116 devAudio = AudioDevice.device; 117 devAudio.open(); 118 if(DEBUG) { System.out.println("< AudioPlayer private constructor completed"); } 119 } 120 121 122 /** 123 * Start playing a stream. The stream will continue to play 124 * until the stream runs out of data, or it is stopped. 125 * @see AudioPlayer#stop 126 */ 127 public synchronized void start(InputStream in) { 128 129 if(DEBUG) { 130 System.out.println("> AudioPlayer.start"); 131 System.out.println(" InputStream = " + in); 132 } 133 devAudio.openChannel(in); 134 notify(); 135 if(DEBUG) { 136 System.out.println("< AudioPlayer.start completed"); 137 } 138 } 139 140 /** 141 * Stop playing a stream. The stream will stop playing, 142 * nothing happens if the stream wasn't playing in the 143 * first place. 144 * @see AudioPlayer#start 145 */ 146 public synchronized void stop(InputStream in) { 147 148 if(DEBUG) { 149 System.out.println("> AudioPlayer.stop"); 150 } 151 152 devAudio.closeChannel(in); 153 if(DEBUG) { 154 System.out.println("< AudioPlayer.stop completed"); 155 } 156 } 157 158 /** 159 * Main mixing loop. This is called automatically when the AudioPlayer 160 * is created. 161 */ 162 public void run() { 163 164 // $$jb: 06.24.99: With the JS API, mixing is no longer done by AudioPlayer 165 // or AudioDevice ... it's done by the API itself, so this bit of legacy 166 // code does nothing. 167 // $$jb: 10.21.99: But it appears that some legacy applications 168 // check to see if this thread is alive or not, so we need to spin here. 169 170 devAudio.play(); 171 if(DEBUG) { 172 System.out.println("AudioPlayer mixing loop."); 173 } 174 while(true) { 175 try{ 176 Thread.sleep(5000); 177 //wait(); 178 } catch(Exception e) { 179 break; 180 // interrupted 181 } 182 } 183 if(DEBUG) { 184 System.out.println("AudioPlayer exited."); 185 } 186 187 } 188 }