4 * This file is part of CameraPlus.
6 * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.org>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 import com.nokia.meego 1.1
25 import com.nokia.extras 1.1
28 import QtMobility.systeminfo 1.2 as Qtm
29 import QtMobility.location 1.2
31 // TODO: flash not ready (battery low or flash not ready message)
32 // TODO: portrait/landscape
33 // TODO: grid lines, face tracking
34 // TODO: select primary/secondary camera.
35 // TODO: disable debug builds.
36 // TODO: a way to get buffers to the application
37 // TODO: fcam like functionality (precise control over capture parameters).
42 property alias dimmer: camDimmer
46 Component.onCompleted: {
47 theme.inverted = true;
48 // TODO: hardcoding device id
49 root.resetCamera(0, settings.mode);
52 function showError(msg) {
57 function resetCamera(deviceId, mode) {
58 if (!cam.reset(deviceId, mode)) {
59 showError(qsTr("Failed to set camera device and mode. Please restart the application."));
64 // NOTE: The source will not reset the position when we lose the signal.
65 // This shouldn't be a big problem as we are course enough.
66 // If we ever need street level updates then this will be an issue.
68 active: settings.useGps
69 // TODO: we cannot bind to cam.running because camera will stop
70 // when the connection dialog pops up and we end up with an infinite loop
71 // active: cam.running && settings.useGps
72 onPositionChanged: geocode.search(position.coordinate.longitude, position.coordinate.latitude);
78 manufacturer: deviceInfo.manufacturer
79 model: deviceInfo.model
80 country: geocode.country
82 suburb: geocode.suburb
83 longitude: positionSource.position.coordinate.longitude
84 longitudeValid: positionSource.position.longitudeValid && settings.useGps
85 latitude: positionSource.position.coordinate.latitude
86 latitudeValid: positionSource.position.latitudeValid && settings.useGps
87 elevation: positionSource.position.coordinate.altitude
88 elevationValid: positionSource.position.altitudeValid && settings.useGps
89 orientation: orientation.orientation
90 artist: settings.creatorName
91 captureDirection: compass.direction
92 captureDirectionValid: compass.directionValid
93 horizontalError: positionSource.position.horizontalAccuracy
94 horizontalErrorValid: positionSource.position.horizontalAccuracyValid && settings.useGps
110 active: cam.running && settings.useGps && settings.useGeotags
136 imageSuffix: cam.imageSuffix
137 videoSuffix: cam.videoSuffix
142 path: fileNaming.path
150 if (!checkBattery()) {
151 pageStack.currentPage.batteryLow();
156 batteryMonitor.check();
160 batteryMonitor.check();
164 function replacePage(file) {
165 pageStack.replace(Qt.resolvedUrl(file), {cam: cam, dimmer: root.dimmer}, true);
168 function openFile(file) {
169 pageStack.push(Qt.resolvedUrl(file), {cam: cam, dimmer: root.dimmer});
172 function openFileNow(file) {
173 pageStack.push(Qt.resolvedUrl(file), {cam: cam, dimmer: root.dimmer}, true);
176 function checkBattery() {
177 // We are fine if we are connected to the charger:
178 if (batteryMonitor.charging) {
182 // If we have enough battery then we are fine:
183 if (!batteryMonitor.critical) {
190 platformStyle: PageStackWindowStyle {
191 cornersVisible: false
193 backgroundColor: "transparent"
199 function setImageResolution() {
200 if (!imageSettings.setResolution(settings.imageAspectRatio, settings.imageResolution)) {
201 showError(qsTr("Failed to set required resolution"));
207 imageSettings.setImageResolution();
216 function setVideoResolution() {
217 if (!videoSettings.setResolution(settings.videoAspectRatio, settings.videoResolution)) {
218 showError(qsTr("Failed to set required resolution"));
224 videoSettings.setVideoResolution();
232 onImageAspectRatioChanged: {
233 imageSettings.setImageResolution();
236 onImageResolutionChanged: {
237 imageSettings.setImageResolution();
240 onVideoResolutionChanged: {
241 videoSettings.setVideoResolution();
252 visible: pageStack.currentPage && pageStack.currentPage.controlsVisible && pageStack.currentPage.focusReticleVisible && cam && cam.autoFocus.canFocus(cam.scene.value);
253 cafStatus: cam ? cam.autoFocus.cafStatus : -1
254 status: cam ? cam.autoFocus.status : -1
259 // TODO: is this needed ?
260 if (platformWindow.active) {
266 if (pipelineManager.error) {
267 // Ignore any subsequent errors.
268 // Killing pulseaudio while recording will lead to an
269 // infinite supply of errors which will break the UI
270 // if we show a banner for each.
274 pipelineManager.error = true;
275 pageStack.currentPage.cameraError();
276 console.log("Camera error (" + code + "): " + message + " " + debug);
277 showError(qsTr("Camera error. Please restart the application."));
279 // We cannot stop camera here. Seems there is a race condition somewhere
280 // which leads to a freeze if we do so.
285 mountProtector.unlock();
289 Component.onDestruction: cam.stop();
291 // We need to show viewfinder below pages.
295 property bool dimmed: false
299 opacity: dimmed ? 1.0 : 0.0
301 Behavior on opacity {
302 PropertyAnimation { duration: 150 }
306 notifications: Sounds {
308 mute: !settings.soundEnabled
316 when: cam.mode == Camera.ImageMode
317 value: settings.imageFlashMode
322 property: "imageFlashMode"
323 when: cam.mode == Camera.ImageMode
324 value: cam.flash.value
330 when: cam.mode == Camera.VideoMode
331 value: settings.videoSceneMode
337 when: cam.mode == Camera.ImageMode
338 value: settings.imageSceneMode
344 when: cam.mode == Camera.ImageMode
345 value: settings.imageEvComp
351 when: cam.mode == Camera.VideoMode
352 value: settings.videoEvComp
357 property: "imageEvComp"
358 when: cam.mode == Camera.ImageMode
359 value: cam.evComp.value
364 property: "videoEvComp"
365 when: cam.mode == Camera.VideoMode
366 value: cam.evComp.value
370 target: cam.whiteBalance
372 when: cam.mode == Camera.ImageMode
373 value: settings.imageWhiteBalance
377 target: cam.whiteBalance
379 when: cam.mode == Camera.VideoMode
380 value: settings.videoWhiteBalance
384 target: cam.colorTone
386 when: cam.mode == Camera.ImageMode
387 value: settings.imageColorFilter
391 target: cam.colorTone
393 when: cam.mode == Camera.VideoMode
394 value: settings.videoColorFilter
400 when: cam.mode == Camera.ImageMode
401 value: settings.imageIso
407 when: cam.mode == Camera.ImageMode
412 target: cam.videoMute
414 value: settings.videoMuted
420 manufacturer: deviceInfo.manufacturer
421 model: deviceInfo.model
433 if (cam.mode == Camera.VideoMode) {
434 replacePage("VideoPage.qml");
437 replacePage("ImagePage.qml");
443 policyLost: pipelineManager.state == "policyLost"
444 show: !pageStack.currentPage || (pageStack.currentPage.standbyVisible && pageStack.currentPage.status == PageStatus.Active && pipelineManager.showStandBy)