From: <to...@us...> - 2007-02-12 23:45:37
|
Revision: 50 http://techne-dev.svn.sourceforge.net/techne-dev/?rev=50&view=rev Author: tonit Date: 2007-02-12 15:45:37 -0800 (Mon, 12 Feb 2007) Log Message: ----------- Modified Paths: -------------- sandbox/tonit/techne.audio/.classpath Added Paths: ----------- sandbox/tonit/techne.audio/src/techne/audio/itunes/ sandbox/tonit/techne.audio/src/techne/audio/itunes/Activator.java sandbox/tonit/techne.audio/src/techne/audio/itunes/ItunesMusicSource.java sandbox/tonit/techne.audio/src/techne/audio/player/MusicSource.java sandbox/tonit/techne.audio/src/techne/audio/player/PlayerControl.java sandbox/tonit/techne.audio/src/techne/audio/player/internal/JavaZoomPlayerThread.java sandbox/tonit/techne.audio/src/techne/audio/player/internal/PlayerImpl.java sandbox/tonit/techne.audio/src/techne/audio/player/internal/PlayerState.java sandbox/tonit/techne.audio/src/techne/audio/player/internal/SingleTrackMusicSource.java sandbox/tonit/techne.audio/src/techne/audio/samplemusic/ sandbox/tonit/techne.audio/src/techne/audio/samplemusic/Activator.java sandbox/tonit/techne.audio/src/techne/audio/samplemusic/SampleMusicSource.java sandbox/tonit/techne.audio/src/techne/audio/tui/ sandbox/tonit/techne.audio/src/techne/audio/tui/internal/ sandbox/tonit/techne.audio/src/techne/audio/tui/internal/Activator.java sandbox/tonit/techne.audio/src/techne/audio/tui/internal/PlayerControlCommand.java Modified: sandbox/tonit/techne.audio/.classpath =================================================================== --- sandbox/tonit/techne.audio/.classpath 2007-02-12 23:29:24 UTC (rev 49) +++ sandbox/tonit/techne.audio/.classpath 2007-02-12 23:45:37 UTC (rev 50) @@ -4,5 +4,6 @@ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="lib" path="/techne-env/development/lib/osgi.jar"/> <classpathentry kind="lib" path="resources/lib/jl1.0.jar"/> + <classpathentry kind="lib" path="/techne-env/bundle/org.apache.felix.shell-0.9.0-incubator-SNAPSHOT.jar"/> <classpathentry kind="output" path="bin"/> </classpath> Added: sandbox/tonit/techne.audio/src/techne/audio/itunes/Activator.java =================================================================== --- sandbox/tonit/techne.audio/src/techne/audio/itunes/Activator.java (rev 0) +++ sandbox/tonit/techne.audio/src/techne/audio/itunes/Activator.java 2007-02-12 23:45:37 UTC (rev 50) @@ -0,0 +1,16 @@ +package techne.audio.itunes; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator { + + public void start(BundleContext ctx) throws Exception { + System.out.println("Loading itunes support for techne.audio"); + } + + public void stop(BundleContext arg0) throws Exception { + System.out.println("Removing itunes support for techne.audio"); + } + +} Added: sandbox/tonit/techne.audio/src/techne/audio/itunes/ItunesMusicSource.java =================================================================== --- sandbox/tonit/techne.audio/src/techne/audio/itunes/ItunesMusicSource.java (rev 0) +++ sandbox/tonit/techne.audio/src/techne/audio/itunes/ItunesMusicSource.java 2007-02-12 23:45:37 UTC (rev 50) @@ -0,0 +1,45 @@ +package techne.audio.itunes; + +import java.io.InputStream; + +import org.osgi.service.component.ComponentContext; + +import techne.audio.player.MusicSource; +import techne.audio.player.internal.JavaZoomPlayerThread; + +/** + * todo: + * - find local itunes Library.xml + * - read favourites (most played) + * - give streams (next()) + * + * @author tmenzel + * + */ +public class ItunesMusicSource implements MusicSource { + + public InputStream current() { + // TODO Auto-generated method stub + return null; + } + + public boolean hasNext() { + // TODO Auto-generated method stub + return false; + } + + public InputStream next() { + // TODO Auto-generated method stub + return null; + } + + // Declarative Services methods.. + protected void activate(ComponentContext context) { + System.out.println("Started itunes MusicSource for techne.audio"); + } + + public void deactivate(ComponentContext context) throws Exception { + System.out.println("Stopped itunes MusicSource for techne.audio"); + } + +} Added: sandbox/tonit/techne.audio/src/techne/audio/player/MusicSource.java =================================================================== --- sandbox/tonit/techne.audio/src/techne/audio/player/MusicSource.java (rev 0) +++ sandbox/tonit/techne.audio/src/techne/audio/player/MusicSource.java 2007-02-12 23:45:37 UTC (rev 50) @@ -0,0 +1,10 @@ +package techne.audio.player; + +import java.io.InputStream; + +public interface MusicSource { + InputStream next(); + boolean hasNext(); + InputStream current(); + +} Added: sandbox/tonit/techne.audio/src/techne/audio/player/PlayerControl.java =================================================================== --- sandbox/tonit/techne.audio/src/techne/audio/player/PlayerControl.java (rev 0) +++ sandbox/tonit/techne.audio/src/techne/audio/player/PlayerControl.java 2007-02-12 23:45:37 UTC (rev 50) @@ -0,0 +1,8 @@ +package techne.audio.player; + +public interface PlayerControl { + void play(); + void stop(); + void pause(); + int getState(); +} Added: sandbox/tonit/techne.audio/src/techne/audio/player/internal/JavaZoomPlayerThread.java =================================================================== --- sandbox/tonit/techne.audio/src/techne/audio/player/internal/JavaZoomPlayerThread.java (rev 0) +++ sandbox/tonit/techne.audio/src/techne/audio/player/internal/JavaZoomPlayerThread.java 2007-02-12 23:45:37 UTC (rev 50) @@ -0,0 +1,81 @@ +package techne.audio.player.internal; + +import techne.audio.player.MusicSource; + +/** + * * Thread that represents a ready to go music player To control it, use the + * PlayerControls + */ +public class JavaZoomPlayerThread extends Thread { + MusicSource musicSource; + private PlayerImpl pla; + + private int state = PlayerState.STATE_IDLE; + private int lastpos = 0; + + public synchronized void changeState(int state) { + System.out.println("SWITCHING STATE FROM " + this.state + " to " + + state + " at pos " + lastpos); + this.state = state; + if (state != PlayerState.STATE_PLAY) { + // break event + if (pla != null) { + pla.pause(); + + System.out.println("adding " + pla.getPosition() + " to " + + lastpos); + lastpos += pla.getPosition(); + } + } + } + + public void run() { + try { + while (state != PlayerState.STATE_OFF) { + if (this.state == PlayerState.STATE_PLAY) { + if (pla == null || pla.isComplete()) { + if (musicSource.hasNext()) { + pla = new PlayerImpl(musicSource.next()); + pla.play(0, Integer.MAX_VALUE); + } else { + changeState(PlayerState.STATE_IDLE); + } + } else { + // resume + System.out.println("resume at pos " + lastpos); + // resume requires re-opening stream..:-( + pla = new PlayerImpl(musicSource.current()); + pla.play(lastpos, Integer.MAX_VALUE); + } + } + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + System.out.println(e.getMessage()); + throw new RuntimeException(e); + } + System.out.println("MusicPlayer Thread closed!"); + } + + public void close() { + changeState(PlayerState.STATE_OFF); + pla.close(); + } + + public MusicSource getMusicSource() { + return musicSource; + } + + + + public void setMusicSource(MusicSource musicSource) { + this.musicSource = musicSource; + } + + public int getCurrentPlayerState() { + return state; + } + + +} Added: sandbox/tonit/techne.audio/src/techne/audio/player/internal/PlayerImpl.java =================================================================== --- sandbox/tonit/techne.audio/src/techne/audio/player/internal/PlayerImpl.java (rev 0) +++ sandbox/tonit/techne.audio/src/techne/audio/player/internal/PlayerImpl.java 2007-02-12 23:45:37 UTC (rev 50) @@ -0,0 +1,222 @@ +package techne.audio.player.internal; + +import java.io.InputStream; + +import javazoom.jl.decoder.Bitstream; +import javazoom.jl.decoder.BitstreamException; +import javazoom.jl.decoder.Decoder; +import javazoom.jl.decoder.Header; +import javazoom.jl.decoder.JavaLayerException; +import javazoom.jl.decoder.SampleBuffer; +import javazoom.jl.player.AudioDevice; +import javazoom.jl.player.FactoryRegistry; + +public class PlayerImpl { + + /** + * The MPEG audio bitstream. + */ + // javac blank final bug. + /* final */private Bitstream bitstream; + + /** + * The MPEG audio decoder. + */ + /* final */private Decoder decoder; + + /** + * The AudioDevice the audio samples are written to. + */ + private AudioDevice audio; + + /** + * Has the player been closed? + */ + private boolean closed = false; + + /** + * Has the player played back all frames from the stream? + */ + private boolean complete = false; + + private int lastPosition = 0; + + /** + * Creates a new <code>Player</code> instance. + */ + public PlayerImpl(InputStream stream) throws JavaLayerException { + bitstream = new Bitstream(stream); + decoder = new Decoder(); + + FactoryRegistry r = FactoryRegistry.systemRegistry(); + audio = r.createAudioDevice(); + + audio.open(decoder); + } + + public void play() throws JavaLayerException { + play(Integer.MAX_VALUE); + } + + public boolean play(final int start, final int end) { + boolean ret = true; + boolean res = true; + int offset = start; + try { + while (offset-- > 0 && ret) { + ret = skipFrame(); + } + res = play(end - start); + + } catch (JavaLayerException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new RuntimeException(e); + } + return res; + } + + /** + * skips over a single frame + * + * @return false if there are no more frames to decode, true otherwise. + */ + protected boolean skipFrame() throws JavaLayerException { + Header h = bitstream.readFrame(); + if (h == null) + return false; + bitstream.closeFrame(); + return true; + } + + /** + * Plays a number of MPEG audio frames. + * + * @param frames + * The number of frames to play. + * @return true if the last frame was played, or false if there are more + * frames. + */ + public boolean play(int frames) throws JavaLayerException { + boolean ret = true; + + while (frames-- > 0 && ret) { + ret = decodeFrame(); + } + + if (!ret) { + // last frame, ensure all data flushed to the audio device. + AudioDevice out = audio; + if (out != null) { + out.flush(); + synchronized (this) { + complete = (!closed); + close(); + } + } + } + return ret; + } + + /** + * Cloases this player. Any audio currently playing is stopped immediately. + */ + public synchronized void close() { + AudioDevice out = audio; + if (out != null) { + closed = true; + audio = null; + // this may fail, so ensure object state is set up before + // calling this method. + out.close(); + lastPosition = out.getPosition(); + try { + bitstream.close(); + } catch (BitstreamException ex) { + } + } + } + + /** + * Returns the completed status of this player. + * + * @return true if all available MPEG audio frames have been decoded, or + * false otherwise. + */ + public synchronized boolean isComplete() { + return complete; + } + + /** + * Retrieves the position in milliseconds of the current audio sample being + * played. This method delegates to the <code> + * AudioDevice</code> that is + * used by this player to sound the decoded audio samples. + */ + public int getPosition() { + int position = lastPosition; + + AudioDevice out = audio; + if (out != null) { + position = out.getPosition(); + } + return position; + } + + /** + * Decodes a single frame. + * + * @return true if there are no more frames to decode, false otherwise. + */ + protected boolean decodeFrame() throws JavaLayerException { + try { + AudioDevice out = audio; + if (out == null) { + return false; + } + Header h = bitstream.readFrame(); + if (h == null) { + return false; + } + // sample buffer set when decoder constructed + SampleBuffer output = (SampleBuffer) decoder.decodeFrame(h, + bitstream); + + synchronized (this) { + out = audio; + if (out != null) { + out.write(output.getBuffer(), 0, output.getBufferLength()); + } + } + + bitstream.closeFrame(); + } catch (RuntimeException ex) { + throw new JavaLayerException("Exception decoding audio frame", ex); + } + /* + * catch (IOException ex) { System.out.println("exception decoding audio + * frame: "+ex); return false; } catch (BitstreamException bitex) { + * System.out.println("exception decoding audio frame: "+bitex); return + * false; } catch (DecoderException decex) { + * System.out.println("exception decoding audio frame: "+decex); return + * false; } + */ + return true; + } + + public void pause() { + AudioDevice out = audio; + if (out != null) { + closed = true; + audio = null; + // this may fail, so ensure object state is set up before + // calling this method. + out.close(); + lastPosition = out.getPosition(); + try { + bitstream.close(); + } catch (BitstreamException ex) { + } + } + } +} Added: sandbox/tonit/techne.audio/src/techne/audio/player/internal/PlayerState.java =================================================================== --- sandbox/tonit/techne.audio/src/techne/audio/player/internal/PlayerState.java (rev 0) +++ sandbox/tonit/techne.audio/src/techne/audio/player/internal/PlayerState.java 2007-02-12 23:45:37 UTC (rev 50) @@ -0,0 +1,9 @@ +package techne.audio.player.internal; + +public class PlayerState { + public static final int STATE_IDLE = 0; + public static final int STATE_OFF = -1; + + public static final int STATE_PLAY = 1; + public static final int STATE_PAUSE = 2; +} Added: sandbox/tonit/techne.audio/src/techne/audio/player/internal/SingleTrackMusicSource.java =================================================================== --- sandbox/tonit/techne.audio/src/techne/audio/player/internal/SingleTrackMusicSource.java (rev 0) +++ sandbox/tonit/techne.audio/src/techne/audio/player/internal/SingleTrackMusicSource.java 2007-02-12 23:45:37 UTC (rev 50) @@ -0,0 +1,52 @@ +package techne.audio.player.internal; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import techne.audio.player.MusicSource; + +public class SingleTrackMusicSource implements MusicSource { + boolean repeat = false; + private URL url; + // count of next() requests + int count = 0; + + public SingleTrackMusicSource(URL url) { + this.url = url; + } + + public boolean hasNext() { + return (repeat || count == 0); + } + + public InputStream next() { + synchronized (this) { + if (count == 0) { + count++; + try { + System.out.println("MusicSource: giving " + url.toExternalForm()); + return url.openConnection().getInputStream(); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + } + return null; + } + + public void setRepeat(boolean rep) { + this.repeat = rep; + } + + public InputStream current() { + try { + return url.openConnection().getInputStream(); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + +} Added: sandbox/tonit/techne.audio/src/techne/audio/samplemusic/Activator.java =================================================================== --- sandbox/tonit/techne.audio/src/techne/audio/samplemusic/Activator.java (rev 0) +++ sandbox/tonit/techne.audio/src/techne/audio/samplemusic/Activator.java 2007-02-12 23:45:37 UTC (rev 50) @@ -0,0 +1,16 @@ +package techne.audio.samplemusic; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator { + + public void start(BundleContext ctx) throws Exception { + System.out.println("Loading samplemusic support for techne.audio"); + } + + public void stop(BundleContext arg0) throws Exception { + System.out.println("Removing samplemusic support for techne.audio"); + } + +} Added: sandbox/tonit/techne.audio/src/techne/audio/samplemusic/SampleMusicSource.java =================================================================== --- sandbox/tonit/techne.audio/src/techne/audio/samplemusic/SampleMusicSource.java (rev 0) +++ sandbox/tonit/techne.audio/src/techne/audio/samplemusic/SampleMusicSource.java 2007-02-12 23:45:37 UTC (rev 50) @@ -0,0 +1,72 @@ +package techne.audio.samplemusic; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import org.osgi.service.component.ComponentContext; + +import techne.audio.player.MusicSource; + +/** + * Provides a sample MusicSource. MP3 Files are included right in the bundle. + * + * Its Self-Contained (does not require network, local mp3s or itunes) + * + * @author tmenzel + * + */ +public class SampleMusicSource implements MusicSource { + + boolean repeat = false; + private URL url; + // count of next() requests + int count = 0; + + public SampleMusicSource() { + } + + public boolean hasNext() { + return (repeat || count == 0); + } + + public InputStream next() { + synchronized (this) { + if (count == 0) { + count++; + try { + System.out.println("MusicSource: giving " + url.toExternalForm()); + return url.openConnection().getInputStream(); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + } + return null; + } + + public void setRepeat(boolean rep) { + this.repeat = rep; + } + + public InputStream current() { + try { + return url.openConnection().getInputStream(); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + // Declarative Services methods.. + protected void activate(ComponentContext context) { + System.out.println("Started sample MusicSource for techne.audio"); + url = context.getBundleContext().getBundle().getResource("TotallyFreeSong.mp3"); + } + + public void deactivate(ComponentContext context) throws Exception { + System.out.println("Stopped sample MusicSource for techne.audio"); + } + +} Added: sandbox/tonit/techne.audio/src/techne/audio/tui/internal/Activator.java =================================================================== --- sandbox/tonit/techne.audio/src/techne/audio/tui/internal/Activator.java (rev 0) +++ sandbox/tonit/techne.audio/src/techne/audio/tui/internal/Activator.java 2007-02-12 23:45:37 UTC (rev 50) @@ -0,0 +1,15 @@ +package techne.audio.tui.internal; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator { + + public void start(BundleContext ctx) throws Exception { + System.out.println("Shell Support ON"); + } + + public void stop(BundleContext arg0) throws Exception { + System.out.println("Shell Support OFF"); + } +} Added: sandbox/tonit/techne.audio/src/techne/audio/tui/internal/PlayerControlCommand.java =================================================================== --- sandbox/tonit/techne.audio/src/techne/audio/tui/internal/PlayerControlCommand.java (rev 0) +++ sandbox/tonit/techne.audio/src/techne/audio/tui/internal/PlayerControlCommand.java 2007-02-12 23:45:37 UTC (rev 50) @@ -0,0 +1,54 @@ +package techne.audio.tui.internal; + +import java.io.PrintStream; +import java.util.StringTokenizer; + +import org.apache.felix.shell.Command; + +import techne.audio.player.PlayerControl; + +public class PlayerControlCommand implements Command { + private PlayerControl control; + + public void execute(String s, PrintStream out, PrintStream err) { + out.println("audio command recognized!"); + if (control != null) { + StringTokenizer st = new StringTokenizer(s, " "); + + st.nextToken(); // Ignore the command name. + String cmd = st.nextToken(); + if ("play".equals(cmd)) { + control.play(); + }else if ("stop".equals(cmd)) { + control.stop(); + }else if ("pause".equals(cmd)) { + control.pause(); + }else if ("state".equals(cmd)) { + out.println("Current state: " + control.getState()); + }else + { + out.println("Command " + cmd + " unknown"); + out.println(getUsage()); + } + }else { + err.println("no PlayerControl instance assigned!"); + } + } + + public String getName() { + return "audio"; + } + + public String getShortDescription() { + return "Controls PlayerControl Service with felix shell"; + } + + public String getUsage() { + return "audio <play> or <stop> or <pause> or <state>"; + } + + public void setControl(PlayerControl control) { + this.control = control; + } + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |