Set media.name to '*'.
[harmattan/cameraplus] / lib / qtcammode_p.h
index fd31945..b724ffd 100644 (file)
@@ -1,24 +1,57 @@
 // -*- c++ -*-
 
+/*!
+ * This file is part of CameraPlus.
+ *
+ * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
 #ifndef QT_CAM_MODE_P_H
 #define QT_CAM_MODE_P_H
 
 #include <QSize>
+#include <QFileInfo>
+#include <QDir>
 #include "qtcamdevice_p.h"
+#include "qtcamanalysisbin.h"
 #include <gst/pbutils/encoding-profile.h>
 #include <gst/pbutils/encoding-target.h>
+#include "qtcamgstreamermessagehandler.h"
+
+#ifndef GST_USE_UNSTABLE_API
+#define GST_USE_UNSTABLE_API
+#endif /* GST_USE_UNSTABLE_API */
+#include <gst/interfaces/photography.h>
+
+#define PREVIEW_CAPS "video/x-raw-rgb, width = (int) %1, height = (int) %2, bpp = (int) 32, depth = (int) 24, red_mask = (int) 65280, green_mask = (int) 16711680, blue_mask = (int) -16777216"
 
 class QtCamDevicePrivate;
 class PreviewImageHandler;
 class DoneHandler;
 
-#define CAPS "video/x-raw-yuv, width = (int) %1, height = (int) %2, framerate = (fraction) %3/%4"
-
 class QtCamModePrivate {
 public:
-  QtCamModePrivate(QtCamDevicePrivate *d) : id(-1), dev(d), night(false) {}
+  QtCamModePrivate(QtCamDevicePrivate *d) : id(-1), dev(d) {}
   virtual ~QtCamModePrivate() {}
 
+  void init(DoneHandler *handler) {
+    doneHandler = handler;
+  }
+
   int modeId(const char *mode) {
     if (!dev->cameraBin) {
       return -1;
@@ -34,7 +67,7 @@ public:
       return -1;
     }
 
-    GParamSpecEnum *e = (GParamSpecEnum *)pspec;
+    GParamSpecEnum *e = G_PARAM_SPEC_ENUM(pspec);
     GEnumClass *klass = e->enum_class;
 
     for (unsigned x = 0; x < klass->n_values; x++) {
@@ -48,8 +81,17 @@ public:
 
   GstEncodingProfile *loadProfile(const QString& path, const QString& name) {
     GError *error = NULL;
+    QString targetPath;
+    QFileInfo info(path);
+    if (!info.isAbsolute()) {
+      targetPath = QDir(DATA_DIR).absoluteFilePath(path);
+    }
+    else {
+      targetPath = info.filePath();
+    }
 
-    GstEncodingTarget *target = gst_encoding_target_load_from_file(path.toUtf8().data(), &error);
+    GstEncodingTarget *target = gst_encoding_target_load_from_file(targetPath.toUtf8().constData(),
+                                                                  &error);
     if (!target) {
       qCritical() << "Failed to load encoding target from" << path << error->message;
       g_error_free(error);
@@ -68,13 +110,28 @@ public:
     return profile;
   }
 
-  void setCaps(const char *property, const QSize& resolution, const QPair<int, int> frameRate) {
+  void resetCaps(const char *property) {
     if (!dev->cameraBin) {
       return;
     }
 
-    // TODO: allow proceeding without specifying a frame rate (maybe we can calculate it ?)
-    if (frameRate.first <= 0 || frameRate.second <= 0) {
+    g_object_set(dev->cameraBin, property, NULL, NULL);
+  }
+
+  bool inNightMode() {
+    if (!dev->cameraBin) {
+      return false;
+    }
+
+    int val = 0;
+
+    g_object_get(dev->videoSource, "scene-mode", &val, NULL);
+
+    return val == GST_PHOTOGRAPHY_SCENE_MODE_NIGHT;
+  }
+
+  void setCaps(const char *property, const QSize& resolution, int fps) {
+    if (!dev->cameraBin) {
       return;
     }
 
@@ -82,22 +139,130 @@ public:
       return;
     }
 
-    QString capsString = QString(CAPS)
-      .arg(resolution.width()).arg(resolution.height())
-      .arg(frameRate.first).arg(frameRate.second);
+    GstCaps *caps = 0;
+
+    if (fps <= 0) {
+      caps = gst_caps_new_simple("video/x-raw-yuv",
+                                "width", G_TYPE_INT, resolution.width(),
+                                "height", G_TYPE_INT, resolution.height(),
+                                NULL);
+    }
+    else {
+      caps = gst_caps_new_simple("video/x-raw-yuv",
+                                "width", G_TYPE_INT, resolution.width(),
+                                "height", G_TYPE_INT, resolution.height(),
+                                "framerate",
+                                GST_TYPE_FRACTION_RANGE, fps - 1, 1, fps + 1, 1,
+                                NULL);
+    }
+
+    GstCaps *old = 0;
+
+    g_object_get(dev->cameraBin, property, &old, NULL);
 
-    GstCaps *caps = gst_caps_from_string(capsString.toAscii());
+    if (gst_caps_is_equal(caps, old)) {
+      gst_caps_unref(old);
+      gst_caps_unref(caps);
+
+      return;
+    }
 
     g_object_set(dev->cameraBin, property, caps, NULL);
 
-    gst_caps_unref(caps);
+    if (old) {
+      gst_caps_unref(old);
+    }
+  }
+
+  void setPreviewSize(const QSize& size) {
+    if (!dev->cameraBin) {
+      return;
+    }
+
+    if (size.width() <= 0 && size.height() <= 0) {
+      g_object_set(dev->cameraBin, "preview-caps", NULL, "post-previews", FALSE, NULL);
+    }
+    else {
+      QString preview = QString(PREVIEW_CAPS).arg(size.width()).arg(size.height());
+
+      GstCaps *caps = gst_caps_from_string(preview.toLatin1());
+
+      if (!dev->conf->isPreviewSupported()) {
+       qWarning() << "Cannot set preview caps. Preview not supported";
+       gst_caps_unref(caps);
+       return;
+      }
+
+      g_object_set(dev->cameraBin, "preview-caps", caps, "post-previews", TRUE, NULL);
+
+      gst_caps_unref(caps);
+    }
+  }
+
+  void setFileName(const QString& file) {
+    fileName = file;
+  }
+
+  void setTempFileName(const QString& file) {
+    tempFileName = file;
+  }
+
+  void enableViewfinderFilters() {
+    if (dev->viewfinderFilters) {
+      dev->viewfinderFilters->setBlocked(false);
+    }
+  }
+
+  void disableViewfinderFilters() {
+    if (dev->viewfinderFilters) {
+      dev->viewfinderFilters->setBlocked(true);
+    }
   }
 
   int id;
+  QtCamMode *q_ptr;
   QtCamDevicePrivate *dev;
   PreviewImageHandler *previewImageHandler;
   DoneHandler *doneHandler;
-  bool night;
+  QString fileName;
+  QString tempFileName;
+};
+
+class DoneHandler : public QtCamGStreamerMessageHandler {
+public:
+  DoneHandler(QtCamModePrivate *m, const char *done, QObject *parent = 0) :
+    QtCamGStreamerMessageHandler(done, parent) {
+    mode = m;
+  }
+
+  virtual ~DoneHandler() { }
+
+  virtual void handleMessage(GstMessage *message) {
+    // If we have a temp file then we rename it:
+    if (!mode->tempFileName.isEmpty() && !mode->fileName.isEmpty()) {
+      if (!QFile::rename(mode->tempFileName, mode->fileName)) {
+       qCritical() << "Failed to rename" << mode->tempFileName << "to" << mode->fileName;
+      }
+    }
+
+    QString fileName;
+    const GstStructure *s = gst_message_get_structure(message);
+    if (gst_structure_has_field(s, "filename")) {
+      const char *str = gst_structure_get_string(s, "filename");
+      if (str) {
+       fileName = QString::fromUtf8(str);
+      }
+    }
+
+    if (fileName.isEmpty()) {
+      fileName = mode->fileName;
+    }
+
+    QMetaObject::invokeMethod(mode->q_ptr, "saved", Qt::QueuedConnection,
+                             Q_ARG(QString, fileName));
+  }
+
+  QtCamModePrivate *mode;
 };
 
 #endif /* QT_CAM_MODE_P_H */