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