Move qt_cam_copy_register to QtCamera
[harmattan/cameraplus] / lib / qtcamdevice.cpp
index 93139e3..ed00c5e 100644 (file)
@@ -1,3 +1,23 @@
+/*!
+ * 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
+ */
+
 #include "qtcamdevice.h"
 #include "qtcamviewfinder.h"
 #include "qtcamconfig.h"
@@ -8,6 +28,9 @@
 #include "qtcammode.h"
 #include "qtcamimagemode.h"
 #include "qtcamvideomode.h"
+#include "qtcamnotifications.h"
+#include "qtcampropertysetter.h"
+#include "qtcamanalysisbin.h"
 
 QtCamDevice::QtCamDevice(QtCamConfig *config, const QString& name,
                         const QVariant& id, QObject *parent) :
@@ -24,8 +47,18 @@ QtCamDevice::QtCamDevice(QtCamConfig *config, const QString& name,
     return;
   }
 
+  d_ptr->propertySetter = new QtCamPropertySetter(d_ptr);
+
   d_ptr->createAndAddElement(d_ptr->conf->audioSource(), "audio-source", "QtCameraAudioSrc");
-  d_ptr->createAndAddVideoSource();
+  if (!d_ptr->conf->wrapperVideoSource().isEmpty() &&
+      !d_ptr->conf->wrapperVideoSourceProperty().isEmpty()) {
+    d_ptr->createAndAddVideoSourceAndWrapper();
+  }
+  else {
+    d_ptr->createAndAddVideoSource();
+  }
+
+  d_ptr->setDevicePoperty();
 
   int flags =
     0x00000001 /* no-audio-conversion - Do not use audio conversion elements */
@@ -37,12 +70,19 @@ QtCamDevice::QtCamDevice(QtCamConfig *config, const QString& name,
 
   d_ptr->setAudioCaptureCaps();
 
-  // TODO: audio bitrate
-  // TODO: video bitrate
-  // TODO: filters
-  // TODO: capabilities
-  // TODO: custom properties for jifmux, mp4mux, audio encoder, video encoder, sink & video source
-  // color tune, scene modes
+  QStringList viewfinderFilters = d_ptr->conf->viewfinderFilters();
+  if (!viewfinderFilters.isEmpty()) {
+    d_ptr->viewfinderFilters =
+      QtCamAnalysisBin::create(viewfinderFilters, "QtCamViewfinderFilters");
+
+    if (!d_ptr->viewfinderFilters) {
+      qWarning() << "Failed to create viewfinder filters";
+    }
+    else {
+      g_object_set(d_ptr->cameraBin, "viewfinder-filter", d_ptr->viewfinderFilters->bin(), NULL);
+    }
+  }
+
   d_ptr->listener = new QtCamGStreamerMessageListener(gst_element_get_bus(d_ptr->cameraBin),
                                                      d_ptr, this);
 
@@ -55,21 +95,38 @@ QtCamDevice::QtCamDevice(QtCamConfig *config, const QString& name,
   g_signal_connect(d_ptr->cameraBin, "notify::idle",
                   G_CALLBACK(QtCamDevicePrivate::on_idle_changed), d_ptr);
 
-  g_signal_connect(d_ptr->wrapperVideoSource, "notify::ready-for-capture",
-                  G_CALLBACK(QtCamDevicePrivate::on_ready_for_capture_changed), d_ptr);
+  if (d_ptr->wrapperVideoSource) {
+    g_signal_connect(d_ptr->wrapperVideoSource, "notify::ready-for-capture",
+                    G_CALLBACK(QtCamDevicePrivate::on_ready_for_capture_changed), d_ptr);
+  }
+  else {
+    g_signal_connect(d_ptr->videoSource, "notify::ready-for-capture",
+                    G_CALLBACK(QtCamDevicePrivate::on_ready_for_capture_changed), d_ptr);
+  }
 
   d_ptr->image = new QtCamImageMode(d_ptr, this);
   d_ptr->video = new QtCamVideoMode(d_ptr, this);
+
+  d_ptr->notifications = new QtCamNotifications(this, this);
 }
 
 QtCamDevice::~QtCamDevice() {
-  stop();
+  stop(true);
 
   d_ptr->image->deactivate();
   d_ptr->video->deactivate();
 
   delete d_ptr->image; d_ptr->image = 0;
   delete d_ptr->video; d_ptr->video = 0;
+
+  delete d_ptr->propertySetter;
+
+  delete d_ptr->viewfinderFilters;
+
+  if (d_ptr->cameraBin) {
+    gst_object_unref(d_ptr->cameraBin);
+  }
+
   delete d_ptr; d_ptr = 0;
 }
 
@@ -84,24 +141,26 @@ bool QtCamDevice::setViewfinder(QtCamViewfinder *viewfinder) {
   }
 
   if (!viewfinder) {
-    qWarning() << "QtCamDevice: viewfinder cannot be unset.";
-    return false;
-  }
+    if (d_ptr->cameraBin) {
+      g_object_set(d_ptr->cameraBin, "viewfinder-sink", NULL, NULL);
+    }
 
-  if (d_ptr->viewfinder) {
-    qWarning() << "QtCamDevice: viewfinder cannot be replaced.";
-    return false;
-  }
+    d_ptr->sink = 0;
 
-  if (!viewfinder->setDevice(this)) {
-    return false;
+    d_ptr->viewfinder = 0;
+    return true;
   }
 
   d_ptr->viewfinder = viewfinder;
+  d_ptr->sink = 0;
 
   return true;
 }
 
+QtCamViewfinder *QtCamDevice::viewfinder() const {
+  return d_ptr->viewfinder;
+}
+
 bool QtCamDevice::start() {
   if (d_ptr->error) {
     qWarning() << "Pipeline must be stopped first because of an error.";
@@ -140,10 +199,30 @@ bool QtCamDevice::start() {
     return false;
   }
 
+  // We need to wait for startup to complet. There's a race condition somewhere in the pipeline.
+  // If we set the scene mode to night and update the resolution while starting up
+  // then subdevsrc2 barfs:
+  // streaming task paused, reason not-negotiated (-4)
+  GstState state;
+  if (err != GST_STATE_CHANGE_ASYNC) {
+    return true;
+  }
+
+  if (gst_element_get_state(d_ptr->cameraBin, &state, 0, GST_CLOCK_TIME_NONE)
+      != GST_STATE_CHANGE_SUCCESS) {
+    // We are seriously screwed up :(
+    return false;
+  }
+
+  if (state != GST_STATE_PLAYING) {
+    // Huh ? Is this even possible ??
+    return false;
+  }
+
   return true;
 }
 
-bool QtCamDevice::stop() {
+bool QtCamDevice::stop(bool force) {
   if (!d_ptr->cameraBin) {
     return true;
   }
@@ -151,6 +230,9 @@ bool QtCamDevice::stop() {
   if (d_ptr->error) {
     gst_element_set_state(d_ptr->cameraBin, GST_STATE_NULL);
     d_ptr->error = false;
+
+    d_ptr->viewfinder->stop();
+
     return true;
   }
 
@@ -163,7 +245,9 @@ bool QtCamDevice::stop() {
   }
 
   if (!isIdle()) {
-    return false;
+    if (!force) {
+      return false;
+    }
   }
 
   // First we go to ready:
@@ -176,6 +260,8 @@ bool QtCamDevice::stop() {
   // Now to NULL
   gst_element_set_state(d_ptr->cameraBin, GST_STATE_NULL);
 
+  d_ptr->viewfinder->stop();
+
   return true;
 }
 
@@ -234,4 +320,8 @@ QtCamGStreamerMessageListener *QtCamDevice::listener() const {
   return d_ptr->listener;
 }
 
+QtCamNotifications *QtCamDevice::notifications() const {
+  return d_ptr->notifications;
+}
+
 #include "moc_qtcamdevice.cpp"