2fdc6efa3c490f3332f97330bc17bcb9f18cfa4c
[harmattan/cameraplus] / qml / CameraView.qml
1 // -*- qml -*-
2
3 /*!
4  * This file is part of CameraPlus.
5  *
6  * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
7  *
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.
12  *
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.
17  *
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
21  */
22
23 import QtQuick 2.0
24 import QtCamera 1.0
25 import CameraPlus 1.0
26
27 // TODO: reset reticle and roi when we stop camera or change mode
28
29 Viewfinder {
30     id: viewfinder
31     property bool pressed: focusReticle.locked || preview.animationRunning
32         || (loader.item ? loader.item.pressed : false)
33     property int policyMode: loader.item ? loader.item.policyMode : CameraResources.None
34
35     camera: cam
36     cameraConfig: cam.cameraConfig
37     renderingEnabled: mainView.currentItem == viewfinder
38
39     Component.onDestruction: cam.stop()
40
41     GridLines {
42         x: viewfinder.renderArea.x
43         y: viewfinder.renderArea.y
44         width: viewfinder.renderArea.width
45         height: viewfinder.renderArea.height
46         visible: settings.gridEnabled
47     }
48
49     Camera {
50         id: cam
51         sounds: Sounds {
52             id: sounds
53             mute: !settings.soundEnabled
54             volume: volumeControl.fullVolume ? Sounds.VolumeHigh : Sounds.VolumeLow
55             imageCaptureStart: platformSettings.imageCaptureStartedSound
56             imageCaptureEnd: platformSettings.imageCaptureEndedSound
57             videoRecordingStart: platformSettings.videoRecordingStartedSound
58             videoRecordingEnd: platformSettings.videoRecordingEndedSound
59             autoFocusAcquired: platformSettings.autoFocusAcquiredSound
60         }
61
62         onFocusChanged: focus.value = Focus.ContinuousNormal
63         onRoiChanged: roi.normalize = false
64
65         onRunningChanged: {
66             if (!cam.running) {
67                 mountProtector.unlockAll()
68             }
69         }
70
71         onError: {
72             if (pipelineManager.error) {
73                 // Ignore any subsequent errors.
74                 // Killing pulseaudio while recording will lead to an
75                 // infinite supply of errors which will break the UI
76                 // if we show a banner for each.
77                 return
78             }
79
80             pipelineManager.error = true
81             if (loader.item) {
82                 loader.item.cameraError()
83             }
84
85             console.log("Camera error (" + code + "): " + message + " " + debug)
86             showError(qsTr("Camera error. Please restart the application."))
87             // We cannot stop camera here. Seems there is a race condition somewhere
88             // which leads to a freeze if we do so.
89         }
90
91     }
92
93     SoundVolumeControl {
94         id: volumeControl
95     }
96
97     BatteryInfo {
98         id: batteryMonitor
99         active: cam.running
100
101         function check() {
102             if (!checkBattery()) {
103                 loader.item.batteryLow()
104             }
105         }
106
107         onChargingChanged: {
108             batteryMonitor.check()
109         }
110
111         onCriticalChanged: {
112             batteryMonitor.check()
113         }
114     }
115
116     PreviewImage {
117         id: preview
118     }
119
120     FocusReticle {
121         id: focusReticle
122         cam: cam
123         videoResolution: viewfinder.videoResolution
124         renderArea: viewfinder.renderArea
125
126         visible: loader.item != null && loader.item.controlsVisible &&
127             cam.autoFocus.canFocus(cam.scene.value)
128         cafStatus: cam ? cam.autoFocus.cafStatus : -1
129         status: cam ? cam.autoFocus.status : -1
130     }
131
132     Loader {
133         id: loader
134         property string src: cam.mode == Camera.VideoMode ? "VideoOverlay.qml" : "ImageOverlay.qml"
135         anchors.fill: parent
136         source: Qt.resolvedUrl(src)
137     }
138
139     Connections {
140         target: loader.item
141         onPreviewAvailable: preview.setPreview(uri)
142     }
143
144     Binding {
145         target: loader.item
146         property: "cam"
147         value: cam
148         when: loader.item != null
149     }
150
151     Binding {
152         target: loader.item
153         property: "animationRunning"
154         value: preview.animationRunning
155         when: loader.item != null
156     }
157
158     /* Camera bindings */
159     Binding {
160         target: cam.flash
161         property: "value"
162         when: cam.mode == Camera.ImageMode
163         value: settings.imageFlashMode
164     }
165
166     Binding {
167         target: settings
168         property: "imageFlashMode"
169         when: cam.mode == Camera.ImageMode
170         value: cam.flash.value
171     }
172
173     Binding {
174         target: cam.scene
175         property: "value"
176         when: cam.mode == Camera.VideoMode
177         value: settings.videoSceneMode
178     }
179
180     Binding {
181         target: cam.scene
182         property: "value"
183         when: cam.mode == Camera.ImageMode
184         value: settings.imageSceneMode
185     }
186
187     Binding {
188         target: cam.evComp
189         property: "value"
190         when: cam.mode == Camera.ImageMode
191         value: settings.imageEvComp
192     }
193
194     Binding {
195         target: cam.evComp
196         property: "value"
197         when: cam.mode == Camera.VideoMode
198         value: settings.videoEvComp
199     }
200
201     Binding {
202         target: settings
203         property: "imageEvComp"
204         when: cam.mode == Camera.ImageMode
205         value: cam.evComp.value
206     }
207
208     Binding {
209         target: settings
210         property: "videoEvComp"
211         when: cam.mode == Camera.VideoMode
212         value: cam.evComp.value
213     }
214
215     Binding {
216         target: cam.whiteBalance
217         property: "value"
218         when: cam.mode == Camera.ImageMode
219         value: settings.imageWhiteBalance
220     }
221
222     Binding {
223         target: cam.whiteBalance
224         property: "value"
225         when: cam.mode == Camera.VideoMode
226         value: settings.videoWhiteBalance
227     }
228
229     Binding {
230         target: cam.colorTone
231         property: "value"
232         when: cam.mode == Camera.ImageMode
233         value: settings.imageColorFilter
234     }
235
236     Binding {
237         target: cam.colorTone
238         property: "value"
239         when: cam.mode == Camera.VideoMode
240         value: settings.videoColorFilter
241     }
242
243     Binding {
244         target: cam.iso
245         property: "value"
246         when: cam.mode == Camera.ImageMode
247         value: settings.imageIso
248     }
249
250     Binding {
251         target: settings
252         property: "imageIso"
253         when: cam.mode == Camera.ImageMode
254         value: cam.iso.value
255     }
256
257     Binding {
258         target: cam.videoMute
259         property: "enabled"
260         value: settings.videoMuted
261     }
262
263     Binding {
264         target: cam.roi
265         property: "enabled"
266         value: settings.faceDetectionEnabled && !focusReticle.pressed && !focusReticle.touchMode && cam.mode == Camera.ImageMode
267     }
268
269     function policyLost() {
270         if (loader.item) {
271             loader.item.policyLost()
272         }
273     }
274
275     function checkBattery() {
276         // We are fine if we are connected to the charger:
277         if (batteryMonitor.charging) {
278             return true
279         }
280
281         // If we have enough battery then we are fine:
282         if (!batteryMonitor.critical) {
283             return true
284         }
285
286         return false
287     }
288 }