Updated application sources 70/22370/1
authorPawel Sierszen <p.sierszen@samsung.com>
Mon, 2 Jun 2014 12:51:25 +0000 (14:51 +0200)
committerPawel Sierszen <p.sierszen@samsung.com>
Mon, 2 Jun 2014 12:51:25 +0000 (14:51 +0200)
Change-Id: Iaa2e8d2ca1787835e36ec4b58204651a30378963
Signed-off-by: Pawel Sierszen <p.sierszen@samsung.com>
project/config.xml
project/css/style.css
project/index.html
project/js/app.systemIO.js
project/js/main.js

index 5035b4f..95f7adb 100644 (file)
@@ -1,15 +1,37 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://sample-web-application.tizen.org/SelfCamera" version="2.2.0" viewmodes="maximized">
-       <access origin="*" subdomains="true"/>
-       <tizen:application id="QvgnlNAjTV.SelfCamera" package="QvgnlNAjTV" required_version="2.2"/>
-       <content src="index.html"/>
-       <icon src="icon.png"/>
-       <name>Self Camera</name>
-       <feature name="http://tizen.org/feature/screen.size.normal.720.1280"/>
-       <tizen:privilege name="http://tizen.org/privilege/application.launch"/>
-       <tizen:privilege name="http://tizen.org/privilege/filesystem.read"/>
-       <tizen:privilege name="http://tizen.org/privilege/filesystem.write"/>
-       <tizen:privilege name="http://tizen.org/privilege/content.read"/>
-       <tizen:privilege name="http://tizen.org/privilege/content.write"/>
-       <tizen:setting screen-orientation="portrait" context-menu="disable" background-support="disable" encryption="disable" install-location="auto"/>
+<widget
+    xmlns="http://www.w3.org/ns/widgets"
+    xmlns:tizen="http://tizen.org/ns/widgets"
+    id="http://sample-web-application.tizen.org/SelfCamera"
+    version="2.2.0"
+    viewmodes="maximized">
+
+    <tizen:application
+        id="QvgnlNAjTV.SelfCamera"
+        package="QvgnlNAjTV"
+        required_version="2.2" />
+
+    <content src="index.html" />
+
+    <icon src="icon.png" />
+
+    <name>Self Camera</name>
+
+    <feature name="http://tizen.org/feature/screen.size.normal.720.1280" />
+
+    <tizen:privilege name="http://tizen.org/privilege/application.launch" />
+    <tizen:privilege name="http://tizen.org/privilege/filesystem.read" />
+    <tizen:privilege name="http://tizen.org/privilege/filesystem.write" />
+    <tizen:privilege name="http://tizen.org/privilege/content.read" />
+    <tizen:privilege name="http://tizen.org/privilege/content.write" />
+
+    <tizen:setting
+        screen-orientation="portrait"
+        context-menu="disable"
+        background-support="disable"
+        encryption="disable"
+        install-location="auto" />
+
+    <access origin="*" subdomains="true" />
+
 </widget>
index 6f9b4c7..30a9b66 100644 (file)
 * {
-       font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+    font-family: Lucida Sans, Arial, Helvetica, sans-serif;
 }
 
 body {
-       height: 100%;
-       width: 100%;
-       padding: 0;
-       margin: 0;
-       background-color: black;
+    height: 100%;
+    width: 100%;
+    padding: 0;
+    margin: 0;
+    background-color: black;
+    -webkit-user-select: none;
 }
 
 
 #camera {
-       width: 100%;
-       height: 100%;
-       overflow: hidden;
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
 }
 
 #video {
-       display: block;
+    display: block;
 }
 
 .timers {
-       position: absolute;
-       width: 100%;
-       background-color: rgba(10, 10, 10, 0.4);
-       top: 0;
-       left: 0;
+    position: absolute;
+    width: 100%;
+    background-color: rgba(10, 10, 10, 0.4);
+    top: 0;
+    left: 0;
 }
 
 .timers div {
-       float: left;
-       width: 34px;
-       height: 34px;
-       background-size: 34px;
-       background-color: transparent;
-       background-repeat: no-repeat;
-       z-index: 10;
-       margin: 0 4px;
+    float: left;
+    width: 34px;
+    height: 34px;
+    background-size: 34px;
+    background-color: transparent;
+    background-repeat: no-repeat;
+    z-index: 10;
+    margin: 0 4px;
 }
 
 .timers div.selected {
-       background-color: rgba(0,0,0,0.2);
+    background-color: rgba(0,0,0,0.2);
 }
 
 div#timer2 {
-       background-image: url('../images/timer_2.png');
-       margin: 8px;
+    background-image: url('../images/timer_2.png');
+    margin: 8px;
 }
 
 div#timer2.selected {
-       background-image: url('../images/timer_2_selected.png');
-       margin: 8px;
+    background-image: url('../images/timer_2_selected.png');
+    margin: 8px;
 }
 
 div#timer5 {
-       background-image: url('../images/timer_5.png');
-       margin: 8px;
+    background-image: url('../images/timer_5.png');
+    margin: 8px;
 }
 
 div#timer5.selected {
-       background-image: url('../images/timer_5_selected.png');
-       margin: 8px;
+    background-image: url('../images/timer_5_selected.png');
+    margin: 8px;
 }
 
 div#timer10 {
-       background-image: url('../images/timer_10.png');
-       margin: 8px;
+    background-image: url('../images/timer_10.png');
+    margin: 8px;
 }
 
 div#timer10.selected {
-       background-image: url('../images/timer_10_selected.png');
-       margin: 8px;
+    background-image: url('../images/timer_10_selected.png');
+    margin: 8px;
 }
 
 div#countdown {
-       position: absolute;
-       width: 100%;
-       height: 100%;
-       top: 20%;
-       font-size: 200pt;
-       text-align: center;
-       vertical-align: middle;
-       color: rgba(135,226,0,0.8);
-       margin: auto 0;
-       z-index: 10;
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    top: 20%;
+    font-size: 200pt;
+    text-align: center;
+    vertical-align: middle;
+    color: rgba(135,226,0,0.8);
+    margin: auto 0;
+    z-index: 10;
 }
 
 div#thumbnail { /* image size: 80x91, *0.7 */
-       position: absolute;
-       width: 56px;
-       height: 64px;
-       left: 13px;
-       bottom: 19px;
-       background-size: 56px 64px;
-       background-color: transparent;
-       background-image: url('../images/none.png');
-       background-reapeat: no-repeat;
-       z-index: 100;
+    position: absolute;
+    width: 56px;
+    height: 64px;
+    left: 13px;
+    bottom: 19px;
+    background-size: 56px 64px;
+    background-color: transparent;
+    background-image: url('../images/none.png');
+    background-reapeat: no-repeat;
+    z-index: 100;
 }
 
 div#shutter-container {
-       width: 100%;
-       height: 86px;
-       position: absolute;
-       bottom: 0;
-       z-index: 11
+    width: 100%;
+    height: 86px;
+    position: absolute;
+    bottom: 0;
+    z-index: 11;
 }
 
 div#shutter {
-       height: 86px;
-       width: 90px;
-       background-size: 86px;
-       background-color: transparent;
-       background-image: url('../images/shutter.png');
-       background-repeat: no-repeat;
-       margin: 0px auto;
-       z-index: 11
+    height: 86px;
+    width: 90px;
+    background-size: 86px;
+    background-color: transparent;
+    background-image: url('../images/shutter.png');
+    background-repeat: no-repeat;
+    margin: 0px auto;
+    z-index: 11;
 }
 
 div#shutter.active {
-       background-image: url('../images/shutter2.png');
+    background-image: url('../images/shutter2.png');
 }
 
 div#bar {
-       position: absolute;
-       height: 43px;
-       width: 100%;
-       left: 0px;
-       bottom: 0px;
-       z-index: 10;
-       background-size: 100% 100%;
-       background-color: transparent;
-       background-image: url('../images/bar.png');
-       background-repeat: no-repeat;
+    position: absolute;
+    height: 43px;
+    width: 100%;
+    left: 0px;
+    bottom: 0px;
+    z-index: 10;
+    background-size: 100% 100%;
+    background-color: transparent;
+    background-image: url('../images/bar.png');
+    background-repeat: no-repeat;
 }
 
 div#countdown {
-       display: none;
-       width: 100%;
-       height: 80%;
-       position: absolute;
-       background-size: 100%;
-       z-index: 15;
+    display: none;
+    width: 100%;
+    height: 80%;
+    position: absolute;
+    background-size: 100%;
+    z-index: 15;
 }
 
 .audio {
-       position: absolute;
-       top: 100px;
-       left: 10px;
-       opacity: 1;
+    position: absolute;
+    top: 100px;
+    left: 10px;
+    opacity: 1;
 }
 
 #upImage {
-       position: absolute;
-       top: 4px;
-       left: 4px;
-       width: 48px;
-       height: 48px;
-       background-size: 100%;
-       background-color: black;
-       background-position:center;
-       background-repeat: no-repeat;
+    position: absolute;
+    top: 4px;
+    left: 4px;
+    width: 48px;
+    height: 48px;
+    background-size: 100%;
+    background-color: black;
+    background-position:center;
+    background-repeat: no-repeat;
+}
+
+#failure {
+    display: none;
+    z-index: 200;
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    width: 100%;
+    height: 100%;
+    background: rgba(0,0,0,0.8);
+    color: yellow;
+    font-weight: bold;
+    text-align: center;
+    font-size: 18pt;
+    padding-top: 75%;
 }
index 6f47acb..253a319 100644 (file)
@@ -1,38 +1,43 @@
 <!DOCTYPE html>
 <html>
 <head>
-       <meta charset="utf-8"/>
-       <meta name="viewport" content="width=360, user-scalable=no"/>
-       <meta name="description" content="SelfCamera"/>
 
-       <title>Self camera</title>
+    <meta charset="utf-8"/>
+    <meta name="viewport" content="width=360, user-scalable=no"/>
 
-       <link rel="stylesheet" type="text/css" href="css/style.css"/>
-       <script src="tizen-web-ui-fw/latest/js/jquery.min.js"></script>
-       <script src="js/app.systemIO.js"></script>
-       <script src="js/main.js"></script>
-</head>
+    <title>Self camera</title>
+    <meta name="description" content="SelfCamera"/>
+
+    <script src="/usr/share/tizen-web-ui-fw/latest/js/jquery.min.js"></script>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+    <script src="js/app.systemIO.js"></script>
+    <script src="js/main.js"></script>
 
+</head>
 <body>
-       <div id="camera"></div>
 
-       <div id="countdown"></div>
+    <div id="camera"></div>
+
+    <div id="countdown"></div>
+
+    <div class="timers">
+        <div id="timer2"></div>
+        <div id="timer5"></div>
+        <div id="timer10"></div>
+    </div>
 
-       <div class="timers">
-               <div id="timer2"></div>
-               <div id="timer5"></div>
-               <div id="timer10"></div>
-       </div>
+    <div id="thumbnail">
+        <div id="upImage"></div>
+    </div>
 
-       <div id="thumbnail">
-               <div id="upImage"></div>
-       </div>
+    <div id="shutter-container">
+        <div id="shutter"></div>
+    </div>
 
-       <div id="shutter-container">
-               <div id="shutter"></div>
-       </div>
+    <div id="bar"></div>
 
-       <div id="bar"></div>
+    <div id="failure">Failed to take photo!</div>
 
 </body>
 </html>
index cf6166c..365b8b6 100644 (file)
@@ -1,3 +1,19 @@
+/*
+ *      Copyright 2013  Samsung Electronics Co., Ltd
+ *
+ *      Licensed under the Flora License, Version 1.1 (the "License");
+ *      you may not use this file except in compliance with the License.
+ *      You may obtain a copy of the License at
+ *
+ *              http://floralicense.org/license/
+ *
+ *      Unless required by applicable law or agreed to in writing, software
+ *      distributed under the License is distributed on an "AS IS" BASIS,
+ *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *      See the License for the specific language governing permissions and
+ *      limitations under the License.
+ */
+
 /*jslint devel: true*/
 /*global tizen, $, app, localStorage */
 
  * @class SystemIO
  */
 function SystemIO() {
-       'use strict';
+    'use strict';
 }
 
 (function () { // strict mode wrapper
-       'use strict';
-       SystemIO.prototype = {
-               /**
-                * Creates new empty file in specified location
-                * 
-                * @param {File} directoryHandle
-                * @param {string} fileName
-                */
-               createFile: function SystemIO_createFile(directoryHandle, fileName) {
-
-                       try {
-                               return directoryHandle.createFile(fileName);
-                       } catch (e) {
-                               console.error('SystemIO_createFile error: ' + e.message);
-                               return false;
-                       }
-               },
+    'use strict';
+    SystemIO.prototype = {
+        /**
+         * Creates new empty file in specified location
+         * @param {File} directoryHandle
+         * @param {string} fileName
+         */
+        createFile: function SystemIO_createFile(directoryHandle, fileName) {
+            try {
+                return directoryHandle.createFile(fileName);
+            } catch (e) {
+                console.error('SystemIO_createFile error: ' + e.message);
+                return false;
+            }
+        },
 
-               /**
-                * Writes content to file stream
-                * 
-                * @param {File} file handler
-                * @param {string} file content
-                * @param {function} on success callback with one argument {File} fileHandle
-                * @param {string} content encoding
-                */
-               writeFile: function SystemIO_writeFile(fileHandle, fileContent, onSuccess, onError, contentEncoding) {
-                       onError = onError || function () {};
-                       fileHandle.openStream('w', function (fileStream) {
-                               try {
-                                       if (contentEncoding === 'base64') {
-                                               fileStream.writeBase64(fileContent);
-                                       } else {
-                                               fileStream.write(fileContent);
-                                       }
-                                       fileStream.close();
-                               } catch(e) {
-                                       onError(fileHandle);
-                               }
-                               if (typeof onSuccess === 'function') {
-                                       onSuccess(fileHandle);
-                               }
-                       }, onError, 'UTF-8');
-               },
+        /**
+         * Writes content to file stream
+         * @param {File} file handler
+         * @param {string} file content
+         * @param {function} on success callback with one argument {File}
+         *     fileHandle
+         * @param {string} content encoding
+         */
+        writeFile: function SystemIO_writeFile(fileHandle, fileContent,
+            onSuccess, onError, contentEncoding) {
+            onError = onError || function () {};
+            fileHandle.openStream('w', function (fileStream) {
+                try {
+                    if (contentEncoding === 'base64') {
+                        fileStream.writeBase64(fileContent);
+                    } else {
+                        fileStream.write(fileContent);
+                    }
+                    fileStream.close();
+                } catch (e) {
+                    fileStream.close();
+                    onError(fileHandle);
+                    return;
+                }
+                if (typeof onSuccess === 'function') {
+                    onSuccess(fileHandle);
+                }
+            }, onError, 'UTF-8');
+        },
 
-               /**
-                * Opens specified location
-                * 
-                * @param {string} directory path
-                * @param {function} on success callback
-                * @param {function} on error callback
-                * @param {string} mode
-                */
-               openDir: function SystemIO_openDir(directoryPath, onSuccess, onError, openMode) {
-                       openMode = openMode || 'rw';
-                       onSuccess = onSuccess || function () {};
-                       onError = onError || function () {};
+        /**
+         * Opens specified location
+         * @param {string} directory path
+         * @param {function} on success callback
+         * @param {function} on error callback
+         * @param {string} mode
+         */
+        openDir: function SystemIO_openDir(directoryPath, onSuccess, onError,
+            openMode) {
+            openMode = openMode || 'rw';
+            onSuccess = onSuccess || function () {};
+            onError = onError || function () {};
 
-                       try {
-                               tizen.filesystem.resolve(directoryPath, onSuccess, onError, openMode);
-                       } catch (e) {
-                               console.error('SystemIO_openDir error:' + e.message);
-                       }
-               },
+            try {
+                tizen.filesystem.resolve(directoryPath, onSuccess, onError,
+                    openMode);
+            } catch (e) {
+                console.error('SystemIO_openDir error:' + e.message);
+            }
+        },
 
-               /**
-                * Get list of files
-                * 
-                * @param {string} directoryPath directory path
-                * @param {function} onSuccess on success callback
-                * @param {function} onError on error callback
-                * @param {string} fileMask
-                */
-               dir: function SystemIO_dir(directoryPath, onSuccess, onError, fileMask) {
-                       fileMask = fileMask || '';
-                       onSuccess = onSuccess || function () {};
+        /**
+         * Get list of files
+         * @param {string} directoryPath directory path
+         * @param {function} onSuccess on success callback
+         * @param {function} onError on error callback
+         * @param {string} fileMask
+         */
+        dir:
+            function SystemIO_dir(directoryPath, onSuccess, onError, fileMask) {
+            fileMask = fileMask || '';
+            onSuccess = onSuccess || function () {};
 
-                       function onOpenDir(dir) {
-                               var filter = null;
-                               if (typeof dir === 'undefined') {
-                                       throw {message: 'dir is not object'};
-                               }
-                               if (!dir.toString().match('File')) {
-                                       throw {message: 'dir is not instance of File'};
-                               }
-                               fileMask = (typeof fileMask === 'string') ? {name: fileMask} : fileMask;
-                               filter = fileMask || null;
-                               dir.listFiles(onSuccess, onError, filter);
-                       }
+            function onOpenDir(dir) {
+                var filter = null;
+                if (typeof dir === 'undefined') {
+                    throw {message: 'dir is not object'};
+                }
+                if (!dir.toString().match('File')) {
+                    throw {message: 'dir is not instance of File'};
+                }
+                fileMask = (typeof fileMask === 'string')
+                    ? {name: fileMask} : fileMask;
+                filter = fileMask || null;
+                dir.listFiles(onSuccess, onError, filter);
+            }
 
-                       function onOpenDirError(e) {
-                               console.error('onOpenDirError: ' + e.message);
-                       }
+            function onOpenDirError(e) {
+                console.error('onOpenDirError: ' + e.message);
+            }
 
-                       try {
-                               this.openDir(directoryPath, onOpenDir, onOpenDirError, 'r');
-                       } catch (e) {
-                               console.error('SystemIO_dir error:' + e.message);
-                       }
-               },
+            try {
+                this.openDir(directoryPath, onOpenDir, onOpenDirError, 'r');
+            } catch (e) {
+                console.error('SystemIO_dir error:' + e.message);
+            }
+        },
 
-               /**
-                * Parse specified filepath and returns data parts
-                * 
-                * @param {string} filePath
-                * @returnss {array}
-                */
-               getPathData: function SystemIO_getPathData(filePath) {
-                       var path = {
-                               originalPath: filePath,
-                               fileName: '',
-                               dirName: ''
-                       },
-                               splittedPath = filePath.split('/');
+        /**
+         * Parse specified filepath and returns data parts
+         * @param {string} filePath
+         * @returnss {array}
+         */
+        getPathData: function SystemIO_getPathData(filePath) {
+            var path = {
+                originalPath: filePath,
+                fileName: '',
+                dirName: ''
+            },
+                splittedPath = filePath.split('/');
 
-                       path.fileName = splittedPath.pop();
-                       path.dirName = splittedPath.join('/') || '/';
+            path.fileName = splittedPath.pop();
+            path.dirName = splittedPath.join('/') || '/';
 
-                       return path;
-               },
+            return path;
+        },
 
-               /**
-                * Save specified content to file
-                * 
-                * @param {string} file path
-                * @param {string} file content
-                * @param {string} file encoding
-                */
-               saveFileContent: function SystemIO_saveFileContent(filePath, fileContent, onSaveSuccess, onSaveFailure, fileEncoding) {
-                       var pathData = this.getPathData(filePath),
-                               self = this,
-                               fileHandle;
+        /**
+         * Save specified content to file
+         * @param {string} file path
+         * @param {string} file content
+         * @param {string} file encoding
+         */
+        saveFileContent: function SystemIO_saveFileContent(filePath,
+            fileContent, onSaveSuccess, onSaveFailure, fileEncoding) {
+            var pathData = this.getPathData(filePath),
+                self = this,
+                fileHandle;
 
-                       function onOpenDirSuccess(dir) {
-                               // create new file
-                               fileHandle = self.createFile(dir, pathData.fileName);
-                               if (fileHandle !== false) {
-                                       // save data into this file
-                                       self.writeFile(fileHandle, fileContent, onSaveSuccess, onSaveFailure, fileEncoding);
-                               } else {
-                                       onSaveFailure();
-                               }
-                       }
+            function onOpenDirSuccess(dir) {
+                // create new file
+                fileHandle = self.createFile(dir, pathData.fileName);
+                if (fileHandle !== false) {
+                    // save data into this file
+                    self.writeFile(fileHandle, fileContent, onSaveSuccess,
+                        onSaveFailure, fileEncoding);
+                } else {
+                    onSaveFailure();
+                }
+            }
 
-                       // open directory
-                       this.openDir(pathData.dirName, onOpenDirSuccess, onSaveFailure);
-               },
+            // open directory
+            this.openDir(pathData.dirName, onOpenDirSuccess, onSaveFailure);
+        },
 
-               /**
-                * Deletes node with specified path
-                * 
-                * @param {string} node path
-                * @param {function} success callback
-                */
-               deleteNode: function SystemIO_deleteNode(nodePath, onSuccess) {
-                       var pathData = this.getPathData(nodePath),
-                               self = this;
+        /**
+         * Deletes node with specified path
+         * @param {string} node path
+         * @param {function} success callback
+         */
+        deleteNode: function SystemIO_deleteNode(nodePath, onSuccess) {
+            var pathData = this.getPathData(nodePath),
+                self = this;
 
-                       function onDeleteSuccess() {
-                               onSuccess();
-                       }
+            function onDeleteSuccess() {
+                tizen.content.scanFile(nodePath, function () {});
+                onSuccess();
+            }
 
-                       function onDeleteError(e) {
-                               console.error('SystemIO_deleteNode:_onDeleteError', e);
-                       }
+            function onDeleteError(e) {
+                console.error('SystemIO_deleteNode:_onDeleteError', e);
+            }
 
-                       function onOpenDirSuccess(dir) {
-                               var onListFiles = function (files) {
-                                       if (files.length > 0) {
-                                               // file exists;
-                                               if (files[0].isDirectory) {
-                                                       self.deleteDir(dir, files[0].fullPath, onDeleteSuccess, onDeleteError);
-                                               } else {
-                                                       self.deleteFile(dir, files[0].fullPath, onDeleteSuccess, onDeleteError);
-                                               }
-                                       } else {
-                                               onDeleteSuccess();
-                                       }
-                               };
+            function onOpenDirSuccess(dir) {
+                var onListFiles = function (files) {
+                    if (files.length > 0) {
+                        // file exists;
+                        if (files[0].isDirectory) {
+                            self.deleteDir(dir, files[0].fullPath,
+                                onDeleteSuccess, onDeleteError);
+                        } else {
+                            self.deleteFile(dir, files[0].fullPath,
+                                onDeleteSuccess, onDeleteError);
+                        }
+                    } else {
+                        onDeleteSuccess();
+                    }
+                };
 
-                               // check file exists;
-                               dir.listFiles(onListFiles, function (e) {
-                                       console.error(e);
-                               }, {
-                                       name: pathData.fileName
-                               });
-                       }
+                // check file exists;
+                dir.listFiles(onListFiles, function (e) {
+                    console.error(e);
+                }, {
+                    name: pathData.fileName
+                });
+            }
 
-                       this.openDir(pathData.dirName, onOpenDirSuccess, function (e) {
-                               console.error('openDir error:' + e.message);
-                               alert("Cannot save photo\n" + e.message);
-                       });
-               },
+            this.openDir(pathData.dirName, onOpenDirSuccess, function (e) {
+                console.error('openDir error:' + e.message);
+                alert("Cannot save photo\n" + e.message);
+            });
+        },
 
-               /**
-                * Deletes specified file
-                * 
-                * @param {File} dir
-                * @param {string} filePath file path
-                * @param {function} onDeleteSuccess delete success callback
-                * @param {function} onDeleteError delete error callback
-                */
-               deleteFile: function SystemIO_deleteFile(dir, filePath, onDeleteSuccess, onDeleteError) {
-                       try {
-                               dir.deleteFile(filePath, onDeleteSuccess, onDeleteError);
-                       } catch (e) {
-                               console.error('SystemIO_deleteFile error:' + e.message);
-                               return false;
-                       }
-               },
+        /**
+         * Deletes specified file
+         * @param {File} dir
+         * @param {string} filePath file path
+         * @param {function} onDeleteSuccess delete success callback
+         * @param {function} onDeleteError delete error callback
+         */
+        deleteFile: function SystemIO_deleteFile(dir, filePath, onDeleteSuccess,
+            onDeleteError) {
+            try {
+                dir.deleteFile(filePath, onDeleteSuccess, onDeleteError);
+            } catch (e) {
+                console.error('SystemIO_deleteFile error:' + e.message);
+                return false;
+            }
+        },
 
-               /**
-                * Deletes specified directory
-                * 
-                * @param {File} dir
-                * @param {string} dir path
-                * @param {function} delete success callback
-                * @param {function} delete error callback
-                * @returns {boolean}
-                */
-               deleteDir: function SystemIO_deleteDir(dir, dirPath, onDeleteSuccess, onDeleteError) {
-                       try {
-                               dir.deleteDirectory(dirPath, false, onDeleteSuccess, onDeleteError);
-                       } catch (e) {
-                               console.error('SystemIO_deleteDir error:' + e.message);
-                               return false;
-                       }
+        /**
+         * Deletes specified directory
+         * @param {File} dir
+         * @param {string} dir path
+         * @param {function} delete success callback
+         * @param {function} delete error callback
+         * @returns {boolean}
+         */
+        deleteDir: function SystemIO_deleteDir(dir, dirPath, onDeleteSuccess,
+            onDeleteError) {
+            try {
+                dir.deleteDirectory(dirPath, false, onDeleteSuccess,
+                    onDeleteError);
+            } catch (e) {
+                console.error('SystemIO_deleteDir error:' + e.message);
+                return false;
+            }
 
-                       return true;
-               },
+            return true;
+        },
 
-               /**
-                * The method check the file exists;
-                * @param {string} filePath
-                * @param {function} onCheck success callback
-                * @returns {undefined}
-                */
-               fileExists: function SystemIO_fileExists(filePath, onCheck) {
-                       var pathData = this.getPathData(filePath);
+        /**
+         * The method check the file exists;
+         * @param {string} filePath
+         * @param {function} onCheck success callback
+         * @returns {undefined}
+         */
+        fileExists: function SystemIO_fileExists(filePath, onCheck) {
+            var pathData = this.getPathData(filePath);
 
-                       function onOpenDirSuccess(dir) {
-                               try {
-                                       dir.resolve(pathData.fileName);
-                                       onCheck(true);
-                               } catch (error) {
-                                       onCheck(false);
-                               }
-                       }
+            function onOpenDirSuccess(dir) {
+                try {
+                    dir.resolve(pathData.fileName);
+                    onCheck(true);
+                } catch (error) {
+                    onCheck(false);
+                }
+            }
 
-                       // if directory not exists, the file also not exists;
-                       function onOpenDirError(error) {
-                               onCheck(false);
-                       }
+            // if directory not exists, the file also not exists;
+            function onOpenDirError(error) {
+                onCheck(false);
+            }
 
-                       // open directory
-                       this.openDir(pathData.dirName, onOpenDirSuccess, onOpenDirError);
-               }
-       };
+            // open directory
+            this.openDir(pathData.dirName, onOpenDirSuccess, onOpenDirError);
+        }
+    };
 }());
\ No newline at end of file
index dead835..1a2c84c 100644 (file)
  */
 
 /*jslint devel: true*/
-/*global $, Audio, window, localStorage, tizen, canvas, SystemIO, document, navigator, clearInterval, setInterval, setTimeout */
+/*global $, Audio, window, localStorage, tizen, canvas, SystemIO, document,
+  navigator, clearInterval, setInterval, setTimeout */
 var selfCamera;
 function SelfCamera() {
-       "use strict";
+    "use strict";
 }
 
 (function () {
-       "use strict";
-       var DELAY_2_SECOND = 2, DELAY_5_SECOND = 5, DELAY_10_SECOND = 10;
-       var previewLock = false;
-
-       SelfCamera.prototype = {
-               countdown: -1, // current value after clicking the camera button
-               countdownTimeoutID: -1,
-               countSound: new Audio('sounds/sounds_count.wav'),
-               img: document.createElement('canvas'),
-               filename: '',
-               loadDirectory: '',
-               parentSaveDirectory: 'file:///opt/usr/media/',
-               saveDirectory: 'file:///opt/usr/media/Images/',
-               IMG_PREFIX: 'SelfCamera_',
-               shutterSound: new Audio('sounds/sounds_Shutter_01.wav'),
-               timer: null, // value set by the buttons
-               systemIO: null,
-               video: null,
-               src: null,
-               isMediaWorking: false
-       };
-
-       SelfCamera.prototype.setTimer = function setTimer(value) {
-               this.timer = value;
-               $('#timer2, #timer5, #timer10').removeClass('selected');
-               $('#timer' + value).addClass('selected');
-               if (this.isMediaWorking) {
-                       try {
-                               selfCamera.video.play();
-                       } catch (e) {
-                               console.error(e);
-                       }
-               }
-       };
-
-       SelfCamera.prototype.onCaptureVideoSuccess = function onCaptureVideoSuccess(stream) {
-               var urlStream;
-               urlStream = window.webkitURL.createObjectURL(stream);
-               this.isMediaWorking = true;
-               this.createVideoElement(urlStream);
-               this.setTimer(DELAY_2_SECOND);
-       };
-
-       SelfCamera.prototype.createVideoElement = function (src) {
-               this.video = $('<video/>', {
-                       autoplay: 'autoplay',
-                       id: 'video',
-                       style: 'height:' + $(window).height() + 'px',
-                       src: src
-               }).appendTo("#camera").get(0);
-
-               this.bindVideoEvents();
-       };
-
-       SelfCamera.prototype.onCaptureVideoError = function onCaptureVideoError(e) {
-               // alert("Video Capture Error");
-               console.error(e);
-       };
-
-       SelfCamera.prototype.startPreview = function startPreview() {
-               var options = {
-                       audio: true,
-                       video: true
-               };
-
-               navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
-               try {
-                       if (typeof (navigator.getUserMedia) === 'function') {
-                               navigator.getUserMedia(options, this.onCaptureVideoSuccess.bind(this), this.onCaptureVideoError.bind(this));
-                       }
-               } catch (e) {
-                       alert('navigator.getUserMedia() error.');
-                       console.error('navigator.getUserMedia() error: ' + e.message);
-               }
-
-       };
-
-       SelfCamera.prototype.launchPreview = function launchPreview() {
-               var service, onReply, self = this;
-               if (previewLock) {
-                       return false;
-               }
-               if (this.filename === '') {
-                       return false;
-               }
-               this.showPhotoPreview(this.filename);
-               return true;
-       };
-
-       SelfCamera.prototype.showGallery = function showGallery(service) {
-               var onReply, self = this;
-               onReply = {
-                       onsuccess: function (data) {
-                               self.showPhotoPreview(data[0].value[0]);
-                       },
-                       onfailure: function () {}
-               };
-
-               try {
-                       tizen.application.launchAppControl(
-                               service,
-                               null,
-                               function () {
-                                       setTimeout(function() {previewLock = false;}, 700);
-                               },
-                               function (err) {
-                                       previewLock = false;
-                                       console.error('Gallery launch failed: ' + err.message);
-                               },
-                               onReply
-                       );
-                       previewLock = true;
-               } catch (exc) {
-                       alert('Exception: ' + exc.message);
-               }
-       };
-
-       SelfCamera.prototype.showPhotoPreview = function showPhotoPreview(file) {
-               var service, onReply, self = this;
-               service = new tizen.ApplicationControl('http://tizen.org/appcontrol/operation/view', file, "image/*");
-               onReply = {onsuccess: function () {}, onfailure: function () {}};
-
-               try {
-                       tizen.application.launchAppControl(
-                               service,
-                               null,
-                               function () {
-                                       setTimeout(function() {previewLock = false;}, 700);
-                               },
-                               function (err) {
-                                       previewLock = false;
-                                       console.error('Photo launch failed: ' + err.message);
-                               },
-                               onReply
-                       );
-                       previewLock = true;
-               } catch (exc) {
-                       alert('Exception: ' + exc.message);
-               }
-       };
-
-       SelfCamera.prototype.setLoadDirectory = function setLoadDirectory(dirName) {
-               this.loadDirectory = dirName;
-               if (!this.loadDirectory.match(/\/$/)) {
-                       this.loadDirectory += '/';
-               }
-       };
-
-       SelfCamera.prototype.saveCanvas = function saveCanvas(canvas, fileName) {
-               var data,
-                       self = this,
-                       onSuccess = function (fileHandle) {
-                               this.setLoadDirectory(this.getFileDirectoryURI(fileHandle));
-                               tizen.content.scanFile(
-                                       fileName,
-                                       function () {
-                                               setTimeout(function(){ self.loadThumbnail(true, true); }, 200);
-                                       },
-                                       function () {
-                                               console.error('scanFile: file not found');
-                                               self.loadThumbnail(true, false);
-                                       });
-                       }.bind(this),
-                       onFailure = function (e) {
-                               alert("Failed to take photo!");
-                       };
-
-               try {
-                       data = canvas.toDataURL().replace('data:image/png;base64,', '').replace('data:,', '');
-                       if (data === '') {
-                               throw {message: "No image source"};
-                       }
-               } catch (e) {
-                       this.filename = '';
-                       console.error('canvas.toDataUrl error: ' + e.message);
-                       alert("Data source error: " + e.message);
-                       return;
-               }
-
-               try {
-                       this.systemIO.deleteNode(fileName, function () {
-                               try {
-                                       this.systemIO.saveFileContent(fileName, data, onSuccess, onFailure, 'base64');
-                               } catch (e) {
-                                       console.error('saveDataToFile error: ' + e.message);
-                               }
-                       }.bind(this));
-               } catch (e2) {
-                       console.error('Delete old file error: ' + e2.message);
-               }
-       };
-
-       SelfCamera.prototype.captureImage = function captureImage(video) {
-               var sourceWidth = window.innerWidth,
-                       sourceHeight = window.innerHeight,
-                       sourceX = (sourceWidth - $(video).width()) / 2,
-                       sourceY = (sourceHeight - $(video).height()) / 2;
-
-               this.img.width = sourceWidth;
-               this.img.height = sourceHeight;
-
-               // Crop image to viewport dimension
-               this.img.getContext('2d').drawImage(video, sourceX, sourceY, $(video).width(), $(video).height());
-
-               // To get best available dimension
-               // this.img.width = video.videoWidth;
-               // this.img.height = video.videoHeight;
-               // this.img.getContext('2d').drawImage(video, 0, 0);
-       };
-
-       SelfCamera.prototype.setFileName = function setFileName(filename) {
-               this.filename = filename;
-               this.loadThumbnail(false, false);
-       };
-
-       SelfCamera.prototype.getTimestamp = function getTimestamp() {
-               var d = new Date();
-               return '' + d.getUTCFullYear() +
-                       '-' + d.getUTCMonth() +
-                       '-' + d.getUTCDay() +
-                       '-' + d.getUTCHours() +
-                       '-' + d.getUTCMinutes() +
-                       '-' + d.getUTCSeconds() +
-                       '-' + d.getUTCMilliseconds();
-       };
-
-       SelfCamera.prototype.takePhoto = function takePhoto() {
-               this.captureImage(this.video);
-               this.filename = this.IMG_PREFIX + this.getTimestamp() + '.png';
-               this.savePhoto();
-       };
-
-       SelfCamera.prototype.savePhoto = function savePhoto() {
-               var self = this;
-               this.saveCanvas(this.img, this.saveDirectory + this.filename);
-       };
-
-       SelfCamera.prototype.findLastPhoto = function findLastPhoto(onFind) {
-               tizen.content.find(
-                       function (files) {
-                               if (files.length !== 0) {
-                                       onFind(files[0].contentURI);
-                               } else {
-                                       onFind(null);
-                               }
-                       },
-                       null,
-                       null,
-                       new tizen.CompositeFilter("INTERSECTION",
-                               [
-                                       new tizen.AttributeFilter("title", "STARTSWITH", this.IMG_PREFIX),
-                                       new tizen.AttributeFilter("type", "EXACTLY", 'IMAGE')
-                               ]),
-                       new tizen.SortMode("modifiedDate", "DESC")
-               );
-       };
-
-       SelfCamera.prototype.onCountdownTimeout = function onCountdownTimeout() {
-               this.countdown -= 1;
-               if (this.countdown < 0) {
-                       this.clearCountdown();
-                       this.shutterSound.play();
-                       try {
-                               this.takePhoto();
-                       } catch (e) {
-                               console.error(e);
-                       }
-               } else {
-                       $('#countdown').text(this.countdown);
-                       this.countSound.currentTime = 0;
-                       this.countSound.play();
-                       this.countdownTimeoutID = setTimeout(this.onCountdownTimeout.bind(this), 1000);
-               }
-       };
-
-       SelfCamera.prototype.startCountdown = function startCountdown(startValue) {
-               $("#thumbnail").hide();
-               $(".timers div").off("click");
-               if (this.countdownTimeoutID > 0) {
-                       clearTimeout(this.countdownTimeoutID);
-                       this.countdownTimeoutID = -1;
-               }
-               this.countdown = startValue || this.timer;
-               this.countdownTimeoutID = setTimeout(this.onCountdownTimeout.bind(this), 1000);
-               $('#countdown').show().text(this.countdown);
-               this.countSound.currentTime = 0;
-               this.countSound.play();
-       };
-
-       SelfCamera.prototype.clearCountdown = function clearCountdown() {
-               $('#countdown').text('').hide();
-               this.countdown = -1;
-               clearTimeout(this.countdownTimeoutID);
-               this.countdownTimeoutID = -1;
-               this.bindTimerClicks();
-       };
-
-       SelfCamera.prototype.bindVideoEvents = function () {
-               var self = this;
-               $(this.video).on("stalled", function (e) {
-                       this.load();
-               });
-               $(this.video).on("playing", function () {
-                       var margin = ($(window).width() - $(self.video).width()) / 2,
-                               width = Math.round($(window).height() *
-                                       self.video.videoWidth / self.video.videoHeight);
-                       $(self.video).css({
-                               'margin-left': margin + 'px',
-                               'width': width + 'px'
-                       });
-               });
-               $(this.video).on('click', function () { this.play(); });
-       };
-
-       SelfCamera.prototype.bindEvents = function bindEvents() {
-               var self = this;
-
-               document.addEventListener('webkitvisibilitychange', function (event) {
-                       self.clearCountdown();
-                       previewLock = false;
-                       if (document.webkitVisibilityState === 'visible') {
-                               if (self.video !== null) {
-                                       self.reloadSaveDirectory(function () {
-                                               self.video.play();
-                                       });
-                               }
-                               self.loadThumbnail(true, false);
-                       }
-               });
-
-               $('shutter').mousedown(function (ev) {
-                       $('shutter').addClass('active');
-               }).mouseup(function (ev) {
-                       $('shutter').removeClass('active');
-               }).on('touchstart', function (ev) {
-                       $('shutter').addClass('active');
-               }).on('touchend', function (ev) {
-                       $('shutter').removeClass('active');
-               });
-
-               $(window).on('tizenhwkey', function (e) {
-                       if (e.originalEvent.keyName === "back") {
-                               if (self.countdownTimeoutID !== -1) {
-                                       self.clearCountdown();
-                                       self.loadThumbnail(true, false);
-                               } else {
-                                       tizen.application.getCurrentApplication().exit();
-                               }
-                       }
-               });
-
-               this.bindTimerClicks();
-
-               $('#thumbnail').on('click', this.launchPreview.bind(this));
-               $('#shutter').on('touchstart', this.shutterTouched.bind(this));
-       };
-
-       SelfCamera.prototype.shutterTouched = function () {
-               if (this.isMediaWorking) {
-                       this.startCountdown();
-               } else {
-                       alert("To be able to take pictures you have to allow application to use" +
-                                       " your media. Please restart app and allow Self Camera to" +
-                                       " access media content.");
-               }
-       };
-
-       SelfCamera.prototype.bindTimerClicks = function bindTimerClicks() {
-               $('#timer2').on('click', this.setTimer.bind(this, DELAY_2_SECOND));
-               $('#timer5').on('click', this.setTimer.bind(this, DELAY_5_SECOND));
-               $('#timer10').on('click', this.setTimer.bind(this, DELAY_10_SECOND));
-       };
-
-       // Fix for file.parent.toURI() + escaping white signs
-       SelfCamera.prototype.getFileDirectoryURI = function (file) {
-               var dirURI;
-               dirURI = encodeURI(
-                       file.toURI()
-                               .split('/')
-                               .slice(0, -1)
-                               .join('/')
-               );
-               return dirURI;
-       };
-
-       SelfCamera.prototype.loadThumbnail = function (show, animate) {
-               var self = this, image;
-               show    = show    || false;
-               animate = animate || false;
-               this.findLastPhoto(function (file) {
-                       if (file) {
-                               self.filename = file;
-                               file = file + '?r=' + Math.random();
-                               image = new Image();
-                               image.onload = function() {
-                                       $('#upImage').css('background-image', 'url(' + file + ')');
-                                       $('#thumbnail').css('background-image', 'url("./images/transparent.png")');
-                                       if (show) {
-                                               if (animate) {
-                                                       $('#thumbnail').css({'opacity':0.01}).show().animate({'opacity':1.00});
-                                               }
-                                               else {
-                                                       $('#thumbnail').show();
-                                               }
-                                       }
-                               }
-                               image.src = file;
-                       } else {
-                               self.filename = '';
-                               $('#thumbnail').hide();
-                               $('#upImage').css('background-image', '');
-                       }
-               }.bind(this));
-       };
-
-       SelfCamera.prototype.reloadSaveDirectory = function (callback) {
-               var self = this;
-               tizen.filesystem.resolve('images', function () {
-                       callback();
-               }, function () {
-                       self.systemIO.openDir(self.parentSaveDirectory, function (dir) {
-                               dir.createDirectory('Images');
-                               callback();
-                       }, function () {
-                               console.error('no parent directory');
-                               callback();
-                       });
-               }, 'r');
-       };
-
-       SelfCamera.prototype.init = function init() {
-               var self = this;
-               this.reloadSaveDirectory(function () {
-                       self.systemIO = new SystemIO();
-                       self.loadThumbnail(true, false);
-                       self.startPreview();
-                       self.bindEvents();
-               });
-       };
+    "use strict";
+    var DELAY_2_SECOND = 2, DELAY_5_SECOND = 5, DELAY_10_SECOND = 10;
+
+    SelfCamera.prototype = {
+        countdown: -1, // current value after clicking the camera button
+        countdownTimeoutID: -1,
+        countSound: new Audio('sounds/sounds_count.wav'),
+        img: document.createElement('canvas'),
+        filename: '',
+        loadDirectory: '',
+        parentSaveDirectory: 'file:///opt/usr/media/',
+        saveDirectory: 'file:///opt/usr/media/Images/',
+        IMG_PREFIX: 'SelfCamera_',
+        shutterSound: new Audio('sounds/sounds_Shutter_01.wav'),
+        timer: null, // value set by the buttons
+        systemIO: null,
+        video: null,
+        src: null,
+        isMediaWorking: false,
+        previewLock: false
+    };
+
+    /**
+     * Initialize timer buttons
+     * @param {Number} value - number of countdown seconds
+     */
+    SelfCamera.prototype.setTimer = function setTimer(value) {
+        this.timer = value;
+        // clear buttons
+        $('#timer2, #timer5, #timer10').removeClass('selected');
+        // mark active button
+        $('#timer' + value).addClass('selected');
+        // if media is working
+        if (this.isMediaWorking) {
+            try {
+                // try to play stream
+                selfCamera.video.play();
+            } catch (e) {
+                console.error(e);
+            }
+        }
+    };
+
+    /**
+     * Stream object handler
+     * @param {Stream} stream
+     */
+    SelfCamera.prototype.onCaptureVideoSuccess =
+        function onCaptureVideoSuccess(stream) {
+            var urlStream;
+            // create stream
+            urlStream = window.webkitURL.createObjectURL(stream);
+            this.isMediaWorking = true;
+            // create video element with stream handler
+            this.createVideoElement(urlStream);
+            // initialize timer buttons options
+            this.setTimer(DELAY_2_SECOND);
+        };
+
+    /**
+     * Create HTML video element and adds it to DOM
+     * @param {Stream} src
+     */
+    SelfCamera.prototype.createVideoElement = function (src) {
+        this.video = $('<video/>', {
+            autoplay: 'autoplay',
+            id: 'video',
+            style: 'height:' + $(window).height() + 'px',
+            src: src
+        }).appendTo("#camera").get(0);
+
+        this.bindVideoEvents();
+    };
+
+    SelfCamera.prototype.onCaptureVideoError = function onCaptureVideoError(e) {
+        console.error(e);
+    };
+
+    /**
+     * Enable navigator media options to manage video stream
+     */
+    SelfCamera.prototype.startPreview = function startPreview() {
+        // declare what will be used by this application
+        var options = {
+            audio: true,
+            video: true
+        };
+
+        navigator.getUserMedia = navigator.getUserMedia
+            || navigator.webkitGetUserMedia;
+        try {
+            if (typeof (navigator.getUserMedia) === 'function') {
+                // ask user to grant permissions to use media objects
+                navigator.getUserMedia(options,
+                    this.onCaptureVideoSuccess.bind(this),
+                    this.onCaptureVideoError.bind(this));
+            }
+        } catch (e) {
+            alert('navigator.getUserMedia() error.');
+            console.error('navigator.getUserMedia() error: ' + e.message);
+        }
+    };
+
+    /**
+     * Launch service to display taken photo
+     * @retutn {Boolean} success or failure
+     */
+    SelfCamera.prototype.launchPreview = function launchPreview() {
+        var service, onReply, self = this;
+        // if preview is locked
+        if (this.previewLock) {
+            return false;
+        }
+        // if filename is invalid
+        if (this.filename === '') {
+            return false;
+        }
+        // try to launch service
+        this.showPhotoPreview(this.filename);
+        return true;
+    };
+
+    /**
+     * TODO unused function ?
+     */
+    SelfCamera.prototype.showGallery = function showGallery(service) {
+        var onReply, self = this;
+        onReply = {
+            onsuccess: function (data) {
+                self.showPhotoPreview(data[0].value[0]);
+            },
+            onfailure: function () {}
+        };
+
+        try {
+            tizen.application.launchAppControl(
+                service,
+                null,
+                function () {
+                    setTimeout(function () {self.previewLock = false; }, 700);
+                },
+                function (err) {
+                    self.previewLock = false;
+                    console.error('Gallery launch failed: ' + err.message);
+                },
+                onReply
+            );
+            self.previewLock = true;
+        } catch (exc) {
+            alert('Exception: ' + exc.message);
+        }
+    };
+
+    /**
+     * Run external application service to show taken photo
+     * @param {File} file
+     */
+    SelfCamera.prototype.showPhotoPreview = function showPhotoPreview(file) {
+        var service, onReply, self = this;
+
+        // configure service
+        service = new tizen.ApplicationControl(
+            'http://tizen.org/appcontrol/operation/view',
+            file
+        );
+        onReply = {onsuccess: function () {}, onfailure: function () {}};
+
+        try {
+            // trye to launch service
+            tizen.application.launchAppControl(
+                service,
+                null,
+                function () {
+                    setTimeout(function () {self.previewLock = false; }, 700);
+                },
+                function (err) {
+                    self.previewLock = false;
+                    console.error('Photo launch failed: ' + err.message);
+                },
+                onReply
+            );
+            self.previewLock = true;
+        } catch (exc) {
+            alert('Exception: ' + exc.message);
+        }
+    };
+
+    /**
+     * Set dir for new images
+     * @param {String} dirName
+     */
+    SelfCamera.prototype.setLoadDirectory = function setLoadDirectory(dirName) {
+        this.loadDirectory = dirName;
+        if (!this.loadDirectory.match(/\/$/)) {
+            this.loadDirectory += '/';
+        }
+    };
+
+    /**
+     * Display for 3s failure message
+     */
+    SelfCamera.prototype.showFailureMessage = function showFailureMessage() {
+        $('#failure').css('display', 'block');
+        setTimeout(
+            function () {
+                $('#failure').css('display', 'none');
+            },
+            3000
+        );
+    };
+
+    /**
+     * Saves taken screenshoot to file
+     * @param {Object} canvas
+     * @param {String} fileName
+     */
+    SelfCamera.prototype.saveCanvas = function saveCanvas(canvas, fileName) {
+        var data,
+            self = this,
+            // successful save callback
+            onSuccess = function (fileHandle) {
+                self.setLoadDirectory(self.getFileDirectoryURI(fileHandle));
+                tizen.content.scanFile(
+                    fileName,
+                    function () {
+                        // if taken photo exists load it as thumb
+                        self.loadThumbnail(true, true);
+                    },
+                    function () {
+                        console.error('scanFile: file not found');
+                        self.loadThumbnail(true, false);
+                    }
+                );
+            }.bind(this),
+            // failure save callback
+            onFailure = function (e) {
+                console.log('Failed to take photo.');
+                self.showFailureMessage();
+                // if file wasn't saved properly
+                // delete corrupted file
+                self.systemIO.deleteNode(fileName,
+                    function () {
+                        console.log('Deleted corrupted file.');
+                        setTimeout(
+                            function () {
+                                // back to old thumb
+                                self.loadThumbnail(true, false);
+                            },
+                            1000
+                        );
+                    });
+            };
+
+        try {
+            // get base64 data from canvas
+            data = canvas.toDataURL().replace('data:image/png;base64,', '')
+                .replace('data:,', '');
+            if (data === '') { // if data is not valid
+                throw {message: "No image source"};
+            }
+        } catch (e) { // if can't get valid base64 info
+            this.filename = '';
+            console.error('canvas.toDataUrl error: ' + e.message);
+            alert("Data source error: " + e.message);
+            return;
+        }
+
+        try {
+            this.systemIO.deleteNode(fileName, function () {
+                try {
+                    // try to save file data into file
+                    this.systemIO.saveFileContent(fileName, data, onSuccess,
+                        onFailure, 'base64');
+                } catch (e) {
+                    console.error('saveDataToFile error: ' + e.message);
+                }
+            }.bind(this));
+        } catch (e2) {
+            console.error('Delete old file error: ' + e2.message);
+        }
+    };
+
+    /**
+     * Take screenshoot from the current displaying video frame
+     * @param {Video} video
+     */
+    SelfCamera.prototype.captureImage = function captureImage(video) {
+        var sourceWidth = window.innerWidth,
+            sourceHeight = window.innerHeight,
+            sourceX = (sourceWidth - $(video).width()) / 2,
+            sourceY = (sourceHeight - $(video).height()) / 2;
+
+        this.img.width = sourceWidth;
+        this.img.height = sourceHeight;
+
+        // Crop image to viewport dimension
+        this.img.getContext('2d').drawImage(video, sourceX, sourceY,
+            $(video).width(), $(video).height());
+
+        // To get best available dimension
+        // this.img.width = video.videoWidth;
+        // this.img.height = video.videoHeight;
+        // this.img.getContext('2d').drawImage(video, 0, 0);
+    };
+
+    /**
+     * Sets current file name
+     */
+    SelfCamera.prototype.setFileName = function setFileName(filename) {
+        this.filename = filename;
+        this.loadThumbnail(false, false);
+    };
+
+    /**
+     * Changes Date object into string timestamp
+     * @return {String} timestamp
+     */
+    SelfCamera.prototype.getTimestamp = function getTimestamp() {
+        var d = new Date();
+        return d.getUTCFullYear() +
+            '-' + d.getUTCMonth() +
+            '-' + d.getUTCDay() +
+            '-' + d.getUTCHours() +
+            '-' + d.getUTCMinutes() +
+            '-' + d.getUTCSeconds() +
+            '-' + d.getUTCMilliseconds();
+    };
+
+    /**
+     * Creates screenshoot and save on device hard drive
+     */
+    SelfCamera.prototype.takePhoto = function takePhoto() {
+        this.captureImage(this.video);
+        this.filename = this.IMG_PREFIX + this.getTimestamp() + '.png';
+        this.savePhoto();
+    };
+
+    /**
+     * Saves canvas screenshoot on device hard drive
+     */
+    SelfCamera.prototype.savePhoto = function savePhoto() {
+        var self = this;
+        this.saveCanvas(this.img, this.saveDirectory + this.filename);
+    };
+
+    /**
+     * Find last taken photo with specified prefix
+     * @param {Function} onFind callback
+     */
+    SelfCamera.prototype.findLastPhoto = function findLastPhoto(onFind) {
+        // find all images in content storage with specified prefix
+        tizen.content.find(
+            function (files) {
+                if (files.length !== 0) {
+                    // run callback with last image
+                    onFind(files[0].contentURI);
+                } else {
+                    onFind(null);
+                }
+            },
+            null,
+            null,
+            new tizen.CompositeFilter("INTERSECTION",
+                [
+                    new tizen.AttributeFilter("title", "STARTSWITH",
+                        this.IMG_PREFIX),
+                    new tizen.AttributeFilter("type", "EXACTLY", 'IMAGE')
+                ]),
+            new tizen.SortMode("modifiedDate", "DESC")
+        );
+    };
+
+    /**
+     * Count down step handler
+     */
+    SelfCamera.prototype.onCountdownTimeout = function onCountdownTimeout() {
+        // update steps to the end
+        this.countdown -= 1;
+        // it it is last step
+        if (this.countdown < 0) {
+            // remove DOM element
+            this.clearCountdown();
+            this.shutterSound.play();
+            try {
+                // take photo
+                this.takePhoto();
+            } catch (e) {
+                console.error(e);
+            }
+        } else { // if it isn't last step
+            // update DOM element
+            $('#countdown').text(this.countdown);
+            this.countSound.currentTime = 0;
+            this.countSound.play();
+            // set new timeout
+            this.countdownTimeoutID =
+                setTimeout(this.onCountdownTimeout.bind(this), 1000);
+        }
+    };
+
+    /**
+     * Display count down element on the screen
+     * and starts counting down to zero from startVlue
+     * @param {Number} startValue
+     */
+    SelfCamera.prototype.startCountdown = function startCountdown(startValue) {
+        // hide thumb
+        $("#thumbnail").hide();
+        // unbind timer buttons click listeners
+        $(".timers div").off("click");
+        // if there is running count down switch it off
+        if (this.countdownTimeoutID > 0) {
+            clearTimeout(this.countdownTimeoutID);
+            this.countdownTimeoutID = -1;
+        }
+        // set number of seconds to end
+        this.countdown = startValue || this.timer;
+        // launch timer and remember its id
+        this.countdownTimeoutID =
+            setTimeout(this.onCountdownTimeout.bind(this), 1000);
+        // show countdown element
+        $('#countdown').show().text(this.countdown);
+        this.countSound.currentTime = 0;
+        this.countSound.play();
+    };
+
+    /**
+     * Clear count down informations
+     */
+    SelfCamera.prototype.clearCountdown = function clearCountdown() {
+        // hide countdown DOM element
+        $('#countdown').text('').hide();
+        this.countdown = -1;
+        // clear current countdown id
+        clearTimeout(this.countdownTimeoutID);
+        this.countdownTimeoutID = -1;
+        // refresh bindings to timer buttons
+        this.bindTimerClicks();
+    };
+
+    /**
+     * Resize video element to full screen
+     */
+    SelfCamera.prototype.resizeVideo = function () {
+        var w = this.video.videoWidth, // video height
+            h = this.video.videoHeight, // video width
+            W = $(window).width(), // window width
+            H = $(window).height(), // window height
+            // is video stream resolution greater than window resolution
+            wide = w / h >= W / H,
+            margin,
+            size;
+        // if stream hasn't been loaded yet
+        if (w <= 0 || h <= 0) {
+            setTimeout(this.resizeVideo.bind(this), 100); // wait for stream
+            return;
+        }
+        if (wide) {
+            size = Math.round(w * H / h);
+            margin = (W - size) / 2;
+            $(this.video).css({
+                'margin-left': margin + 'px',
+                'margin-top': '0 px',
+                'width': size + 'px',
+                'height': H + 'px'
+            });
+        } else {
+            size = Math.round(h * W / w);
+            margin = (H - size) / 2;
+            $(this.video).css({
+                'margin-left': '0 px',
+                'margin-top': margin + 'px',
+                'width': W + 'px',
+                'height': size + 'px'
+            });
+        }
+        $('#camera').css({
+            'width': W + 'px',
+            'height': H + 'px'
+        });
+    };
+
+    /**
+     * Bind event handlers to video element
+     */
+    SelfCamera.prototype.bindVideoEvents = function () {
+        // handle video stream suspendtion
+        $(this.video).on("stalled", function (e) {
+            this.load();
+        });
+        // when video start playind
+        $(this.video).on("playing", this.resizeVideo.bind(this));
+        $(this.video).on('click', function () { this.play(); });
+    };
+
+    /**
+     * Bind event handlers to DOM elements
+     */
+    SelfCamera.prototype.bindEvents = function bindEvents() {
+        var self = this;
+
+        document.addEventListener('webkitvisibilitychange', function (event) {
+            self.clearCountdown();
+            self.previewLock = false;
+            if (document.webkitVisibilityState === 'visible') {
+                self.reloadSaveDirectory();
+                if (self.video !== null) {
+                    self.video.play();
+                }
+                self.loadThumbnail(true, false);
+            }
+        });
+
+        $('shutter').mousedown(function (ev) {
+            $('shutter').addClass('active');
+        }).mouseup(function (ev) {
+            $('shutter').removeClass('active');
+        }).on('touchstart', function (ev) {
+            $('shutter').addClass('active');
+        }).on('touchend', function (ev) {
+            $('shutter').removeClass('active');
+        });
+
+        $(window).on('tizenhwkey', function (e) {
+            if (e.originalEvent.keyName === "back") {
+                if (self.countdownTimeoutID !== -1) {
+                    self.clearCountdown();
+                    self.loadThumbnail(true, false);
+                } else {
+                    tizen.application.getCurrentApplication().exit();
+                }
+            }
+        });
+
+        this.bindTimerClicks();
+
+        $('#thumbnail').on('click', this.launchPreview.bind(this));
+        $('#shutter').on('touchstart', this.shutterTouched.bind(this));
+    };
+
+    /**
+     * Handle press shutter buttton
+     */
+    SelfCamera.prototype.shutterTouched = function () {
+        if (this.previewLock) {
+            return;
+        }
+        // if media is working
+        if (this.isMediaWorking) {
+            // start count down
+            this.startCountdown();
+        } else { // if media doesn't work display information message
+            alert("To be able to take pictures you have to allow application "
+                + "to use your media. Please restart app and allow "
+                + "Self Camera to access media content.");
+        }
+    };
+
+    /**
+     * Sets handlers for click event to timer buttons
+     */
+    SelfCamera.prototype.bindTimerClicks = function bindTimerClicks() {
+        $('#timer2').on('click', this.setTimer.bind(this, DELAY_2_SECOND));
+        $('#timer5').on('click', this.setTimer.bind(this, DELAY_5_SECOND));
+        $('#timer10').on('click', this.setTimer.bind(this, DELAY_10_SECOND));
+    };
+
+    // FIX for file.parent.toURI() + escaping white signs
+    /**
+     * Retrieve parent directory URI from file URI
+     * @param {File} file
+     * @return {String} file parent directory URI
+     */
+    SelfCamera.prototype.getFileDirectoryURI = function (file) {
+        var dirURI;
+        dirURI = encodeURI(
+            file.toURI()
+                .split('/')
+                .slice(0, -1)
+                .join('/')
+        );
+        return dirURI;
+    };
+
+    /**
+     * Loads thumb image and add it to appropriate DOM element
+     * @param {Boolean} show
+     * @param {Boolean} animate
+     */
+    SelfCamera.prototype.loadThumbnail = function (show, animate) {
+        var self = this, image;
+        show    = show    || false;
+        animate = animate || false;
+        // find last taken photo
+        this.findLastPhoto(function (file) {
+            if (file) {
+                self.filename = file;
+                file = this.fixURI(file) + '?r=' + Math.random();
+                // create new image object
+                image = new Image();
+                // add listener load event
+                image.onload = function () {
+                    // update DOM element css styles
+                    $('#upImage').css('background-image', 'url(' + file + ')');
+                    $('#thumbnail').css('background-image',
+                        'url("./images/transparent.png")');
+                    if (show) {
+                        if (animate) {
+                            $('#thumbnail').css({'opacity': 0.01}).show()
+                                .animate({'opacity': 1.00});
+                        } else {
+                            $('#thumbnail').show();
+                        }
+                    }
+                };
+                // start downloading image
+                image.src = file;
+            } else { // if thera are no photos in expected catalog
+                self.filename = '';
+                $('#thumbnail').hide();
+                $('#upImage').css('background-image', '');
+            }
+        }.bind(this));
+    };
+
+    /**
+     * FIXes invalid URI returned by API's File::contentURI
+     * See File::toURI() issue https://bugs.tizendev.org/jira/browse/N_SE-54639
+     * @param {String} invaliduri
+     * @return {String} valid file URI
+     */
+    SelfCamera.prototype.fixURI = function (invaliduri) {
+        var scheme, address, k;
+        invaliduri = invaliduri.split('://');
+        scheme = invaliduri[0];
+        invaliduri.shift();
+        address = invaliduri.join('://').split('/');
+        for (k = address.length - 1; k >= 0; k -= 1) {
+            address[k] = encodeURIComponent(address[k]);
+        }
+        return scheme + '://' + address.join('/');
+    };
+
+    /**
+     * Check if exists Images directory, creates new one if doesn't
+     * @param {Function} callback
+     */
+    SelfCamera.prototype.reloadSaveDirectory = function (callback) {
+        var self = this;
+        callback = callback || function () {};
+        tizen.filesystem.resolve('images', function () {
+            // if Images directory exists just call callback
+            callback();
+        }, function () {
+            // if Images directory doesn't exists
+            // create new on and call callback
+            self.systemIO.openDir(self.parentSaveDirectory, function (dir) {
+                dir.createDirectory('Images');
+                callback();
+            }, function () {
+                console.error('no parent directory');
+                callback();
+            });
+        }, 'r');
+    };
+
+    /**
+     * Initialize self camera application
+     */
+    SelfCamera.prototype.init = function init() {
+        var self = this;
+        this.reloadSaveDirectory(function () {
+            self.systemIO = new SystemIO();
+            self.loadThumbnail(true, false);
+            self.startPreview();
+            self.bindEvents();
+        });
+    };
 
 }());
 
 selfCamera = new SelfCamera();
 $(document).ready(function () {
-       "use strict";
-       selfCamera.init();
+    "use strict";
+    selfCamera.init();
 });