/* * Copyright (C) 2014 Haruki Hasegawa * * 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. */ /// =============================================================== // Most of declarations and Javadoc comments are copied from // /frameworks/base/media/java/android/media/MediaPlayer.java /* * Copyright (C) 2006 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 com.h6ah4i.android.media; import java.io.FileDescriptor; import java.io.IOException; import android.content.Context; import android.media.AudioManager; import android.net.Uri; import com.h6ah4i.android.media.compat.AudioAttributes; public interface IBasicMediaPlayer extends IReleasable { /** * Unspecified media player error. * * @see com.h6ah4i.android.media.IBasicMediaPlayer.OnErrorListener */ public static final int MEDIA_ERROR_UNKNOWN = 1; /** * Media server died. In this case, the application must release the * MediaPlayer object and instantiate a new one. * * @see com.h6ah4i.android.media.IBasicMediaPlayer.OnErrorListener */ public static final int MEDIA_ERROR_SERVER_DIED = 100; /** * The video is streamed and its container is not valid for progressive * playback i.e the video's index (e.g moov atom) is not at the start of the * file. * * @see com.h6ah4i.android.media.IBasicMediaPlayer.OnErrorListener */ public static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200; /** * Some operation takes too long to complete, usually more than 3-5 seconds. */ public static final int MEDIA_ERROR_TIMED_OUT = -110; /** File or network related operation errors. */ public static final int MEDIA_ERROR_IO = -1004; /** Bitstream is not conforming to the related coding standard or file spec. */ public static final int MEDIA_ERROR_MALFORMED = -1007; /** * Bitstream is conforming to the related coding standard or file spec, but * the media framework does not support the feature. */ public static final int MEDIA_ERROR_UNSUPPORTED = -1010; /** * Unspecified media player info. * * @see com.h6ah4i.android.media.IBasicMediaPlayer.OnInfoListener */ public static final int MEDIA_INFO_UNKNOWN = 1; /** * The player just pushed the very first video frame for rendering. * * @see com.h6ah4i.android.media.IBasicMediaPlayer.OnInfoListener */ public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; /** * The video is too complex for the decoder: it can't decode frames fast * enough. Possibly only the audio plays fine at this stage. * * @see com.h6ah4i.android.media.IBasicMediaPlayer.OnInfoListener */ public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; /** * MediaPlayer is temporarily pausing playback internally in order to buffer * more data. * * @see com.h6ah4i.android.media.IBasicMediaPlayer.OnInfoListener */ public static final int MEDIA_INFO_BUFFERING_START = 701; /** * MediaPlayer is resuming playback after filling buffers. * * @see com.h6ah4i.android.media.IBasicMediaPlayer.OnInfoListener */ public static final int MEDIA_INFO_BUFFERING_END = 702; /** * Bad interleaving means that a media has been improperly interleaved or * not interleaved at all, e.g has all the video samples first then all the * audio ones. Video is playing but a lot of disk seeks may be happening. * * @see com.h6ah4i.android.media.IBasicMediaPlayer.OnInfoListener */ public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; /** * The media cannot be seeked (e.g live stream) * * @see com.h6ah4i.android.media.IBasicMediaPlayer.OnInfoListener */ public static final int MEDIA_INFO_NOT_SEEKABLE = 801; /** * A new set of metadata is available. * * @see com.h6ah4i.android.media.IBasicMediaPlayer.OnInfoListener */ public static final int MEDIA_INFO_METADATA_UPDATE = 802; /** * Subtitle track was not supported by the media framework. * * @see com.h6ah4i.android.media.IBasicMediaPlayer.OnInfoListener */ public static final int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901; /** * Reading the subtitle track takes too long. * * @see com.h6ah4i.android.media.IBasicMediaPlayer.OnInfoListener */ public static final int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902; /** * Interface definition for a callback to be invoked when playback of a * media source has completed. */ public interface OnCompletionListener { /** * Called when the end of a media source is reached during playback. * * @param mp the MediaPlayer that reached the end of the file */ void onCompletion(IBasicMediaPlayer mp); } /** * Interface definition for a callback to be invoked when the media source * is ready for playback. */ public interface OnPreparedListener { /** * Called when the media file is ready for playback. * * @param mp the MediaPlayer that is ready for playback */ void onPrepared(IBasicMediaPlayer mp); } /** * Interface definition of a callback to be invoked indicating the * completion of a seek operation. */ public interface OnSeekCompleteListener { /** * Called to indicate the completion of a seek operation. * * @param mp the MediaPlayer that issued the seek operation */ void onSeekComplete(IBasicMediaPlayer mp); } /** * Interface definition of a callback to be invoked indicating buffering * status of a media resource being streamed over the network. */ public interface OnBufferingUpdateListener { /** * Called to update status in buffering a media stream received through * progressive HTTP download. The received buffering percentage * indicates how much of the content has been buffered or played. For * example a buffering update of 80 percent when half the content has * already been played indicates that the next 30 percent of the content * to play has been buffered. * * @param mp the MediaPlayer the update pertains to * @param percent the percentage (0-100) of the content that has been * buffered or played thus far */ void onBufferingUpdate(IBasicMediaPlayer mp, int percent); } /** * Interface definition of a callback to be invoked to communicate some info * and/or warning about the media or its playback. */ public interface OnInfoListener { /** * Called to indicate an info or a warning. * * @param mp the MediaPlayer the info pertains to. * @param what the type of info or warning. * <ul> * <li>{@link #MEDIA_INFO_UNKNOWN} * <li>{@link #MEDIA_INFO_VIDEO_TRACK_LAGGING} * <li>{@link #MEDIA_INFO_VIDEO_RENDERING_START} * <li>{@link #MEDIA_INFO_BUFFERING_START} * <li>{@link #MEDIA_INFO_BUFFERING_END} * <li>{@link #MEDIA_INFO_BAD_INTERLEAVING} * <li>{@link #MEDIA_INFO_NOT_SEEKABLE} * <li>{@link #MEDIA_INFO_METADATA_UPDATE} * <li>{@link #MEDIA_INFO_UNSUPPORTED_SUBTITLE} * <li>{@link #MEDIA_INFO_SUBTITLE_TIMED_OUT} * </ul> * @param extra an extra code, specific to the info. Typically * implementation dependent. * @return True if the method handled the info, false if it didn't. * Returning false, or not having an OnErrorListener at all, * will cause the info to be discarded. */ boolean onInfo(IBasicMediaPlayer mp, int what, int extra); } /** * Interface definition of a callback to be invoked when there has been an * error during an asynchronous operation (other errors will throw * exceptions at method call time). */ public interface OnErrorListener { /** * Called to indicate an error. * * @param mp the MediaPlayer the error pertains to * @param what the type of error that has occurred: * <ul> * <li>{@link #MEDIA_ERROR_UNKNOWN} * <li>{@link #MEDIA_ERROR_SERVER_DIED} * </ul> * @param extra an extra code, specific to the error. Typically * implementation dependent. * <ul> * <li>{@link #MEDIA_ERROR_IO} * <li>{@link #MEDIA_ERROR_MALFORMED} * <li>{@link #MEDIA_ERROR_UNSUPPORTED} * <li>{@link #MEDIA_ERROR_TIMED_OUT} * </ul> * @return True if the method handled the error, false if it didn't. * Returning false, or not having an OnErrorListener at all, * will cause the OnCompletionListener to be called. */ boolean onError(IBasicMediaPlayer mp, int what, int extra); } /** * Starts or resumes playback. If playback had previously been paused, * playback will continue from where it was paused. If playback had been * stopped, or never started before, playback will start at the beginning. * * @throws IllegalStateException if it is called in an invalid state */ void start() throws IllegalStateException; /** * Stops playback after playback has been stopped or paused. * * @throws IllegalStateException if the internal player engine has not been * initialized. */ void stop() throws IllegalStateException; /** * Pauses playback. Call start() to resume. * * @throws IllegalStateException if the internal player engine has not been * initialized. */ void pause() throws IllegalStateException; /** * Sets the data source as a content Uri. * * @param context the Context to use when resolving the Uri * @param uri the Content URI of the data you want to play * @throws IllegalStateException if it is called in an invalid state */ void setDataSource(Context context, Uri uri) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException; /** * Sets the data source (FileDescriptor) to use. It is the caller's * responsibility to close the file descriptor. It is safe to do so as soon * as this call returns. * * @param fd the FileDescriptor for the file you want to play * @throws IllegalStateException if it is called in an invalid state */ void setDataSource(FileDescriptor fd) throws IOException, IllegalArgumentException, IllegalStateException; /** * Sets the data source (FileDescriptor) to use. The FileDescriptor must be * seekable (N.B. a LocalSocket is not seekable). It is the caller's * responsibility to close the file descriptor. It is safe to do so as soon * as this call returns. * * @param fd the FileDescriptor for the file you want to play * @param offset the offset into the file where the data to be played * starts, in bytes * @param length the length in bytes of the data to be played * @throws IllegalStateException if it is called in an invalid state */ void setDataSource(FileDescriptor fd, long offset, long length) throws IOException, IllegalArgumentException, IllegalStateException; /** * Sets the data source (file-path or http/rtsp URL) to use. * * @param path the path of the file, or the http/rtsp URL of the stream you * want to play * @throws IllegalStateException if it is called in an invalid state * <p> * When <code>path</code> refers to a local file, the file may * actually be opened by a process other than the calling * application. This implies that the pathname should be an * absolute path (as any other process runs with unspecified * current working directory), and that the pathname should * reference a world-readable file. As an alternative, the * application could first open the file for reading, and then * use the file descriptor form * {@link #setDataSource(FileDescriptor)}. */ void setDataSource(String path) throws IOException, IllegalArgumentException, IllegalStateException; /** * Prepares the player for playback, synchronously. After setting the * datasource and the display surface, you need to either call prepare() or * prepareAsync(). For files, it is OK to call prepare(), which blocks until * MediaPlayer is ready for playback. * * @throws IllegalStateException if it is called in an invalid state */ void prepare() throws IOException, IllegalStateException; /** * Prepares the player for playback, asynchronously. After setting the * datasource and the display surface, you need to either call prepare() or * prepareAsync(). For streams, you should call prepareAsync(), which * returns immediately, rather than blocking until enough data has been * buffered. * * @throws IllegalStateException if it is called in an invalid state */ void prepareAsync() throws IllegalStateException; /** * Seeks to specified time position. * * @param msec the offset in milliseconds from the start to seek to * @throws IllegalStateException if the internal player engine has not been * initialized */ void seekTo(int msec) throws IllegalStateException; /** * Releases resources associated with this MediaPlayer object. It is * considered good practice to call this method when you're done using the * MediaPlayer. In particular, whenever an Activity of an application is * paused (its onPause() method is called), or stopped (its onStop() method * is called), this method should be invoked to release the MediaPlayer * object, unless the application has a special need to keep the object * around. In addition to unnecessary resources (such as memory and * instances of codecs) being held, failure to call this method immediately * if a MediaPlayer object is no longer needed may also lead to continuous * battery consumption for mobile devices, and playback failure for other * applications if no multiple instances of the same codec are supported on * a device. Even if multiple instances of the same codec are supported, * some performance degradation may be expected when unnecessary multiple * instances are used at the same time. */ @Override void release(); /** * Resets the MediaPlayer to its uninitialized state. After calling this * method, you will have to initialize it again by setting the data source * and calling prepare(). */ void reset(); /** * Returns the audio session ID. * * @return the audio session ID. Note that * the audio session ID is 0 only if a problem occurred when the * MediaPlayer was contructed. */ int getAudioSessionId(); /** * Sets the audio session ID. * * @param sessionId the audio session ID. The audio session ID is a system * wide unique identifier for the audio stream played by this * MediaPlayer instance. The primary use of the audio session ID * is to associate audio effects to a particular instance of * MediaPlayer: if an audio session ID is provided when creating * an audio effect, this effect will be applied only to the audio * content of media players within the same audio session and not * to the output mix. When created, a MediaPlayer instance * automatically generates its own audio session ID. However, it * is possible to force this player to be part of an already * existing audio session by calling this method. This method * must be called before one of the overloaded * <code> setDataSource </code> methods. * @throws IllegalStateException if it is called in an invalid state */ void setAudioSessionId(int sessionId) throws IllegalArgumentException, IllegalStateException; /** * Gets the duration of the file. * * @return the duration in milliseconds, if no duration is available (for * example, if streaming live content), -1 is returned. */ int getDuration(); /** * Sets the player to be looping or non-looping. * * @param looping whether to loop or not */ void setLooping(boolean looping); /** * Gets the current playback position. * * @return the current position in milliseconds */ int getCurrentPosition(); /** * Checks whether the MediaPlayer is looping or non-looping. * * @return true if the MediaPlayer is currently looping, false otherwise */ boolean isLooping(); /** * Checks whether the MediaPlayer is playing. * * @return true if currently playing, false otherwise * @throws IllegalStateException if the internal player engine has not been * initialized or has been released. */ boolean isPlaying() throws IllegalStateException; /** * Attaches an auxiliary effect to the player. A typical auxiliary effect is * a reverberation effect which can be applied on any sound source that * directs a certain amount of its energy to this effect. This amount is * defined by setAuxEffectSendLevel(). * <p> * After creating an auxiliary effect (e.g. * {@link android.media.audiofx.EnvironmentalReverb}), retrieve its ID with * {@link android.media.audiofx.AudioEffect#getId()} and use it when calling * this method to attach the player to the effect. * <p> * To detach the effect from the player, call this method with a null effect * id. * <p> * This method must be called after one of the overloaded * <code> setDataSource </code> methods. * * @param effectId system wide unique id of the effect to attach */ void attachAuxEffect(int effectId); /** * Sets the volume on this player. This API is recommended for balancing the * output of audio streams within an application. Unless you are writing an * application to control user settings, this API should be used in * preference to {@link AudioManager#setStreamVolume(int, int, int)} which * sets the volume of ALL streams of a particular type. Note that the passed * volume values are raw scalars in range 0.0 to 1.0. UI controls should be * scaled logarithmically. * * @param leftVolume left volume scalar * @param rightVolume right volume scalar */ void setVolume(float leftVolume, float rightVolume); /** * Sets the audio stream type for this MediaPlayer. See {@link AudioManager} * for a list of stream types. Must call this method before prepare() or * prepareAsync() in order for the target stream type to become effective * thereafter. * * @param streamtype the audio stream type * @see android.media.AudioManager */ void setAudioStreamType(int streamtype); /** * Sets the send level of the player to the attached auxiliary effect. * The level value range is 0 to 1.0. * <p> * By default the send level is 0, so even if an effect is attached to the * player this method must be called for the effect to be applied. * <p> * Note that the passed level value is a raw scalar. UI controls should be * scaled logarithmically: the gain applied by audio framework ranges from * -72dB to 0dB, so an appropriate conversion from linear UI input x to * level is: x == 0 -> level = 0 0 < x <= R -> level = 10^(72*(x-R)/20/R) * * @param level send level scalar */ void setAuxEffectSendLevel(float level); /** * Set the low-level power management behavior for this MediaPlayer. * <p> * This function has the MediaPlayer access the low-level power manager * service to control the device's power usage while playing is occurring. * The parameter is a combination of {@link android.os.PowerManager} wake * flags. Use of this method requires * {@link android.Manifest.permission#WAKE_LOCK} permission. By default, no * attempt is made to keep the device awake during playback. * * @param context the Context to use * @param mode the power/wake mode to set * @see android.os.PowerManager */ void setWakeMode(Context context, int mode); /** * Register a callback to be invoked when the status of a network stream's * buffer has changed. * * @param listener the callback that will be run. */ void setOnBufferingUpdateListener(OnBufferingUpdateListener listener); /** * Register a callback to be invoked when the end of a media source has been * reached during playback. * * @param listener the callback that will be run */ void setOnCompletionListener(OnCompletionListener listener); /** * Register a callback to be invoked when an error has happened during an * asynchronous operation. * * @param listener the callback that will be run */ void setOnErrorListener(OnErrorListener listener); /** * Register a callback to be invoked when an info/warning is available. * * @param listener the callback that will be run */ void setOnInfoListener(OnInfoListener listener); /** * Register a callback to be invoked when the media source is ready for * playback. * * @param listener the callback that will be run */ void setOnPreparedListener(OnPreparedListener listener); /** * Register a callback to be invoked when a seek operation has been * completed. * * @param listener the callback that will be run */ void setOnSeekCompleteListener(OnSeekCompleteListener listener); /** * Set the MediaPlayer to start when this MediaPlayer finishes playback * (i.e. reaches the end of the stream). The media framework will attempt to * transition from this player to the next as seamlessly as possible. The * next player can be set at any time before completion. The next player * must be prepared by the app, and the application should not call start() * on it. The next MediaPlayer must be different from 'this'. An exception * will be thrown if next == this. The application may call * setNextMediaPlayer(null) to indicate no next player should be * started at the end of playback. If the current player is looping, it will * keep looping and the next player will not be started. * * @param next the player to start after this one completes playback. */ void setNextMediaPlayer(IBasicMediaPlayer next); /** * Sets the audio attributes for this MediaPlayer. See * {@link AudioAttributes} for how to build and configure an instance of * this class. You must call this method before {@link #prepare()} or * {@link #prepareAsync()} in order for the audio attributes to become * effective thereafter. * * @param attributes a non-null set of audio attributes */ void setAudioAttributes(AudioAttributes attributes); }