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