Added a floating toolbar to be used instead of the top left buttons.
[harmattan/cameraplus] / qml / RecordingPage.qml
1 // -*- qml -*-
2
3 /*!
4  * This file is part of CameraPlus.
5  *
6  * Copyright (C) 2012 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 1.1
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 // TODO: losing resources in the middle of recording will produce corrupted video
30 // TODO: optional resources?
31
32 CameraPage {
33         id: page
34         modesVisible: false
35         property bool error: false
36
37         policyMode: CameraResources.Recording
38
39         controlsVisible: cam.running && videoMode.recording && !cameraMode.animationRunning && !previewAnimationRunning && !error
40
41         orientationLock: PageOrientation.LockLandscape
42
43         function policyLost() {
44                 page.stopRecording();
45         }
46
47         function cameraError() {
48                 error = true;
49                 page.stopRecording();
50         }
51
52         Component.onDestruction: videoMode.stopRecording();
53
54         onStatusChanged: {
55                 if (page.status == PageStatus.Active) {
56                         startRecording();
57                 }
58         }
59
60         function startRecording() {
61                 if (!pipelineManager.acquired || pipelineManager.hijacked) {
62                         showError(qsTr("Failed to acquire needed resources."));
63                         pageStack.pop(undefined, true);
64                         return;
65                 }
66
67                 metaData.setMetaData();
68
69                 if (!mountProtector.lock()) {
70                         showError(qsTr("Failed to lock images directory."));
71                         pageStack.pop(undefined, true);
72                         return;
73                 }
74
75                 var file = fileNaming.videoFileName();
76                 var tmpFile = fileNaming.temporaryVideoFileName();
77
78                 if (!videoMode.startRecording(file, tmpFile)) {
79                         showError(qsTr("Failed to record video. Please restart the camera."));
80                         pageStack.pop(undefined, true);
81                         mountProtector.unlock();
82                 }
83
84                 // TODO: sometimes this fails (fast stop after start).
85                 trackerStore.storeVideo(file);
86         }
87
88         function stopRecording() {
89                 mountProtector.unlock();
90                 // Something is fishy here but if there is an error
91                 // and we use immediate mode then the page never gets destroyed.
92                 pageStack.pop(undefined, error ? false : true);
93         }
94
95         DisplayState {
96                 inhibitDim: true
97         }
98
99         onBatteryLow: {
100                 if (!checkBattery()) {
101                         page.stopRecording();
102                         showError(qsTr("Not enough battery to record video."));
103                 }
104         }
105
106         CaptureButton {
107                 id: recording
108                 anchors.right: parent.right
109                 anchors.rightMargin: 20
110                 anchors.verticalCenter: parent.verticalCenter
111                 iconSource: "image://theme/icon-m-camera-video-record"
112                 width: 75
113                 height: 75
114                 opacity: 0.5
115
116                 onClicked: page.stopRecording();
117                 visible: controlsVisible
118         }
119
120         Connections {
121                 target: Qt.application
122                 onActiveChanged: {
123                         if (!Qt.application.active) {
124                                 page.stopRecording();
125                         }
126                 }
127         }
128
129         VideoMode {
130                 id: videoMode
131                 camera: cam
132         }
133
134         Rectangle {
135                 anchors.top: parent.top
136                 anchors.topMargin: 20
137                 anchors.left: parent.left
138                 anchors.leftMargin: 20
139                 width: 48
140                 height: col.height
141                 color: "black"
142                 border.color: "gray"
143                 radius: 20
144                 opacity: 0.5
145                 visible: controlsVisible
146
147                 Column {
148                         id: col
149                         width: parent.width
150                         spacing: 5
151
152                         Indicator {
153                                 id: resolutionIndicator
154                                 source: "image://theme/" + Data.videoIcon(settings.videoResolution);
155                         }
156
157                         Indicator {
158                                 id: wbIndicator
159                                 source: visible ? "image://theme/" + Data.wbIcon(settings.videoWhiteBalance) + "-screen" : ""
160                                 visible: settings.videoWhiteBalance != WhiteBalance.Auto
161                         }
162
163                         Indicator {
164                                 id: cfIndicator
165                                 source: "image://theme/" + Data.cfIcon(settings.videoColorFilter) + "-screen"
166                                 visible: settings.videoColorFilter != ColorTone.Normal
167                         }
168
169                         Indicator {
170                                 id: gpsIndicator
171                                 visible: settings.useGps
172                                 source: "image://theme/icon-m-camera-location"
173
174                                 PropertyAnimation on opacity  {
175                                         easing.type: Easing.OutSine
176                                         loops: Animation.Infinite
177                                         from: 0.2
178                                         to: 1.0
179                                         duration: 1000
180                                         running: settings.useGps && !positionSource.position.longitudeValid
181                                         alwaysRunToEnd: true
182                                 }
183                         }
184                 }
185         }
186
187         Rectangle {
188                 anchors.bottom: parent.bottom
189                 anchors.right: parent.right
190                 anchors.rightMargin: 20
191                 anchors.bottomMargin: 20
192
193                 visible: controlsVisible
194
195                 color: "black"
196                 opacity: 0.5
197                 width: 100
198                 height: 30
199
200                 Timer {
201                         id: recordingDuration
202
203                         property int duration: 0
204
205                         running: videoMode.recording
206                         interval: 1000
207                         repeat: true
208
209                         onTriggered: {
210                                 duration = duration + 1;
211                                 if (duration == 3600) {
212                                         page.stopRecording();
213                                         showError(qsTr("Maximum recording time reached."));
214                                 }
215                                 else if (!checkDiskSpace()) {
216                                         page.stopRecording();
217                                         showError(qsTr("Not enough space to continue recording."));
218                                 }
219                         }
220                 }
221
222                 Image {
223                         id: recordingIcon
224                         source: "image://theme/icon-m-camera-ongoing-recording"
225                         width: 20
226                         height: 20
227                         anchors.verticalCenter: parent.verticalCenter
228                         anchors.left: parent.left
229                         anchors.leftMargin: 5
230                         sourceSize.width: 20
231                         sourceSize.height: 20
232                 }
233
234                 Label {
235                         function formatDuration(dur) {
236                                 var secs = parseInt(recordingDuration.duration);
237                                 var minutes = Math.floor(secs / 60);
238                                 var seconds = secs - (minutes * 60);
239
240                                 var date = new Date();
241                                 date.setSeconds(seconds);
242                                 date.setMinutes(minutes);
243                                 return Qt.formatTime(date, "mm:ss");
244                         }
245
246                         id: durationLabel
247                         text: formatDuration(recordingDuration.duration);
248                         anchors.left: recordingIcon.right
249                         anchors.leftMargin: 5
250                 }
251         }
252
253         CameraToolBar {
254                 id: toolBar
255                 anchors.bottom: parent.bottom
256                 anchors.bottomMargin: 20
257                 anchors.left: parent.left
258                 anchors.leftMargin: 20
259                 opacity: 0.5
260                 targetWidth: parent.width - (anchors.leftMargin * 2) - (66 * 1.5)
261                 visible: controlsVisible
262                 expanded: settings.showToolBar
263                 onExpandedChanged: settings.showToolBar = expanded;
264
265                 items: [
266                 VideoTorchButton {
267                         camera: cam
268                 },
269                 VideoEvCompButton {
270                         onClicked: toolBar.push(items);
271                 },
272                 VideoWhiteBalanceButton {
273                         onClicked: toolBar.push(items);
274                 },
275                 VideoColorFilterButton {
276                         onClicked: toolBar.push(items);
277                 },
278                 ToolIcon {
279                         iconSource: "image://theme/icon-m-toolbar-view-menu-white"
280                         onClicked: openFile("VideoSettingsPage.qml");
281                 }
282                 ]
283         }
284 }