Added the ability to control playback volume from post capture
[harmattan/cameraplus] / declarative / videoplayer.cpp
index 29cfea4..8ab4017 100644 (file)
  */
 
 #include "videoplayer.h"
+#if defined(QT4)
 #include <QDeclarativeInfo>
-#include "qtcamgraphicsviewfinder.h"
+#elif defined(QT5)
+#include <QQmlInfo>
+#endif
 #include "cameraconfig.h"
 #include <QTimer>
+#include "qtcamviewfinderrenderer.h"
+#include <QPainter>
+#include <QMatrix4x4>
+#include <cmath>
 
+#if defined(QT4)
 VideoPlayer::VideoPlayer(QDeclarativeItem *parent) :
   QDeclarativeItem(parent),
+#elif defined(QT5)
+VideoPlayer::VideoPlayer(QQuickItem *parent) :
+  QQuickPaintedItem(parent),
+#endif
   m_config(0),
-  m_vf(0),
+  m_renderer(0),
   m_bin(0),
   m_state(VideoPlayer::StateStopped),
   m_timer(new QTimer(this)),
@@ -36,6 +48,16 @@ VideoPlayer::VideoPlayer(QDeclarativeItem *parent) :
   m_timer->setSingleShot(false);
   m_timer->setInterval(500);
   QObject::connect(m_timer, SIGNAL(timeout()), this, SIGNAL(positionChanged()));
+
+#if defined(QT4)
+  setFlag(QGraphicsItem::ItemHasNoContents, false);
+#endif
+
+#if defined(QT5)
+  setRenderTarget(QQuickPaintedItem::FramebufferObject);
+  setSmooth(false);
+  setAntialiasing(false);
+#endif
 }
 
 VideoPlayer::~VideoPlayer() {
@@ -48,16 +70,45 @@ VideoPlayer::~VideoPlayer() {
 }
 
 void VideoPlayer::componentComplete() {
+#if defined(QT4)
+  QDeclarativeItem::componentComplete();
+#elif defined(QT5)
+  QQuickPaintedItem::componentComplete();
+#endif
+
+  if (!m_config) {
+    qmlInfo(this) << "CameraConfig not set";
+    return;
+  }
 
+  m_renderer = QtCamViewfinderRenderer::create(m_config->config(), this);
+  if (!m_renderer) {
+    qmlInfo(this) << "Failed to create viewfinder renderer";
+    return;
+  }
+
+  m_renderer->resize(QSizeF(width(), height()));
+  QObject::connect(m_renderer, SIGNAL(updateRequested()), this, SLOT(updateRequested()));
+
+  if (m_bin) {
+    g_object_set(m_bin, "video-sink", m_renderer->sinkElement(), NULL);
+  }
 }
 
 void VideoPlayer::classBegin() {
+#if defined(QT4)
+  QDeclarativeItem::classBegin();
+#elif defined(QT5)
+  QQuickPaintedItem::classBegin();
+#endif
+
   m_bin = gst_element_factory_make ("playbin2", "VideoPlayerBin");
   if (!m_bin) {
     qmlInfo(this) << "Failed to create playbin2";
     return;
   }
 
+  g_signal_connect (G_OBJECT (m_bin), "notify::volume", G_CALLBACK (on_volume_changed), this);
   g_object_set (m_bin, "flags", 99, NULL);
 
   GstElement *elem = gst_element_factory_make("pulsesink", "VideoPlayerPulseSink");
@@ -65,7 +116,6 @@ void VideoPlayer::classBegin() {
     qmlInfo(this) << "Failed to create pulsesink";
   }
   else {
-    // TODO: properties on sink
     g_object_set (m_bin, "audio-sink", elem, NULL);
   }
 
@@ -102,15 +152,8 @@ void VideoPlayer::setCameraConfig(CameraConfig *config) {
 
   if (m_config != config) {
     m_config = config;
-    // TODO: We need fence sync here.
-    m_vf = new QtCamGraphicsViewfinder(m_config->config(), this);
-    m_vf->resize(QSizeF(width(), height()));
     emit cameraConfigChanged();
   }
-
-  if (m_bin) {
-    g_object_set(m_bin, "video-sink", m_vf->sinkElement(), NULL);
-  }
 }
 
 qint64 VideoPlayer::duration() const {
@@ -199,10 +242,46 @@ bool VideoPlayer::stop() {
 }
 
 void VideoPlayer::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) {
+#if defined(QT4)
   QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
+#elif defined(QT5)
+  QQuickPaintedItem::geometryChanged(newGeometry, oldGeometry);
+#endif
+
+  if (m_renderer) {
+    m_renderer->resize(newGeometry.size());
+  }
+}
+
+#if defined(QT4)
+void VideoPlayer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+                      QWidget *widget) {
+
+  Q_UNUSED(widget);
+  Q_UNUSED(option);
+
+  painter->fillRect(boundingRect(), Qt::black);
+
+#elif defined(QT5)
+void VideoPlayer::paint(QPainter *painter) {
+  painter->fillRect(contentsBoundingRect(), Qt::black);
 
-  if (m_vf) {
-    m_vf->resize(newGeometry.size());
+#endif
+
+  if (!m_renderer) {
+    return;
+  }
+
+  bool needsNativePainting = m_renderer->needsNativePainting();
+
+  if (needsNativePainting) {
+    painter->beginNativePainting();
+  }
+
+  m_renderer->paint(QMatrix4x4(painter->combinedTransform()), painter->viewport());
+
+  if (needsNativePainting) {
+    painter->endNativePainting();
   }
 }
 
@@ -349,3 +428,33 @@ gboolean VideoPlayer::bus_call(GstBus *bus, GstMessage *msg, gpointer data) {
 
   return TRUE;  
 }
+
+void VideoPlayer::updateRequested() {
+  update();
+}
+
+quint32 VideoPlayer::volume() {
+  double vol = 1.0;
+  g_object_get (m_bin, "volume", &vol, NULL);
+
+  qint32 res = (int)round(vol * 100.0);
+
+  return res;
+}
+
+void VideoPlayer::setVolume(quint32 volume) {
+  if (VideoPlayer::volume() != volume) {
+    double vol = volume / 100.0;
+    g_object_set (m_bin, "volume", vol, NULL);
+    emit volumeChanged();
+  }
+}
+
+void VideoPlayer::on_volume_changed(GObject *object, GParamSpec *pspec, gpointer user_data) {
+  Q_UNUSED(object);
+  Q_UNUSED(pspec);
+
+  VideoPlayer *player = (VideoPlayer *) user_data;
+
+  QMetaObject::invokeMethod(player, "volumeChanged", Qt::QueuedConnection);
+}