diff --git a/plugin.xml b/plugin.xml
index f441c6e..fda60c6 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -67,6 +67,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ubuntu/CaptureWidget.qml b/src/ubuntu/CaptureWidget.qml
new file mode 100644
index 0000000..e3fe20e
--- /dev/null
+++ b/src/ubuntu/CaptureWidget.qml
@@ -0,0 +1,119 @@
+/*
+ *
+ * Copyright 2013 Canonical Ltd.
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+import QtQuick 2.0
+import QtMultimedia 5.0
+
+Rectangle {
+ property string shootImagePath: "shoot.png"
+ function isSuffix(str, suffix) {
+ return String(str).substr(String(str).length - suffix.length) == suffix
+ }
+
+ id: ui
+ color: "#252423"
+ anchors.fill: parent
+
+ Camera {
+ objectName: "camera"
+ id: camera
+ onError: {
+ console.log(errorString);
+ }
+ videoRecorder.audioBitRate: 128000
+ videoRecorder.mediaContainer: "mp4"
+ imageCapture {
+ onImageSaved: {
+ root.exec("Camera", "onImageSaved", [path]);
+ ui.destroy();
+ }
+ }
+ }
+ VideoOutput {
+ id: output
+ source: camera
+ width: parent.width
+ height: parent.height
+ }
+
+ Item {
+ anchors.bottom: parent.bottom
+ width: parent.width
+ height: shootButton.height
+ BorderImage {
+ id: leftBackground
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.right: middle.left
+ anchors.topMargin: units.dp(2)
+ anchors.bottomMargin: units.dp(2)
+ source: "toolbar-left.png"
+ Image {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: parent.iconSpacing
+ source: "back.png"
+ width: units.gu(6)
+ height: units.gu(5)
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ root.exec("Camera", "cancel");
+ }
+ }
+ }
+ }
+ BorderImage {
+ id: middle
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ height: shootButton.height + units.gu(1)
+ width: shootButton.width
+ source: "toolbar-middle.png"
+ Image {
+ id: shootButton
+ width: units.gu(8)
+ height: width
+ anchors.horizontalCenter: parent.horizontalCenter
+ source: shootImagePath
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ camera.imageCapture.capture();
+ }
+ }
+ }
+ }
+ BorderImage {
+ id: rightBackground
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.left: middle.right
+ anchors.topMargin: units.dp(2)
+ anchors.bottomMargin: units.dp(2)
+ source: "toolbar-right.png"
+ }
+ }
+}
diff --git a/src/ubuntu/back.png b/src/ubuntu/back.png
new file mode 100644
index 0000000..af78faa
Binary files /dev/null and b/src/ubuntu/back.png differ
diff --git a/src/ubuntu/camera.cpp b/src/ubuntu/camera.cpp
new file mode 100644
index 0000000..eada5dc
--- /dev/null
+++ b/src/ubuntu/camera.cpp
@@ -0,0 +1,143 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+#include "camera.h"
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+const char code[] = "\
+var component, object; \
+function createObject() { \
+ component = Qt.createComponent(%1); \
+ if (component.status == Component.Ready) \
+ finishCreation(); \
+ else \
+ component.statusChanged.connect(finishCreation); \
+} \
+function finishCreation() { \
+ CordovaWrapper.object = component.createObject(root, \
+ {root: root, cordova: cordova}); \
+} \
+createObject()";
+
+
+Camera::Camera(Cordova *cordova):
+ CPlugin(cordova),
+ _lastScId(0),
+ _lastEcId(0) {
+}
+
+bool Camera::preprocessImage(QString &path) {
+ bool convertToPNG = (*_options.find("encodingType")).toInt() == Camera::PNG;
+ int quality = (*_options.find("quality")).toInt();
+ int width = (*_options.find("targetWidth")).toInt();
+ int height = (*_options.find("targetHeight")).toInt();
+
+ QImage image(path);
+ if (width <= 0)
+ width = image.width();
+ if (height <= 0)
+ height = image.height();
+ image = image.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+
+ QFile oldImage(path);
+ QTemporaryFile newImage;
+
+ const char *type;
+ if (convertToPNG) {
+ newImage.setFileTemplate("imgXXXXXX.png");
+ type = "png";
+ } else {
+ newImage.setFileTemplate("imgXXXXXX.jpg");
+ type = "jpg";
+ }
+
+ newImage.open();
+ newImage.setAutoRemove(false);
+ image.save(newImage.fileName(), type, quality);
+
+ path = newImage.fileName();
+ oldImage.remove();
+
+ return true;
+}
+
+void Camera::onImageSaved(QString path) {
+ bool dataURL = _options.find("destinationType")->toInt() == Camera::DATA_URL;
+
+ QString cbParams;
+ if (preprocessImage(path)) {
+ QString absolutePath = QFileInfo(path).absoluteFilePath();
+ if (dataURL) {
+ QFile image(absolutePath);
+ image.open(QIODevice::ReadOnly);
+ QByteArray content = image.readAll().toBase64();
+ cbParams = QString("\"%1\"").arg(content.data());
+ image.remove();
+ } else {
+ cbParams = CordovaInternal::format(QUrl::fromLocalFile(absolutePath).toString());
+ }
+ }
+
+ this->callback(_lastScId, cbParams);
+
+ _lastEcId = _lastScId = 0;
+}
+
+void Camera::takePicture(int scId, int ecId, int quality, int destinationType, int/*sourceType*/, int targetWidth, int targetHeight, int encodingType,
+ int/*mediaType*/, bool/*allowEdit*/, bool/*correctOrientation*/, bool/*saveToPhotoAlbum*/, const QVariantMap &/*popoverOptions*/, int/*cameraDirection*/) {
+ if (_camera.isNull()) {
+ _camera = QSharedPointer(new QCamera());
+ }
+
+ if (((_lastScId || _lastEcId) && (_lastScId != scId && _lastEcId != ecId)) || !_camera->isAvailable() || _camera->lockStatus() != QCamera::Unlocked) {
+ this->cb(_lastEcId, "Device is busy");
+ return;
+ }
+
+ _options.clear();
+ _options.insert("quality", quality);
+ _options.insert("destinationType", destinationType);
+ _options.insert("targetWidth", targetWidth);
+ _options.insert("targetHeight", targetHeight);
+ _options.insert("encodingType", encodingType);
+
+ _lastScId = scId;
+ _lastEcId = ecId;
+
+ QString path = m_cordova->get_app_dir() + "/../qml/CaptureWidget.qml";
+
+ // TODO: relative url
+ QString qml = QString(code).arg(CordovaInternal::format(path));
+ m_cordova->execQML(qml);
+}
+
+void Camera::cancel() {
+ m_cordova->execQML("CordovaWrapper.object.destroy()");
+ this->cb(_lastEcId, "canceled");
+
+ _lastEcId = _lastScId = 0;
+}
diff --git a/src/ubuntu/camera.h b/src/ubuntu/camera.h
new file mode 100644
index 0000000..aa06698
--- /dev/null
+++ b/src/ubuntu/camera.h
@@ -0,0 +1,76 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+#ifndef CAMERA_H
+#define CAMERA_H
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+class Camera: public CPlugin {
+ Q_OBJECT
+public:
+ explicit Camera(Cordova *cordova);
+
+ virtual const QString fullName() override {
+ return Camera::fullID();
+ }
+
+ virtual const QString shortName() override {
+ return "Camera";
+ }
+
+ static const QString fullID() {
+ return "Camera";
+ }
+
+public slots:
+ void takePicture(int scId, int ecId, int quality, int destinationType, int/*sourceType*/, int targetWidth, int targetHeight, int encodingType,
+ int/*mediaType*/, bool/*allowEdit*/, bool/*correctOrientation*/, bool/*saveToPhotoAlbum*/, const QVariantMap &popoverOptions, int cameraDirection);
+ void cancel();
+
+ void onImageSaved(QString path);
+
+private:
+ bool preprocessImage(QString &path);
+
+ int _lastScId;
+ int _lastEcId;
+ QSharedPointer _camera;
+
+ QVariantMap _options;
+protected:
+ enum DestinationType {
+ DATA_URL = 0,
+ FILE_URI = 1
+ };
+ enum EncodingType {
+ JPEG = 0,
+ PNG = 1
+ };
+};
+
+#endif // CAMERA_H
diff --git a/src/ubuntu/shoot.png b/src/ubuntu/shoot.png
new file mode 100644
index 0000000..c093b63
Binary files /dev/null and b/src/ubuntu/shoot.png differ
diff --git a/src/ubuntu/toolbar-left.png b/src/ubuntu/toolbar-left.png
new file mode 100644
index 0000000..720d7f6
Binary files /dev/null and b/src/ubuntu/toolbar-left.png differ
diff --git a/src/ubuntu/toolbar-middle.png b/src/ubuntu/toolbar-middle.png
new file mode 100644
index 0000000..77595bb
Binary files /dev/null and b/src/ubuntu/toolbar-middle.png differ
diff --git a/src/ubuntu/toolbar-right.png b/src/ubuntu/toolbar-right.png
new file mode 100644
index 0000000..e4e6aa6
Binary files /dev/null and b/src/ubuntu/toolbar-right.png differ