Renamed ImageSettings.qml and VideoSettings.qml to ImageModeSettings.qml and VideoMod...
[harmattan/cameraplus] / qml / VideoOverlay.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 import "data.js" as Data
27
28 Item {
29     id: overlay
30     property bool recording: false
31
32     property Camera cam
33     property bool animationRunning: false
34     property int policyMode: recording == true ? CameraResources.Recording : CameraResources.Video
35     property bool controlsVisible: !animationRunning && cam != null && cam.running
36         && dimmer.opacity == 0.0 && !cameraMode.busy
37     property bool pressed: overlay.recording || capture.pressed ||
38         zoomSlider.pressed || modeButton.pressed
39
40     signal previewAvailable(string uri)
41
42     anchors.fill: parent
43
44     VideoMode {
45         id: videoMode
46         camera: cam
47         onPreviewAvailable: overlay.previewAvailable(preview)
48     }
49
50     ZoomSlider {
51         id: zoomSlider
52         camera: cam
53         anchors.top: parent.top
54         anchors.topMargin: 0
55         anchors.horizontalCenter: parent.horizontalCenter
56         visible: controlsVisible
57     }
58
59     ModeButton {
60         id: modeButton
61         anchors.bottom: parent.bottom
62         anchors.right: parent.right
63         anchors.rightMargin: 20
64         anchors.bottomMargin: 20
65         visible: controlsVisible && !overlay.recording
66     }
67
68     ZoomCaptureButton {
69         id: zoomCapture
70         onReleased: overlay.toggleRecording()
71     }
72
73     ZoomCaptureCancel {
74         anchors.fill: parent
75         zoomCapture: zoomCapture
76     }
77
78     CaptureButton {
79         id: capture
80         anchors.right: parent.right
81         anchors.rightMargin: 20
82         anchors.verticalCenter: parent.verticalCenter
83         iconId: overlay.recording ? cameraTheme.captureButtonRecordingIconId : cameraTheme.captureButtonVideoIconId
84         width: 75
85         height: 75
86         opacity: 0.5
87
88         onClicked: overlay.toggleRecording()
89
90         visible: controlsVisible && (!settings.zoomAsShutter && keys.active)
91     }
92
93     CameraToolBar {
94         id: toolBar
95         anchors.bottom: parent.bottom
96         anchors.bottomMargin: 20
97         anchors.left: parent.left
98         anchors.leftMargin: 20
99         opacity: 0.5
100         targetWidth: parent.width - (anchors.leftMargin * 2) - (66 * 1.5)
101         visible: controlsVisible
102         expanded: settings.showToolBar
103         onExpandedChanged: settings.showToolBar = expanded;
104
105         tools: CameraToolBarTools {
106             VideoTorchButton {
107                 camera: cam
108             }
109
110             VideoSceneButton {
111                 visible: !overlay.recording
112                 onClicked: toolBar.push(tools)
113             }
114
115             VideoEvCompButton {
116                 onClicked: toolBar.push(tools)
117             }
118
119             VideoWhiteBalanceButton {
120                 onClicked: toolBar.push(tools)
121             }
122
123             VideoColorFilterButton {
124                 onClicked: toolBar.push(tools)
125             }
126
127             VideoMuteButton {
128             }
129         }
130     }
131
132     Rectangle {
133         anchors.top: parent.top
134         anchors.topMargin: 20
135         anchors.left: parent.left
136         anchors.leftMargin: 20
137         width: 48
138         height: col.height
139         color: "black"
140         border.color: "gray"
141         radius: 20
142         opacity: 0.5
143         visible: controlsVisible
144
145         Column {
146             id: col
147             width: parent.width
148             spacing: 5
149
150             Indicator {
151                 id: resolutionIndicator
152                 source: "image://theme/" + Data.videoIcon(settings.videoResolution)
153             }
154
155             Indicator {
156                 id: wbIndicator
157                 source: visible ? "image://theme/" + Data.wbIcon(settings.videoWhiteBalance) + "-screen" : ""
158                 visible: settings.videoWhiteBalance != WhiteBalance.Auto
159             }
160
161             Indicator {
162                 id: cfIndicator
163                 source: "image://theme/" + Data.cfIcon(settings.videoColorFilter) + "-screen"
164                 visible: settings.videoColorFilter != ColorTone.Normal
165             }
166
167             Indicator {
168                 id: gpsIndicator
169                 visible: settings.useGps
170                 source: cameraTheme.gpsIndicatorIcon
171
172                 PropertyAnimation on opacity  {
173                     easing.type: Easing.OutSine
174                     loops: Animation.Infinite
175                     from: 0.2
176                     to: 1.0
177                     duration: 1000
178                     running: settings.useGps && !positionSource.position.longitudeValid
179                     alwaysRunToEnd: true
180                 }
181             }
182         }
183     }
184
185     DisplayState {
186         inhibitDim: overlay.recording
187     }
188
189     Connections {
190         target: Qt.application
191         onActiveChanged: {
192             if (!Qt.application.active && overlay.recording) {
193                 overlay.stopRecording()
194             }
195         }
196     }
197
198     Timer {
199         id: recordingDuration
200         property int duration: 0
201         running: overlay.recording
202         interval: 1000
203         repeat: true
204
205         onTriggered: {
206             duration = duration + 1
207
208             if (duration == 3600) {
209                 overlay.stopRecording()
210                 showError(qsTr("Maximum recording time reached."))
211             } else if (!checkDiskSpace()) {
212                 page.stopRecording()
213                 showError(qsTr("Not enough space to continue recording."))
214             }
215
216         }
217     }
218
219     RecordingDurationLabel {
220         visible: overlay.recording
221         duration: recordingDuration.duration
222     }
223
224     function doStartRecording() {
225         if (!overlay.recording) {
226             return
227         }
228
229         if (!pipelineManager.acquired || pipelineManager.hijacked) {
230             showError(qsTr("Failed to acquire needed resources."))
231             overlay.recording = false
232             return
233         }
234
235         metaData.setMetaData()
236
237         if (!mountProtector.lock()) {
238             showError(qsTr("Failed to lock images directory."))
239             overlay.recording = false
240             return
241         }
242
243         var file = fileNaming.videoFileName()
244         var tmpFile = fileNaming.temporaryVideoFileName()
245
246         if (!videoMode.startRecording(file, tmpFile)) {
247             showError(qsTr("Failed to record video. Please restart the camera."))
248             mountProtector.unlock()
249             overlay.recording = false
250             return
251         }
252
253         trackerStore.storeVideo(file);
254     }
255
256     function startRecording() {
257         if (!fileSystem.available) {
258             showError(qsTr("Camera cannot record videos in mass storage mode."))
259         } else if (!checkBattery()) {
260             showError(qsTr("Not enough battery to record video."))
261         } else if (!checkDiskSpace()) {
262             showError(qsTr("Not enough space to record video."))
263         } else {
264             recordingDuration.duration = 0
265             overlay.recording = true
266             doStartRecording()
267         }
268     }
269
270     function stopRecording() {
271         videoMode.stopRecording(true)
272         mountProtector.unlock()
273         overlay.recording = false
274     }
275
276     function toggleRecording() {
277         if (overlay.recording) {
278             overlay.stopRecording()
279         } else {
280             overlay.startRecording()
281         }
282     }
283
284     function cameraError() {
285         overlay.stopRecording()
286     }
287
288     function policyLost() {
289         overlay.stopRecording()
290     }
291
292     function batteryLow() {
293         if (!overlay.recording) {
294             return
295         }
296
297         if (!checkBattery()) {
298             overlay.stopRecording()
299             showError(qsTr("Not enough battery to record video."))
300         }
301     }
302
303 }