/* global videodb:true,storageState:true,firstScanEnded:true, MediaDB,updateDialog,playerShowing,hidePlayer,updateLoadingSpinner, addToMetadataQueue,thumbnailList,currentVideo,resetCurrentVideo, hideSelectView,thumbnailClickHandler,startParsingMetadata */ /* exported initDB */ 'use strict'; // // This file is part of the Gaia Video app. It uses the MediaDB libarary // and the code in metadata.js to ensure that the videos[] array is up to date. // function initDB() { // use excludeFilter to ignore dummy files from camera. videodb = new MediaDB('videos', null, {excludeFilter: /DCIM\/\d{3}MZLLA\/\.VID_\d{4}\.3gp$/}); videodb.onupgrading = function(evt) { // show dialog in upgradestart, when it finished, it will turned to ready. storageState = MediaDB.UPGRADING; updateDialog(); }; videodb.onunavailable = function(event) { storageState = event.detail; // If player is playing, we need to hide the player which pauses the player // and unloads the video file. if (playerShowing) { hidePlayer(true); } updateDialog(); }; // On devices that have internal and external storage, we get this event // when the user pulls the sdcard out. If we're playing a video when that // happens, we need to stop or risk a crash. videodb.oncardremoved = function() { if (playerShowing) { hidePlayer(true); } }; videodb.onscanend = function() { // If this was the first scan after startup, then tell // performance monitors that the app is finally fully loaded and stable. if (!firstScanEnded) { firstScanEnded = true; window.performance.mark('fullyLoaded'); } updateDialog(); updateLoadingSpinner(); }; videodb.oncreated = function(event) { event.detail.forEach(videoCreated); }; videodb.ondeleted = function(event) { event.detail.forEach(videoDeleted); }; videodb.onenumerable = function() { storageState = false; updateDialog(); enumerateDB(); }; // The video app is relying on the mediadb auto-scanning to scan the db // when it becomes ready or when the SD card has been mounted or remounted. // This 'ready' handler is responsible for removing the 'unplug your ...' // overlay (displayed when USB storage is enabled when the device is connected // via USB cable), when the USB cable is unplugged. videodb.onready = function() { storageState = false; updateDialog(); // It is possible during startup to queue metadata to parse before // the MediaDB is ready to be able to parse it. So now that we are // ready, we should try again and parse metadata for any queued videos. startParsingMetadata(); }; } // Remember whether we've already run the enumeration step var enumerated = false; // This function runs once when the app starts up. It gets all known videos // from the MediaDB and handles the appropriately function enumerateDB() { if (enumerated) { return; } enumerated = true; var firstBatchDisplayed = false; var batch = []; var batchSize = 4; videodb.enumerate('date', null, 'prev', function(videoinfo) { // When we're done with the enumeration flush any batched files if (videoinfo === null) { flush(); return; } var isVideo = videoinfo.metadata.isVideo; // If we know this is not a video, ignore it if (isVideo === false) { return; } // If we don't have metadata for this video yet, add it to the // metadata queue to get processed. Once the metadata is // available, it will be passed to addVideo() if (isVideo === undefined) { addToMetadataQueue(videoinfo); return; } // If we've parsed the metadata and know this is a video, display it. if (isVideo === true) { batch.push(videoinfo); if (batch.length >= batchSize) { flush(); batchSize *= 2; } } }); function flush() { batch.forEach(addVideo); batch.length = 0; if (!firstBatchDisplayed) { firstBatchDisplayed = true; // Tell performance monitors that "above the fold" content is displayed // and is ready to interact with. window.performance.mark('visuallyLoaded'); window.performance.mark('contentInteractive'); // Remove the attribute to trigger gaia header font-fit logic, defer it // until now to postpone the overhead. Also, do this asynchronously to // avoid interrupting the enumerating of the db. setTimeout(function() { var headers = document.querySelectorAll('gaia-header'); for (var i = 0; i < headers.length; ++i) { headers[i].removeAttribute('no-font-fit'); } }); } } } function addVideo(videodata) { if (!videodata || !videodata.metadata.isVideo) { return; } // Create the thumbnail view for this video and insert it at the right spot var view = thumbnailList.addItem(videodata); // thumbnailClickHandler is defined in video.js view.addTapListener(thumbnailClickHandler); view.updateTitleText(); // If we just added the first video we need to hide the "no video" overlay if (thumbnailList.count === 1) { updateDialog(); } } function videoCreated(videoinfo) { // When MediaDB tells us about a new video, we add it to the queue for // metadata parsing when we are able to do that. addToMetadataQueue(videoinfo); } function videoDeleted(filename) { // In tablet landscape mode, we use currentVideo to be the current playing // video and last played video. When deleting file and the file is playing or // last played video, we need to change the it to the next, previous or null. if (currentVideo && filename === currentVideo.name) { resetCurrentVideo(); } // And remove its thumbnail from the document thumbnailList.removeItem(filename); // If we just deleted the last video we need to display the "no video" overlay // and go back to thumbnail list view in case we were in thumbnail select view if (thumbnailList.count === 0) { updateDialog(); hideSelectView(); } }