Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
194 lines
6 KiB
JavaScript
Executable file
194 lines
6 KiB
JavaScript
Executable file
/* 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();
|
|
}
|
|
}
|