From b33e6d46726ee275eaa00be8800339f1fce4585e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 7 Apr 2014 14:04:49 +0200 Subject: [PATCH 01/38] Android: Release the surface texture when not in use With some Android versions the preview texture is released when the application is suspended. If we don't release the texture in our code, the preview will be empty when the application resumes. Task-number: QTBUG-38165 Change-Id: I72244727081d8f94ee5f6cb0ab660ca59f4bb2de Reviewed-by: Yoann Lopes --- .../android/src/mediacapture/qandroidcamerasession.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp index b1b3f848..6051cf96 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp @@ -286,8 +286,10 @@ void QAndroidCameraSession::close() void QAndroidCameraSession::setVideoPreview(QObject *videoOutput) { - if (m_videoOutput) + if (m_videoOutput) { m_videoOutput->stop(); + m_videoOutput->reset(); + } if (videoOutput) { connect(videoOutput, SIGNAL(readyChanged(bool)), this, SLOT(onVideoOutputReady(bool))); @@ -368,8 +370,12 @@ void QAndroidCameraSession::stopPreview() m_camera->stopPreview(); m_camera->setPreviewSize(QSize()); - if (m_videoOutput) + m_camera->setPreviewTexture(0); + + if (m_videoOutput) { m_videoOutput->stop(); + m_videoOutput->reset(); + } m_previewStarted = false; } From af73d55efffa1dca928038cd4f392eb7def7c7e1 Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Wed, 9 Apr 2014 17:02:25 +0200 Subject: [PATCH 02/38] Doc: Improved example documentation -added instructions on how to run the example (using \include to insert a section from qtbase/doc/global/) -updated copyright year -removed links to Qt 4 API -rearranged some of the sections -created links from the example pages to Qt Multimedia -fixed QDoc warnings related to the example pages Task-number: QTBUG-33597 Change-Id: Id45ce5cbd40dbfa384abd7260a316f6f6837c186 Reviewed-by: Yoann Lopes Reviewed-by: Sze Howe Koh --- .../audiodevices/doc/src/audiodevices.qdoc | 9 ++--- .../audioengine/doc/src/audioengine.qdoc | 10 ++--- .../audioinput/doc/src/audioinput.qdoc | 9 +++-- .../audiooutput/doc/src/audiooutput.qdoc | 9 +++-- .../audiorecorder/doc/src/audiorecorder.qdoc | 12 ++++-- .../doc/src/declarative-camera.qdoc | 37 ++++++------------- .../doc/src/declarative-radio.qdoc | 10 ++--- .../multimedia/spectrum/doc/src/spectrum.qdoc | 6 +-- .../multimedia/video/doc/src/qmlvideo.qdoc | 11 +++--- .../multimedia/video/doc/src/qmlvideofx.qdoc | 11 +++--- .../camera/doc/src/camera.qdoc | 8 ++-- .../player/doc/src/player.qdoc | 5 ++- .../doc/src/videographicsitem.qdoc | 6 ++- .../videowidget/doc/src/videowidget.qdoc | 6 ++- 14 files changed, 73 insertions(+), 76 deletions(-) diff --git a/examples/multimedia/audiodevices/doc/src/audiodevices.qdoc b/examples/multimedia/audiodevices/doc/src/audiodevices.qdoc index d7558448..bdf1590f 100644 --- a/examples/multimedia/audiodevices/doc/src/audiodevices.qdoc +++ b/examples/multimedia/audiodevices/doc/src/audiodevices.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -29,8 +29,8 @@ \example audiodevices \title Audio Devices Example \ingroup multimedia_examples - \brief The Audio Devices example shows the application of the audio devices APIs - + \brief The Audio Devices example shows the application of the audio devices + APIs. This example shows how to create a simple application to list and test the configuration for the various audio devices available on the device @@ -38,6 +38,5 @@ \image audiodevices.png + \include examples-run.qdocinc */ - - diff --git a/examples/multimedia/audioengine/doc/src/audioengine.qdoc b/examples/multimedia/audioengine/doc/src/audioengine.qdoc index c83247df..52a37713 100644 --- a/examples/multimedia/audioengine/doc/src/audioengine.qdoc +++ b/examples/multimedia/audioengine/doc/src/audioengine.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -30,10 +30,10 @@ \title AudioEngine Example \ingroup multimedia_examples \brief The Audio Engine example demonstrates 3D sound control using - the QtAudioEngine API. + the Qt Audio Engine API. - \image audioengine.png + The Audio Engine example demonstrates 3D sound control using the + \l{Qt Audio Engine QML Types}{Qt Audio Engine} API. + \include examples-run.qdocinc */ - - diff --git a/examples/multimedia/audioinput/doc/src/audioinput.qdoc b/examples/multimedia/audioinput/doc/src/audioinput.qdoc index 39ef2615..11a513a9 100644 --- a/examples/multimedia/audioinput/doc/src/audioinput.qdoc +++ b/examples/multimedia/audioinput/doc/src/audioinput.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -37,7 +37,8 @@ Qt provides the QAudioInput class to enable audio functionality within a standard application user interface. - This example calculates the maximum linear value of the input audio from the microphone and displays the output. + This example calculates the maximum linear value of the input audio from the + microphone and displays the output. + + \include examples-run.qdocinc */ - - diff --git a/examples/multimedia/audiooutput/doc/src/audiooutput.qdoc b/examples/multimedia/audiooutput/doc/src/audiooutput.qdoc index bc79e6a5..60c9d00d 100644 --- a/examples/multimedia/audiooutput/doc/src/audiooutput.qdoc +++ b/examples/multimedia/audiooutput/doc/src/audiooutput.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -31,13 +31,14 @@ \ingroup multimedia_examples \brief The Audio Output Example show the use of the QAudioOutput API. - The example demonstrates the basic use cases of the QAudioOutput class. + The example demonstrates the basic use cases of the QAudioOutput class from + \l{Qt Multimedia}. \image audiooutput-example.png This example provides a tone generator to supply continuous audio playback. The first button allows pause and resume of the playback, and the second button allows toggling between push and pull modes of operation. + + \include examples-run.qdocinc */ - - diff --git a/examples/multimedia/audiorecorder/doc/src/audiorecorder.qdoc b/examples/multimedia/audiorecorder/doc/src/audiorecorder.qdoc index 8453ea34..35f6c051 100644 --- a/examples/multimedia/audiorecorder/doc/src/audiorecorder.qdoc +++ b/examples/multimedia/audiorecorder/doc/src/audiorecorder.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -34,6 +34,12 @@ It demonstrates the discovery of the supported devices and codecs and the use of recording functions in the QAudioRecorder class. + \image audiorecorder.png + + \include examples-run.qdocinc + + \section1 Displaying the Window and Audio Settings + We display a window for the user to select the appropriate audio input, codec, container, and sample rate. Allow a setting of either quality or bitrate. Finally, the output file can be selected and recording can be @@ -49,7 +55,7 @@ \l{QMultimedia::NormalQuality}, while the bitrates are hardcoded into the list. - \image audiorecorder.png + \section1 Recording Audio To record audio we simply create a QAudioRecorder object. @@ -96,5 +102,3 @@ ui->statusbar->showMessage(tr("Recorded %1 sec").arg(duration / 1000)); \endcode */ - - diff --git a/examples/multimedia/declarative-camera/doc/src/declarative-camera.qdoc b/examples/multimedia/declarative-camera/doc/src/declarative-camera.qdoc index 02e77854..8c87b1d4 100644 --- a/examples/multimedia/declarative-camera/doc/src/declarative-camera.qdoc +++ b/examples/multimedia/declarative-camera/doc/src/declarative-camera.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -34,35 +34,22 @@ or video. \image qml-camera.png -This example demonstrates how to use the Qt Multimedia QML API to access -camera functions. It shows how to change settings and to capture images. +This example demonstrates how to use the +\l{Qt Multimedia QML Types}{Qt Multimedia QML API} to access camera functions. +It shows how to change settings and to capture images. + +\include examples-run.qdocinc + +\section1 Application Structure Most of the QML code supports the user interface for this application with the camera types being mostly found in \e {declarative-camera.qml} and \e {CaptureControls.qml}. -In \e {declarative-camera.qml} the \l Camera is initialized with an id -of \e {camera}, a photo preview is setup, states are implemented for image -preview or capture and \l CaptureControls is initialized. The initial -\e state is \e PhotoCapture. \l CameraCapture includes a handler, \e onImageCaptured, -for the \l {imageCaptured} signal. The handler sets up the application to process -the preview including a change in the user interface state. The \l PhotoPreview -becomes visible with any key press being picked up by the handler -in PhotoPreview and returning the state to \e PhotoCapture. - -\e CaptureControls, which is implemented in \e {CaptureControls.qml}, +CaptureControls, which is implemented in \e {CaptureControls.qml}, generates a column on the right hand side of the screen which includes control -buttons for \e focus (not initially visible), \e {capture}, \e {flash modes}, -\e {white balance}, \e {exposure compensation}, and if a preview is -available a \e {preview} button. The last button exits from the application. - -When the Capture button is pressed the \e onClicked handler calls -\l {Camera::captureImage()}{captureImage()} - - - - - - +buttons for focus (not initially visible), capture, flash modes, +white balance, exposure compensation, and if a preview is +available, a preview button. The last button exits from the application. */ diff --git a/examples/multimedia/declarative-radio/doc/src/declarative-radio.qdoc b/examples/multimedia/declarative-radio/doc/src/declarative-radio.qdoc index 99c41114..bb1a5d89 100644 --- a/examples/multimedia/declarative-radio/doc/src/declarative-radio.qdoc +++ b/examples/multimedia/declarative-radio/doc/src/declarative-radio.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -31,8 +31,8 @@ \brief Demonstrates the radio functionality \ingroup multimedia_examples - This examples uses the Qt Multimedia Radio QML type to list the available - channels on the FM frequency. + This examples uses the \l{Qt Multimedia} \l Radio QML type to list the + available channels on the FM frequency. + + \include examples-run.qdocinc */ - - diff --git a/examples/multimedia/spectrum/doc/src/spectrum.qdoc b/examples/multimedia/spectrum/doc/src/spectrum.qdoc index 28083895..3c846afd 100644 --- a/examples/multimedia/spectrum/doc/src/spectrum.qdoc +++ b/examples/multimedia/spectrum/doc/src/spectrum.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -59,6 +59,6 @@ (FFT) of a segment of audio data. An open-source library, \l{http://ldesoras.free.fr/prod.html}{FFTReal}, against which the application is dynamically linked, is used to compute the transform. + + \include examples-run.qdocinc */ - - diff --git a/examples/multimedia/video/doc/src/qmlvideo.qdoc b/examples/multimedia/video/doc/src/qmlvideo.qdoc index 6d683349..1e80cd17 100644 --- a/examples/multimedia/video/doc/src/qmlvideo.qdoc +++ b/examples/multimedia/video/doc/src/qmlvideo.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -34,8 +34,6 @@ resize; rotate; change aspect ratio) which can be applied to QML \l{VideoOutput} items. -\section1 Overview - This example demonstrates the various manipulations (move; resize; rotate; change aspect ratio) which can be applied to QML \l{VideoOutput} items. @@ -50,7 +48,9 @@ which moves across the \l{VideoOutput} item. \image qmlvideo-overlay.png -\section1 Application structure +\include examples-run.qdocinc + +\section1 Application Structure The \l{video/qmlvideo/qml/qmlvideo/main.qml} file creates a UI which includes the following items: @@ -127,7 +127,7 @@ instance, the embedded \l{video/qmlvideo/qml/qmlvideo/Content.qml}{Content} item creates either a \l{MediaPlayer} or a \l{Camera} item. -\section1 Calculating and displaying QML painting rate +\section1 Calculating and Displaying QML Painting Rate \input multimedia/doc/src/examples/video-qml-paint-rate.qdocinc @@ -145,4 +145,3 @@ object to a JavaScript function, which will eventually call frequencyItem.notify \printuntil SLOT(qmlFramePainted())); */ - diff --git a/examples/multimedia/video/doc/src/qmlvideofx.qdoc b/examples/multimedia/video/doc/src/qmlvideofx.qdoc index b7bd78ac..80f087e7 100644 --- a/examples/multimedia/video/doc/src/qmlvideofx.qdoc +++ b/examples/multimedia/video/doc/src/qmlvideofx.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -34,9 +34,11 @@ can be used to apply postprocessing effects, expressed in \c GLSL, to video and camera viewfinder content. +\include examples-run.qdocinc + \section1 Overview -This example shows how a \l {ShaderEffectItem} can be used to apply +This example shows how a \l {ShaderEffect} can be used to apply postprocessing effects, expressed in GLSL, to QML \l {VideoOutput} items. It also shows how native code can be combined with QML to implement more @@ -73,7 +75,7 @@ for Effect*.qml files in the list above to see the full range. \section1 Application structure Shader effects can be applied to video or viewfinder content using -\l{ShaderEffectItem}, as shown in the following example, which applies +\l{ShaderEffect}, as shown in the following example, which applies a wiggly effect to the content: \code @@ -171,7 +173,7 @@ is based on the \l{ShaderEffect}: \skipto import \printuntil /^\}/ -The interface of the \l Effect allows for derived effects to specify the +The interface of Effect allows for derived effects to specify the number of parameters which they support (and therefore the number of sliders which should be displayed), and whether a vertical dividing line should be drawn between transformed and untransformed image regions. As an example, here is the @@ -219,4 +221,3 @@ object to a JavaScript function, which will eventually call frequencyItem.notify \printuntil SLOT(qmlFramePainted())); */ - diff --git a/examples/multimediawidgets/camera/doc/src/camera.qdoc b/examples/multimediawidgets/camera/doc/src/camera.qdoc index d1a855d4..5f668348 100644 --- a/examples/multimediawidgets/camera/doc/src/camera.qdoc +++ b/examples/multimediawidgets/camera/doc/src/camera.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -35,10 +35,12 @@ \brief The Camera Example shows how to use the API to capture a still image or video. -The Camera Example demonstrates how you can use Qt Multimedia to implement +The Camera Example demonstrates how you can use \l{Qt Multimedia} to implement some basic Camera functionality to take still images and record video clips with audio. +\include examples-run.qdocinc + A Camera class is created that will act as our Camera. It has a user interface, control functions, setting values and a means of defining the location where the image or video clip is to be saved. It will also store the image and video @@ -74,5 +76,3 @@ is started with a call to \l {QMediaRecorder::record()}. \image camera-example.png */ - - diff --git a/examples/multimediawidgets/player/doc/src/player.qdoc b/examples/multimediawidgets/player/doc/src/player.qdoc index 2dfb7c3d..29121dce 100644 --- a/examples/multimediawidgets/player/doc/src/player.qdoc +++ b/examples/multimediawidgets/player/doc/src/player.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -34,6 +34,8 @@ This example creates a simple multimedia player. We can play audio and or video files using various codecs. + \include examples-run.qdocinc + The example uses a QMediaPlayer object passed into a QVideoWidget to control the video output. To give the application playlist capability we also use a QPlayList object. @@ -93,4 +95,3 @@ \endcode */ - diff --git a/examples/multimediawidgets/videographicsitem/doc/src/videographicsitem.qdoc b/examples/multimediawidgets/videographicsitem/doc/src/videographicsitem.qdoc index 3ccdba5f..1e392ce8 100644 --- a/examples/multimediawidgets/videographicsitem/doc/src/videographicsitem.qdoc +++ b/examples/multimediawidgets/videographicsitem/doc/src/videographicsitem.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -32,9 +32,11 @@ \brief This example demonstrates how to stream video on a graphics scene. The Video Graphics Item example shows how to implement a QGraphicsItem that displays video on a - graphics scene using Qt Multimedia's QAbstractVideoSurface. + graphics scene using \l{Qt Multimedia}'s QAbstractVideoSurface. \image video-videographicsitem.png \sa {Video Widget Example} + + \include examples-run.qdocinc */ diff --git a/examples/multimediawidgets/videowidget/doc/src/videowidget.qdoc b/examples/multimediawidgets/videowidget/doc/src/videowidget.qdoc index 805a830b..6b93a3c1 100644 --- a/examples/multimediawidgets/videowidget/doc/src/videowidget.qdoc +++ b/examples/multimediawidgets/videowidget/doc/src/videowidget.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the documentation of the Qt Toolkit. @@ -32,7 +32,9 @@ \brief This example is a simple video player The Video Widget example denonstrates how to implement a video widget using - Qt Multimedia's QAbstractVideoSurface. + \l{Qt Multimedia}'s QAbstractVideoSurface. \image video-videowidget.png + + \include examples-run.qdocinc */ From 60a911096f04b5159b99ad444bc9ad9aedf42eb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Thu, 3 Apr 2014 17:26:05 +0200 Subject: [PATCH 03/38] Android: Use QMutexLock in camera callbacks. We should not release the locks before the native callbacks returns. Change-Id: Ia2691f6c5be66a3dcf371e48e3bac7498b401833 Reviewed-by: Yoann Lopes --- src/plugins/android/src/wrappers/jcamera.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/plugins/android/src/wrappers/jcamera.cpp b/src/plugins/android/src/wrappers/jcamera.cpp index b0e9f89f..f43e2308 100644 --- a/src/plugins/android/src/wrappers/jcamera.cpp +++ b/src/plugins/android/src/wrappers/jcamera.cpp @@ -82,27 +82,24 @@ static QJNIObjectPrivate rectToArea(const QRect &rect) // native method for QtCamera.java static void notifyAutoFocusComplete(JNIEnv* , jobject, int id, jboolean success) { - g_objectMapMutex.lock(); + QMutexLocker locker(&g_objectMapMutex); JCamera *obj = g_objectMap.value(id, 0); - g_objectMapMutex.unlock(); if (obj) Q_EMIT obj->autoFocusComplete(success); } static void notifyPictureExposed(JNIEnv* , jobject, int id) { - g_objectMapMutex.lock(); + QMutexLocker locker(&g_objectMapMutex); JCamera *obj = g_objectMap.value(id, 0); - g_objectMapMutex.unlock(); if (obj) Q_EMIT obj->pictureExposed(); } static void notifyPictureCaptured(JNIEnv *env, jobject, int id, jbyteArray data) { - g_objectMapMutex.lock(); + QMutexLocker locker(&g_objectMapMutex); JCamera *obj = g_objectMap.value(id, 0); - g_objectMapMutex.unlock(); if (obj) { QByteArray bytes; int arrayLength = env->GetArrayLength(data); @@ -114,9 +111,8 @@ static void notifyPictureCaptured(JNIEnv *env, jobject, int id, jbyteArray data) static void notifyFrameFetched(JNIEnv *env, jobject, int id, jbyteArray data) { - g_objectMapMutex.lock(); + QMutexLocker locker(&g_objectMapMutex); JCamera *obj = g_objectMap.value(id, 0); - g_objectMapMutex.unlock(); if (obj) { QByteArray bytes; int arrayLength = env->GetArrayLength(data); From b088962950dbc4c6f0219de30b0d9a8cf47a3376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Thu, 3 Apr 2014 18:09:48 +0200 Subject: [PATCH 04/38] Android: Camera code clean-up Change-Id: Ib400afde12067764c3dcc0f44e40ddc1abb3012f Reviewed-by: Yoann Lopes --- src/plugins/android/jar/jar.pri | 2 +- .../{QtCamera.java => QtCameraListener.java} | 160 +----- src/plugins/android/src/wrappers/jcamera.cpp | 474 +++++++++++------- src/plugins/android/src/wrappers/jcamera.h | 8 +- 4 files changed, 307 insertions(+), 337 deletions(-) rename src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/{QtCamera.java => QtCameraListener.java} (52%) diff --git a/src/plugins/android/jar/jar.pri b/src/plugins/android/jar/jar.pri index d8bc59a7..d31839c6 100644 --- a/src/plugins/android/jar/jar.pri +++ b/src/plugins/android/jar/jar.pri @@ -6,7 +6,7 @@ API_VERSION = android-11 JAVACLASSPATH += $$PWD/src JAVASOURCES += $$PWD/src/org/qtproject/qt5/android/multimedia/QtAndroidMediaPlayer.java \ - $$PWD/src/org/qtproject/qt5/android/multimedia/QtCamera.java \ + $$PWD/src/org/qtproject/qt5/android/multimedia/QtCameraListener.java \ $$PWD/src/org/qtproject/qt5/android/multimedia/QtSurfaceTextureListener.java \ $$PWD/src/org/qtproject/qt5/android/multimedia/QtSurfaceTextureHolder.java \ $$PWD/src/org/qtproject/qt5/android/multimedia/QtMultimediaUtils.java \ diff --git a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCamera.java b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCameraListener.java similarity index 52% rename from src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCamera.java rename to src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCameraListener.java index f03053f1..27002fd2 100644 --- a/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCamera.java +++ b/src/plugins/android/jar/src/org/qtproject/qt5/android/multimedia/QtCameraListener.java @@ -48,98 +48,33 @@ import android.util.Log; import java.lang.Math; import java.util.concurrent.locks.ReentrantLock; -public class QtCamera implements Camera.ShutterCallback, - Camera.PictureCallback, - Camera.AutoFocusCallback, - Camera.PreviewCallback +public class QtCameraListener implements Camera.ShutterCallback, + Camera.PictureCallback, + Camera.AutoFocusCallback, + Camera.PreviewCallback { private int m_cameraId = -1; - private Camera m_camera = null; - private byte[] m_cameraPreviewFirstBuffer = null; - private byte[] m_cameraPreviewSecondBuffer = null; - private int m_actualPreviewBuffer = 0; + private byte[][] m_cameraPreviewBuffer = null; + private volatile int m_actualPreviewBuffer = 0; private final ReentrantLock m_buffersLock = new ReentrantLock(); - private boolean m_isReleased = false; private boolean m_fetchEachFrame = false; private static final String TAG = "Qt Camera"; - private QtCamera(int id, Camera cam) + private QtCameraListener(int id) { m_cameraId = id; - m_camera = cam; } - public static QtCamera open(int cameraId) + public void preparePreviewBuffer(Camera camera) { - try { - Camera cam = Camera.open(cameraId); - return new QtCamera(cameraId, cam); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - return null; - } - - public Camera.Parameters getParameters() - { - return m_camera.getParameters(); - } - - public void lock() - { - try { - m_camera.lock(); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - - public void unlock() - { - try { - m_camera.unlock(); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - - public void release() - { - m_isReleased = true; - m_camera.release(); - } - - public void reconnect() - { - try { - m_camera.reconnect(); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - - public void setDisplayOrientation(int degrees) - { - m_camera.setDisplayOrientation(degrees); - } - - public void setParameters(Camera.Parameters params) - { - try { - m_camera.setParameters(params); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - - public void setPreviewTexture(SurfaceTexture surfaceTexture) - { - try { - m_camera.setPreviewTexture(surfaceTexture); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } + Camera.Size previewSize = camera.getParameters().getPreviewSize(); + double bytesPerPixel = ImageFormat.getBitsPerPixel(camera.getParameters().getPreviewFormat()) / 8.0; + int bufferSizeNeeded = (int)Math.ceil(bytesPerPixel*previewSize.width*previewSize.height); + m_buffersLock.lock(); + if (m_cameraPreviewBuffer == null || m_cameraPreviewBuffer[0].length < bufferSizeNeeded) + m_cameraPreviewBuffer = new byte[2][bufferSizeNeeded]; + m_buffersLock.unlock(); } public void fetchEachFrame(boolean fetch) @@ -147,51 +82,6 @@ public class QtCamera implements Camera.ShutterCallback, m_fetchEachFrame = fetch; } - public void startPreview() - { - Camera.Size previewSize = m_camera.getParameters().getPreviewSize(); - double bytesPerPixel = ImageFormat.getBitsPerPixel(m_camera.getParameters().getPreviewFormat()) / 8.0; - int bufferSizeNeeded = (int)Math.ceil(bytesPerPixel*previewSize.width*previewSize.height); - - //We need to clear preview buffers queue here, but there is no method to do it - //Though just resetting preview callback do the trick - m_camera.setPreviewCallback(null); - m_buffersLock.lock(); - if (m_cameraPreviewFirstBuffer == null || m_cameraPreviewFirstBuffer.length < bufferSizeNeeded) - m_cameraPreviewFirstBuffer = new byte[bufferSizeNeeded]; - if (m_cameraPreviewSecondBuffer == null || m_cameraPreviewSecondBuffer.length < bufferSizeNeeded) - m_cameraPreviewSecondBuffer = new byte[bufferSizeNeeded]; - addCallbackBuffer(); - m_buffersLock.unlock(); - m_camera.setPreviewCallbackWithBuffer(this); - - m_camera.startPreview(); - } - - public void stopPreview() - { - m_camera.stopPreview(); - } - - public void autoFocus() - { - m_camera.autoFocus(this); - } - - public void cancelAutoFocus() - { - m_camera.cancelAutoFocus(); - } - - public void takePicture() - { - try { - m_camera.takePicture(this, null, this); - } catch(Exception e) { - Log.d(TAG, e.getMessage()); - } - } - public byte[] lockAndFetchPreviewBuffer() { //This method should always be followed by unlockPreviewBuffer() @@ -199,10 +89,7 @@ public class QtCamera implements Camera.ShutterCallback, //We should reset actualBuffer flag here to make sure we will not use old preview with future captures byte[] result = null; m_buffersLock.lock(); - if (m_actualPreviewBuffer == 1) - result = m_cameraPreviewFirstBuffer; - else if (m_actualPreviewBuffer == 2) - result = m_cameraPreviewSecondBuffer; + result = m_cameraPreviewBuffer[(m_actualPreviewBuffer == 1) ? 0 : 1]; m_actualPreviewBuffer = 0; return result; } @@ -213,14 +100,9 @@ public class QtCamera implements Camera.ShutterCallback, m_buffersLock.unlock(); } - private void addCallbackBuffer() + public byte[] callbackBuffer() { - if (m_isReleased) - return; - - m_camera.addCallbackBuffer((m_actualPreviewBuffer == 1) - ? m_cameraPreviewSecondBuffer - : m_cameraPreviewFirstBuffer); + return m_cameraPreviewBuffer[(m_actualPreviewBuffer == 1) ? 1 : 0]; } @Override @@ -243,13 +125,13 @@ public class QtCamera implements Camera.ShutterCallback, if (data != null && m_fetchEachFrame) notifyFrameFetched(m_cameraId, data); - if (data == m_cameraPreviewFirstBuffer) + if (data == m_cameraPreviewBuffer[0]) m_actualPreviewBuffer = 1; - else if (data == m_cameraPreviewSecondBuffer) + else if (data == m_cameraPreviewBuffer[1]) m_actualPreviewBuffer = 2; else m_actualPreviewBuffer = 0; - addCallbackBuffer(); + camera.addCallbackBuffer(m_cameraPreviewBuffer[(m_actualPreviewBuffer == 1) ? 1 : 0]); m_buffersLock.unlock(); } diff --git a/src/plugins/android/src/wrappers/jcamera.cpp b/src/plugins/android/src/wrappers/jcamera.cpp index f43e2308..5401e6d1 100644 --- a/src/plugins/android/src/wrappers/jcamera.cpp +++ b/src/plugins/android/src/wrappers/jcamera.cpp @@ -41,19 +41,19 @@ #include "jcamera.h" -#include #include #include #include "qandroidmultimediautils.h" -#include #include #include +#include QT_BEGIN_NAMESPACE -static jclass g_qtCameraClass = 0; -static QMap g_objectMap; -static QMutex g_objectMapMutex; +static jclass g_qtCameraListenerClass = 0; +static QMutex g_cameraMapMutex; +typedef QMap CameraMap; +Q_GLOBAL_STATIC(CameraMap, g_cameraMap) static QRect areaToRect(jobject areaObj) { @@ -79,31 +79,30 @@ static QJNIObjectPrivate rectToArea(const QRect &rect) return area; } -// native method for QtCamera.java +// native method for QtCameraLisener.java static void notifyAutoFocusComplete(JNIEnv* , jobject, int id, jboolean success) { - QMutexLocker locker(&g_objectMapMutex); - JCamera *obj = g_objectMap.value(id, 0); + QMutexLocker locker(&g_cameraMapMutex); + JCamera *obj = g_cameraMap->value(id, 0); if (obj) Q_EMIT obj->autoFocusComplete(success); } static void notifyPictureExposed(JNIEnv* , jobject, int id) { - QMutexLocker locker(&g_objectMapMutex); - JCamera *obj = g_objectMap.value(id, 0); + QMutexLocker locker(&g_cameraMapMutex); + JCamera *obj = g_cameraMap->value(id, 0); if (obj) Q_EMIT obj->pictureExposed(); } static void notifyPictureCaptured(JNIEnv *env, jobject, int id, jbyteArray data) { - QMutexLocker locker(&g_objectMapMutex); - JCamera *obj = g_objectMap.value(id, 0); + QMutexLocker locker(&g_cameraMapMutex); + JCamera *obj = g_cameraMap->value(id, 0); if (obj) { - QByteArray bytes; - int arrayLength = env->GetArrayLength(data); - bytes.resize(arrayLength); + const int arrayLength = env->GetArrayLength(data); + QByteArray bytes(arrayLength, Qt::Uninitialized); env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data()); Q_EMIT obj->pictureCaptured(bytes); } @@ -111,46 +110,30 @@ static void notifyPictureCaptured(JNIEnv *env, jobject, int id, jbyteArray data) static void notifyFrameFetched(JNIEnv *env, jobject, int id, jbyteArray data) { - QMutexLocker locker(&g_objectMapMutex); - JCamera *obj = g_objectMap.value(id, 0); + QMutexLocker locker(&g_cameraMapMutex); + JCamera *obj = g_cameraMap->value(id, 0); if (obj) { - QByteArray bytes; - int arrayLength = env->GetArrayLength(data); - bytes.resize(arrayLength); + const int arrayLength = env->GetArrayLength(data); + QByteArray bytes(arrayLength, Qt::Uninitialized); env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data()); Q_EMIT obj->frameFetched(bytes); } } -class JCameraInstantiator : public QObject +class JCameraPrivate : public QObject { Q_OBJECT public: - JCameraInstantiator() : QObject(0) {} - QJNIObjectPrivate result() {return lastCamera;} -public slots: - void openCamera(int cameraId) - { - QJNIEnvironmentPrivate env; - lastCamera = QJNIObjectPrivate::callStaticObjectMethod(g_qtCameraClass, - "open", - "(I)Lorg/qtproject/qt5/android/multimedia/QtCamera;", - cameraId); - } -private: - QJNIObjectPrivate lastCamera; -}; + JCameraPrivate(); + ~JCameraPrivate(); -class JCameraWorker : public QObject -{ - Q_OBJECT - friend class JCamera; - - JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread *workerThread); - ~JCameraWorker(); + Q_INVOKABLE bool init(int cameraId); Q_INVOKABLE void release(); + Q_INVOKABLE void lock(); + Q_INVOKABLE void unlock(); + Q_INVOKABLE void reconnect(); Q_INVOKABLE JCamera::CameraFacing getFacing(); Q_INVOKABLE int getNativeOrientation(); @@ -182,6 +165,7 @@ class JCameraWorker : public QObject Q_INVOKABLE void setFocusAreas(const QList &areas); Q_INVOKABLE void autoFocus(); + Q_INVOKABLE void cancelAutoFocus(); Q_INVOKABLE bool isAutoExposureLockSupported(); Q_INVOKABLE bool getAutoExposureLock(); @@ -212,26 +196,23 @@ class JCameraWorker : public QObject Q_INVOKABLE void startPreview(); Q_INVOKABLE void stopPreview(); + Q_INVOKABLE void takePicture(); + Q_INVOKABLE void fetchEachFrame(bool fetch); Q_INVOKABLE void fetchLastPreviewFrame(); Q_INVOKABLE void applyParameters(); Q_INVOKABLE QStringList callParametersStringListMethod(const QByteArray &methodName); - Q_INVOKABLE void callVoidMethod(const QByteArray &methodName); int m_cameraId; - QJNIObjectPrivate m_info; - QJNIObjectPrivate m_parameters; - + QMutex m_parametersMutex; QSize m_previewSize; int m_rotation; - - JCamera *q; - - QThread *m_workerThread; - QMutex m_parametersMutex; + QJNIObjectPrivate m_info; + QJNIObjectPrivate m_parameters; QJNIObjectPrivate m_camera; + QJNIObjectPrivate m_cameraListener; Q_SIGNALS: void previewSizeChanged(); @@ -245,122 +226,137 @@ Q_SIGNALS: void previewFetched(const QByteArray &preview); }; +JCamera::JCamera(JCameraPrivate *d, QThread *worker) + : QObject(), + d_ptr(d), + m_worker(worker) - -JCamera::JCamera(int cameraId, jobject cam, QThread *workerThread) - : QObject() { qRegisterMetaType >(); qRegisterMetaType >(); qRegisterMetaType >(); - d = new JCameraWorker(this, cameraId, cam, workerThread); - connect(d, &JCameraWorker::previewSizeChanged, this, &JCamera::previewSizeChanged); - connect(d, &JCameraWorker::previewStarted, this, &JCamera::previewStarted); - connect(d, &JCameraWorker::previewStopped, this, &JCamera::previewStopped); - connect(d, &JCameraWorker::autoFocusStarted, this, &JCamera::autoFocusStarted); - connect(d, &JCameraWorker::whiteBalanceChanged, this, &JCamera::whiteBalanceChanged); - connect(d, &JCameraWorker::previewFetched, this, &JCamera::previewFetched); + connect(d, &JCameraPrivate::previewSizeChanged, this, &JCamera::previewSizeChanged); + connect(d, &JCameraPrivate::previewStarted, this, &JCamera::previewStarted); + connect(d, &JCameraPrivate::previewStopped, this, &JCamera::previewStopped); + connect(d, &JCameraPrivate::autoFocusStarted, this, &JCamera::autoFocusStarted); + connect(d, &JCameraPrivate::whiteBalanceChanged, this, &JCamera::whiteBalanceChanged); + connect(d, &JCameraPrivate::previewFetched, this, &JCamera::previewFetched); } JCamera::~JCamera() { + Q_D(JCamera); if (d->m_camera.isValid()) { - g_objectMapMutex.lock(); - g_objectMap.remove(d->m_cameraId); - g_objectMapMutex.unlock(); + g_cameraMapMutex.lock(); + g_cameraMap->remove(d->m_cameraId); + g_cameraMapMutex.unlock(); } - d->deleteLater(); + + release(); + m_worker->exit(); + m_worker->wait(5000); } JCamera *JCamera::open(int cameraId) { - QThread *cameraThread = new QThread; - connect(cameraThread, &QThread::finished, cameraThread, &QThread::deleteLater); - cameraThread->start(); - JCameraInstantiator *instantiator = new JCameraInstantiator; - instantiator->moveToThread(cameraThread); - QMetaObject::invokeMethod(instantiator, "openCamera", - Qt::BlockingQueuedConnection, - Q_ARG(int, cameraId)); - QJNIObjectPrivate camera = instantiator->result(); - delete instantiator; - - if (!camera.isValid()) { - cameraThread->terminate(); - delete cameraThread; + JCameraPrivate *d = new JCameraPrivate(); + QThread *worker = new QThread; + worker->start(); + d->moveToThread(worker); + connect(worker, &QThread::finished, d, &JCameraPrivate::deleteLater); + bool ok = false; + QMetaObject::invokeMethod(d, "init", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ok), Q_ARG(int, cameraId)); + if (!ok) { + worker->quit(); + worker->wait(5000); + delete d; + delete worker; return 0; - } else { - return new JCamera(cameraId, camera.object(), cameraThread); } + + JCamera *q = new JCamera(d, worker); + g_cameraMapMutex.lock(); + g_cameraMap->insert(cameraId, q); + g_cameraMapMutex.unlock(); + return q; } int JCamera::cameraId() const { + Q_D(const JCamera); return d->m_cameraId; } void JCamera::lock() { - QMetaObject::invokeMethod(d, "callVoidMethod", - Qt::BlockingQueuedConnection, - Q_ARG(QByteArray, "lock")); + Q_D(JCamera); + QMetaObject::invokeMethod(d, "lock", Qt::BlockingQueuedConnection); } void JCamera::unlock() { - QMetaObject::invokeMethod(d, "callVoidMethod", - Qt::BlockingQueuedConnection, - Q_ARG(QByteArray, "unlock")); + Q_D(JCamera); + QMetaObject::invokeMethod(d, "unlock", Qt::BlockingQueuedConnection); } void JCamera::reconnect() { - QMetaObject::invokeMethod(d, "callVoidMethod", Q_ARG(QByteArray, "reconnect")); + Q_D(JCamera); + QMetaObject::invokeMethod(d, "reconnect"); } void JCamera::release() { - QMetaObject::invokeMethod(d, "release"); + Q_D(JCamera); + QMetaObject::invokeMethod(d, "release", Qt::BlockingQueuedConnection); } JCamera::CameraFacing JCamera::getFacing() { + Q_D(JCamera); return d->getFacing(); } int JCamera::getNativeOrientation() { + Q_D(JCamera); return d->getNativeOrientation(); } QSize JCamera::getPreferredPreviewSizeForVideo() { + Q_D(JCamera); return d->getPreferredPreviewSizeForVideo(); } QList JCamera::getSupportedPreviewSizes() { + Q_D(JCamera); return d->getSupportedPreviewSizes(); } JCamera::ImageFormat JCamera::getPreviewFormat() { + Q_D(JCamera); return d->getPreviewFormat(); } void JCamera::setPreviewFormat(ImageFormat fmt) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setPreviewFormat", Q_ARG(JCamera::ImageFormat, fmt)); } QSize JCamera::previewSize() const { + Q_D(const JCamera); return d->m_previewSize; } void JCamera::setPreviewSize(const QSize &size) { + Q_D(JCamera); d->m_parametersMutex.lock(); bool areParametersValid = d->m_parameters.isValid(); d->m_parametersMutex.unlock(); @@ -373,176 +369,211 @@ void JCamera::setPreviewSize(const QSize &size) void JCamera::setPreviewTexture(jobject surfaceTexture) { - QMetaObject::invokeMethod(d, "setPreviewTexture", Q_ARG(void *, surfaceTexture)); + Q_D(JCamera); + QMetaObject::invokeMethod(d, "setPreviewTexture", Qt::BlockingQueuedConnection, Q_ARG(void *, surfaceTexture)); } bool JCamera::isZoomSupported() { + Q_D(JCamera); return d->isZoomSupported(); } int JCamera::getMaxZoom() { + Q_D(JCamera); return d->getMaxZoom(); } QList JCamera::getZoomRatios() { + Q_D(JCamera); return d->getZoomRatios(); } int JCamera::getZoom() { + Q_D(JCamera); return d->getZoom(); } void JCamera::setZoom(int value) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setZoom", Q_ARG(int, value)); } QStringList JCamera::getSupportedFlashModes() { + Q_D(JCamera); return d->callParametersStringListMethod("getSupportedFlashModes"); } QString JCamera::getFlashMode() { + Q_D(JCamera); return d->getFlashMode(); } void JCamera::setFlashMode(const QString &value) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setFlashMode", Q_ARG(QString, value)); } QStringList JCamera::getSupportedFocusModes() { + Q_D(JCamera); return d->callParametersStringListMethod("getSupportedFocusModes"); } QString JCamera::getFocusMode() { + Q_D(JCamera); return d->getFocusMode(); } void JCamera::setFocusMode(const QString &value) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setFocusMode", Q_ARG(QString, value)); } int JCamera::getMaxNumFocusAreas() { + Q_D(JCamera); return d->getMaxNumFocusAreas(); } QList JCamera::getFocusAreas() { + Q_D(JCamera); return d->getFocusAreas(); } void JCamera::setFocusAreas(const QList &areas) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setFocusAreas", Q_ARG(QList, areas)); } void JCamera::autoFocus() { + Q_D(JCamera); QMetaObject::invokeMethod(d, "autoFocus"); } void JCamera::cancelAutoFocus() { - QMetaObject::invokeMethod(d, "callVoidMethod", Q_ARG(QByteArray, "cancelAutoFocus")); + Q_D(JCamera); + QMetaObject::invokeMethod(d, "cancelAutoFocus", Qt::QueuedConnection); } bool JCamera::isAutoExposureLockSupported() { + Q_D(JCamera); return d->isAutoExposureLockSupported(); } bool JCamera::getAutoExposureLock() { + Q_D(JCamera); return d->getAutoExposureLock(); } void JCamera::setAutoExposureLock(bool toggle) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setAutoExposureLock", Q_ARG(bool, toggle)); } bool JCamera::isAutoWhiteBalanceLockSupported() { + Q_D(JCamera); return d->isAutoWhiteBalanceLockSupported(); } bool JCamera::getAutoWhiteBalanceLock() { + Q_D(JCamera); return d->getAutoWhiteBalanceLock(); } void JCamera::setAutoWhiteBalanceLock(bool toggle) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setAutoWhiteBalanceLock", Q_ARG(bool, toggle)); } int JCamera::getExposureCompensation() { + Q_D(JCamera); return d->getExposureCompensation(); } void JCamera::setExposureCompensation(int value) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setExposureCompensation", Q_ARG(int, value)); } float JCamera::getExposureCompensationStep() { + Q_D(JCamera); return d->getExposureCompensationStep(); } int JCamera::getMinExposureCompensation() { + Q_D(JCamera); return d->getMinExposureCompensation(); } int JCamera::getMaxExposureCompensation() { + Q_D(JCamera); return d->getMaxExposureCompensation(); } QStringList JCamera::getSupportedSceneModes() { + Q_D(JCamera); return d->callParametersStringListMethod("getSupportedSceneModes"); } QString JCamera::getSceneMode() { + Q_D(JCamera); return d->getSceneMode(); } void JCamera::setSceneMode(const QString &value) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setSceneMode", Q_ARG(QString, value)); } QStringList JCamera::getSupportedWhiteBalance() { + Q_D(JCamera); return d->callParametersStringListMethod("getSupportedWhiteBalance"); } QString JCamera::getWhiteBalance() { + Q_D(JCamera); return d->getWhiteBalance(); } void JCamera::setWhiteBalance(const QString &value) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setWhiteBalance", Q_ARG(QString, value)); } void JCamera::setRotation(int rotation) { + Q_D(JCamera); //We need to do it here and not in worker class because we cache rotation d->m_parametersMutex.lock(); bool areParametersValid = d->m_parameters.isValid(); @@ -556,110 +587,143 @@ void JCamera::setRotation(int rotation) int JCamera::getRotation() const { + Q_D(const JCamera); return d->m_rotation; } QList JCamera::getSupportedPictureSizes() { + Q_D(JCamera); return d->getSupportedPictureSizes(); } void JCamera::setPictureSize(const QSize &size) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setPictureSize", Q_ARG(QSize, size)); } void JCamera::setJpegQuality(int quality) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "setJpegQuality", Q_ARG(int, quality)); } void JCamera::takePicture() { - QMetaObject::invokeMethod(d, "callVoidMethod", Q_ARG(QByteArray, "takePicture")); + Q_D(JCamera); + QMetaObject::invokeMethod(d, "takePicture", Qt::BlockingQueuedConnection); } void JCamera::fetchEachFrame(bool fetch) { + Q_D(JCamera); QMetaObject::invokeMethod(d, "fetchEachFrame", Q_ARG(bool, fetch)); } void JCamera::fetchLastPreviewFrame() { + Q_D(JCamera); QMetaObject::invokeMethod(d, "fetchLastPreviewFrame"); } QJNIObjectPrivate JCamera::getCameraObject() { - return d->m_camera.getObjectField("m_camera", "Landroid/hardware/Camera;"); + Q_D(JCamera); + return d->m_camera; } void JCamera::startPreview() { + Q_D(JCamera); QMetaObject::invokeMethod(d, "startPreview"); } void JCamera::stopPreview() { + Q_D(JCamera); QMetaObject::invokeMethod(d, "stopPreview"); } - -//JCameraWorker - -JCameraWorker::JCameraWorker(JCamera *camera, int cameraId, jobject cam, QThread *workerThread) - : QObject(0) - , m_cameraId(cameraId) - , m_rotation(0) - , m_parametersMutex(QMutex::Recursive) - , m_camera(cam) +JCameraPrivate::JCameraPrivate() + : QObject(), + m_parametersMutex(QMutex::Recursive) { - q = camera; - m_workerThread = workerThread; - moveToThread(m_workerThread); - - if (m_camera.isValid()) { - g_objectMapMutex.lock(); - g_objectMap.insert(cameraId, q); - g_objectMapMutex.unlock(); - - m_info = QJNIObjectPrivate("android/hardware/Camera$CameraInfo"); - m_camera.callStaticMethod("android/hardware/Camera", - "getCameraInfo", - "(ILandroid/hardware/Camera$CameraInfo;)V", - cameraId, m_info.object()); - - QJNIObjectPrivate params = m_camera.callObjectMethod("getParameters", - "()Landroid/hardware/Camera$Parameters;"); - m_parameters = QJNIObjectPrivate(params); - } } -JCameraWorker::~JCameraWorker() +JCameraPrivate::~JCameraPrivate() { - m_workerThread->quit(); } -void JCameraWorker::release() +bool JCameraPrivate::init(int cameraId) +{ + m_cameraId = cameraId; + m_camera = QJNIObjectPrivate::callStaticObjectMethod("android/hardware/Camera", + "open", + "(I)Landroid/hardware/Camera;", + cameraId); + + if (!m_camera.isValid()) + return false; + + m_cameraListener = QJNIObjectPrivate(g_qtCameraListenerClass, "(I)V", m_cameraId); + m_info = QJNIObjectPrivate("android/hardware/Camera$CameraInfo"); + m_camera.callStaticMethod("android/hardware/Camera", + "getCameraInfo", + "(ILandroid/hardware/Camera$CameraInfo;)V", + cameraId, + m_info.object()); + + QJNIObjectPrivate params = m_camera.callObjectMethod("getParameters", + "()Landroid/hardware/Camera$Parameters;"); + m_parameters = QJNIObjectPrivate(params); + + return true; +} + +void JCameraPrivate::release() { m_previewSize = QSize(); m_parametersMutex.lock(); m_parameters = QJNIObjectPrivate(); m_parametersMutex.unlock(); - m_camera.callMethod("release"); + if (m_camera.isValid()) + m_camera.callMethod("release"); } -JCamera::CameraFacing JCameraWorker::getFacing() +void JCameraPrivate::lock() +{ + m_camera.callMethod("lock"); +} + +void JCameraPrivate::unlock() +{ + m_camera.callMethod("unlock"); +} + +void JCameraPrivate::reconnect() +{ + QJNIEnvironmentPrivate env; + m_camera.callMethod("reconnect"); + if (env->ExceptionCheck()) { +#ifdef QT_DEBUG + env->ExceptionDescribe(); +#endif // QT_DEBUG + env->ExceptionDescribe(); + } +} + +JCamera::CameraFacing JCameraPrivate::getFacing() { return JCamera::CameraFacing(m_info.getField("facing")); } -int JCameraWorker::getNativeOrientation() +int JCameraPrivate::getNativeOrientation() { return m_info.getField("orientation"); } -QSize JCameraWorker::getPreferredPreviewSizeForVideo() +QSize JCameraPrivate::getPreferredPreviewSizeForVideo() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -672,7 +736,7 @@ QSize JCameraWorker::getPreferredPreviewSizeForVideo() return QSize(size.getField("width"), size.getField("height")); } -QList JCameraWorker::getSupportedPreviewSizes() +QList JCameraPrivate::getSupportedPreviewSizes() { QList list; @@ -695,7 +759,7 @@ QList JCameraWorker::getSupportedPreviewSizes() return list; } -JCamera::ImageFormat JCameraWorker::getPreviewFormat() +JCamera::ImageFormat JCameraPrivate::getPreviewFormat() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -705,7 +769,7 @@ JCamera::ImageFormat JCameraWorker::getPreviewFormat() return JCamera::ImageFormat(m_parameters.callMethod("getPreviewFormat")); } -void JCameraWorker::setPreviewFormat(JCamera::ImageFormat fmt) +void JCameraPrivate::setPreviewFormat(JCamera::ImageFormat fmt) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -716,7 +780,7 @@ void JCameraWorker::setPreviewFormat(JCamera::ImageFormat fmt) applyParameters(); } -void JCameraWorker::updatePreviewSize() +void JCameraPrivate::updatePreviewSize() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -728,14 +792,14 @@ void JCameraWorker::updatePreviewSize() emit previewSizeChanged(); } -void JCameraWorker::setPreviewTexture(void *surfaceTexture) +void JCameraPrivate::setPreviewTexture(void *surfaceTexture) { m_camera.callMethod("setPreviewTexture", "(Landroid/graphics/SurfaceTexture;)V", static_cast(surfaceTexture)); } -bool JCameraWorker::isZoomSupported() +bool JCameraPrivate::isZoomSupported() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -745,7 +809,7 @@ bool JCameraWorker::isZoomSupported() return m_parameters.callMethod("isZoomSupported"); } -int JCameraWorker::getMaxZoom() +int JCameraPrivate::getMaxZoom() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -755,7 +819,7 @@ int JCameraWorker::getMaxZoom() return m_parameters.callMethod("getMaxZoom"); } -QList JCameraWorker::getZoomRatios() +QList JCameraPrivate::getZoomRatios() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -777,7 +841,7 @@ QList JCameraWorker::getZoomRatios() return ratios; } -int JCameraWorker::getZoom() +int JCameraPrivate::getZoom() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -787,7 +851,7 @@ int JCameraWorker::getZoom() return m_parameters.callMethod("getZoom"); } -void JCameraWorker::setZoom(int value) +void JCameraPrivate::setZoom(int value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -798,7 +862,7 @@ void JCameraWorker::setZoom(int value) applyParameters(); } -QString JCameraWorker::getFlashMode() +QString JCameraPrivate::getFlashMode() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -814,7 +878,7 @@ QString JCameraWorker::getFlashMode() return value; } -void JCameraWorker::setFlashMode(const QString &value) +void JCameraPrivate::setFlashMode(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -827,7 +891,7 @@ void JCameraWorker::setFlashMode(const QString &value) applyParameters(); } -QString JCameraWorker::getFocusMode() +QString JCameraPrivate::getFocusMode() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -843,7 +907,7 @@ QString JCameraWorker::getFocusMode() return value; } -void JCameraWorker::setFocusMode(const QString &value) +void JCameraPrivate::setFocusMode(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -856,7 +920,7 @@ void JCameraWorker::setFocusMode(const QString &value) applyParameters(); } -int JCameraWorker::getMaxNumFocusAreas() +int JCameraPrivate::getMaxNumFocusAreas() { if (QtAndroidPrivate::androidSdkVersion() < 14) return 0; @@ -869,7 +933,7 @@ int JCameraWorker::getMaxNumFocusAreas() return m_parameters.callMethod("getMaxNumFocusAreas"); } -QList JCameraWorker::getFocusAreas() +QList JCameraPrivate::getFocusAreas() { QList areas; @@ -897,7 +961,7 @@ QList JCameraWorker::getFocusAreas() return areas; } -void JCameraWorker::setFocusAreas(const QList &areas) +void JCameraPrivate::setFocusAreas(const QList &areas) { if (QtAndroidPrivate::androidSdkVersion() < 14) return; @@ -927,13 +991,20 @@ void JCameraWorker::setFocusAreas(const QList &areas) applyParameters(); } -void JCameraWorker::autoFocus() +void JCameraPrivate::autoFocus() { - m_camera.callMethod("autoFocus"); + m_camera.callMethod("autoFocus", + "(Landroid/hardware/Camera$AutoFocusCallback;)V", + m_cameraListener.object()); emit autoFocusStarted(); } -bool JCameraWorker::isAutoExposureLockSupported() +void JCameraPrivate::cancelAutoFocus() +{ + m_camera.callMethod("cancelAutoFocus"); +} + +bool JCameraPrivate::isAutoExposureLockSupported() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -946,7 +1017,7 @@ bool JCameraWorker::isAutoExposureLockSupported() return m_parameters.callMethod("isAutoExposureLockSupported"); } -bool JCameraWorker::getAutoExposureLock() +bool JCameraPrivate::getAutoExposureLock() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -959,7 +1030,7 @@ bool JCameraWorker::getAutoExposureLock() return m_parameters.callMethod("getAutoExposureLock"); } -void JCameraWorker::setAutoExposureLock(bool toggle) +void JCameraPrivate::setAutoExposureLock(bool toggle) { if (QtAndroidPrivate::androidSdkVersion() < 14) return; @@ -973,7 +1044,7 @@ void JCameraWorker::setAutoExposureLock(bool toggle) applyParameters(); } -bool JCameraWorker::isAutoWhiteBalanceLockSupported() +bool JCameraPrivate::isAutoWhiteBalanceLockSupported() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -986,7 +1057,7 @@ bool JCameraWorker::isAutoWhiteBalanceLockSupported() return m_parameters.callMethod("isAutoWhiteBalanceLockSupported"); } -bool JCameraWorker::getAutoWhiteBalanceLock() +bool JCameraPrivate::getAutoWhiteBalanceLock() { if (QtAndroidPrivate::androidSdkVersion() < 14) return false; @@ -999,7 +1070,7 @@ bool JCameraWorker::getAutoWhiteBalanceLock() return m_parameters.callMethod("getAutoWhiteBalanceLock"); } -void JCameraWorker::setAutoWhiteBalanceLock(bool toggle) +void JCameraPrivate::setAutoWhiteBalanceLock(bool toggle) { if (QtAndroidPrivate::androidSdkVersion() < 14) return; @@ -1013,7 +1084,7 @@ void JCameraWorker::setAutoWhiteBalanceLock(bool toggle) applyParameters(); } -int JCameraWorker::getExposureCompensation() +int JCameraPrivate::getExposureCompensation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1023,7 +1094,7 @@ int JCameraWorker::getExposureCompensation() return m_parameters.callMethod("getExposureCompensation"); } -void JCameraWorker::setExposureCompensation(int value) +void JCameraPrivate::setExposureCompensation(int value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1034,7 +1105,7 @@ void JCameraWorker::setExposureCompensation(int value) applyParameters(); } -float JCameraWorker::getExposureCompensationStep() +float JCameraPrivate::getExposureCompensationStep() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1044,7 +1115,7 @@ float JCameraWorker::getExposureCompensationStep() return m_parameters.callMethod("getExposureCompensationStep"); } -int JCameraWorker::getMinExposureCompensation() +int JCameraPrivate::getMinExposureCompensation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1054,7 +1125,7 @@ int JCameraWorker::getMinExposureCompensation() return m_parameters.callMethod("getMinExposureCompensation"); } -int JCameraWorker::getMaxExposureCompensation() +int JCameraPrivate::getMaxExposureCompensation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1064,7 +1135,7 @@ int JCameraWorker::getMaxExposureCompensation() return m_parameters.callMethod("getMaxExposureCompensation"); } -QString JCameraWorker::getSceneMode() +QString JCameraPrivate::getSceneMode() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1080,7 +1151,7 @@ QString JCameraWorker::getSceneMode() return value; } -void JCameraWorker::setSceneMode(const QString &value) +void JCameraPrivate::setSceneMode(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1093,7 +1164,7 @@ void JCameraWorker::setSceneMode(const QString &value) applyParameters(); } -QString JCameraWorker::getWhiteBalance() +QString JCameraPrivate::getWhiteBalance() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1109,7 +1180,7 @@ QString JCameraWorker::getWhiteBalance() return value; } -void JCameraWorker::setWhiteBalance(const QString &value) +void JCameraPrivate::setWhiteBalance(const QString &value) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1124,7 +1195,7 @@ void JCameraWorker::setWhiteBalance(const QString &value) emit whiteBalanceChanged(); } -void JCameraWorker::updateRotation() +void JCameraPrivate::updateRotation() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1132,7 +1203,7 @@ void JCameraWorker::updateRotation() applyParameters(); } -QList JCameraWorker::getSupportedPictureSizes() +QList JCameraPrivate::getSupportedPictureSizes() { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1155,7 +1226,7 @@ QList JCameraWorker::getSupportedPictureSizes() return list; } -void JCameraWorker::setPictureSize(const QSize &size) +void JCameraPrivate::setPictureSize(const QSize &size) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1166,7 +1237,7 @@ void JCameraWorker::setPictureSize(const QSize &size) applyParameters(); } -void JCameraWorker::setJpegQuality(int quality) +void JCameraPrivate::setJpegQuality(int quality) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1177,49 +1248,71 @@ void JCameraWorker::setJpegQuality(int quality) applyParameters(); } -void JCameraWorker::startPreview() +void JCameraPrivate::startPreview() { - callVoidMethod("startPreview"); + //We need to clear preview buffers queue here, but there is no method to do it + //Though just resetting preview callback do the trick + m_camera.callMethod("setPreviewCallbackWithBuffer", + "(Landroid/hardware/Camera$PreviewCallback;)V", + jobject(0)); + m_cameraListener.callMethod("preparePreviewBuffer", "(Landroid/hardware/Camera;)V", m_camera.object()); + QJNIObjectPrivate buffer = m_cameraListener.callObjectMethod("callbackBuffer"); + m_camera.callMethod("addCallbackBuffer", "([B)V", buffer.object()); + m_camera.callMethod("setPreviewCallbackWithBuffer", + "(Landroid/hardware/Camera$PreviewCallback;)V", + m_cameraListener.object()); + m_camera.callMethod("startPreview"); emit previewStarted(); } -void JCameraWorker::stopPreview() +void JCameraPrivate::stopPreview() { - callVoidMethod("stopPreview"); + m_camera.callMethod("stopPreview"); emit previewStopped(); } -void JCameraWorker::fetchEachFrame(bool fetch) +void JCameraPrivate::takePicture() { - m_camera.callMethod("fetchEachFrame", "(Z)V", fetch); + m_camera.callMethod("takePicture", "(Landroid/hardware/Camera$ShutterCallback;" + "Landroid/hardware/Camera$PictureCallback;" + "Landroid/hardware/Camera$PictureCallback;)V", + m_cameraListener.object(), + jobject(0), + m_cameraListener.object()); } -void JCameraWorker::fetchLastPreviewFrame() +void JCameraPrivate::fetchEachFrame(bool fetch) +{ + m_cameraListener.callMethod("fetchEachFrame", "(Z)V", fetch); +} + +void JCameraPrivate::fetchLastPreviewFrame() { QJNIEnvironmentPrivate env; - QJNIObjectPrivate dataObj = m_camera.callObjectMethod("lockAndFetchPreviewBuffer", "()[B"); - if (!dataObj.object()) { - m_camera.callMethod("unlockPreviewBuffer"); + QJNIObjectPrivate data = m_cameraListener.callObjectMethod("lockAndFetchPreviewBuffer", "()[B"); + if (!data.isValid()) { + m_cameraListener.callMethod("unlockPreviewBuffer"); return; } - jbyteArray data = static_cast(dataObj.object()); - QByteArray bytes; - int arrayLength = env->GetArrayLength(data); - bytes.resize(arrayLength); - env->GetByteArrayRegion(data, 0, arrayLength, (jbyte*)bytes.data()); - m_camera.callMethod("unlockPreviewBuffer"); + const int arrayLength = env->GetArrayLength(static_cast(data.object())); + QByteArray bytes(arrayLength, Qt::Uninitialized); + env->GetByteArrayRegion(static_cast(data.object()), + 0, + arrayLength, + reinterpret_cast(bytes.data())); + m_cameraListener.callMethod("unlockPreviewBuffer"); emit previewFetched(bytes); } -void JCameraWorker::applyParameters() +void JCameraPrivate::applyParameters() { m_camera.callMethod("setParameters", "(Landroid/hardware/Camera$Parameters;)V", m_parameters.object()); } -QStringList JCameraWorker::callParametersStringListMethod(const QByteArray &methodName) +QStringList JCameraPrivate::callParametersStringListMethod(const QByteArray &methodName) { QMutexLocker parametersLocker(&m_parametersMutex); @@ -1235,7 +1328,6 @@ QStringList JCameraWorker::callParametersStringListMethod(const QByteArray &meth QJNIObjectPrivate string = list.callObjectMethod("get", "(I)Ljava/lang/Object;", i); - stringList.append(string.toString()); } } @@ -1244,12 +1336,6 @@ QStringList JCameraWorker::callParametersStringListMethod(const QByteArray &meth return stringList; } -void JCameraWorker::callVoidMethod(const QByteArray &methodName) -{ - m_camera.callMethod(methodName.constData()); -} - - static JNINativeMethod methods[] = { {"notifyAutoFocusComplete", "(IZ)V", (void *)notifyAutoFocusComplete}, {"notifyPictureExposed", "(I)V", (void *)notifyPictureExposed}, @@ -1259,13 +1345,13 @@ static JNINativeMethod methods[] = { bool JCamera::initJNI(JNIEnv *env) { - jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtCamera"); + jclass clazz = env->FindClass("org/qtproject/qt5/android/multimedia/QtCameraListener"); if (env->ExceptionCheck()) env->ExceptionClear(); if (clazz) { - g_qtCameraClass = static_cast(env->NewGlobalRef(clazz)); - if (env->RegisterNatives(g_qtCameraClass, + g_qtCameraListenerClass = static_cast(env->NewGlobalRef(clazz)); + if (env->RegisterNatives(g_qtCameraListenerClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { return false; diff --git a/src/plugins/android/src/wrappers/jcamera.h b/src/plugins/android/src/wrappers/jcamera.h index 81c334eb..ec5bcc3c 100644 --- a/src/plugins/android/src/wrappers/jcamera.h +++ b/src/plugins/android/src/wrappers/jcamera.h @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE class QThread; -class JCameraWorker; +class JCameraPrivate; class JCamera : public QObject { @@ -175,9 +175,11 @@ Q_SIGNALS: void frameFetched(const QByteArray &frame); private: - JCamera(int cameraId, jobject cam, QThread *workerThread); + JCamera(JCameraPrivate *d, QThread *worker); - JCameraWorker *d; + Q_DECLARE_PRIVATE(JCamera) + JCameraPrivate *d_ptr; + QScopedPointer m_worker; }; QT_END_NAMESPACE From 4c8284de46052970de001c5c9b96c4fa365f89b4 Mon Sep 17 00:00:00 2001 From: Niels Weber Date: Mon, 14 Apr 2014 18:36:40 +0200 Subject: [PATCH 05/38] Rework qmlvideofx example Task-number: QTBUG-38121 Change-Id: If06ba6ce2c66b4d735baaeb56e004861c62ea533 Reviewed-by: Alessandro Portale --- .../multimedia/video/qmlvideofx/Info.plist | 30 ++ .../qmlvideofx/android/AndroidManifest.xml | 48 +++ .../qmlvideofx/images/Dropdown_arrows.png | Bin 0 -> 1156 bytes .../video/qmlvideofx/images/Slider_bar.png | Bin 0 -> 1129 bytes .../video/qmlvideofx/images/Slider_handle.png | Bin 0 -> 2784 bytes .../video/qmlvideofx/images/Triangle_Top.png | Bin 0 -> 2212 bytes .../qmlvideofx/images/Triangle_bottom.png | Bin 0 -> 2125 bytes .../video/qmlvideofx/images/close.png | Bin 1799 -> 0 bytes .../video/qmlvideofx/images/folder.png | Bin 1841 -> 0 bytes .../qmlvideofx/images/icon_BackArrow.png | Bin 0 -> 1268 bytes .../video/qmlvideofx/images/icon_Folder.png | Bin 0 -> 1829 bytes .../video/qmlvideofx/images/icon_Menu.png | Bin 0 -> 990 bytes .../video/qmlvideofx/images/titlebar.png | Bin 1436 -> 0 bytes .../video/qmlvideofx/images/titlebar.sci | 5 - .../multimedia/video/qmlvideofx/images/up.png | Bin 662 -> 0 bytes examples/multimedia/video/qmlvideofx/main.cpp | 16 +- .../qmlvideofx/qml/qmlvideofx/Button.qml | 23 +- .../qmlvideofx/qml/qmlvideofx/Content.qml | 3 +- .../qml/qmlvideofx/ContentImage.qml | 2 +- .../qml/qmlvideofx/ContentVideo.qml | 21 +- .../qmlvideofx/Curtain.qml} | 81 ++-- .../qmlvideofx/qml/qmlvideofx/Divider.qml | 31 +- .../qml/qmlvideofx/EffectBillboard.qml | 2 +- .../qml/qmlvideofx/EffectBlackAndWhite.qml | 2 +- .../qml/qmlvideofx/EffectGaussianBlur.qml | 2 +- .../qml/qmlvideofx/EffectIsolate.qml | 4 +- .../qml/qmlvideofx/EffectMagnify.qml | 4 +- .../qml/qmlvideofx/EffectPageCurl.qml | 2 +- .../qml/qmlvideofx/EffectPixelate.qml | 2 +- .../qml/qmlvideofx/EffectPosterize.qml | 2 +- .../qml/qmlvideofx/EffectRipple.qml | 4 +- ...Detection2.qml => EffectSelectionList.qml} | 37 +- .../qml/qmlvideofx/EffectSelectionPanel.qml | 154 ------- .../qml/qmlvideofx/EffectSharpen.qml | 2 +- .../qml/qmlvideofx/EffectShockwave.qml | 2 +- .../qmlvideofx/EffectSobelEdgeDetection1.qml | 2 +- .../qmlvideofx/qml/qmlvideofx/EffectToon.qml | 2 +- .../qml/qmlvideofx/EffectWobble.qml | 2 +- .../qmlvideofx/qml/qmlvideofx/FileBrowser.qml | 100 ++--- .../qmlvideofx/qml/qmlvideofx/FileOpen.qml | 125 ++++-- .../video/qmlvideofx/qml/qmlvideofx/Main.qml | 287 ++++++++++++ .../qml/qmlvideofx/ParameterPanel.qml | 15 +- .../qmlvideofx/qml/qmlvideofx/Slider.qml | 133 +++--- .../qml/qmlvideofx/main-largescreen.qml | 186 -------- .../qml/qmlvideofx/main-smallscreen.qml | 408 ------------------ .../video/qmlvideofx/qmlvideofx.pro | 12 +- .../video/qmlvideofx/qmlvideofx.qrc | 21 +- 47 files changed, 729 insertions(+), 1043 deletions(-) create mode 100644 examples/multimedia/video/qmlvideofx/Info.plist create mode 100644 examples/multimedia/video/qmlvideofx/android/AndroidManifest.xml create mode 100644 examples/multimedia/video/qmlvideofx/images/Dropdown_arrows.png create mode 100644 examples/multimedia/video/qmlvideofx/images/Slider_bar.png create mode 100644 examples/multimedia/video/qmlvideofx/images/Slider_handle.png create mode 100644 examples/multimedia/video/qmlvideofx/images/Triangle_Top.png create mode 100644 examples/multimedia/video/qmlvideofx/images/Triangle_bottom.png delete mode 100644 examples/multimedia/video/qmlvideofx/images/close.png delete mode 100644 examples/multimedia/video/qmlvideofx/images/folder.png create mode 100644 examples/multimedia/video/qmlvideofx/images/icon_BackArrow.png create mode 100644 examples/multimedia/video/qmlvideofx/images/icon_Folder.png create mode 100644 examples/multimedia/video/qmlvideofx/images/icon_Menu.png delete mode 100644 examples/multimedia/video/qmlvideofx/images/titlebar.png delete mode 100644 examples/multimedia/video/qmlvideofx/images/titlebar.sci delete mode 100644 examples/multimedia/video/qmlvideofx/images/up.png rename examples/multimedia/video/qmlvideofx/{shaders/sobeledgedetection2.fsh => qml/qmlvideofx/Curtain.qml} (57%) rename examples/multimedia/video/qmlvideofx/qml/qmlvideofx/{EffectSobelEdgeDetection2.qml => EffectSelectionList.qml} (56%) delete mode 100644 examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionPanel.qml create mode 100644 examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Main.qml delete mode 100644 examples/multimedia/video/qmlvideofx/qml/qmlvideofx/main-largescreen.qml delete mode 100644 examples/multimedia/video/qmlvideofx/qml/qmlvideofx/main-smallscreen.qml diff --git a/examples/multimedia/video/qmlvideofx/Info.plist b/examples/multimedia/video/qmlvideofx/Info.plist new file mode 100644 index 00000000..8fc24251 --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/Info.plist @@ -0,0 +1,30 @@ + + + + + UISupportedInterfaceOrientations + + UIInterfaceOrientationLandscapeRight + + UIInterfaceOrientation + UIInterfaceOrientationLandscapeRight + CFBundleIconFile + + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleExecutable + qmlvideofx + CFBundleIdentifier + com.digia.${PRODUCT_NAME:rfc1034identifier} + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleName + ${PRODUCT_NAME} + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + + diff --git a/examples/multimedia/video/qmlvideofx/android/AndroidManifest.xml b/examples/multimedia/video/qmlvideofx/android/AndroidManifest.xml new file mode 100644 index 00000000..0612d484 --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/android/AndroidManifest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/multimedia/video/qmlvideofx/images/Dropdown_arrows.png b/examples/multimedia/video/qmlvideofx/images/Dropdown_arrows.png new file mode 100644 index 0000000000000000000000000000000000000000..0a9e25ce27d5270f9c36690b97e06e2f019a4e68 GIT binary patch literal 1156 zcmaJ>TWHi+7*1!j+R}^n%PcI1IM@oEWHOi337vH=nd*Qk<8;IdKA1^P+fb8}CTEW)M5XFJEvO*U2SHD2r~2R+lALpXzVG|5 z$%$Oo?#6mwJw;KC**#*OtWD(ct*#~SXAO=O)rx|hj&6OK8(9}46ASwkV zGY$K-J;N649_}hA!vji8rFZ=TIvjxr=n%`m(T^Cm;Kb=gU4iUfGfRU-2p)*jUxMn9 zav+T?2%=0lpaeM%@I1psqCC&Ffl!bOu|ab40WKm$c_GvemM)rjv(#Q8FLo~ZBBwar zkFhDRY`I)!%3%gseJmG?#axY0C_oSad&t1D6EN&;6$KI6ilv!YLk4gabiG3A!m&fRglMsID)gZJdW+5(! zDWokZV`LQ&I#Q`(t{-7!_ahUeyLr$m$%FxNfNS#jb%fDSusu%4Mx*cL5xK* znQ$taitWsBTqc~1Cfj3tC(kE$rjzZFOob~VrKCdxSGej|E?<@F4uftI&my$6qfqU% zkPa4;7PRWIgsbW;anQulp&+MUw@tVzr(_Cxe z_2|XPu?V>9xiGEXT=?{9#Ck7J-Q73ko%!SS|8wVGX)ES80lsD5^X%_;>JnF*CrT$C z;jI%b$38C9PFx#Zs9Sq#I`Q~=Z))A!6?HEjzW2>}UgfTNX0IncHvTq)a+mI3{O6^A z&2G;-)_?AK?%bc_^MmWxwA8#CY3&;Sb?yE$%*x_HKVM6&4pODd+^U)b)S&xc$Y#34 JGpWPJJ_D)3d(!{_ literal 0 HcmV?d00001 diff --git a/examples/multimedia/video/qmlvideofx/images/Slider_bar.png b/examples/multimedia/video/qmlvideofx/images/Slider_bar.png new file mode 100644 index 0000000000000000000000000000000000000000..84be50fae9eb1a8c9e25b7dd2866977ce956b9d1 GIT binary patch literal 1129 zcmaJ=TWHfz7>@Hc2lE0VIzX^pdV&RlBCuPP5IfVBJ8LC1+dQaxpoz*%Yty zG7<6iq6l7KB8nFfpR6~;hcTI=59&mi`rv~%)S)OSp3HUnU=1Pp&(HsT|Lr^7wbjcC z3yKN|f+&nF=i&r0W*oNj^C#f%yzATU;@>P3NuoNf8KngS5+O-zf*_^{EieuRsbhUF ztRRT7^W{VmCHa-Cs3}gtj&WLwj?n~BvBc5^u?-^71Y2Y^NPf6>lLWF9Bv<=*7q5q5 ztGv9^fOVbK39++H3`pdX#h}7sF@XY+04$|lHCZc24)e0uw%rs7hC@(Wko;X#lCK3} z&49q?^f*KpO#_B;(q13K(2IcEMY|~%ei;YtWql0m_Jfg!#Mum~nT>PNkzDu`BwG>E zS&B-h)6TTVsTnO49S8($4!7HZBOGRjiUiA{n#EZL4w|AN>qypAU^5C$S_%b8Tt7D5KFPio-wk{*%~Dbm)+ZLsLr`B3@i`v7Jh1 z!v++PW+XJNJv+tPRt;%ptEPi+9Ro^vL6lY7Q8tX=c{Zk+NKi!>LFw z0*0Gr<=nM+bMlQ~rQEgna$+f53}vtOuT^JVSU9zu*x{Nwez1EBi1(IMU3$A%xbWsNmuU2N=7-OOE`#}=%daLbeVT4J0{o_{y6N-ZktKYHcP k9wPJcRi->G-g`~mB1$dz>% literal 0 HcmV?d00001 diff --git a/examples/multimedia/video/qmlvideofx/images/Slider_handle.png b/examples/multimedia/video/qmlvideofx/images/Slider_handle.png new file mode 100644 index 0000000000000000000000000000000000000000..aebecdf19812d0701549d2831b2cb0f9e3ca0233 GIT binary patch literal 2784 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 VOYLgpA~ydy?QNV$x2)->{sW`9vPb{` literal 0 HcmV?d00001 diff --git a/examples/multimedia/video/qmlvideofx/images/Triangle_Top.png b/examples/multimedia/video/qmlvideofx/images/Triangle_Top.png new file mode 100644 index 0000000000000000000000000000000000000000..5768e953618f2b7ee3ca72de44bcf9eaf4536ae0 GIT binary patch literal 2212 zcmaJ@eK=HUA0GK8ktnh07$u4sgBfO+G-JkR<8wrzcFY`RWaf;SBSWgCh_`&NY(7#d z=_(X&s7Xz1g(b3*3Cm*Jq!QPrwiWN0HtqYz>pj;w=Xsvr^}Fxi*Zs$n>F?{Iqh+jx zLZNiLJZXW*ia|b04K?JSGTOEkS=Ph!P&f#Rf)iLG5JllYks#p3XGMd7Ad8b2*ABX% zP|BNl%uqO#v6IAx_!ySL2P5GN5i|2k(0wnxcftVyAqd)VKkiEi;MFXE*;QeIu z-${is`~f#e1Oj-By$#zIhXV)%49)>hAmFS4J6oI`))sjQHaG_ooh$Y?GM3rSdPLP7#2!5#yNqOmw4k*MIXv$H`wY{ZEIm?g0hh|QN6XrP!a z;t63MBmfkQtVk#xCZmx||1N(jay`9~8h#Sk6CK!m?O}82CaYG7S{*4uBkY5yS^R7fs?VpNsvnd|$Af<#TaZ z7K=ra!74`kU!z_!A^K5lzX}&Qe3d>ZK=dv`g#F8^25%Hfb*&eT!jwGg43!Ja=?2wr z=18UweItpd@ZKmT>IzL5U!`KG&|<;Fm>SYDda&52>zWfuBS_Q7 zQfBG$nCsx=>bjWnbn1}b(|1KL&KSMsmQ>!9$K1FRzGu(Jrcmqt7p5siXPYxdTUuH? ziYuE(VhQw1Kd&CQUD>L)z1%PK)Vubvv9aS#^wF?<{lhe)(}x>(UCBHkWvqFK*3f35 zV~^!sH_q>dSDVH3OvIU-Y;QHvyi&7`srhSH|4bBHz0`I!p`|Sp9}%~v`_ZFEXom5+ z;x=ICv8?(UpV3~?vq_i~j49e!VDtdgTiZe#7zog~vbp(L>yRd^cXDWG$XPE97jvgI zKW$_hs=j(Pxu5IM+w@K)fZC^X@k8m+hbm;FmF`e&!9i8f$oSgifQZf)9$uLVkMZ^K}`s3E^+-KiE~6)mKM_uPWHW{J^L$DJjwIDJ%1@7jMup ztfnJ8C(lKy58I5-T`ku(JPmEq&vbm-6OC!h%F2=!dT)Nh$Zh`4=j}S1X}Ns&HvP;_ zYSm0Mn8P_D%|)OsTROgm1BiIr^kvV7naB}keaYk;JK>o(USL$Cf-%m^$n46pH=4#dn zv}j2`kZMpe&GHUA5P` zN9%ZNBhdHbweU-^Y~^__1Wg}2uzI)IR0uezDGaXKu5m--V6us<`Dm(#vPVEzM8qe9 zV)^sf0;oK~!t;`BaSPLWB1KyT=qplJ^_9D)&Ev|u7u!=i=kzDe%E~)PE{&-cukcRP z0V_$}-K6F-l1_kU3lc9{va!>&7{?nYh7t=?;} zUae_!*gosnbm}=8pyxSP65l~kxhaxJJ}5{3rKw%_SeO2BW=3$<`Sy<84R@qc>HB+s zZq2OTNa+p#xbY%bShnxdNUUytoHOWIrG`rUHm~-N4w8~b+We~ZN7@Y9MYY3l{%cms zPmAv>N}S6|OOp-nZxR`D{ijfdvo*c6h*xGCr1>V*=>{+R`uc*YcuHQa?ez6PGruy8 zUYk+BU?%G2jtg<=|T%u2$L3i)~GHKQDxQr-W)) Wn>By4>VAdd-rz;|rPWZsP5lqF0Fg5Q literal 0 HcmV?d00001 diff --git a/examples/multimedia/video/qmlvideofx/images/Triangle_bottom.png b/examples/multimedia/video/qmlvideofx/images/Triangle_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..50940966662cf4ddb032f0d6ab79870c29434321 GIT binary patch literal 2125 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 diff --git a/examples/multimedia/video/qmlvideofx/images/folder.png b/examples/multimedia/video/qmlvideofx/images/folder.png deleted file mode 100644 index e53e2ad464eb993256a6c3567fc940498e26fc8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1841 zcmV-12hRA3P)9|L49p`#xU4GZ@fvQeveOhMvleo>008ifO8IGNhL6l< z{aUZrfA(%cEtd36rDb`~5h&i@?>h4N=Z>SC^MS7v0Pr3AhPvW{!YtC8Kp67{Yezaio**gBp{PBs5AnA1STdDNvaJP%raE3$dUQ|HILYASttAYhF-m+ z1X3^@i%$v6MXS}KsHp7LSdt_-oeqrph9OBFgo7@S-~zFD(&qs{5P`b-Jf+v;->=iD z|3%Z=kcgH7c&w;6`{x#mRh652Kgvq0(9qC`^78U|1I{KAiNHDFfZKBeLCJ$~#D!?$ z1{k|@LBoR*j{ND=2mw$P6l5RTw5iFSo0q0EnKh!>tc4^+;JP`6D_2~&bZG#qn_AG; z_Bhhh(-$NI0MTd^gM&_txSR+C+>pXI5s3~06b1mixaYW+Y&Oeldw%`YHdA_tO*hV5 z5^)iizi{LI6Bkfjy$U;b{uFApdch*o#9}cx9DO*~{TFcN!H%aph8bf*tHC_~%K?B1 zF%%XV@#AM2q1Cz3`p_D@@=816@%d|=3{ezeu`EF>sz7jD1ULs9^N)3Y+I@LJ0f-VP zt4znv-Rm$k@+q2|>(SZSnUaJc2p|#=i^ajg!CW`}`~LdoC!UmohzUHn%8DJk*Q2ZJ zD89L-5e|nVbpZ}A&Ux>3hs!fICZ)6z08pwpS~lA7#FO=S;>oQza^!GI0ssdCfKWKP z|NRp^;gk)gNXw96=WaXx+5Ils+8#qF6q@&5A_72&#S-8g!~h@|2p@X)*!i*lRsaBq zMX{l^01Zt`v96^Ny}iBj-pfcpJU-d<3;;Oi{>VhE`|=k<_u_y=A_i+V!?VBmHlBZB z7uwrjPA*Gqst2Y@003^6fA8CGrPhq|A;^OG!H=5J*LMzk_wGq%fcRtyW&}9rU6(En z2EFbG5{WxcNvSds^`rG$r5GOW#leFIZkwAa!K@4bKp+t6xbo#qIIo4^aZMmP&tGk! zL?!}wcuNh=fA#@7JO4H#z@`Q0c7gHn(2Kv_cl5Kvhd<Kj7jHJ9 zuov4NZN#y6-oU9-T>vJx;-m<>{XD=q_XDURqKq?VF8;2tFlV!UL#>dPYk^G8pf`%p z>O>HwCJ~TsVEf}O*tKH^y1G7rD9WY;h|N6@OpCYxY#}1*>ACuh&6f4cRSl)u2Oe0C zQI80nUWDEtLJ${j5)2KXq%<4d-QBk`K*T`Fj^)W9qLmq$hJ)2r1^2IOsUfXK4UJBO z-Y7z$U|$^ofb+T^AALBCt=k^K$*#9?sN)@1(hMYnbAA@Uaw0OFJlV6qxH$K_>+Q9| z((J`hC>ab!8PrExm=j+6TJw= zl9%VqX$OV|WiXm!c;mJA-1j6fOQb3z)6h{@TUfewT{UUcD(LhgbVeCuvfD)>;W+-# zei}ukIr!u2C%ztmSt5F+Qub0=`F)St*Vl?xYbMm1$*d?Pll()iNj)lMSoUiEv&Y$M4(!4!6tiUT_np3g`R)fCEHSws^6rqpq&7 za?P4*QmYlvXq7OTwD5Yy>3^1ixe$?7rIzojD9_(+x7Uiku^|3@_+vjf=l}PMh`wjD fEpp4{;>3Rd&!+YNzwAbe00000NkvXXu0mjfMH*<- diff --git a/examples/multimedia/video/qmlvideofx/images/icon_BackArrow.png b/examples/multimedia/video/qmlvideofx/images/icon_BackArrow.png new file mode 100644 index 0000000000000000000000000000000000000000..6823de0040faa2b40088178f9de0aaa2a33f4ee9 GIT binary patch literal 1268 zcmeAS@N?(olHy`uVBq!ia0vp^LO?9T!3HFAj=Wa~Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS=07?@QuLn2Bde0{8v^Kf6`()~Xj@TAnpKdC8`Lf!&sHg;q@=(~U%$M( zT(8_%FTW^V-_X+15@d#vkuFe$ZgFK^Nn(X=Ua>OF1ees}+T7#d8#0MoBXEYLU9GXQxBrqI_HztY@Xxa#7Ppj3o=u^L<)Qdy9y zACy|0Us{w5jJPyqkW~d%&PAz-CHX}m`T04pPz=b(FUc>?$S+WE4mMNJ@J&q4%mWE% zf_3=%T6yLbmn7yTr+T{BDgn*V%gju%aP^Az77Ltu^?{Dj2SqJXRKtXT=?BDwCtM&0p7c}mfa$#mn6UdBzjZM%Fs6CBIEGZ* zS~GROm$RWr`(DGQ1?R4rZ+N65vSvm8gZW?fGn%#QS}+KIuEBnAvb~;U`Nsi%k*|0eOlwSa_!rIo8bZ;=T@q0$a;AATeJNhA+d{% zOSE3}v5GZmo%#~&yYAQulP7Xn8)tAcajww`UlQ}9>qOXm4&xU-LEbN>u`X-YIu-JK z{={qbdzaNIF8#fC_2Ww2OWT*5asFNR_36j+m78n2dwz&%{)tVt&Mn;f_^!F3xaf_= e2hP>ANHDZN+w`o>Y1uwdIppc;=d#Wzp$P!%^~9C{ literal 0 HcmV?d00001 diff --git a/examples/multimedia/video/qmlvideofx/images/icon_Folder.png b/examples/multimedia/video/qmlvideofx/images/icon_Folder.png new file mode 100644 index 0000000000000000000000000000000000000000..62d97004fb01e085c3060619ac68dbec2fa7e8aa GIT binary patch literal 1829 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 diff --git a/examples/multimedia/video/qmlvideofx/main.cpp b/examples/multimedia/video/qmlvideofx/main.cpp index 7465deab..f221c954 100644 --- a/examples/multimedia/video/qmlvideofx/main.cpp +++ b/examples/multimedia/video/qmlvideofx/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -48,12 +48,6 @@ #include "filereader.h" #include "trace.h" -#ifdef SMALL_SCREEN_LAYOUT - static const QLatin1String MainQmlFile("main-smallscreen.qml"); -#else - static const QLatin1String MainQmlFile("main-largescreen.qml"); -#endif - #ifdef PERFORMANCEMONITOR_SUPPORT #include "performancemonitordeclarative.h" #endif @@ -99,7 +93,7 @@ int main(int argc, char *argv[]) QQuickView viewer; - viewer.setSource(QLatin1String("qrc:///qml/qmlvideofx/") + MainQmlFile); + viewer.setSource(QUrl(QLatin1String("qrc:///qml/qmlvideofx/Main.qml"))); QQuickItem *rootObject = viewer.rootObject(); rootObject->setProperty("fileName", fileName); viewer.rootObject()->setProperty("volume", volume); @@ -128,13 +122,9 @@ int main(int argc, char *argv[]) viewer.setTitle("qmlvideofx"); viewer.setFlags(Qt::Window | Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); - viewer.setMinimumSize(QSize(600, 400)); + viewer.setMinimumSize(QSize(640, 360)); -#ifdef SMALL_SCREEN_PHYSICAL - viewer.showFullScreen(); -#else viewer.show(); -#endif // Delay invocation of init until the event loop has started, to work around // a GL context issue on Harmattan: without this, we get the following error diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Button.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Button.qml index eb82acee..dd7cca60 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Button.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Button.qml @@ -43,29 +43,33 @@ import QtQuick 2.0 Rectangle { id: root - color: textColor - radius: 0.25 * height + color: "transparent" + height: itemHeight + width: itemWidth property string text - property color bgColor: "white" - property color bgColorSelected: "red" - property color textColor: "black" + property color bgColor: "transparent" + property color bgColorSelected: "#14aaff" + property color textColor: "white" property alias enabled: mouseArea.enabled + property bool active: true + property alias horizontalAlign: text.horizontalAlignment signal clicked Rectangle { anchors { fill: parent; margins: 1 } color: mouseArea.pressed ? bgColorSelected : bgColor - radius: 0.25 * height + radius: 0.1 * height Text { id: text - anchors.centerIn: parent + clip: true text: root.text - font.pixelSize: 0.5 * parent.height + anchors { fill: parent; margins: scaledMargin } + font.pixelSize: fontSize color: mouseArea.pressed ? bgColor : textColor - horizontalAlignment: Text.AlignHCenter + horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter } @@ -75,6 +79,7 @@ Rectangle { onClicked: { root.clicked() } + enabled: active } } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Content.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Content.qml index d3a2e9f4..72b7cca7 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Content.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Content.qml @@ -39,11 +39,10 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 Rectangle { id: root - color: "black" property alias effect: effectLoader.item property alias gripSize: divider.gripSize property string effectSource diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentImage.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentImage.qml index 0fa047bb..2bce20bf 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentImage.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentImage.qml @@ -39,7 +39,7 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 Image { fillMode: Image.PreserveAspectFit diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentVideo.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentVideo.qml index be09f7ea..6491ceff 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentVideo.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ContentVideo.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -39,13 +39,14 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 import QtMultimedia 5.0 VideoOutput { source: mediaPlayer property alias mediaSource: mediaPlayer.source property alias volume: mediaPlayer.volume + property bool isRunning: true MediaPlayer { id: mediaPlayer @@ -55,5 +56,21 @@ VideoOutput { } function play() { mediaPlayer.play() } + function pause() { mediaPlayer.pause() } function stop() { mediaPlayer.stop() } + + function toggleplay() { + if (isRunning) { + pause() + isRunning = false + } else { + play() + isRunning = true + } + } + + MouseArea { + anchors.fill: parent + onClicked: toggleplay() + } } diff --git a/examples/multimedia/video/qmlvideofx/shaders/sobeledgedetection2.fsh b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Curtain.qml similarity index 57% rename from examples/multimedia/video/qmlvideofx/shaders/sobeledgedetection2.fsh rename to examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Curtain.qml index 039a567d..253e3c39 100644 --- a/examples/multimedia/video/qmlvideofx/shaders/sobeledgedetection2.fsh +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Curtain.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -39,39 +39,56 @@ ** ****************************************************************************/ -// Based on http://rastergrid.com/blog/downloads/frei-chen-edge-detector/ +import QtQuick 2.0 -#version 130 -uniform sampler2D source; -uniform float dividerValue; -uniform float weight; -mat3 G[2] = mat3[]( - mat3( 1.0, 2.0, 1.0, 0.0, 0.0, 0.0, -1.0, -2.0, -1.0 ), - mat3( 1.0, 0.0, -1.0, 2.0, 0.0, -2.0, 1.0, 0.0, -1.0 ) -); -uniform lowp float qt_Opacity; -in vec2 qt_TexCoord0; -out vec4 FragmentColor; -void main() { - vec2 uv = qt_TexCoord0.xy; - vec4 c = vec4(0.0); - if (uv.x < dividerValue) { - mat3 intensity; - float conv[2]; - vec3 sample; - for (int i=0; i<3; ++i) { - for (int j=0; j<3; ++j) { - sample = texelFetch(source, ivec2(gl_FragCoord) + ivec2(i-1, j-1), 0).rgb; - intensity[i][j] = length(sample) * weight; +Rectangle { + id: root + color: "transparent" + radius: 5 + property alias value: grip.value + property color gripColor: "transparent" + property real gripSize: 20 + property real gripTolerance: 3.0 + property real increment: 0.1 + property bool enabled: true + property string imageSource: "qrc:/images/Triangle_Top.png" + + Rectangle { + id: grip + property real value: 0.5 + x: (value * parent.width) - width/2 + anchors.verticalCenter: parent.verticalCenter + width: root.gripTolerance * root.gripSize + height: width + radius: width/2 + color: "transparent" + + Image { + id: sliderhandleimage + source: imageSource + anchors.centerIn: parent + } + + MouseArea { + id: mouseArea + enabled: root.enabled + anchors.fill: parent + drag { + target: grip + axis: Drag.XAxis + minimumX: -parent.width/2 + maximumX: root.width - parent.width/2 + } + onPositionChanged: { + if (drag.active) + updatePosition() + } + onReleased: { + updatePosition() + } + function updatePosition() { + value = (grip.x + grip.width/2) / grip.parent.width } } - for (int i=0; i<2; ++i) { - float dp3 = dot(G[i][0], intensity[0]) + dot(G[i][1], intensity[1]) + dot(G[i][2], intensity[2]); - conv[i] = dp3 * dp3; - } - c = vec4(0.5 * sqrt(conv[0]*conv[0] + conv[1]*conv[1])); - } else { - c = texture2D(source, qt_TexCoord0); } - FragmentColor = qt_Opacity * c; } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Divider.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Divider.qml index 390818bb..45c2606f 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Divider.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Divider.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -39,7 +39,7 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 Rectangle { id: root @@ -53,21 +53,34 @@ Rectangle { id: line anchors { top: parent.top; bottom: parent.bottom } x: parent.value * parent.width - (width / 2) - width: 2 - color: "red" + width: 4 + color: "#14aaff" } - Slider { + // topgrip + Curtain { id: slider increment: 0.0 - lineColor: "transparent" - fillColor: "transparent" - gripColor: "red" anchors { top: parent.top - topMargin: gripSize / 2 + topMargin: (gripSize / 2) + 5 left: parent.left right: parent.right } + onValueChanged: slider2.value = slider.value + } + + // bottomgrip + Curtain { + id: slider2 + increment: 0.0 + anchors { + bottom: parent.bottom + bottomMargin: (gripSize / 2) + 5 + left: parent.left + right: parent.right + } + imageSource: "qrc:/images/Triangle_bottom.png" + onValueChanged: slider.value = slider2.value } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBillboard.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBillboard.qml index 4e3adc3e..1e207724 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBillboard.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBillboard.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "grid spacing" + name: "Grid Spacing" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBlackAndWhite.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBlackAndWhite.qml index 5e37c70c..85f2abc7 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBlackAndWhite.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectBlackAndWhite.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "threshold" + name: "Threshold" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectGaussianBlur.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectGaussianBlur.qml index 00fab044..f0cad528 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectGaussianBlur.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectGaussianBlur.qml @@ -49,7 +49,7 @@ Item { property real dividerValue: 0.5 property ListModel parameters: ListModel { ListElement { - name: "radius" + name: "Radius" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectIsolate.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectIsolate.qml index f3650419..80c7ccae 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectIsolate.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectIsolate.qml @@ -44,11 +44,11 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "hue" + name: "Hue" value: 0.5 } ListElement { - name: "width" + name: "Width" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectMagnify.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectMagnify.qml index d93e72c9..3fd35eaa 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectMagnify.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectMagnify.qml @@ -46,11 +46,11 @@ Effect { divider: false parameters: ListModel { ListElement { - name: "radius" + name: "Radius" value: 0.5 } ListElement { - name: "diffraction" + name: "Diffraction" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPageCurl.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPageCurl.qml index e4fc1f78..c035b9b6 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPageCurl.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPageCurl.qml @@ -45,7 +45,7 @@ Effect { divider: false parameters: ListModel { ListElement { - name: "extent" + name: "Extent" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPixelate.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPixelate.qml index 002a74a4..7a0f2198 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPixelate.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPixelate.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "granularity" + name: "Granularity" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPosterize.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPosterize.qml index bda47376..084b28c1 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPosterize.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectPosterize.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "gamma" + name: "Gamma" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectRipple.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectRipple.qml index 7932b4c1..e0a2b022 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectRipple.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectRipple.qml @@ -44,11 +44,11 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "amplitude" + name: "Amplitude" value: 0.5 } ListElement { - name: "frequency" + name: "Frequency" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSobelEdgeDetection2.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionList.qml similarity index 56% rename from examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSobelEdgeDetection2.qml rename to examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionList.qml index 33336537..fa92bb7c 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSobelEdgeDetection2.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionList.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -41,16 +41,27 @@ import QtQuick 2.0 -Effect { - parameters: ListModel { - ListElement { - name: "threshold" - value: 0.5 - } - } - - // Transform slider values, and bind result to shader uniforms - property real weight: parameters.get(0).value - - fragmentShaderFilename: "sobeledgedetection2.fsh" +ListModel { + id: sources + ListElement { name: "No effect"; source: "EffectPassThrough.qml" } + ListElement { name: "Billboard"; source: "EffectBillboard.qml" } + ListElement { name: "Black & white"; source: "EffectBlackAndWhite.qml" } + ListElement { name: "Blur"; source: "EffectGaussianBlur.qml" } + ListElement { name: "Edge detection"; source: "EffectSobelEdgeDetection1.qml" } + ListElement { name: "Emboss"; source: "EffectEmboss.qml" } + ListElement { name: "Glow"; source: "EffectGlow.qml" } + ListElement { name: "Isolate"; source: "EffectIsolate.qml" } + //ListElement { name: "Magnify"; source: "EffectMagnify.qml" } + ListElement { name: "Page curl"; source: "EffectPageCurl.qml" } + ListElement { name: "Pixelate"; source: "EffectPixelate.qml" } + ListElement { name: "Posterize"; source: "EffectPosterize.qml" } + ListElement { name: "Ripple"; source: "EffectRipple.qml" } + ListElement { name: "Sepia"; source: "EffectSepia.qml" } + ListElement { name: "Sharpen"; source: "EffectSharpen.qml" } + ListElement { name: "Shockwave"; source: "EffectShockwave.qml" } + ListElement { name: "Tilt shift"; source: "EffectTiltShift.qml" } + ListElement { name: "Toon"; source: "EffectToon.qml" } + ListElement { name: "Warhol"; source: "EffectWarhol.qml" } + ListElement { name: "Wobble"; source: "EffectWobble.qml" } + ListElement { name: "Vignette"; source: "EffectVignette.qml" } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionPanel.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionPanel.qml deleted file mode 100644 index 948a4e88..00000000 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSelectionPanel.qml +++ /dev/null @@ -1,154 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Mobility Components. -** -** $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$ -** -****************************************************************************/ -import QtQuick 2.0 - -Rectangle { - id: root - property int itemHeight: 25 - property string effectSource: "" - - signal clicked - - QtObject { - id: d - property Item selectedItem - } - - ListModel { - id: sources - ListElement { name: "No effect"; source: "EffectPassThrough.qml" } - ListElement { name: "Billboard"; source: "EffectBillboard.qml" } - ListElement { name: "Black & white"; source: "EffectBlackAndWhite.qml" } - ListElement { name: "Blur"; source: "EffectGaussianBlur.qml" } - ListElement { name: "Edge detection"; source: "EffectSobelEdgeDetection1.qml" } - //ListElement { name: "Edge detection (Sobel, #2)"; source: "EffectSobelEdgeDetection2.qml" } - ListElement { name: "Emboss"; source: "EffectEmboss.qml" } - ListElement { name: "Glow"; source: "EffectGlow.qml" } - ListElement { name: "Isolate"; source: "EffectIsolate.qml" } - ListElement { name: "Magnify"; source: "EffectMagnify.qml" } - ListElement { name: "Page curl"; source: "EffectPageCurl.qml" } - ListElement { name: "Pixelate"; source: "EffectPixelate.qml" } - ListElement { name: "Posterize"; source: "EffectPosterize.qml" } - ListElement { name: "Ripple"; source: "EffectRipple.qml" } - ListElement { name: "Sepia"; source: "EffectSepia.qml" } - ListElement { name: "Sharpen"; source: "EffectSharpen.qml" } - ListElement { name: "Shockwave"; source: "EffectShockwave.qml" } - ListElement { name: "Tilt shift"; source: "EffectTiltShift.qml" } - ListElement { name: "Toon"; source: "EffectToon.qml" } - ListElement { name: "Warhol"; source: "EffectWarhol.qml" } - ListElement { name: "Wobble"; source: "EffectWobble.qml" } - ListElement { name: "Vignette"; source: "EffectVignette.qml" } - } - - Component { - id: sourceDelegate - Item { - id: sourceDelegateItem - width: root.width - height: itemHeight - - Button { - id: sourceSelectorItem - anchors.centerIn: parent - width: 0.9 * parent.width - height: 0.8 * itemHeight - text: name - onClicked: { - if (d.selectedItem) - d.selectedItem.state = "baseState" - d.selectedItem = sourceDelegateItem - d.selectedItem.state = "selected" - effectSource = source - root.clicked() - } - } - - states: [ - State { - name: "selected" - PropertyChanges { - target: sourceSelectorItem - bgColor: "#ff8888" - } - } - ] - - Component.onCompleted: { - if (name == "No effect") { - state = "selected" - d.selectedItem = sourceDelegateItem - } - } - - transitions: [ - Transition { - from: "*" - to: "*" - ColorAnimation { - properties: "color" - easing.type: Easing.OutQuart - duration: 500 - } - } - ] - } - } - - Flickable { - anchors.fill: parent - contentHeight: (itemHeight * sources.count) + layout.anchors.topMargin + layout.spacing - clip: true - - Column { - id: layout - - anchors { - fill: parent - topMargin: 10 - } - - Repeater { - model: sources - delegate: sourceDelegate - } - } - } -} diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSharpen.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSharpen.qml index 25215980..f59544dc 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSharpen.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSharpen.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "sharpness" + name: "Sharpness" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectShockwave.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectShockwave.qml index 0e1b1785..746445b4 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectShockwave.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectShockwave.qml @@ -45,7 +45,7 @@ Effect { id: root parameters: ListModel { ListElement { - name: "amplitude" + name: "Amplitude" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSobelEdgeDetection1.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSobelEdgeDetection1.qml index 6724a844..7b03dbfd 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSobelEdgeDetection1.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectSobelEdgeDetection1.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "threshold" + name: "Threshold" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectToon.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectToon.qml index ff985e56..ecba4062 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectToon.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectToon.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "threshold" + name: "Threshold" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectWobble.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectWobble.qml index 97e7c061..aa07c1a6 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectWobble.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/EffectWobble.qml @@ -44,7 +44,7 @@ import QtQuick 2.0 Effect { parameters: ListModel { ListElement { - name: "amplitude" + name: "Amplitude" value: 0.5 } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileBrowser.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileBrowser.qml index 7c861036..c75b6f25 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileBrowser.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileBrowser.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -39,12 +39,13 @@ ** ****************************************************************************/ -import QtQuick 2.0 -import Qt.labs.folderlistmodel 2.0 +import QtQuick 2.1 +import Qt.labs.folderlistmodel 2.1 Rectangle { id: fileBrowser color: "transparent" + z: 4 property string folder property bool shown: loader.sourceComponent @@ -75,12 +76,12 @@ Rectangle { Rectangle { id: root - color: "white" + color: "black" property bool showFocusHighlight: false property variant folders: folders1 property variant view: view1 property alias folder: folders1.folder - property color textColor: "black" + property color textColor: "white" FolderListModel { id: folders1 @@ -112,7 +113,7 @@ Rectangle { fileBrowser.selectFile(path) } width: root.width - height: 52 + height: itemHeight color: "transparent" Rectangle { @@ -126,10 +127,12 @@ Rectangle { } Item { - width: 48; height: 48 + width: itemHeight; height: itemHeight Image { - source: "qrc:/images/folder.png" - anchors.centerIn: parent + source: "qrc:/images/icon_Folder.png" + fillMode: Image.PreserveAspectFit + anchors.fill: parent + anchors.margins: scaledMargin visible: folders.isFolder(index) } } @@ -138,8 +141,8 @@ Rectangle { id: nameText anchors.fill: parent; verticalAlignment: Text.AlignVCenter text: fileName - anchors.leftMargin: 54 - font.pixelSize: 32 + anchors.leftMargin: itemHeight + scaledMargin + font.pixelSize: fontSize color: (wrapper.ListView.isCurrentItem && root.showFocusHighlight) ? palette.highlightedText : textColor elide: Text.ElideRight } @@ -262,56 +265,45 @@ Rectangle { Keys.onPressed: root.keyPressed(event.key) } - Rectangle { + Button { id: cancelButton - width: 100 - height: titleBar.height - 7 - color: "black" - anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter } - - Text { - anchors { fill: parent; margins: 4 } - text: "Cancel" - color: "white" - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - font.pixelSize: 20 - } - - MouseArea { - anchors.fill: parent - onClicked: fileBrowser.selectFile("") - } + width: itemWidth + height: itemHeight + color: "#353535" + anchors { bottom: parent.bottom; right: parent.right; margins: 5 * scaledMargin } + text: "Cancel" + horizontalAlign: Text.AlignHCenter + onClicked: fileBrowser.selectFile("") } Keys.onPressed: { root.keyPressed(event.key); - if (event.key == Qt.Key_Return || event.key == Qt.Key_Select || event.key == Qt.Key_Right) { + if (event.key === Qt.Key_Return || event.key === Qt.Key_Select || event.key === Qt.Key_Right) { view.currentItem.launch(); event.accepted = true; - } else if (event.key == Qt.Key_Left) { + } else if (event.key === Qt.Key_Left) { up(); } } - BorderImage { - source: "qrc:/images/titlebar.sci"; + // titlebar + Rectangle { + color: "black" width: parent.width; - height: 52 - y: -7 + height: itemHeight id: titleBar Rectangle { id: upButton - width: 48 - height: titleBar.height - 7 + width: titleBar.height + height: titleBar.height color: "transparent" - Image { anchors.centerIn: parent; source: "qrc:/images/up.png" } - MouseArea { id: upRegion; anchors.centerIn: parent - width: 56 - height: 56 - onClicked: up() - } + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + anchors.margins: scaledMargin + + Image { anchors.fill: parent; anchors.margins: scaledMargin; source: "qrc:/images/icon_BackArrow.png" } + MouseArea { id: upRegion; anchors.fill: parent; onClicked: up() } states: [ State { name: "pressed" @@ -321,23 +313,23 @@ Rectangle { ] } - Rectangle { - color: "gray" - x: 48 - width: 1 - height: 44 - } - Text { anchors.left: upButton.right; anchors.right: parent.right; height: parent.height - anchors.leftMargin: 4; anchors.rightMargin: 4 + anchors.leftMargin: 10; anchors.rightMargin: 4 text: folders.folder color: "white" - elide: Text.ElideLeft; horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignVCenter - font.pixelSize: 32 + elide: Text.ElideLeft; horizontalAlignment: Text.AlignLeft; verticalAlignment: Text.AlignVCenter + font.pixelSize: fontSize } } + Rectangle { + color: "#353535" + width: parent.width + height: 1 + anchors.top: titleBar.bottom + } + function down(path) { if (folders == folders1) { view = view2 diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileOpen.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileOpen.qml index 716f4165..b0542cb8 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileOpen.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileOpen.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -39,56 +39,95 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 Rectangle { id: root - color: "white" - property int buttonHeight: 35 - property int topMargin: 0 - + color: "#151515" + signal openCamera signal openImage signal openVideo - signal openCamera signal close - Rectangle { - anchors { - top: parent.top; - topMargin: root.topMargin - bottom: parent.bottom; - horizontalCenter: parent.horizontalCenter + Column { + anchors.fill: parent + spacing: 10 + Rectangle { + height: itemHeight + width: itemHeight + color: "transparent" + anchors.right: parent.right + Image { + id: menu + source: "qrc:///images/icon_Menu.png" + anchors { + right: parent.right + top: parent.top + margins: scaledMargin + } + } + MouseArea { + anchors.fill: parent + onClicked: fileOpen.state == "expanded" ? fileOpen.state = "collapsed" : fileOpen.state = "expanded" + } } - width: 0.9 * parent.width - color: "transparent" - - Column { - anchors.fill: parent - spacing: 5 - Button { - text: "Open image" - height: buttonHeight - width: parent.width - onClicked: root.openImage() - } - Button { - text: "Open video" - height: buttonHeight - width: parent.width - onClicked: root.openVideo() - } - Button { - text: "Start camera" - height: buttonHeight - width: parent.width - onClicked: root.openCamera() - } - Button { - text: "Reset" - height: buttonHeight - width: parent.width - onClicked: root.close() - } + Rectangle { + width: 0.9 * parent.width + height: 1 + color: "#353535" + anchors.left: parent.left + } + Button { + text: "Start camera" + height: itemHeight + width: parent.width + onClicked: root.openCamera() + active: fileOpen.state == "expanded" + } + Rectangle { + width: 0.9 * parent.width + height: 1 + color: "#353535" + anchors.left: parent.left + } + Button { + text: "Open image" + height: itemHeight + width: parent.width + onClicked: root.openImage() + active: fileOpen.state == "expanded" + } + Rectangle { + width: 0.9 * parent.width + height: 1 + color: "#353535" + anchors.left: parent.left + } + Button { + text: "Open video" + height: itemHeight + width: parent.width + onClicked: root.openVideo() + active: fileOpen.state == "expanded" + } + Rectangle { + width: 0.9 * parent.width + height: 1 + color: "#353535" + anchors.left: parent.left + } + Button { + text: "Reset" + height: itemHeight + width: parent.width + onClicked: root.close() + active: fileOpen.state == "expanded" + } + Rectangle { + width: 0.9 * parent.width + height: 1 + color: "#353535" + anchors.left: parent.left } } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Main.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Main.qml new file mode 100644 index 00000000..5ec13750 --- /dev/null +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Main.qml @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Window 2.1 + +Rectangle { + id: root + color: "black" + property string fileName + property alias volume: content.volume + property bool perfMonitorsLogging: false + property bool perfMonitorsVisible: false + property int pixDens: Math.ceil(Screen.pixelDensity) + property int itemWidth: 25 * pixDens + property int itemHeight: 10 * pixDens + property int windowWidth: Screen.desktopAvailableWidth + property int windowHeight: Screen.desktopAvailableHeight + property int scaledMargin: 2 * pixDens + property int fontSize: 5 * pixDens + + QtObject { + id: d + property real gripSize: 20 + } + + Content { + id: content + color: "transparent" + anchors { + top: parent.top + left: parent.left + right: parent.right + bottom: parameterPanel.top + margins: scaledMargin + leftMargin: scaledMargin + itemHeight + } + gripSize: d.gripSize + } + + ParameterPanel { + id: parameterPanel + anchors { + left: parent.left + right: listview.left + bottom: parent.bottom + margins: scaledMargin + leftMargin: scaledMargin + itemHeight + } + gripSize: d.gripSize + height: root.itemHeight * 2.5 + width: root.itemWidth * 3 + + } + + + Button { + id: effectName + anchors { + right: parent.right + bottom: perfHolder.top + top: content.bottom + margins: scaledMargin + } + + text: "No effect" + width: itemWidth * 2 + onClicked: { + effectName.visible = false + listview.visible = true + } + color: "#303030" + } + + + ListView { + id: listview + width: itemWidth * 2 + anchors { + right: parent.right + bottom: perfHolder.top + top: parent.top + margins: scaledMargin + } + visible: false + + model: EffectSelectionList {} + delegate: effectDelegate + + highlight: Rectangle { color: "#14aaff"; radius: 5 } + highlightFollowsCurrentItem: true + highlightRangeMode: ListView.StrictlyEnforceRange + clip: true + focus: true + + Component { + id: effectDelegate + Button { + text: name + width: itemWidth * 2 + onClicked: { + content.effectSource = source + listview.visible = false + effectName.text = name + effectName.visible = true + parameterPanel.model = content.effect.parameters + + } + } + } + } + + Rectangle { + id: perfHolder + color: "transparent" + anchors { + right: parent.right + bottom: parent.bottom + margins: scaledMargin + } + height: root.itemHeight * 1.5 + width: root.itemWidth + + Loader { + id: performanceLoader + function init() { + console.log("[qmlvideofx] performanceLoader.init logging " + root.perfMonitorsLogging + " visible " + root.perfMonitorsVisible) + var enabled = root.perfMonitorsLogging || root.perfMonitorsVisible + source = enabled ? "../performancemonitor/PerformanceItem.qml" : "" + } + onLoaded: { + item.parent = perfHolder + item.anchors.top = perfHolder.top + item.anchors.bottom = perfHolder.bottom + item.anchors.left = perfHolder.left + item.anchors.right = perfHolder.right + item.logging = root.perfMonitorsLogging + item.displayed = root.perfMonitorsVisible + item.init() + } + } + } + + FileOpen { + id: fileOpen + state: "collapsed" + anchors { + left: parent.left + top: parent.top + bottom: parent.bottom + margins: scaledMargin + } + width: itemHeight + scaledMargin + z: 2 + opacity: 0.9 + + states: [ + State { + name: "expanded" + PropertyChanges { + target: fileOpen + width: itemWidth * 1.5 + opacity: 0.8 + } + }, + State { + name: "collapsed" + PropertyChanges { + target: fileOpen + width: itemHeight + scaledMargin + opacity: 0.9 + } + } + ] + + transitions: [ + Transition { + NumberAnimation { target: fileOpen; property: "width"; duration: 400 } + NumberAnimation { target: fileOpen; property: "opacity"; duration: 400 } + } + ] + } + + FileBrowser { + id: imageFileBrowser + anchors.fill: root + Component.onCompleted: fileSelected.connect(content.openImage) + } + + FileBrowser { + id: videoFileBrowser + anchors.fill: root + Component.onCompleted: fileSelected.connect(content.openVideo) + } + + Component.onCompleted: { + fileOpen.openImage.connect(openImage) + fileOpen.openVideo.connect(openVideo) + fileOpen.openCamera.connect(openCamera) + fileOpen.close.connect(close) + } + + function init() { + if (Qt.platform.os === "linux" || Qt.platform.os === "windows" || Qt.platform.os === "osx" || Qt.platform.os === "unix") { + if (Screen.desktopAvailableWidth > 1280) { + windowWidth = 1280 + } + if (Screen.desktopAvailableHeight > 720) { + windowHeight = 720 + } + } + + height = windowHeight + width = windowWidth + + console.log("[qmlvideofx] root.init") + console.log("Height: ", Screen.desktopAvailableHeight) + console.log("Width: ", Screen.desktopAvailableWidth) + console.log("Pixels per mm: ", Math.ceil(Screen.pixelDensity)) + console.log("Orientation: ", Screen.orientation) + imageFileBrowser.folder = imagePath + videoFileBrowser.folder = videoPath + content.init() + performanceLoader.init() + if (fileName != "") + content.openVideo(fileName) + } + + function qmlFramePainted() { + if (performanceLoader.item) + performanceLoader.item.qmlFramePainted() + } + + function openImage() { + imageFileBrowser.show() + } + + function openVideo() { + videoFileBrowser.show() + } + + function openCamera() { + content.openCamera() + } + + function close() { + content.init() + } +} diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ParameterPanel.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ParameterPanel.qml index 83c0d4c8..aa4315c9 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ParameterPanel.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/ParameterPanel.qml @@ -47,17 +47,12 @@ Rectangle { height: view.model.count * sliderHeight property color lineColor: "black" property real gripSize: 25 - property real spacing: 10 - property real sliderHeight: 40 + property real spacing: 20 + property real sliderHeight: 60 property ListModel model: ListModel { } - Rectangle { - anchors.fill: parent - color: "black" - opacity: 0.5 - radius: 10 - } + anchors.topMargin: 10 Component { id: editDelegate @@ -77,10 +72,10 @@ Rectangle { bottom: parent.bottom left: parent.left } - font.pixelSize: 0.5 * parent.height + font.pixelSize: fontSize horizontalAlignment: Text.AlignRight verticalAlignment: Text.AlignVCenter - width: 150 + width: 8 * fontSize } Slider { diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Slider.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Slider.qml index c1253702..97b52c87 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Slider.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Slider.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. @@ -39,91 +39,84 @@ ** ****************************************************************************/ -import QtQuick 2.0 +import QtQuick 2.1 Rectangle { id: root color: "transparent" radius: 5 property alias value: grip.value - property color fillColor: "white" - property color lineColor: "black" - property color gripColor: "white" - property real gripSize: 20 + property color fillColor: "#14aaff" + property real gripSize: 40 property real gripTolerance: 3.0 property real increment: 0.1 property bool enabled: true Rectangle { - anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter } - height: 3 - color: displayedColor(root.lineColor) - - Rectangle { - anchors { fill: parent; margins: 1 } - color: root.fillColor + id: slider + anchors { + left: parent.left + right: parent.right + verticalCenter: parent.verticalCenter } - } + height: 10 + color: "transparent" - MouseArea { - anchors.fill: parent - enabled: root.enabled - onClicked: { - if (parent.width) { - var newValue = mouse.x / parent.width - if (Math.abs(newValue - parent.value) > parent.increment) { - if (newValue > parent.value) - parent.value = Math.min(1.0, parent.value + parent.increment) - else - parent.value = Math.max(0.0, parent.value - parent.increment) + BorderImage { + id: sliderbarimage + source: "qrc:/images/Slider_bar.png" + anchors { fill: parent; margins: 1 } + border.right: 5 + border.left: 5 + } + Rectangle { + height: parent.height -2 + anchors.left: parent.left + anchors.right: grip.horizontalCenter + color: root.fillColor + radius: 3 + border.width: 1 + border.color: Qt.darker(color, 1.3) + opacity: 0.8 + } + Rectangle { + id: grip + property real value: 0.5 + x: (value * parent.width) - width/2 + anchors.verticalCenter: parent.verticalCenter + width: root.gripTolerance * root.gripSize + height: width + radius: width/2 + color: "transparent" + + Image { + id: sliderhandleimage + source: "qrc:/images/Slider_handle.png" + anchors.centerIn: parent + } + + MouseArea { + id: mouseArea + enabled: root.enabled + anchors.fill: parent + drag { + target: grip + axis: Drag.XAxis + minimumX: -parent.width/2 + maximumX: root.width - parent.width/2 + } + onPositionChanged: { + if (drag.active) + updatePosition() + } + onReleased: { + updatePosition() + } + function updatePosition() { + value = (grip.x + grip.width/2) / slider.width } } } - } - Rectangle { - id: grip - property real value: 0.5 - x: (value * parent.width) - width/2 - anchors.verticalCenter: parent.verticalCenter - width: root.gripTolerance * root.gripSize - height: width - radius: width/2 - color: "transparent" - - MouseArea { - id: mouseArea - enabled: root.enabled - anchors.fill: parent - drag { - target: grip - axis: Drag.XAxis - minimumX: -parent.width/2 - maximumX: root.width - parent.width/2 - } - onPositionChanged: { - if (drag.active) - updatePosition() - } - onReleased: { - updatePosition() - } - function updatePosition() { - value = (grip.x + grip.width/2) / grip.parent.width - } - } - - Rectangle { - anchors.centerIn: parent - width: root.gripSize - height: width - radius: width/2 - color: root.gripColor - } - } - - function displayedColor(c) { - var tint = Qt.rgba(c.r, c.g, c.b, 0.25) - return enabled ? c : Qt.tint(c, tint) } } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/main-largescreen.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/main-largescreen.qml deleted file mode 100644 index 63a0a01a..00000000 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/main-largescreen.qml +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Mobility Components. -** -** $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$ -** -****************************************************************************/ - -import QtQuick 2.0 - -Rectangle { - id: root - width: 900 - height: 600 - color: "grey" - property string fileName - property alias volume: content.volume - property bool perfMonitorsLogging: false - property bool perfMonitorsVisible: false - - QtObject { - id: d - property real gripSize: 20 - } - - Rectangle { - id: inner - anchors.fill: parent - color: "grey" - - Content { - id: content - anchors { - top: parent.top - bottom: parent.bottom - left: parent.left - right: effectSelectionPanel.left - margins: 5 - } - gripSize: d.gripSize - width: 600 - height: 600 - } - - Loader { - id: performanceLoader - function init() { - console.log("[qmlvideofx] performanceLoader.init logging " + root.perfMonitorsLogging + " visible " + root.perfMonitorsVisible) - var enabled = root.perfMonitorsLogging || root.perfMonitorsVisible - source = enabled ? "../performancemonitor/PerformanceItem.qml" : "" - } - onLoaded: { - item.parent = content - item.anchors.top = content.top - item.anchors.left = content.left - item.anchors.right = content.right - item.logging = root.perfMonitorsLogging - item.displayed = root.perfMonitorsVisible - item.init() - } - } - - ParameterPanel { - id: parameterPanel - anchors { - left: parent.left - bottom: parent.bottom - right: effectSelectionPanel.left - margins: 20 - } - gripSize: d.gripSize - } - - EffectSelectionPanel { - id: effectSelectionPanel - anchors { - top: parent.top - bottom: fileOpen.top - right: parent.right - margins: 5 - } - width: 300 - itemHeight: 40 - onEffectSourceChanged: { - content.effectSource = effectSource - parameterPanel.model = content.effect.parameters - } - } - - FileOpen { - id: fileOpen - anchors { - right: parent.right - bottom: parent.bottom - margins: 5 - } - width: effectSelectionPanel.width - height: 165 - buttonHeight: 32 - topMargin: 10 - } - } - - FileBrowser { - id: imageFileBrowser - anchors.fill: root - Component.onCompleted: fileSelected.connect(content.openImage) - } - - FileBrowser { - id: videoFileBrowser - anchors.fill: root - Component.onCompleted: fileSelected.connect(content.openVideo) - } - - Component.onCompleted: { - fileOpen.openImage.connect(openImage) - fileOpen.openVideo.connect(openVideo) - fileOpen.openCamera.connect(openCamera) - fileOpen.close.connect(close) - } - - function init() { - console.log("[qmlvideofx] main.init") - imageFileBrowser.folder = imagePath - videoFileBrowser.folder = videoPath - content.init() - performanceLoader.init() - if (fileName != "") - content.openVideo(fileName) - } - - function qmlFramePainted() { - if (performanceLoader.item) - performanceLoader.item.qmlFramePainted() - } - - function openImage() { - imageFileBrowser.show() - } - - function openVideo() { - videoFileBrowser.show() - } - - function openCamera() { - content.openCamera() - } - - function close() { - content.openImage("qrc:/images/qt-logo.png") - } -} diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/main-smallscreen.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/main-smallscreen.qml deleted file mode 100644 index f715dc8c..00000000 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/main-smallscreen.qml +++ /dev/null @@ -1,408 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Mobility Components. -** -** $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$ -** -****************************************************************************/ - -import QtQuick 2.0 - -Rectangle { - id: root - width: 640 - height: 360 - color: "grey" - property string fileName - property alias volume: content.volume - property bool perfMonitorsLogging: false - property bool perfMonitorsVisible: false - - QtObject { - id: d - property bool dialogShown: (fileOpenContainer.state == "shown" || - effectSelectionPanel.state == "shown" || - videoFileBrowser.shown || - imageFileBrowser.shown) - property real gripSize: 40 - } - - // Create ScreenSaver element via Loader, so this app will still run if the - // SystemInfo module is not available - Loader { - source: "DisableScreenSaver.qml" - } - - Loader { - id: performanceLoader - - Connections { - target: d - onDialogShownChanged: - if (performanceLoader.item) - performanceLoader.item.enabled = !d.dialogShown - ignoreUnknownSignals: true - } - - function init() { - console.log("[qmlvideofx] performanceLoader.init logging " + root.perfMonitorsLogging + " visible " + root.perfMonitorsVisible) - var enabled = root.perfMonitorsLogging || root.perfMonitorsVisible - source = enabled ? "../performancemonitor/PerformanceItem.qml" : "" - } - - onLoaded: { - item.parent = root - item.anchors.top = root.top - item.anchors.left = root.left - item.logging = root.perfMonitorsLogging - item.displayed = root.perfMonitorsVisible - item.init() - } - } - - Rectangle { - id: inner - anchors.fill: parent - color: "grey" - - Content { - id: content - anchors.fill: parent - gripSize: d.gripSize - onVideoFramePainted: performanceLoader.item.videoFramePainted() - } - - ParameterPanel { - id: parameterPanel - anchors { - left: parent.left; - right: parent.right; - margins: 10 - } - y: parent.height - gripSize: d.gripSize - - states: [ - State { - name: "shown" - PropertyChanges { - target: parameterPanel - y: parent.height - (parameterPanel.height + 10) - } - } - ] - - transitions: [ - Transition { - from: "*" - to: "*" - NumberAnimation { - properties: "y" - easing.type: Easing.OutQuart - duration: 500 - } - } - ] - - state: (enabled && !d.dialogShown) ? "shown" : "baseState" - } - - EffectSelectionPanel { - id: effectSelectionPanel - anchors { - top: parent.top; - bottom: parameterPanel.top; - margins: 10 - } - x: parent.width - width: parent.width - 40 - opacity: 0.75 - radius: 20 - itemHeight: 50 - - states: [ - State { - name: "shown" - PropertyChanges { - target: effectSelectionPanel - x: 20 - } - } - ] - - transitions: [ - Transition { - from: "*" - to: "*" - NumberAnimation { - properties: "x" - easing.type: Easing.OutQuart - duration: 500 - } - } - ] - - onEffectSourceChanged: { - content.effectSource = effectSource - if (content.effect.parameters.count) { - parameterPanel.model = content.effect.parameters - parameterPanel.enabled = true - } else { - parameterPanel.enabled = false - } - } - - onClicked: state = "baseState" - } - - Rectangle { - id: fileOpenContainer - anchors { - top: parent.top - bottom: parameterPanel.top - margins: 10 - } - x: -width - width: parent.width - 40 - color: "transparent" - - Column { - anchors.fill: parent - - FileOpen { - id: fileOpen - color: "transparent" - width: parent.width - height: 200 - opacity: 0.75 - radius: 20 - buttonHeight: 40 - } - - MouseArea { - width: parent.width - height: 250 - onClicked: fileOpenContainer.state = "baseState" - } - } - - states: [ - State { - name: "shown" - PropertyChanges { - target: fileOpenContainer - x: 20 - } - } - ] - - transitions: [ - Transition { - from: "*" - to: "*" - NumberAnimation { - properties: "x" - easing.type: Easing.OutQuart - duration: 500 - } - } - ] - } - - Rectangle { - id: splashScreen - anchors { - horizontalCenter: parent.horizontalCenter - verticalCenter: parent.verticalCenter - } - width: 300 - height: 200 - radius: 0.1 * height - color: "white" - opacity: 0.9 - border { color: "black"; width: 2 } - - Text { - anchors { - fill: parent - margins: 5 - } - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - font.pixelSize: 24 - text: "Tap on left side to switch between sources.\n\nTap on right side to switch between effects." - wrapMode: Text.WordWrap - } - - MouseArea { - anchors.fill: parent - onClicked: parent.state = "hidden" - } - - states: [ - State { - name: "hidden" - PropertyChanges { - target: splashScreen - opacity: 0.0 - } - } - ] - - transitions: [ - Transition { - from: "*" - to: "*" - NumberAnimation { - properties: "opacity" - easing.type: Easing.OutQuart - duration: 500 - } - } - ] - } - - HintedMouseArea { - id: fileOpenMouseArea - anchors { - left: parent.left; - top: parent.top; - bottom: parameterPanel.top; - topMargin: 75 - } - width: 100 - onClicked: { - fileOpenMouseArea.hintEnabled = false - effectSelectionPanelMouseArea.hintEnabled = false - splashScreen.state = "hidden" - fileOpenContainer.state = "shown" - } - enabled: !d.dialogShown - } - - HintedMouseArea { - id: effectSelectionPanelMouseArea - anchors { - right: parent.right; - top: parent.top; - bottom: parameterPanel.top; - topMargin: 75 - } - width: 100 - onClicked: { - fileOpenMouseArea.hintEnabled = false - effectSelectionPanelMouseArea.hintEnabled = false - splashScreen.state = "hidden" - effectSelectionPanel.state = "shown" - } - enabled: !d.dialogShown - } - - Image { - source: "qrc:/images/close.png" - - anchors { - top: parent.top - right: parent.right - margins: 5 - } - - MouseArea { - anchors.fill: parent - onClicked: Qt.quit() - } - } - } - - Component.onCompleted: { - fileOpen.openImage.connect(openImage) - fileOpen.openVideo.connect(openVideo) - fileOpen.openCamera.connect(openCamera) - fileOpen.close.connect(close) - } - - FileBrowser { - id: imageFileBrowser - anchors.fill: root - Component.onCompleted: fileSelected.connect(content.openImage) - } - - FileBrowser { - id: videoFileBrowser - anchors.fill: root - Component.onCompleted: fileSelected.connect(content.openVideo) - } - - // Called from main() once root properties have been set - function init() { - console.log("[qmlvideofx] main.init") - imageFileBrowser.folder = imagePath - videoFileBrowser.folder = videoPath - content.init() - performanceLoader.init() - if (fileName != "") { - fileOpenMouseArea.hintEnabled = false - effectSelectionPanelMouseArea.hintEnabled = false - splashScreen.state = "hidden" - content.openVideo(fileName) - } - } - - function qmlFramePainted() { - if (performanceLoader.item) - performanceLoader.item.qmlFramePainted() - } - - function openImage() { - fileOpenContainer.state = "baseState" - imageFileBrowser.show() - } - - function openVideo() { - fileOpenContainer.state = "baseState" - videoFileBrowser.show() - } - - function openCamera() { - fileOpenContainer.state = "baseState" - content.openCamera() - } - - function close() { - fileOpenContainer.state = "baseState" - content.openImage("qrc:/images/qt-logo.png") - } -} diff --git a/examples/multimedia/video/qmlvideofx/qmlvideofx.pro b/examples/multimedia/video/qmlvideofx/qmlvideofx.pro index 56344490..e9633954 100644 --- a/examples/multimedia/video/qmlvideofx/qmlvideofx.pro +++ b/examples/multimedia/video/qmlvideofx/qmlvideofx.pro @@ -10,10 +10,12 @@ RESOURCES += qmlvideofx.qrc include($$PWD/../snippets/performancemonitor/performancemonitordeclarative.pri) -maemo6: { - DEFINES += SMALL_SCREEN_LAYOUT - DEFINES += SMALL_SCREEN_PHYSICAL -} - target.path = $$[QT_INSTALL_EXAMPLES]/multimedia/video/qmlvideofx INSTALLS += target + +ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android + +OTHER_FILES += \ + android/AndroidManifest.xml + +QMAKE_INFO_PLIST = Info.plist diff --git a/examples/multimedia/video/qmlvideofx/qmlvideofx.qrc b/examples/multimedia/video/qmlvideofx/qmlvideofx.qrc index 93cb4f1f..e7a36124 100644 --- a/examples/multimedia/video/qmlvideofx/qmlvideofx.qrc +++ b/examples/multimedia/video/qmlvideofx/qmlvideofx.qrc @@ -1,10 +1,5 @@ - images/close.png - images/folder.png - images/titlebar.png - images/titlebar.sci - images/up.png images/qt-logo.png qml/qmlvideofx/Button.qml qml/qmlvideofx/Content.qml @@ -26,12 +21,10 @@ qml/qmlvideofx/EffectPixelate.qml qml/qmlvideofx/EffectPosterize.qml qml/qmlvideofx/EffectRipple.qml - qml/qmlvideofx/EffectSelectionPanel.qml qml/qmlvideofx/EffectSepia.qml qml/qmlvideofx/EffectSharpen.qml qml/qmlvideofx/EffectShockwave.qml qml/qmlvideofx/EffectSobelEdgeDetection1.qml - qml/qmlvideofx/EffectSobelEdgeDetection2.qml qml/qmlvideofx/EffectTiltShift.qml qml/qmlvideofx/EffectToon.qml qml/qmlvideofx/EffectVignette.qml @@ -40,8 +33,6 @@ qml/qmlvideofx/FileBrowser.qml qml/qmlvideofx/FileOpen.qml qml/qmlvideofx/HintedMouseArea.qml - qml/qmlvideofx/main-largescreen.qml - qml/qmlvideofx/main-smallscreen.qml qml/qmlvideofx/ParameterPanel.qml qml/qmlvideofx/Slider.qml shaders/billboard.fsh @@ -61,11 +52,21 @@ shaders/sharpen.fsh shaders/shockwave.fsh shaders/sobeledgedetection1.fsh - shaders/sobeledgedetection2.fsh shaders/tiltshift.fsh shaders/toon.fsh shaders/vignette.fsh shaders/warhol.fsh shaders/wobble.fsh + images/Slider_handle.png + images/Slider_bar.png + qml/qmlvideofx/Curtain.qml + images/Triangle_bottom.png + images/Triangle_Top.png + images/Dropdown_arrows.png + images/icon_Folder.png + images/icon_BackArrow.png + qml/qmlvideofx/Main.qml + images/icon_Menu.png + qml/qmlvideofx/EffectSelectionList.qml From 78cff36ba8e195c8183c3434498bc7fddeb5c00c Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Thu, 17 Apr 2014 17:24:25 +0200 Subject: [PATCH 06/38] Bump MODULE_VERSION to 5.3.1 Change-Id: Ie88b34ee769ab3abbd0a5ab0fd8b7938475916ae Reviewed-by: Oswald Buddenhagen --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index efd0e68f..ef45a002 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,4 +1,4 @@ load(qt_build_config) CONFIG += qt_example_installs -MODULE_VERSION = 5.3.0 +MODULE_VERSION = 5.3.1 From e3bc29963e31e1d104e89027949aac48c35986d4 Mon Sep 17 00:00:00 2001 From: Fabian Bumberger Date: Wed, 23 Apr 2014 17:49:22 +0200 Subject: [PATCH 07/38] Fix documentation error Change-Id: I98f3e35677b5e07ea35898caec3f241b045b5033 Reviewed-by: Bernd Weimer From c9a3bbc3e69b9965b5c1b9d85f8426896f94c02a Mon Sep 17 00:00:00 2001 From: Andreas Holzammer Date: Fri, 25 Apr 2014 10:28:16 +0200 Subject: [PATCH 08/38] [QNX] Introduce env variable for default audio sink Make it possible to change the default audio sink via a environment variable. Change-Id: Id0e14318fc99a896b8a41196941b758a31d23600 Reviewed-by: Sean Harmer --- src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp index 2555b287..abb68278 100644 --- a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp @@ -208,7 +208,8 @@ void MmRendererMediaPlayerControl::attach() if (m_videoWindowControl) m_videoWindowControl->attachDisplay(m_context); - m_audioId = mmr_output_attach(m_context, "audio:default", "audio"); + const QByteArray defaultAudioDevice = qgetenv("QQNX_RENDERER_DEFAULT_AUDIO_SINK"); + m_audioId = mmr_output_attach(m_context, defaultAudioDevice.isEmpty() ? "audio:default" : defaultAudioDevice.constData(), "audio"); if (m_audioId == -1) { emitMmError("mmr_output_attach() for audio failed"); return; From 2939c9953ad08e659722c2b832f2c35db6de0115 Mon Sep 17 00:00:00 2001 From: Niels Weber Date: Mon, 28 Apr 2014 09:27:03 +0200 Subject: [PATCH 09/38] Add missing background for effect selection list. Also remove highlight and fix button text color. Make Menu animation faster. Task-number: QTBUG-38121 Change-Id: I7d5868d370a8dc7925cee5e694ae043970c569d9 Reviewed-by: Sami Makkonen Reviewed-by: Thomas Hartmann --- .../qmlvideofx/qml/qmlvideofx/Button.qml | 3 +- .../video/qmlvideofx/qml/qmlvideofx/Main.qml | 36 +++++++++++-------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Button.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Button.qml index dd7cca60..20335283 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Button.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Button.qml @@ -60,7 +60,6 @@ Rectangle { Rectangle { anchors { fill: parent; margins: 1 } color: mouseArea.pressed ? bgColorSelected : bgColor - radius: 0.1 * height Text { id: text @@ -68,7 +67,7 @@ Rectangle { text: root.text anchors { fill: parent; margins: scaledMargin } font.pixelSize: fontSize - color: mouseArea.pressed ? bgColor : textColor + color: textColor horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter } diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Main.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Main.qml index 5ec13750..e39eeafd 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Main.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/Main.qml @@ -80,7 +80,7 @@ Rectangle { id: parameterPanel anchors { left: parent.left - right: listview.left + right: effectName.left bottom: parent.bottom margins: scaledMargin leftMargin: scaledMargin + itemHeight @@ -88,46 +88,50 @@ Rectangle { gripSize: d.gripSize height: root.itemHeight * 2.5 width: root.itemWidth * 3 - } - Button { id: effectName anchors { right: parent.right bottom: perfHolder.top - top: content.bottom margins: scaledMargin } text: "No effect" width: itemWidth * 2 + height: itemHeight onClicked: { effectName.visible = false listview.visible = true + lvbg.visible = true } color: "#303030" } + Rectangle { + id: lvbg + width: itemWidth * 2 + color: "black" + opacity: 0.8 + visible: false + + anchors { + right: parent.right + bottom: perfHolder.top + top: parent.top + margins: scaledMargin + } ListView { id: listview width: itemWidth * 2 - anchors { - right: parent.right - bottom: perfHolder.top - top: parent.top - margins: scaledMargin - } + anchors.fill: parent visible: false model: EffectSelectionList {} delegate: effectDelegate - highlight: Rectangle { color: "#14aaff"; radius: 5 } - highlightFollowsCurrentItem: true - highlightRangeMode: ListView.StrictlyEnforceRange clip: true focus: true @@ -139,6 +143,7 @@ Rectangle { onClicked: { content.effectSource = source listview.visible = false + lvbg.visible = false effectName.text = name effectName.visible = true parameterPanel.model = content.effect.parameters @@ -146,6 +151,7 @@ Rectangle { } } } + } } Rectangle { @@ -213,8 +219,8 @@ Rectangle { transitions: [ Transition { - NumberAnimation { target: fileOpen; property: "width"; duration: 400 } - NumberAnimation { target: fileOpen; property: "opacity"; duration: 400 } + NumberAnimation { target: fileOpen; property: "width"; duration: 100 } + NumberAnimation { target: fileOpen; property: "opacity"; duration: 100 } } ] } From c5d184cbe38d8024c6354952d3103423d51638ec Mon Sep 17 00:00:00 2001 From: Niels Weber Date: Mon, 28 Apr 2014 09:39:16 +0200 Subject: [PATCH 10/38] Selecting something now closes menu On a closed menu, the text is now hidden. Task-number: QTBUG-38121 Change-Id: I305fd4f24768115ed21495857cce672d8cbd2135 Reviewed-by: Petref Saraci Reviewed-by: Thomas Hartmann --- .../qmlvideofx/qml/qmlvideofx/FileOpen.qml | 76 ++++++++++++------- 1 file changed, 48 insertions(+), 28 deletions(-) diff --git a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileOpen.qml b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileOpen.qml index b0542cb8..a4de2cbb 100644 --- a/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileOpen.qml +++ b/examples/multimedia/video/qmlvideofx/qml/qmlvideofx/FileOpen.qml @@ -49,28 +49,40 @@ Rectangle { signal openVideo signal close - Column { - anchors.fill: parent - spacing: 10 - Rectangle { - height: itemHeight - width: itemHeight - color: "transparent" - anchors.right: parent.right - Image { - id: menu - source: "qrc:///images/icon_Menu.png" - anchors { - right: parent.right - top: parent.top - margins: scaledMargin - } - } - MouseArea { - anchors.fill: parent - onClicked: fileOpen.state == "expanded" ? fileOpen.state = "collapsed" : fileOpen.state = "expanded" + + Rectangle { + id: menuField + height: itemHeight + width: itemHeight + color: "transparent" + anchors.right: parent.right + Image { + id: menu + source: "qrc:///images/icon_Menu.png" + anchors { + right: parent.right + top: parent.top + margins: scaledMargin } } + MouseArea { + anchors.fill: parent + onClicked: fileOpen.state == "expanded" ? fileOpen.state = "collapsed" : fileOpen.state = "expanded" + } + } + + Column { + anchors { + top: menuField.bottom + right: parent.right + left: parent.left + bottom: parent.bottom + topMargin: 10 + } + + spacing: 10 + visible: fileOpen.state == "expanded" + Rectangle { width: 0.9 * parent.width height: 1 @@ -81,8 +93,10 @@ Rectangle { text: "Start camera" height: itemHeight width: parent.width - onClicked: root.openCamera() - active: fileOpen.state == "expanded" + onClicked: { + fileOpen.state = "collapsed" + root.openCamera() + } } Rectangle { width: 0.9 * parent.width @@ -94,8 +108,10 @@ Rectangle { text: "Open image" height: itemHeight width: parent.width - onClicked: root.openImage() - active: fileOpen.state == "expanded" + onClicked: { + fileOpen.state = "collapsed" + root.openImage() + } } Rectangle { width: 0.9 * parent.width @@ -107,8 +123,10 @@ Rectangle { text: "Open video" height: itemHeight width: parent.width - onClicked: root.openVideo() - active: fileOpen.state == "expanded" + onClicked: { + fileOpen.state = "collapsed" + root.openVideo() + } } Rectangle { width: 0.9 * parent.width @@ -120,8 +138,10 @@ Rectangle { text: "Reset" height: itemHeight width: parent.width - onClicked: root.close() - active: fileOpen.state == "expanded" + onClicked: { + fileOpen.state = "collapsed" + root.close() + } } Rectangle { width: 0.9 * parent.width From 02c0229a058e0779d236bec4c48bdad7d3d78399 Mon Sep 17 00:00:00 2001 From: Niels Weber Date: Mon, 28 Apr 2014 10:52:33 +0200 Subject: [PATCH 11/38] Handle resizing of mainwindow better Task-number: QTBUG-38121 Change-Id: I877fd5c626418a91850d43de31e71351c14eef25 Reviewed-by: Sami Makkonen Reviewed-by: Thomas Hartmann --- examples/multimedia/video/qmlvideofx/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/multimedia/video/qmlvideofx/main.cpp b/examples/multimedia/video/qmlvideofx/main.cpp index f221c954..1b09f7aa 100644 --- a/examples/multimedia/video/qmlvideofx/main.cpp +++ b/examples/multimedia/video/qmlvideofx/main.cpp @@ -122,7 +122,8 @@ int main(int argc, char *argv[]) viewer.setTitle("qmlvideofx"); viewer.setFlags(Qt::Window | Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); - viewer.setMinimumSize(QSize(640, 360)); + viewer.setMinimumSize(QSize(1280, 720)); + viewer.setResizeMode(QQuickView::SizeRootObjectToView); viewer.show(); From 82d96105cea1bca034119adf54a2614c67a24c13 Mon Sep 17 00:00:00 2001 From: Niels Weber Date: Tue, 22 Apr 2014 12:13:23 +0200 Subject: [PATCH 12/38] Fix documentation of qmlvideofx example Make the documentation fit to the current state of the example. Task-number: QTBUG-38121 Change-Id: I3379e3328d07ef8bcdb35a5e3821ab194c3443c4 Reviewed-by: Leena Miettinen Reviewed-by: Sami Makkonen Reviewed-by: Yoann Lopes --- .../doc/images/qmlvideofx-camera-glow.jpg | Bin 0 -> 74914 bytes .../doc/images/qmlvideofx-camera-glow.png | Bin 250540 -> 0 bytes .../doc/images/qmlvideofx-camera-magnify.png | Bin 204923 -> 0 bytes .../doc/images/qmlvideofx-camera-wobble.jpg | Bin 0 -> 62992 bytes .../doc/images/qmlvideofx-effects-menu.jpg | Bin 0 -> 84990 bytes .../doc/images/qmlvideofx-effects-menu.png | Bin 171257 -> 0 bytes .../doc/images/qmlvideofx-source-menu.png | Bin 257292 -> 0 bytes .../images/qmlvideofx-video-edgedetection.jpg | Bin 0 -> 108916 bytes .../images/qmlvideofx-video-edgedetection.png | Bin 279883 -> 0 bytes .../doc/images/qmlvideofx-video-pagecurl.jpg | Bin 0 -> 61450 bytes .../doc/images/qmlvideofx-video-pagecurl.png | Bin 220606 -> 0 bytes .../multimedia/video/doc/src/qmlvideofx.qdoc | 27 ++++++------------ 12 files changed, 9 insertions(+), 18 deletions(-) create mode 100644 examples/multimedia/video/doc/images/qmlvideofx-camera-glow.jpg delete mode 100644 examples/multimedia/video/doc/images/qmlvideofx-camera-glow.png delete mode 100644 examples/multimedia/video/doc/images/qmlvideofx-camera-magnify.png create mode 100644 examples/multimedia/video/doc/images/qmlvideofx-camera-wobble.jpg create mode 100644 examples/multimedia/video/doc/images/qmlvideofx-effects-menu.jpg delete mode 100644 examples/multimedia/video/doc/images/qmlvideofx-effects-menu.png delete mode 100644 examples/multimedia/video/doc/images/qmlvideofx-source-menu.png create mode 100644 examples/multimedia/video/doc/images/qmlvideofx-video-edgedetection.jpg delete mode 100644 examples/multimedia/video/doc/images/qmlvideofx-video-edgedetection.png create mode 100644 examples/multimedia/video/doc/images/qmlvideofx-video-pagecurl.jpg delete mode 100644 examples/multimedia/video/doc/images/qmlvideofx-video-pagecurl.png diff --git a/examples/multimedia/video/doc/images/qmlvideofx-camera-glow.jpg b/examples/multimedia/video/doc/images/qmlvideofx-camera-glow.jpg new file mode 100644 index 0000000000000000000000000000000000000000..777ed4ffc60d8ba42d5f2d52aefe730231c69be4 GIT binary patch literal 74914 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 Wd=$kA`fD@bf4=+Q-XGjwv;PYr_>u?! literal 0 HcmV?d00001 diff --git a/examples/multimedia/video/doc/images/qmlvideofx-camera-glow.png b/examples/multimedia/video/doc/images/qmlvideofx-camera-glow.png deleted file mode 100644 index aca874b6c911504fd07816b6ef11c310a6f3ea19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 250540 zcmV(}K+wO5P)n~cJtoy`n~l|bL2VZWXRFXEC}qfcU{P@P4>o)*AjBn^;vw5=?ke}dyBj_b%DKs zq9sLFn57khA(#{HZbGC*+N$pWNCF%HO=di5Q3HFNpg2d88QROoCP3QQySSKJCO+y zBq;>Jgk=_q(h&F3Dv)rYiD71uF3&l;%V=ii*`YO1Mj-$MD9kdPSP?$-q5+~~9fr;d z0K(YeKxWb5W{DnzUEzRui$m62zj)zO*Y@)69-hAyZr}Ziw|vFUg-5dRo^N{Jd*A#1 zzxhA??EKP)L-+ch{^`H