summaryrefslogtreecommitdiffstats
path: root/media/java
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-01-09 17:51:23 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-01-09 17:51:23 -0800
commitb798689749c64baba81f02e10cf2157c747d6b46 (patch)
treeda394a395ddb1a6cf69193314846b03fe47a397e /media/java
parentf013e1afd1e68af5e3b868c26a653bbfb39538f8 (diff)
downloadframeworks_base-b798689749c64baba81f02e10cf2157c747d6b46.zip
frameworks_base-b798689749c64baba81f02e10cf2157c747d6b46.tar.gz
frameworks_base-b798689749c64baba81f02e10cf2157c747d6b46.tar.bz2
auto import from //branches/cupcake/...@125939
Diffstat (limited to 'media/java')
-rw-r--r--media/java/android/media/AudioManager.java29
-rw-r--r--media/java/android/media/AudioTrack.java2
-rw-r--r--media/java/android/media/JetPlayer.java334
-rw-r--r--media/java/android/media/MediaMetadataRetriever.java18
-rw-r--r--media/java/android/media/ResampleInputStream.java153
5 files changed, 529 insertions, 7 deletions
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index fb325f9..52cf69f 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -670,6 +670,35 @@ public class AudioManager {
}
/**
+ * Sets audio routing to the wired headset on or off.
+ *
+ * @param on set <var>true</var> to route audio to/from wired
+ * headset; <var>false</var> disable wired headset audio
+ * @hide
+ */
+ public void setWiredHeadsetOn(boolean on){
+ // A2DP has higher priority than wired headset, so headset connect/disconnect events
+ // should not affect A2DP routing
+ setRouting(MODE_NORMAL,
+ on ? ROUTE_HEADSET : ROUTE_SPEAKER, ROUTE_ALL & ~ROUTE_BLUETOOTH_A2DP);
+ setRouting(MODE_RINGTONE,
+ on ? ROUTE_HEADSET | ROUTE_SPEAKER : ROUTE_SPEAKER, ROUTE_ALL & ~ROUTE_BLUETOOTH_A2DP);
+ setRouting(MODE_IN_CALL,
+ on ? ROUTE_HEADSET : ROUTE_EARPIECE, ROUTE_ALL);
+ }
+
+ /**
+ * Checks whether audio routing to the wired headset is on or off.
+ *
+ * @return true if audio is being routed to/from wired headset;
+ * false if otherwise
+ * @hide
+ */
+ public boolean isWiredHeadsetOn() {
+ return (getRouting(MODE_NORMAL) & ROUTE_HEADSET) == 0 ? false : true;
+ }
+
+ /**
* Sets the microphone mute on or off.
*
* @param on set <var>true</var> to mute the microphone;
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index c246905..2b7656f 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -269,7 +269,7 @@ public class AudioTrack
// stream type
if( (streamType != AudioManager.STREAM_ALARM) && (streamType != AudioManager.STREAM_MUSIC)
&& (streamType != AudioManager.STREAM_RING) && (streamType != AudioManager.STREAM_SYSTEM)
- && (streamType != AudioManager.STREAM_VOICE_CALL) ) {
+ && (streamType != AudioManager.STREAM_VOICE_CALL) && (streamType != AudioManager.STREAM_NOTIFICATION) ) {
throw (new IllegalArgumentException("Invalid stream type."));
} else {
mStreamType = streamType;
diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java
new file mode 100644
index 0000000..b9268d5
--- /dev/null
+++ b/media/java/android/media/JetPlayer.java
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+
+import java.lang.ref.WeakReference;
+import java.lang.CloneNotSupportedException;
+
+import android.os.Looper;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+/**
+ * JetPlayer provides access to JET content playback and control.
+ * <p>
+ * Use <code>JetPlayer.getJetPlayer()</code> to get an instance of this class.
+ * There can only be one instance of this class at any one time.
+ *
+ * @hide
+ */
+public class JetPlayer
+{
+ //--------------------------------------------
+ // Constants
+ //------------------------
+ /**
+ * The maximum number of simultaneous tracks. Use {@link #getMaxTracks()} to
+ * access this value.
+ */
+ protected static int MAXTRACKS = 32;
+
+ // These constants are to be kept in sync with the ones in include/media/JetPlayer.h
+ protected static final int JET_USERID_UPDATE = 1;
+ protected static final int JET_NUMQUEUEDSEGMENT_UPDATE = 2;
+ protected static final int JET_PAUSE_UPDATE = 3;
+
+
+ //--------------------------------------------
+ // Member variables
+ //------------------------
+ private EventHandler mNativeEventHandler = null;
+
+ /**
+ * Lock to protect event listener updates against event notifications
+ */
+ protected final Object mStatusListenerLock = new Object();
+
+ protected JetStatusUpdateListener mJetStatusUpdateListener = null;
+
+ protected static JetPlayer singletonRef;
+
+
+ //--------------------------------
+ // Used exclusively by native code
+ //--------------------
+ /**
+ * Accessed by native methods: provides access to C++ JetPlayer object
+ */
+ @SuppressWarnings("unused")
+ private int mNativePlayerInJavaObj;
+
+
+ //--------------------------------------------
+ // Constructor, finalize
+ //------------------------
+ public static JetPlayer getJetPlayer() {
+ if (singletonRef == null)
+ singletonRef = new JetPlayer();
+ return singletonRef;
+ }
+
+
+ public Object clone() throws CloneNotSupportedException {
+ // JetPlayer is a singleton class,
+ // so you can't clone a JetPlayer instance
+ throw new CloneNotSupportedException();
+ }
+
+
+ private JetPlayer() {
+
+ native_setup(new WeakReference<JetPlayer>(this),
+ JetPlayer.getMaxTracks(),
+ 1200); //TODO parametrize this (?)
+ }
+
+
+ protected void finalize() {
+ native_finalize();
+ }
+
+
+ public void release() {
+ native_release();
+ }
+
+
+ private void createNativeEventHandler() {
+ Looper looper;
+ if ((looper = Looper.myLooper()) != null) {
+ mNativeEventHandler = new EventHandler(this, looper);
+ } else if ((looper = Looper.getMainLooper()) != null) {
+ mNativeEventHandler = new EventHandler(this, looper);
+ } else {
+ mNativeEventHandler = null;
+ }
+ }
+
+
+ //--------------------------------------------
+ // Getters
+ //------------------------
+ /**
+ * Returns the maximum number of simultaneous MIDI tracks supported by the Jet player
+ */
+ public static int getMaxTracks() {
+ return JetPlayer.MAXTRACKS;
+ }
+
+
+ //--------------------------------------------
+ // Jet functionality
+ //------------------------
+ public boolean openJetFile(String path) {
+ return native_openJetFile(path);
+ }
+
+
+ public boolean closeJetFile() {
+ return native_closeJetFile();
+ }
+
+
+ public boolean play() {
+ return native_playJet();
+ }
+
+
+ public boolean pause() {
+ return native_pauseJet();
+ }
+
+
+ public boolean queueJetSegment(int segmentNum, int libNum, int repeatCount,
+ int transpose, int muteFlags, byte userID) {
+ return native_queueJetSegment(segmentNum, libNum, repeatCount,
+ transpose, muteFlags, userID);
+ }
+
+
+ public boolean queueJetSegmentMuteArray(int segmentNum, int libNum, int repeatCount,
+ int transpose, boolean[] muteArray, byte userID) {
+ if (muteArray.length != JetPlayer.getMaxTracks()) {
+ return false;
+ }
+ return native_queueJetSegmentMuteArray(segmentNum, libNum, repeatCount,
+ transpose, muteArray, userID);
+ }
+
+
+ public boolean setMuteFlags(int muteFlags, boolean sync) {
+ return native_setMuteFlags(muteFlags, sync);
+ }
+
+
+ public boolean setMuteArray(boolean[] muteArray, boolean sync) {
+ if(muteArray.length != JetPlayer.getMaxTracks())
+ return false;
+ return native_setMuteArray(muteArray, sync);
+ }
+
+
+ public boolean setMuteFlag(int trackId, boolean muteFlag, boolean sync) {
+ return native_setMuteFlag(trackId, muteFlag, sync);
+ }
+
+
+ public boolean triggerClip(int clipId) {
+ return native_triggerClip(clipId);
+ }
+
+
+
+ //---------------------------------------------------------
+ // Internal class to handle events posted from native code
+ //------------------------
+ private class EventHandler extends Handler
+ {
+ private JetPlayer mJet;
+
+ public EventHandler(JetPlayer jet, Looper looper) {
+ super(looper);
+ mJet = jet;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case JET_USERID_UPDATE:
+ synchronized (mStatusListenerLock) {
+ if (mJetStatusUpdateListener != null) {
+ mJetStatusUpdateListener.onJetUserIdUpdate(msg.arg1, msg.arg2);
+ }
+ }
+ return;
+ case JET_NUMQUEUEDSEGMENT_UPDATE:
+ synchronized (mStatusListenerLock) {
+ if (mJetStatusUpdateListener != null) {
+ mJetStatusUpdateListener.onJetNumQueuedSegmentUpdate(msg.arg1);
+ }
+ }
+ return;
+ case JET_PAUSE_UPDATE:
+ synchronized (mStatusListenerLock) {
+ if (mJetStatusUpdateListener != null)
+ mJetStatusUpdateListener.onJetPauseUpdate(msg.arg1);
+ }
+ return;
+
+
+ default:
+ loge("Unknown message type " + msg.what);
+ return;
+ }
+ }
+ }
+
+
+ //--------------------------------------------
+ // Jet event listener
+ //------------------------
+ public void setStatusUpdateListener(JetStatusUpdateListener listener) {
+ synchronized(mStatusListenerLock) {
+ mJetStatusUpdateListener = listener;
+ }
+
+ if ((listener != null) && (mNativeEventHandler == null)) {
+ createNativeEventHandler();
+ }
+ }
+
+ /**
+ * Handles the notification when the JET segment userID is updated.
+ */
+ public interface JetStatusUpdateListener {
+ /**
+ * Callback for when JET's currently playing segment userID is updated.
+ *
+ * @param userId the ID of the currently playing segment
+ * @param repeatCount the repetition count for the segment (0 means it plays once)
+ */
+ void onJetUserIdUpdate(int userId, int repeatCount);
+
+ /**
+ * Callback for when JET's number of queued segments is updated.
+ *
+ * @param nbSegments the number of segments in the JET queue
+ */
+ void onJetNumQueuedSegmentUpdate(int nbSegments);
+
+ /**
+ * Callback for when JET pause state is updated.
+ *
+ * @param paused indicates whether JET is paused or not
+ */
+ void onJetPauseUpdate(int paused);
+ };
+
+
+ //--------------------------------------------
+ // Native methods
+ //------------------------
+ private native final boolean native_setup(Object Jet_this,
+ int maxTracks, int trackBufferSize);
+ private native final void native_finalize();
+ private native final void native_release();
+ private native final boolean native_openJetFile(String pathToJetFile);
+ private native final boolean native_closeJetFile();
+ private native final boolean native_playJet();
+ private native final boolean native_pauseJet();
+ private native final boolean native_queueJetSegment(int segmentNum, int libNum,
+ int repeatCount, int transpose, int muteFlags, byte userID);
+ private native final boolean native_queueJetSegmentMuteArray(int segmentNum, int libNum,
+ int repeatCount, int transpose, boolean[] muteArray, byte userID);
+ private native final boolean native_setMuteFlags(int muteFlags, boolean sync);
+ private native final boolean native_setMuteArray(boolean[]muteArray, boolean sync);
+ private native final boolean native_setMuteFlag(int trackId, boolean muteFlag, boolean sync);
+ private native final boolean native_triggerClip(int clipId);
+
+ //---------------------------------------------------------
+ // Called exclusively by native code
+ //--------------------
+ @SuppressWarnings("unused")
+ private static void postEventFromNative(Object jetplayer_ref,
+ int what, int arg1, int arg2) {
+
+ JetPlayer jet = (JetPlayer)((WeakReference)jetplayer_ref).get();
+
+ if( (jet!=null) && (jet.mNativeEventHandler!=null) ){
+ Message m = jet.mNativeEventHandler.obtainMessage(what, arg1, arg2, null);
+ jet.mNativeEventHandler.sendMessage(m);
+ }
+ }
+
+
+ //---------------------------------------------------------
+ // Utils
+ //--------------------
+ private final static String TAG = "JetPlayer-J";
+
+ private static void logd(String msg) {
+ Log.d(TAG, "[ android.media.JetPlayer ] " + msg);
+ }
+
+ private static void loge(String msg) {
+ Log.e(TAG, "[ android.media.JetPlayer ] " + msg);
+ }
+
+}
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 9763bc7..c1a0c21 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -233,10 +233,16 @@ public class MediaMetadataRetriever
public static final int METADATA_KEY_TITLE = 7;
public static final int METADATA_KEY_YEAR = 8;
public static final int METADATA_KEY_DURATION = 9;
- public static final int METADATA_KEY_NUM_TRACKS = 10;
- public static final int METADATA_KEY_IS_DRM_CRIPPLED= 11;
- public static final int METADATA_KEY_CODEC = 12;
- public static final int METADATA_KEY_RATING = 13;
- public static final int METADATA_KEY_COMMENT = 14;
- public static final int METADATA_KEY_COPYRIGHT = 15;
+ public static final int METADATA_KEY_NUM_TRACKS = 10;
+ public static final int METADATA_KEY_IS_DRM_CRIPPLED = 11;
+ public static final int METADATA_KEY_CODEC = 12;
+ public static final int METADATA_KEY_RATING = 13;
+ public static final int METADATA_KEY_COMMENT = 14;
+ public static final int METADATA_KEY_COPYRIGHT = 15;
+ public static final int METADATA_KEY_BIT_RATE = 16;
+ public static final int METADATA_KEY_FRAME_RATE = 17;
+ public static final int METADATA_KEY_VIDEO_FORMAT = 18;
+ public static final int METADATA_KEY_VIDEO_HEIGHT = 19;
+ public static final int METADATA_KEY_VIDEO_WIDTH = 20;
+ // Add more here...
}
diff --git a/media/java/android/media/ResampleInputStream.java b/media/java/android/media/ResampleInputStream.java
new file mode 100644
index 0000000..e26eae5
--- /dev/null
+++ b/media/java/android/media/ResampleInputStream.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.util.Config;
+import android.util.Log;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+
+/**
+ * ResampleInputStream
+ * @hide
+ */
+public final class ResampleInputStream extends InputStream
+{
+ static {
+ System.loadLibrary("media_jni");
+ }
+
+ private final static String TAG = "ResampleInputStream";
+
+ // pcm input stream
+ private InputStream mInputStream;
+
+ // sample rates, assumed to be normalized
+ private final int mRateIn;
+ private final int mRateOut;
+
+ // input pcm data
+ private byte[] mBuf;
+ private int mBufCount;
+
+ // length of 2:1 fir
+ private static final int mFirLength = 29;
+
+ // helper for bytewise read()
+ private final byte[] mOneByte = new byte[1];
+
+ /**
+ * Create a new ResampleInputStream, which converts the sample rate
+ * @param inputStream InputStream containing 16 bit PCM.
+ * @param rateIn the input sample rate.
+ * @param rateOut the output sample rate.
+ * This only handles rateIn == rateOut / 2 for the moment.
+ */
+ public ResampleInputStream(InputStream inputStream, int rateIn, int rateOut) {
+ // only support 2:1 at the moment
+ if (rateIn != 2 * rateOut) throw new IllegalArgumentException("only support 2:1 at the moment");
+ rateIn = 2;
+ rateOut = 1;
+
+ mInputStream = inputStream;
+ mRateIn = rateIn;
+ mRateOut = rateOut;
+ }
+
+ @Override
+ public int read() throws IOException {
+ int rtn = read(mOneByte, 0, 1);
+ return rtn == 1 ? (0xff & mOneByte[0]) : -1;
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ @Override
+ public int read(byte[] b, int offset, int length) throws IOException {
+ if (mInputStream == null) throw new IllegalStateException("not open");
+
+ // ensure that mBuf is big enough to cover requested 'length'
+ int nIn = ((length / 2) * mRateIn / mRateOut + mFirLength) * 2;
+ if (mBuf == null) {
+ mBuf = new byte[nIn];
+ } else if (nIn > mBuf.length) {
+ byte[] bf = new byte[nIn];
+ System.arraycopy(mBuf, 0, bf, 0, mBufCount);
+ mBuf = bf;
+ }
+
+ // read until we have enough data for at least one output sample
+ while (true) {
+ int len = ((mBufCount / 2 - mFirLength) * mRateOut / mRateIn) * 2;
+ if (len > 0) {
+ length = len < length ? len : (length / 2) * 2;
+ break;
+ }
+ // TODO: should mBuf.length below be nIn instead?
+ int n = mInputStream.read(mBuf, mBufCount, mBuf.length - mBufCount);
+ if (n == -1) return -1;
+ mBufCount += n;
+ }
+
+ // resample input data
+ fir21(mBuf, 0, b, offset, length / 2);
+
+ // move any unused bytes to front of mBuf
+ int nFwd = length * mRateIn / mRateOut;
+ mBufCount -= nFwd;
+ if (mBufCount > 0) System.arraycopy(mBuf, nFwd, mBuf, 0, mBufCount);
+
+ return length;
+ }
+
+/*
+ @Override
+ public int available() throws IOException {
+ int nsamples = (mIn - mOut + mInputStream.available()) / 2;
+ return ((nsamples - mFirLength) * mRateOut / mRateIn) * 2;
+ }
+*/
+
+ @Override
+ public void close() throws IOException {
+ try {
+ if (mInputStream != null) mInputStream.close();
+ } finally {
+ mInputStream = null;
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ if (mInputStream != null) {
+ close();
+ throw new IllegalStateException("someone forgot to close ResampleInputStream");
+ }
+ }
+
+ //
+ // fir filter code JNI interface
+ //
+ private static native void fir21(byte[] in, int inOffset,
+ byte[] out, int outOffset, int npoints);
+
+}