org.videolan.vlc.gui.video.PopupManager.java Source code

Java tutorial

Introduction

Here is the source code for org.videolan.vlc.gui.video.PopupManager.java

Source

/*
 * ************************************************************************
 *  PopupManager.java
 * *************************************************************************
 *  Copyright  2016 VLC authors and VideoLAN
 *  Author: Geoffrey Mtais
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *
 *  *************************************************************************
 */

package org.videolan.vlc.gui.video;

import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.view.GestureDetectorCompat;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageView;

import org.videolan.libvlc.IVLCVout;
import org.videolan.libvlc.Media;
import org.videolan.libvlc.MediaPlayer;
import org.videolan.vlc.PlaybackService;
import org.videolan.vlc.R;
import org.videolan.vlc.VLCApplication;
import org.videolan.vlc.gui.preferences.PreferencesActivity;
import org.videolan.vlc.gui.view.PopupLayout;
import org.videolan.vlc.media.MediaDatabase;

public class PopupManager implements PlaybackService.Callback, GestureDetector.OnDoubleTapListener,
        View.OnClickListener, GestureDetector.OnGestureListener, IVLCVout.Callback {

    private static final String TAG = "VLC/PopupManager";

    private static final int FLING_STOP_VELOCITY = 3000;
    private static final int MSG_DELAY = 3000;

    private static final int SHOW_BUTTONS = 0;
    private static final int HIDE_BUTTONS = 1;

    private PlaybackService mService;

    private PopupLayout mRootView;
    private ImageView mExpandButton;
    private ImageView mCloseButton;
    private ImageView mPlayPauseButton;

    public PopupManager(PlaybackService service) {
        mService = service;
    }

    public void removePopup() {
        hideNotification();
        if (mRootView == null)
            return;
        mService.setVideoTrackEnabled(false);
        mService.removeCallback(this);
        final IVLCVout vlcVout = mService.getVLCVout();
        vlcVout.detachViews();
        vlcVout.removeCallback(this);
        mRootView.close();
        mRootView = null;
    }

    public void showPopup() {
        mService.addCallback(this);
        LayoutInflater li = (LayoutInflater) VLCApplication.getAppContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mRootView = (PopupLayout) li.inflate(R.layout.video_popup, null);
        mPlayPauseButton = (ImageView) mRootView.findViewById(R.id.video_play_pause);
        mCloseButton = (ImageView) mRootView.findViewById(R.id.popup_close);
        mExpandButton = (ImageView) mRootView.findViewById(R.id.popup_expand);
        mPlayPauseButton.setOnClickListener(this);
        mCloseButton.setOnClickListener(this);
        mExpandButton.setOnClickListener(this);

        GestureDetectorCompat gestureDetector = new GestureDetectorCompat(mService, this);
        gestureDetector.setOnDoubleTapListener(this);
        mRootView.setGestureDetector(gestureDetector);

        final IVLCVout vlcVout = mService.getVLCVout();
        vlcVout.setVideoView((SurfaceView) mRootView.findViewById(R.id.player_surface));
        vlcVout.attachViews();
        mService.setVideoTrackEnabled(true);
        vlcVout.addCallback(this);
        if (!mService.isPlaying())
            mService.playIndex(mService.getCurrentMediaPosition());
        mService.startService(new Intent(mService, PlaybackService.class));
        showNotification();
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        if (mPlayPauseButton.getVisibility() == View.VISIBLE)
            return false;
        mHandler.sendEmptyMessage(SHOW_BUTTONS);
        mHandler.sendEmptyMessageDelayed(HIDE_BUTTONS, MSG_DELAY);
        return true;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        mService.removePopup();
        mService.switchToVideo();
        return true;
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e) {
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        if (Math.abs(velocityX) > FLING_STOP_VELOCITY || velocityY > FLING_STOP_VELOCITY) {
            stopPlayback();
            return true;
        }
        return false;
    }

    @Override
    public void onNewLayout(IVLCVout vlcVout, int width, int height, int visibleWidth, int visibleHeight,
            int sarNum, int sarDen) {
        if (width * height == 0)
            return;

        double dw = mRootView.getWidth(), dh = mRootView.getHeight();

        // sanity check
        if (dw * dh == 0) {
            Log.e(TAG, "Invalid surface size");
            return;
        }

        // compute the aspect ratio
        double ar;
        if (sarDen == sarNum) {
            /* No indication about the density, assuming 1:1 */
            ar = (double) visibleWidth / (double) visibleHeight;
        } else {
            /* Use the specified aspect ratio */
            double vw = visibleWidth * (double) sarNum / sarDen;
            ar = vw / visibleHeight;
        }

        // compute the display aspect ratio
        double dar = dw / dh;
        if (dar < ar)
            dh = dw / ar;
        else
            dw = dh * ar;

        width = (int) Math.floor(dw);
        height = (int) Math.floor(dh);
        vlcVout.setWindowSize(width, height);
        mRootView.setViewSize(width, height);
    }

    @Override
    public void onSurfacesCreated(IVLCVout vlcVout) {
    }

    @Override
    public void onSurfacesDestroyed(IVLCVout vlcVout) {
    }

    @Override
    public void update() {
    }

    @Override
    public void updateProgress() {
    }

    @Override
    public void onMediaEvent(Media.Event event) {
    }

    @Override
    public void onMediaPlayerEvent(MediaPlayer.Event event) {
        switch (event.type) {
        case MediaPlayer.Event.Stopped:
            mService.removePopup();
            break;
        case MediaPlayer.Event.Playing:
            mRootView.setKeepScreenOn(true);
            mPlayPauseButton.setImageResource(R.drawable.ic_popup_pause);
            showNotification();
            break;
        case MediaPlayer.Event.Paused:
            mRootView.setKeepScreenOn(false);
            mPlayPauseButton.setImageResource(R.drawable.ic_popup_play);
            showNotification();
            break;
        }
    }

    private Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case SHOW_BUTTONS:
                mPlayPauseButton.setVisibility(View.VISIBLE);
                mCloseButton.setVisibility(View.VISIBLE);
                mExpandButton.setVisibility(View.VISIBLE);
                break;
            case HIDE_BUTTONS:
                mPlayPauseButton.setVisibility(View.GONE);
                mCloseButton.setVisibility(View.GONE);
                mExpandButton.setVisibility(View.GONE);
                break;
            }
        }
    };

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.video_play_pause:
            if (mService.hasMedia()) {
                boolean isPLaying = mService.isPlaying();
                if (isPLaying)
                    mService.pause();
                else
                    mService.play();
            }
            break;
        case R.id.popup_close:
            stopPlayback();
            break;
        case R.id.popup_expand:
            mService.removePopup();
            mService.switchToVideo();
            break;
        }
    }

    private void stopPlayback() {
        long time = mService.getTime();
        long length = mService.getLength();
        Uri uri = mService.getCurrentMediaWrapper().getUri();
        //remove saved position if in the last 5 seconds
        if (length - time < 5000)
            time = 0;
        else
            time -= 2000; // go back 2 seconds, to compensate loading time
        mService.stop();

        SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(mService).edit();
        // Save position
        if (mService.isSeekable()) {
            if (MediaDatabase.getInstance().mediaItemExists(uri)) {
                MediaDatabase.getInstance().updateMedia(uri, MediaDatabase.INDEX_MEDIA_TIME, time);
            } else {
                // Video file not in media library, store time just for onResume()
                editor.putLong(PreferencesActivity.VIDEO_RESUME_TIME, time);
            }
        }
    }

    private void showNotification() {
        PendingIntent piStop = PendingIntent.getBroadcast(mService, 0,
                new Intent(PlaybackService.ACTION_REMOTE_STOP), PendingIntent.FLAG_UPDATE_CURRENT);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(mService)
                .setSmallIcon(R.drawable.ic_stat_vlc).setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                .setContentTitle(mService.getTitle()).setContentText(mService.getString(R.string.popup_playback))
                .setAutoCancel(false).setOngoing(true).setDeleteIntent(piStop);

        //Switch
        final Intent notificationIntent = new Intent(PlaybackService.ACTION_REMOTE_SWITCH_VIDEO);
        PendingIntent piExpand = PendingIntent.getBroadcast(mService, 0, notificationIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);
        //PLay Pause
        PendingIntent piPlay = PendingIntent.getBroadcast(mService, 0,
                new Intent(PlaybackService.ACTION_REMOTE_PLAYPAUSE), PendingIntent.FLAG_UPDATE_CURRENT);

        if (mService.isPlaying())
            builder.addAction(R.drawable.ic_popup_pause, mService.getString(R.string.pause), piPlay);
        else
            builder.addAction(R.drawable.ic_popup_play, mService.getString(R.string.play), piPlay);
        builder.addAction(R.drawable.ic_popup_expand_w, mService.getString(R.string.popup_expand), piExpand);

        Notification notification = builder.build();
        try {
            NotificationManagerCompat.from(mService).notify(42, notification);
        } catch (IllegalArgumentException e) {
        }
    }

    private void hideNotification() {
        NotificationManagerCompat.from(mService).cancel(42);
    }
}