From e4580277115ea89ca5b885108702d3d64dbea427 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Tue, 29 Sep 2020 12:01:26 +0300 Subject: Android: rename Android's package name for Qt 6 Rename Android package name org.qtproject.qt5.android to org.qtproject.qt.android to avoid inconsistency with Qt 6 name. Also, we include the major version number in the jar target. Task-number: QTBUG-86969 Change-Id: I261a3422ec81b0504174a132559d9bbf820815f9 Reviewed-by: Alex Blasche --- .../android/multimedia/QtAndroidMediaPlayer.java | 590 +++++++++++++++++++++ .../qt/android/multimedia/QtCameraListener.java | 216 ++++++++ .../multimedia/QtMediaRecorderListener.java | 67 +++ .../qt/android/multimedia/QtMultimediaUtils.java | 138 +++++ .../multimedia/QtSurfaceHolderCallback.java | 73 +++ .../android/multimedia/QtSurfaceTextureHolder.java | 125 +++++ .../multimedia/QtSurfaceTextureListener.java | 60 +++ 7 files changed, 1269 insertions(+) create mode 100644 src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtAndroidMediaPlayer.java create mode 100644 src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtCameraListener.java create mode 100644 src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtMediaRecorderListener.java create mode 100644 src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtMultimediaUtils.java create mode 100644 src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtSurfaceHolderCallback.java create mode 100644 src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtSurfaceTextureHolder.java create mode 100644 src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtSurfaceTextureListener.java (limited to 'src/plugins/android/jar/src/org/qtproject/qt/android') diff --git a/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtAndroidMediaPlayer.java b/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtAndroidMediaPlayer.java new file mode 100644 index 000000000..aa706179c --- /dev/null +++ b/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtAndroidMediaPlayer.java @@ -0,0 +1,590 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtMultimedia 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +package org.qtproject.qt.android.multimedia; + +import java.io.IOException; +import java.lang.String; +import java.util.HashMap; +import java.io.FileInputStream; + +// API is level is < 9 unless marked otherwise. +import android.content.Context; +import android.media.MediaPlayer; +import android.media.AudioAttributes; +import android.net.Uri; +import android.util.Log; +import java.io.FileDescriptor; +import android.content.res.AssetFileDescriptor; +import android.content.res.AssetManager; +import android.view.SurfaceHolder; + +public class QtAndroidMediaPlayer +{ + // 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 onProgressUpdateNative(int progress, long id); + native public void onDurationChangedNative(int duration, long id); + native public void onInfoNative(int what, int extra, long id); + native public void onVideoSizeChangedNative(int width, int height, long id); + native public void onStateChangedNative(int state, long id); + + private MediaPlayer mMediaPlayer = null; + private AudioAttributes mAudioAttributes = null; + private HashMap mHeaders = null; + private Uri mUri = null; + private final long mID; + private final Context mContext; + private boolean mMuted = false; + private int mVolume = 100; + private static final String TAG = "Qt MediaPlayer"; + private SurfaceHolder mSurfaceHolder = null; + + private class State { + final static int Uninitialized = 0x1 /* End */; + final static int Idle = 0x2; + final static int Preparing = 0x4; + final static int Prepared = 0x8; + final static int Initialized = 0x10; + final static int Started = 0x20; + final static int Stopped = 0x40; + final static int Paused = 0x80; + final static int PlaybackCompleted = 0x100; + final static int Error = 0x200; + } + + private volatile int mState = State.Uninitialized; + + /** + * MediaPlayer OnErrorListener + */ + private class MediaPlayerErrorListener + implements MediaPlayer.OnErrorListener + { + @Override + public boolean onError(final MediaPlayer mp, + final int what, + final int extra) + { + setState(State.Error); + 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) + { + setState(State.PlaybackCompleted); + } + + } + + /** + * 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) + { + setState(State.Prepared); + onDurationChangedNative(getDuration(), mID); + } + + } + + /** + * MediaPlayer OnSeekCompleteListener + */ + private class MediaPlayerSeekCompleteListener + implements MediaPlayer.OnSeekCompleteListener + { + + @Override + public void onSeekComplete(final MediaPlayer mp) + { + onProgressUpdateNative(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 Context context, final long id) + { + mID = id; + mContext = context; + } + + public MediaPlayer getMediaPlayerHandle() + { + return mMediaPlayer; + } + + private void setState(int state) + { + if (mState == state) + return; + + mState = state; + + onStateChangedNative(mState, mID); + } + + + private void init() + { + if (mMediaPlayer == null) { + mMediaPlayer = new MediaPlayer(); + setState(State.Idle); + // Make sure the new media player has the volume that was set on the QMediaPlayer + setVolumeHelper(mMuted ? 0 : mVolume); + setAudioAttributes(mMediaPlayer, mAudioAttributes); + } + } + + public void start() + { + if ((mState & (State.Prepared + | State.Started + | State.Paused + | State.PlaybackCompleted)) == 0) { + return; + } + + try { + mMediaPlayer.start(); + setState(State.Started); + } catch (final IllegalStateException e) { + Log.d(TAG, "" + e.getMessage()); + } + } + + + public void pause() + { + if ((mState & (State.Started | State.Paused | State.PlaybackCompleted)) == 0) + return; + + try { + mMediaPlayer.pause(); + setState(State.Paused); + } catch (final IllegalStateException e) { + Log.d(TAG, "" + e.getMessage()); + } + } + + + public void stop() + { + if ((mState & (State.Prepared + | State.Started + | State.Stopped + | State.Paused + | State.PlaybackCompleted)) == 0) { + return; + } + + try { + mMediaPlayer.stop(); + setState(State.Stopped); + } catch (final IllegalStateException e) { + Log.d(TAG, "" + e.getMessage()); + } + } + + + public void seekTo(final int msec) + { + if ((mState & (State.Prepared + | State.Started + | State.Paused + | State.PlaybackCompleted)) == 0) { + return; + } + + try { + mMediaPlayer.seekTo(msec); + } catch (final IllegalStateException e) { + Log.d(TAG, "" + e.getMessage()); + } + } + + + public boolean isPlaying() + { + boolean playing = false; + if ((mState & (State.Idle + | State.Initialized + | State.Prepared + | State.Started + | State.Paused + | State.Stopped + | State.PlaybackCompleted)) == 0) { + return playing; + } + + try { + playing = mMediaPlayer.isPlaying(); + } catch (final IllegalStateException e) { + Log.d(TAG, "" + e.getMessage()); + } + + return playing; + } + + public void prepareAsync() + { + if ((mState & (State.Initialized | State.Stopped)) == 0) + return; + + try { + mMediaPlayer.prepareAsync(); + setState(State.Preparing); + } catch (final IllegalStateException e) { + Log.d(TAG, "" + e.getMessage()); + } + } + + public void initHeaders() + { + mHeaders = new HashMap(); + } + + public void setHeader(final String header, final String value) + { + mHeaders.put(header, value); + } + + public void setDataSource(final String path) + { + if ((mState & State.Uninitialized) != 0) + init(); + + if ((mState & State.Idle) == 0) + return; + + mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayerBufferingListener()); + mMediaPlayer.setOnCompletionListener(new MediaPlayerCompletionListener()); + mMediaPlayer.setOnInfoListener(new MediaPlayerInfoListener()); + mMediaPlayer.setOnSeekCompleteListener(new MediaPlayerSeekCompleteListener()); + mMediaPlayer.setOnVideoSizeChangedListener(new MediaPlayerVideoSizeChangedListener()); + mMediaPlayer.setOnErrorListener(new MediaPlayerErrorListener()); + mMediaPlayer.setOnPreparedListener(new MediaPlayerPreparedListener()); + + if (mSurfaceHolder != null) + mMediaPlayer.setDisplay(mSurfaceHolder); + + AssetFileDescriptor afd = null; + FileInputStream fis = null; + try { + mUri = Uri.parse(path); + final boolean inAssets = (mUri.getScheme().compareTo("assets") == 0); + if (inAssets) { + final String asset = mUri.getPath().substring(1 /* Remove first '/' */); + final AssetManager am = mContext.getAssets(); + afd = am.openFd(asset); + final long offset = afd.getStartOffset(); + final long length = afd.getLength(); + FileDescriptor fd = afd.getFileDescriptor(); + mMediaPlayer.setDataSource(fd, offset, length); + } else if (mUri.getScheme().compareTo("file") == 0) { + fis = new FileInputStream(mUri.getPath()); + FileDescriptor fd = fis.getFD(); + mMediaPlayer.setDataSource(fd); + } else { + if (mHeaders.isEmpty()) + mMediaPlayer.setDataSource(path); + else + mMediaPlayer.setDataSource(mContext, mUri, mHeaders); + } + setState(State.Initialized); + } catch (final IOException e) { + Log.d(TAG, "" + e.getMessage()); + } 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()); + } finally { + try { + if (afd != null) + afd.close(); + if (fis != null) + fis.close(); + } catch (final IOException ioe) { /* Ignore... */ } + + if ((mState & State.Initialized) == 0) { + setState(State.Error); + onErrorNative(MediaPlayer.MEDIA_ERROR_UNKNOWN, + -1004 /*MEDIA_ERROR_IO*/, + mID); + return; + } + } + } + + + public int getCurrentPosition() + { + int currentPosition = 0; + if ((mState & (State.Idle + | State.Initialized + | State.Prepared + | State.Started + | State.Paused + | State.Stopped + | State.PlaybackCompleted)) == 0) { + return currentPosition; + } + + try { + currentPosition = mMediaPlayer.getCurrentPosition(); + } catch (final IllegalStateException e) { + Log.d(TAG, "" + e.getMessage()); + } + + return currentPosition; + } + + + public int getDuration() + { + int duration = 0; + if ((mState & (State.Prepared + | State.Started + | State.Paused + | State.Stopped + | State.PlaybackCompleted)) == 0) { + return duration; + } + + try { + duration = mMediaPlayer.getDuration(); + } catch (final IllegalStateException e) { + Log.d(TAG, "" + e.getMessage()); + } + + return duration; + } + + public void setVolume(int volume) + { + if (volume < 0) + volume = 0; + + if (volume > 100) + volume = 100; + + mVolume = volume; + + if (!mMuted) + setVolumeHelper(mVolume); + } + + private void setVolumeHelper(int volume) + { + if ((mState & (State.Idle + | State.Initialized + | State.Stopped + | State.Prepared + | State.Started + | State.Paused + | State.PlaybackCompleted)) == 0) { + return; + } + + try { + float newVolume = (float)volume / 100; + mMediaPlayer.setVolume(newVolume, newVolume); + } catch (final IllegalStateException e) { + Log.d(TAG, "" + e.getMessage()); + } + } + + public SurfaceHolder display() + { + return mSurfaceHolder; + } + + public void setDisplay(SurfaceHolder sh) + { + mSurfaceHolder = sh; + + if ((mState & State.Uninitialized) != 0) + return; + + mMediaPlayer.setDisplay(mSurfaceHolder); + } + + + public int getVolume() + { + return mVolume; + } + + public void mute(final boolean mute) + { + mMuted = mute; + setVolumeHelper(mute ? 0 : mVolume); + } + + public boolean isMuted() + { + return mMuted; + } + + + public void reset() + { + if ((mState & (State.Idle + | State.Initialized + | State.Prepared + | State.Started + | State.Paused + | State.Stopped + | State.PlaybackCompleted + | State.Error)) == 0) { + return; + } + + mMediaPlayer.reset(); + setState(State.Idle); + } + + public void release() + { + if (mMediaPlayer != null) { + mMediaPlayer.reset(); + mMediaPlayer.release(); + mMediaPlayer = null; + } + + setState(State.Uninitialized); + } + + public void setAudioAttributes(int type, int usage) + { + mAudioAttributes = new AudioAttributes.Builder() + .setUsage(usage) + .setContentType(type) + .build(); + + setAudioAttributes(mMediaPlayer, mAudioAttributes); + } + + static private void setAudioAttributes(MediaPlayer player, AudioAttributes attr) + { + if (player == null || attr == null) + return; + + try { + player.setAudioAttributes(attr); + } catch (final IllegalArgumentException e) { + Log.d(TAG, "" + e.getMessage()); + } + } +} diff --git a/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtCameraListener.java b/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtCameraListener.java new file mode 100644 index 000000000..ff26d90c3 --- /dev/null +++ b/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtCameraListener.java @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtMultimedia 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +package org.qtproject.qt.android.multimedia; + +import android.hardware.Camera; +import android.graphics.ImageFormat; +import android.graphics.SurfaceTexture; +import android.util.Log; +import java.lang.Math; + +public class QtCameraListener implements Camera.ShutterCallback, + Camera.PictureCallback, + Camera.AutoFocusCallback, + Camera.PreviewCallback +{ + private static final String TAG = "Qt Camera"; + + private static final int BUFFER_POOL_SIZE = 2; + + private int m_cameraId = -1; + + private boolean m_notifyNewFrames = false; + private boolean m_notifyWhenFrameAvailable = false; + private byte[][] m_previewBuffers = null; + private byte[] m_lastPreviewBuffer = null; + private Camera.Size m_previewSize = null; + private int m_previewFormat = ImageFormat.NV21; // Default preview format on all devices + private int m_previewBytesPerLine = -1; + + private QtCameraListener(int id) + { + m_cameraId = id; + } + + public void notifyNewFrames(boolean notify) + { + m_notifyNewFrames = notify; + } + + public void notifyWhenFrameAvailable(boolean notify) + { + m_notifyWhenFrameAvailable = notify; + } + + public byte[] lastPreviewBuffer() + { + return m_lastPreviewBuffer; + } + + public int previewWidth() + { + if (m_previewSize == null) + return -1; + + return m_previewSize.width; + } + + public int previewHeight() + { + if (m_previewSize == null) + return -1; + + return m_previewSize.height; + } + + public int previewFormat() + { + return m_previewFormat; + } + + public int previewBytesPerLine() + { + return m_previewBytesPerLine; + } + + public void clearPreviewCallback(Camera camera) + { + camera.setPreviewCallbackWithBuffer(null); + } + + public void setupPreviewCallback(Camera camera) + { + // Clear previous callback (also clears added buffers) + clearPreviewCallback(camera); + m_lastPreviewBuffer = null; + + final Camera.Parameters params = camera.getParameters(); + m_previewSize = params.getPreviewSize(); + m_previewFormat = params.getPreviewFormat(); + + int bufferSizeNeeded = 0; + if (m_previewFormat == ImageFormat.YV12) { + // For YV12, bytes per line must be a multiple of 16 + final int yStride = (int) Math.ceil(m_previewSize.width / 16.0) * 16; + final int uvStride = (int) Math.ceil((yStride / 2) / 16.0) * 16; + final int ySize = yStride * m_previewSize.height; + final int uvSize = uvStride * m_previewSize.height / 2; + bufferSizeNeeded = ySize + uvSize * 2; + + m_previewBytesPerLine = yStride; + + } else { + double bytesPerPixel = ImageFormat.getBitsPerPixel(m_previewFormat) / 8.0; + bufferSizeNeeded = (int) Math.ceil(bytesPerPixel * m_previewSize.width * m_previewSize.height); + + // bytes per line are calculated only for the first plane + switch (m_previewFormat) { + case ImageFormat.NV21: + m_previewBytesPerLine = m_previewSize.width; // 1 byte per sample and tightly packed + break; + case ImageFormat.RGB_565: + case ImageFormat.YUY2: + m_previewBytesPerLine = m_previewSize.width * 2; // 2 bytes per pixel + break; + default: + m_previewBytesPerLine = -1; + break; + } + } + + // We could keep the same buffers when they are already bigger than the required size + // but the Android doc says the size must match, so in doubt just replace them. + if (m_previewBuffers == null || m_previewBuffers[0].length != bufferSizeNeeded) + m_previewBuffers = new byte[BUFFER_POOL_SIZE][bufferSizeNeeded]; + + // Add callback and queue all buffers + camera.setPreviewCallbackWithBuffer(this); + for (byte[] buffer : m_previewBuffers) + camera.addCallbackBuffer(buffer); + } + + @Override + public void onPreviewFrame(byte[] data, Camera camera) + { + // Re-enqueue the last buffer + if (m_lastPreviewBuffer != null) + camera.addCallbackBuffer(m_lastPreviewBuffer); + + m_lastPreviewBuffer = data; + + if (data != null) { + if (m_notifyWhenFrameAvailable) { + m_notifyWhenFrameAvailable = false; + notifyFrameAvailable(m_cameraId); + } + if (m_notifyNewFrames) { + notifyNewPreviewFrame(m_cameraId, data, + m_previewSize.width, m_previewSize.height, + m_previewFormat, + m_previewBytesPerLine); + } + } + } + + @Override + public void onShutter() + { + notifyPictureExposed(m_cameraId); + } + + @Override + public void onPictureTaken(byte[] data, Camera camera) + { + notifyPictureCaptured(m_cameraId, data); + } + + @Override + public void onAutoFocus(boolean success, Camera camera) + { + notifyAutoFocusComplete(m_cameraId, success); + } + + private static native void notifyAutoFocusComplete(int id, boolean success); + private static native void notifyPictureExposed(int id); + private static native void notifyPictureCaptured(int id, byte[] data); + private static native void notifyNewPreviewFrame(int id, byte[] data, int width, int height, + int pixelFormat, int bytesPerLine); + private static native void notifyFrameAvailable(int id); +} diff --git a/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtMediaRecorderListener.java b/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtMediaRecorderListener.java new file mode 100644 index 000000000..bf1763dee --- /dev/null +++ b/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtMediaRecorderListener.java @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtMultimedia 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +package org.qtproject.qt.android.multimedia; + +import android.media.MediaRecorder; + +public class QtMediaRecorderListener implements MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener +{ + private long m_id = -1; + + public QtMediaRecorderListener(long id) + { + m_id = id; + } + + @Override + public void onError(MediaRecorder mr, int what, int extra) + { + notifyError(m_id, what, extra); + } + + @Override + public void onInfo(MediaRecorder mr, int what, int extra) + { + notifyInfo(m_id, what, extra); + } + + private static native void notifyError(long id, int what, int extra); + private static native void notifyInfo(long id, int what, int extra); +} diff --git a/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtMultimediaUtils.java b/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtMultimediaUtils.java new file mode 100644 index 000000000..28d56e0dd --- /dev/null +++ b/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtMultimediaUtils.java @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtMultimedia 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +package org.qtproject.qt.android.multimedia; + +import android.app.Activity; +import android.content.Context; +import android.view.OrientationEventListener; +import android.os.Environment; +import android.media.MediaScannerConnection; +import java.lang.String; +import java.io.File; + +public class QtMultimediaUtils +{ + static private class OrientationListener extends OrientationEventListener + { + static public int deviceOrientation = 0; + + public OrientationListener(Context context) + { + super(context); + } + + @Override + public void onOrientationChanged(int orientation) + { + if (orientation == ORIENTATION_UNKNOWN) + return; + + deviceOrientation = orientation; + } + } + + static private Context m_context = null; + static private OrientationListener m_orientationListener = null; + + static public void setActivity(Activity qtMainActivity, Object qtActivityDelegate) + { + } + + static public void setContext(Context context) + { + m_context = context; + m_orientationListener = new OrientationListener(context); + } + + public QtMultimediaUtils() + { + } + + static void enableOrientationListener(boolean enable) + { + if (enable) + m_orientationListener.enable(); + else + m_orientationListener.disable(); + } + + static int getDeviceOrientation() + { + return m_orientationListener.deviceOrientation; + } + + static String getDefaultMediaDirectory(int type) + { + String dirType = new String(); + switch (type) { + case 0: + dirType = Environment.DIRECTORY_MUSIC; + break; + case 1: + dirType = Environment.DIRECTORY_MOVIES; + break; + case 2: + dirType = Environment.DIRECTORY_DCIM; + break; + default: + break; + } + + File path = new File(""); + if (type == 3) { + // There is no API for knowing the standard location for sounds + // such as voice recording. Though, it's typically in the 'Sounds' + // directory at the root of the external storage + path = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + + File.separator + "Sounds"); + } else { + path = Environment.getExternalStoragePublicDirectory(dirType); + } + + path.mkdirs(); // make sure the directory exists + + return path.getAbsolutePath(); + } + + static void registerMediaFile(String file) + { + MediaScannerConnection.scanFile(m_context, new String[] { file }, null, null); + } +} diff --git a/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtSurfaceHolderCallback.java b/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtSurfaceHolderCallback.java new file mode 100644 index 000000000..62000716b --- /dev/null +++ b/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtSurfaceHolderCallback.java @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtMultimedia 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +package org.qtproject.qt.android.multimedia; + +import android.view.SurfaceHolder; + +public class QtSurfaceHolderCallback implements SurfaceHolder.Callback +{ + private long m_id = -1; + + public QtSurfaceHolderCallback(long id) + { + m_id = id; + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) + { + } + + @Override + public void surfaceCreated(SurfaceHolder holder) + { + notifySurfaceCreated(m_id); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) + { + notifySurfaceDestroyed(m_id); + } + + + private static native void notifySurfaceCreated(long id); + private static native void notifySurfaceDestroyed(long id); +} diff --git a/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtSurfaceTextureHolder.java b/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtSurfaceTextureHolder.java new file mode 100644 index 000000000..ea7a41505 --- /dev/null +++ b/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtSurfaceTextureHolder.java @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the (whatever) 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +package org.qtproject.qt.android.multimedia; + +import android.view.SurfaceHolder; +import android.view.Surface; +import android.graphics.Rect; +import android.graphics.Canvas; + +public class QtSurfaceTextureHolder implements SurfaceHolder +{ + private Surface surfaceTexture; + + public QtSurfaceTextureHolder(Surface surface) + { + surfaceTexture = surface; + } + + @Override + public void addCallback(SurfaceHolder.Callback callback) + { + } + + @Override + public Surface getSurface() + { + return surfaceTexture; + } + + @Override + public Rect getSurfaceFrame() + { + return new Rect(); + } + + @Override + public boolean isCreating() + { + return false; + } + + @Override + public Canvas lockCanvas(Rect dirty) + { + return new Canvas(); + } + + @Override + public Canvas lockCanvas() + { + return new Canvas(); + } + + @Override + public void removeCallback(SurfaceHolder.Callback callback) + { + } + + @Override + public void setFixedSize(int width, int height) + { + } + + @Override + public void setFormat(int format) + { + } + + @Override + public void setKeepScreenOn(boolean screenOn) + { + } + + @Override + public void setSizeFromLayout() + { + } + + @Override + public void setType(int type) + { + } + + @Override + public void unlockCanvasAndPost(Canvas canvas) + { + } +} diff --git a/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtSurfaceTextureListener.java b/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtSurfaceTextureListener.java new file mode 100644 index 000000000..4d929c6ad --- /dev/null +++ b/src/plugins/android/jar/src/org/qtproject/qt/android/multimedia/QtSurfaceTextureListener.java @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtMultimedia 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +package org.qtproject.qt.android.multimedia; + +import android.graphics.SurfaceTexture; + +public class QtSurfaceTextureListener implements SurfaceTexture.OnFrameAvailableListener +{ + private final long m_id; + + public QtSurfaceTextureListener(long id) + { + m_id = id; + } + + @Override + public void onFrameAvailable(SurfaceTexture surfaceTexture) + { + notifyFrameAvailable(m_id); + } + + private static native void notifyFrameAvailable(long id); +} -- cgit v1.2.3