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