|
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.
|