diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:23 -0800 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:23 -0800 |
| commit | b798689749c64baba81f02e10cf2157c747d6b46 (patch) | |
| tree | da394a395ddb1a6cf69193314846b03fe47a397e /media/java | |
| parent | f013e1afd1e68af5e3b868c26a653bbfb39538f8 (diff) | |
| download | frameworks_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.java | 29 | ||||
| -rw-r--r-- | media/java/android/media/AudioTrack.java | 2 | ||||
| -rw-r--r-- | media/java/android/media/JetPlayer.java | 334 | ||||
| -rw-r--r-- | media/java/android/media/MediaMetadataRetriever.java | 18 | ||||
| -rw-r--r-- | media/java/android/media/ResampleInputStream.java | 153 |
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); + +} |
