1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)package org.chromium.media;
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.content.Context;
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.media.AudioManager;
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.media.MediaPlayer;
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.chromium.base.CalledByNative;
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.chromium.base.JNINamespace;
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class implements all the listener interface for android mediaplayer.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Callbacks will be sent to the native class for processing.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@JNINamespace("media")
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MediaPlayerListener implements MediaPlayer.OnPreparedListener,
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MediaPlayer.OnCompletionListener,
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MediaPlayer.OnBufferingUpdateListener,
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MediaPlayer.OnSeekCompleteListener,
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MediaPlayer.OnVideoSizeChangedListener,
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MediaPlayer.OnErrorListener,
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AudioManager.OnAudioFocusChangeListener {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // These values are mirrored as enums in media/base/android/media_player_bridge.h.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Please ensure they stay in sync.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static final int MEDIA_ERROR_FORMAT = 0;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static final int MEDIA_ERROR_DECODE = 1;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 2;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private static final int MEDIA_ERROR_INVALID_CODE = 3;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // These values are copied from android media player.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public static final int MEDIA_ERROR_MALFORMED = -1007;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public static final int MEDIA_ERROR_TIMED_OUT = -110;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Used to determine the class instance to dispatch the native call to.
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private long mNativeMediaPlayerListener = 0;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private final Context mContext;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private MediaPlayerListener(long nativeMediaPlayerListener, Context context) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mNativeMediaPlayerListener = nativeMediaPlayerListener;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mContext = context;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public boolean onError(MediaPlayer mp, int what, int extra) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int errorType;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        switch (what) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            case MediaPlayer.MEDIA_ERROR_UNKNOWN:
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                switch (extra) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    case MEDIA_ERROR_MALFORMED:
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        errorType = MEDIA_ERROR_DECODE;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        break;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    case MEDIA_ERROR_TIMED_OUT:
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        errorType = MEDIA_ERROR_INVALID_CODE;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        break;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    default:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        errorType = MEDIA_ERROR_FORMAT;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        break;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                errorType = MEDIA_ERROR_DECODE;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                errorType = MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            default:
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                // There are some undocumented error codes for android media player.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                // For example, when surfaceTexture got deleted before we setVideoSuface
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                // to NULL, mediaplayer will report error -38. These errors should be ignored
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                // and not be treated as an error to webkit.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                errorType = MEDIA_ERROR_INVALID_CODE;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nativeOnMediaError(mNativeMediaPlayerListener, errorType);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nativeOnVideoSizeChanged(mNativeMediaPlayerListener, width, height);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void onSeekComplete(MediaPlayer mp) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nativeOnSeekComplete(mNativeMediaPlayerListener);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void onBufferingUpdate(MediaPlayer mp, int percent) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nativeOnBufferingUpdate(mNativeMediaPlayerListener, percent);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void onCompletion(MediaPlayer mp) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nativeOnPlaybackComplete(mNativeMediaPlayerListener);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void onPrepared(MediaPlayer mp) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nativeOnMediaPrepared(mNativeMediaPlayerListener);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    @Override
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public void onAudioFocusChange(int focusChange) {
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (focusChange == AudioManager.AUDIOFOCUS_LOSS ||
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            nativeOnMediaInterrupted(mNativeMediaPlayerListener);
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @CalledByNative
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public void releaseResources() {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (mContext != null) {
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // Unregister the wish for audio focus.
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (am != null) {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                am.abandonAudioFocus(this);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    @CalledByNative
124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    private static MediaPlayerListener create(long nativeMediaPlayerListener,
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            Context context, MediaPlayerBridge mediaPlayerBridge) {
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        final MediaPlayerListener listener =
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                new MediaPlayerListener(nativeMediaPlayerListener, context);
1281675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        if (mediaPlayerBridge != null) {
1291675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch            mediaPlayerBridge.setOnBufferingUpdateListener(listener);
1301675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch            mediaPlayerBridge.setOnCompletionListener(listener);
1311675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch            mediaPlayerBridge.setOnErrorListener(listener);
1321675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch            mediaPlayerBridge.setOnPreparedListener(listener);
1331675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch            mediaPlayerBridge.setOnSeekCompleteListener(listener);
1341675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch            mediaPlayerBridge.setOnVideoSizeChangedListener(listener);
1351675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        }
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        am.requestAudioFocus(
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                listener,
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                AudioManager.STREAM_MUSIC,
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                // Request permanent focus.
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return listener;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /**
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * See media/base/android/media_player_listener.cc for all the following functions.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private native void nativeOnMediaError(
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            long nativeMediaPlayerListener,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int errorType);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private native void nativeOnVideoSizeChanged(
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            long nativeMediaPlayerListener,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int width, int height);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private native void nativeOnBufferingUpdate(
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            long nativeMediaPlayerListener,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int percent);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeOnMediaPrepared(long nativeMediaPlayerListener);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeOnPlaybackComplete(long nativeMediaPlayerListener);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeOnSeekComplete(long nativeMediaPlayerListener);
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeOnMediaInterrupted(long nativeMediaPlayerListener);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
170