Reworking resource policy and pipeline handling to use states and transitions
[harmattan/cameraplus] / qml / main.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 com.nokia.extras 1.1
26 import QtCamera 1.0
27 import CameraPlus 1.0
28 import QtMobility.systeminfo 1.2
29 import QtMobility.location 1.2
30
31 // TODO: postcapture
32 // TODO: flash not ready
33 // TODO: focus, caf, ...
34 // TODO: portrait/landscape
35 // TODO: stop viewfinder in settings pages ?
36 // TODO: grid lines, face tracking, ambr
37 // TODO: select primary/secondary camera.
38 // TODO: disable debug builds.
39 // TODO: a way to get buffers to the application
40 // TODO: fcam like functionality (precise control over capture parameters).
41 // TODO: mute video sound
42
43 PageStackWindow {
44         id: root
45
46         property alias dimmer: camDimmer
47
48         showStatusBar: false
49
50         Component.onCompleted: {
51                 theme.inverted = true;
52                 // TODO: hardcoding device id
53                 root.resetCamera(0, settings.mode);
54         }
55
56         function showError(msg) {
57                 error.text = msg;
58                 error.show();
59         }
60
61         function resetCamera(deviceId, mode) {
62                 if (!cam.reset(deviceId, mode)) {
63                         showError(qsTr("Failed to set camera device and mode. Please restart the application."));
64                 }
65         }
66
67         PositionSource {
68                 // NOTE: The source will not reset the position when we lose the signal.
69                 // This shouldn't be a big problem as we are course enough.
70                 // If we ever need street level updates then this will be an issue.
71                 id: positionSource
72                 active: settings.useGps
73                 // TODO: we cannot bind to cam.running because camera will stop
74                 // when the connection dialog pops up and we end up with an infinite loop
75                 // active: cam.running && settings.useGps
76                 onPositionChanged: geocode.search(position.coordinate.longitude, position.coordinate.latitude);
77         }
78
79         MetaData {
80                 id: metaData
81                 camera: cam
82                 manufacturer: deviceInfo.manufacturer
83                 model: deviceInfo.model
84                 country: geocode.country
85                 city: geocode.city
86                 suburb: geocode.suburb
87                 longitude: positionSource.position.coordinate.longitude
88                 longitudeValid: positionSource.position.longitudeValid && settings.useGps
89                 latitude: positionSource.position.coordinate.latitude
90                 latitudeValid: positionSource.position.latitudeValid && settings.useGps
91                 elevation: positionSource.position.coordinate.altitude
92                 elevationValid: positionSource.position.altitudeValid && settings.useGps
93                 orientation: orientation.orientation
94                 artist: settings.creatorName
95                 captureDirection: compass.direction
96                 captureDirectionValid: compass.directionValid
97                 horizontalError: positionSource.position.horizontalAccuracy
98                 horizontalErrorValid: positionSource.position.horizontalAccuracyValid && settings.useGps
99                 dateTimeEnabled: true
100         }
101
102         Orientation {
103                 id: orientation
104                 active: cam.running
105         }
106
107         Compass {
108                 id: compass
109                 active: cam.running
110         }
111
112         ReverseGeocode {
113                 id: geocode
114                 active: cam.running && settings.useGps && settings.useGeotags
115         }
116
117         PipelineManager {
118                 id: pipelineManager
119                 camera: cam
120         }
121
122         DeviceInfo {
123                 id: deviceInfo
124         }
125
126         FSMonitor {
127                 id: fileSystem
128         }
129
130         InfoBanner {
131                 id: error
132         }
133
134         Settings {
135                 id: settings
136         }
137
138         FileNaming {
139                 id: fileNaming
140                 imageSuffix: cam.imageSuffix
141                 videoSuffix: cam.videoSuffix
142         }
143
144         MountProtector {
145                 id: mountProtector
146                 path: fileNaming.path
147         }
148
149         function replacePage(file) {
150                 pageStack.replace(Qt.resolvedUrl(file), {cam: cam}, true);
151         }
152
153         function openFile(file) {
154                 pageStack.push(Qt.resolvedUrl(file), {cam: cam});
155         }
156
157         function openFileNow(file) {
158                 pageStack.push(Qt.resolvedUrl(file), {cam: cam}, true);
159         }
160
161         platformStyle: PageStackWindowStyle {
162                 // TODO: Hack
163                 background: " "
164         }
165
166         ImageSettings {
167                 id: imageSettings
168                 camera: cam
169                 function setImageResolution() {
170                         if (!imageSettings.setResolution(settings.imageAspectRatio, settings.imageResolution)) {
171                                 showError(qsTr("Failed to set required resolution"));
172                         }
173                 }
174
175                 onReadyChanged: {
176                         if (ready) {
177                                 imageSettings.setImageResolution();
178                         }
179                 }
180         }
181
182         VideoSettings {
183                 id: videoSettings
184                 camera: cam
185
186                 function setVideoResolution() {
187                         if (!videoSettings.setResolution(settings.videoAspectRatio, settings.videoResolution)) {
188                                 showError(qsTr("Failed to set required resolution"));
189                         }
190                 }
191
192                 onReadyChanged: {
193                         if (ready) {
194                                 videoSettings.setVideoResolution();
195                         }
196                 }
197         }
198
199         Connections {
200                 target: settings
201
202                 onImageAspectRatioChanged: {
203                         imageSettings.setImageResolution();
204                 }
205
206                 onImageResolutionChanged: {
207                         imageSettings.setImageResolution();
208                 }
209
210                 onVideoResolutionChanged: {
211                         videoSettings.setVideoResolution();
212                 }
213         }
214
215         Camera {
216 /*
217                 onDeviceIdChanged: {
218                         // TODO: is this needed ?
219                         if (platformWindow.active) {
220                                 cam.start();
221                         }
222                 }
223 */
224                 id: cam
225                 anchors.fill: parent
226
227                 onError: {
228                         console.log("Camera error (" + code + "): " + message + " " + debug);
229                         showError(qsTr("Camera error. Please restart the application."));
230                         cam.stop();
231                         resourcePolicy.acquire(CameraResources.None);
232                         mountProtector.unlock();
233                 }
234
235                 onRunningChanged: {
236                         if (!cam.running) {
237                                 mountProtector.unlock();
238                         }
239                 }
240
241                 Component.onDestruction: cam.stop();
242
243                 // TODO: Hack
244                 z: -1
245
246                 Rectangle {
247                         id: camDimmer
248                         z: 1
249                         anchors.fill: parent
250                         opacity: 0
251                         color: "black"
252                 }
253
254                 notifications: Sounds {
255                         id: sounds
256                         mute: !settings.soundEnabled
257                 }
258
259         }
260
261         Binding {
262                 target: cam.flash
263                 property: "value"
264                 when: cam.mode == Camera.ImageMode
265                 value: settings.imageFlashMode
266         }
267
268         Binding {
269                 target: settings
270                 property: "imageFlashMode"
271                 when: cam.mode == Camera.ImageMode
272                 value: cam.flash.value
273         }
274
275         Binding {
276                 target: cam.scene
277                 property: "value"
278                 when: cam.mode == Camera.VideoMode
279                 value: settings.videoSceneMode
280         }
281
282         Binding {
283                 target: cam.scene
284                 property: "value"
285                 when: cam.mode == Camera.ImageMode
286                 value: settings.imageSceneMode
287         }
288
289         Binding {
290                 target: cam.evComp
291                 property: "value"
292                 when: cam.mode == Camera.ImageMode
293                 value: settings.imageEvComp
294         }
295
296         Binding {
297                 target: cam.evComp
298                 property: "value"
299                 when: cam.mode == Camera.VideoMode
300                 value: settings.videoEvComp
301         }
302
303         Binding {
304                 target: settings
305                 property: "imageEvComp"
306                 when: cam.mode == Camera.ImageMode
307                 value: cam.evComp.value
308         }
309
310         Binding {
311                 target: settings
312                 property: "videoEvComp"
313                 when: cam.mode == Camera.VideoMode
314                 value: cam.evComp.value
315         }
316
317         Binding {
318                 target: cam.whiteBalance
319                 property: "value"
320                 when: cam.mode == Camera.ImageMode
321                 value: settings.imageWhiteBalance
322         }
323
324         Binding {
325                 target: cam.whiteBalance
326                 property: "value"
327                 when: cam.mode == Camera.VideoMode
328                 value: settings.videoWhiteBalance
329         }
330
331         Binding {
332                 target: cam.colorTone
333                 property: "value"
334                 when: cam.mode == Camera.ImageMode
335                 value: settings.imageColorFilter
336         }
337
338         Binding {
339                 target: cam.colorTone
340                 property: "value"
341                 when: cam.mode == Camera.VideoMode
342                 value: settings.videoColorFilter
343         }
344
345         Binding {
346                 target: cam.iso
347                 property: "value"
348                 when: cam.mode == Camera.ImageMode
349                 value: settings.imageIso
350         }
351
352         Binding {
353                 target: settings
354                 property: "imageIso"
355                 when: cam.mode == Camera.ImageMode
356                 value: cam.iso.value
357         }
358
359         TrackerStore {
360                 id: trackerStore
361                 active: cam.running
362                 manufacturer: deviceInfo.manufacturer
363                 model: deviceInfo.model
364         }
365
366         ModeController {
367                 id: cameraMode
368                 cam: cam
369                 dimmer: root.dimmer
370         }
371
372         Connections {
373                 target: cam
374                 onModeChanged: {
375                         if (cam.mode == Camera.VideoMode) {
376                                 replacePage("VideoPage.qml");
377                         }
378                         else {
379                                 replacePage("ImagePage.qml");
380                         }
381                 }
382         }
383 }