diff options
Diffstat (limited to 'src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java')
-rw-r--r-- | src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java new file mode 100644 index 000000000..b2115b7d9 --- /dev/null +++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java @@ -0,0 +1,445 @@ +/**************************************************************************** + ** + ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). + ** Contact: http://www.qt-project.org/legal + ** + ** This file is part of the QtMultimedia module of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:LGPL$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and Digia. For licensing terms and + ** conditions see http://qt.digia.com/licensing. For further information + ** use the contact form at http://qt.digia.com/contact-us. + ** + ** GNU Lesser General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU Lesser + ** General Public License version 2.1 as published by the Free Software + ** Foundation and appearing in the file LICENSE.LGPL included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU Lesser General Public License version 2.1 requirements + ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + ** + ** In addition, as a special exception, Digia gives you certain additional + ** rights. These rights are described in the Digia Qt LGPL Exception + ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3.0 as published by the Free Software + ** Foundation and appearing in the file LICENSE.GPL included in the + ** packaging of this file. Please review the following information to + ** ensure the GNU General Public License version 3.0 requirements will be + ** met: http://www.gnu.org/copyleft/gpl.html. + ** + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +package org.qtproject.qt5.android.multimedia; + +import java.io.IOException; +import java.lang.String; + +// API is level is < 9 unless marked otherwise. +import android.app.Activity; +import android.content.Context; +import android.media.MediaPlayer; +import android.net.Uri; +import android.util.Log; + +public class QtAndroidMediaPlayer extends MediaPlayer +{ + // Native callback functions for MediaPlayer + native public void onErrorNative(int what, int extra, long id); + native public void onBufferingUpdateNative(int percent, long id); + native public void onInfoNative(int what, int extra, long id); + native public void onMediaPlayerInfoNative(int what, int extra, long id); + native public void onVideoSizeChangedNative(int width, int height, long id); + + private Uri mUri = null; + private final long mID; + private boolean mMuted = false; + private boolean mPreparing = false; + private boolean mInitialized = false; + private int mVolume = 100; + private static final String TAG = "Qt MediaPlayer"; + private static Context mApplicationContext = null; + + final int MEDIA_PLAYER_INVALID_STATE = 1; + final int MEDIA_PLAYER_PREPARING = 2; + final int MEDIA_PLAYER_READY = 3; + final int MEDIA_PLAYER_DURATION = 4; + final int MEDIA_PLAYER_PROGRESS = 5; + final int MEDIA_PLAYER_FINISHED = 6; + + // Activity set by Qt on load. + static public void setActivity(final Activity activity) + { + try { + mApplicationContext = activity.getApplicationContext(); + } catch(final Exception e) { + Log.d(TAG, e.getMessage()); + } + } + + private class ProgressWatcher implements Runnable + { + @Override + public void run() + { + final int duratation = getDuration(); + int currentPosition = getCurrentPosition(); + + try { + while (duratation >= currentPosition && isPlaying()) { + onMediaPlayerInfoNative(MEDIA_PLAYER_PROGRESS, currentPosition, mID); + Thread.sleep(1000); + currentPosition = getCurrentPosition(); + } + } catch (final InterruptedException e) { + Log.d(TAG, e.getMessage()); + return; + } + } + } + + /** + * MediaPlayer OnErrorListener + */ + private class MediaPlayerErrorListener + implements MediaPlayer.OnErrorListener + { + @Override + public boolean onError(final MediaPlayer mp, + final int what, + final int extra) + { + reset(); + onErrorNative(what, extra, mID); + return true; + } + + } + + /** + * MediaPlayer OnBufferingListener + */ + private class MediaPlayerBufferingListener + implements MediaPlayer.OnBufferingUpdateListener + { + private int mBufferPercent = -1; + @Override + public void onBufferingUpdate(final android.media.MediaPlayer mp, + final int percent) + { + // Avoid updates when percent is unchanged. + // E.g., we keep getting updates when percent == 100 + if (mBufferPercent == percent) + return; + + onBufferingUpdateNative((mBufferPercent = percent), mID); + } + + } + + /** + * MediaPlayer OnCompletionListener + */ + private class MediaPlayerCompletionListener + implements MediaPlayer.OnCompletionListener + { + @Override + public void onCompletion(final MediaPlayer mp) + { + onMediaPlayerInfoNative(MEDIA_PLAYER_FINISHED, 0, mID); + reset(); + } + + } + + /** + * MediaPlayer OnInfoListener + */ + private class MediaPlayerInfoListener + implements MediaPlayer.OnInfoListener + { + @Override + public boolean onInfo(final MediaPlayer mp, + final int what, + final int extra) + { + onInfoNative(what, extra, mID); + return true; + } + + } + + /** + * MediaPlayer OnPreparedListener + */ + private class MediaPlayerPreparedListener + implements MediaPlayer.OnPreparedListener + { + + @Override + public void onPrepared(final MediaPlayer mp) + { + onMediaPlayerInfoNative(MEDIA_PLAYER_DURATION, getDuration(), mID); + onMediaPlayerInfoNative(MEDIA_PLAYER_READY, 0, mID); + mPreparing = false; + } + + } + + /** + * MediaPlayer OnSeekCompleteListener + */ + private class MediaPlayerSeekCompleteListener + implements MediaPlayer.OnSeekCompleteListener + { + + @Override + public void onSeekComplete(final MediaPlayer mp) + { + onMediaPlayerInfoNative(MEDIA_PLAYER_PROGRESS, getCurrentPosition(), mID); + } + + } + + /** + * MediaPlayer OnVideoSizeChangedListener + */ + private class MediaPlayerVideoSizeChangedListener + implements MediaPlayer.OnVideoSizeChangedListener + { + + @Override + public void onVideoSizeChanged(final MediaPlayer mp, + final int width, + final int height) + { + onVideoSizeChangedNative(width, height, mID); + } + + } + + public QtAndroidMediaPlayer(final long id) + { + super(); + mID = id; + setOnBufferingUpdateListener(new MediaPlayerBufferingListener()); + setOnCompletionListener(new MediaPlayerCompletionListener()); + setOnInfoListener(new MediaPlayerInfoListener()); + setOnSeekCompleteListener(new MediaPlayerSeekCompleteListener()); + setOnVideoSizeChangedListener(new MediaPlayerVideoSizeChangedListener()); + setOnErrorListener(new MediaPlayerErrorListener()); + } + + @Override + public void start() + { + if (!mInitialized) { + onMediaPlayerInfoNative(MEDIA_PLAYER_INVALID_STATE, 0, mID); + return; + } + + if (mApplicationContext == null) + return; + + if (mPreparing) + return; + + if (isPlaying()) + return; + + try { + super.start(); + Thread progressThread = new Thread(new ProgressWatcher()); + progressThread.start(); + } catch (final IllegalStateException e) { + reset(); + Log.d(TAG, e.getMessage()); + } + } + + @Override + public void pause() + { + if (!isPlaying()) + return; + + try { + super.pause(); + } catch (final IllegalStateException e) { + reset(); + Log.d(TAG, e.getMessage()); + } + } + + @Override + public void stop() + { + if (!mInitialized) + return; + + try { + super.stop(); + } catch (final IllegalStateException e) { + Log.d(TAG, e.getMessage()); + } finally { + reset(); + } + } + + @Override + public void seekTo(final int msec) + { + if (!mInitialized) + return; + + try { + super.seekTo(msec); + onMediaPlayerInfoNative(MEDIA_PLAYER_PROGRESS, msec, mID); + } catch (final IllegalStateException e) { + Log.d(TAG, e.getMessage()); + } + } + + @Override + public boolean isPlaying() + { + boolean playing = false; + + if (!mInitialized) + return playing; + + try { + playing = super.isPlaying(); + } catch (final IllegalStateException e) { + Log.d(TAG, e.getMessage()); + } + + return playing; + } + + public void setMediaPath(final String path) + { + if (mInitialized) + reset(); + + try { + mPreparing = true; + onMediaPlayerInfoNative(MEDIA_PLAYER_PREPARING, 0, mID); + mUri = Uri.parse(path); + setDataSource(mApplicationContext, mUri); + mInitialized = true; + setOnPreparedListener(new MediaPlayerPreparedListener()); + prepareAsync(); + } catch (final IOException e) { + mPreparing = false; + onErrorNative(MEDIA_ERROR_UNKNOWN, + /* MEDIA_ERROR_UNSUPPORTED= */ -1010, + mID); + } catch (final IllegalArgumentException e) { + Log.d(TAG, e.getMessage()); + } catch (final SecurityException e) { + Log.d(TAG, e.getMessage()); + } catch (final IllegalStateException e) { + Log.d(TAG, e.getMessage()); + } catch (final NullPointerException e) { + Log.d(TAG, e.getMessage()); + } + } + + @Override + public int getCurrentPosition() + { + int currentPosition = 0; + + if (!mInitialized) + return currentPosition; + + try { + currentPosition = super.getCurrentPosition(); + } catch (final IllegalStateException e) { + Log.d(TAG, e.getMessage()); + } + + return currentPosition; + } + + @Override + public int getDuration() + { + int duration = 0; + + if (!mInitialized) + return duration; + + try { + duration = super.getDuration(); + } catch (final IllegalStateException e) { + Log.d(TAG, e.getMessage()); + } + + return duration; + } + + private float adjustVolume(final int volume) + { + if (volume < 1) + return 0.0f; + + if (volume > 98) + return 1.0f; + + return (float) (1-(Math.log(100-volume)/Math.log(100))); + } + + public void setVolume(int volume) + { + if (volume < 0) + volume = 0; + + if (volume > 100) + volume = 100; + + float newVolume = adjustVolume(volume); + + try { + super.setVolume(newVolume, newVolume); + if (!mMuted) + mVolume = volume; + } catch (final IllegalStateException e) { + Log.d(TAG, e.getMessage()); + } + } + + public int getVolume() + { + return mVolume; + } + + public void mute(final boolean mute) + { + mMuted = mute; + setVolume(mute ? 0 : mVolume); + } + + public boolean isMuted() + { + return mMuted; + } + + @Override + public void reset() + { + mInitialized = false; + super.reset(); + } + +} |