mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-11-20 18:06:11 -05:00
Major refactoring of UI code, small UI changes. (#48)
* Major refactoring of UI code, small UI changes. * Single file index.js split up into separate modules * Modules for handling UI view components * Modules for handling JSON/Model data * Modules for support tasks * Module to encapsulate Moonfire API * Main application module * index.js simplified to just activating main app * Settings file functionality expanded * UI adds "Time Format" popup to allow changing time representation * CSS changes/additions to streamline looks * Recordings loading indicator only appears after 500ms delay, if at all * Address first set of PR change requests from Scott. * Add copyright headers to all files (except JSON files) * Fix bug with entering time values in range pickers * Fixed an erroneous comment and/or spelling error here and there * Fixed JSDoc comments where [description] was not filled in * Removed a TODO from NVRApplication as it no longer applies * Fixed bug handling "infinite" case of video segment lengths * Fixed bug in "trim" handler and trim execution * Retrofit video continues loading from separate PR Signed-off-by: Dolf Starreveld <dolf@starreveld.com> * Address PR comments Signed-off-by: Dolf Starreveld <dolf@starreveld.com> * Address PR comments Signed-off-by: Dolf Starreveld <dolf@starreveld.com>
This commit is contained in:
committed by
Scott Lamb
parent
caac324bd5
commit
58152e8d94
245
ui-src/lib/models/CalendarTSRange.js
Normal file
245
ui-src/lib/models/CalendarTSRange.js
Normal file
@@ -0,0 +1,245 @@
|
||||
// vim: set et sw=2 ts=2:
|
||||
//
|
||||
// This file is part of Moonfire NVR, a security camera digital video recorder.
|
||||
// Copyright (C) 2018 Dolf Starreveld <dolf@starreveld.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations including
|
||||
// the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for all
|
||||
// of the code used other than OpenSSL. If you modify file(s) with this
|
||||
// exception, you may extend this exception to your version of the
|
||||
// file(s), but you are not obligated to do so. If you do not wish to do
|
||||
// so, delete this exception statement from your version. If you delete
|
||||
// this exception statement from all source files in the program, then
|
||||
// also delete it here.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import Time90kParser from '../support/Time90kParser';
|
||||
import {TimeStamp90kFormatter} from '../support/TimeFormatter';
|
||||
import Range90k from './Range90k';
|
||||
|
||||
/**
|
||||
* Class representing a calendar timestamp range based on 90k units.
|
||||
*
|
||||
* A calendar timestamp differs from a Range90k in that a date string
|
||||
* is involved on each end as well.
|
||||
*
|
||||
* The range has a start and end property (via getters) and each has three
|
||||
* contained properties:
|
||||
* - dateStr: string for date in ISO8601 format
|
||||
* - timeStr: string for time in ISO8601 format
|
||||
* - ts90k: Number for the timestamp in 90k units
|
||||
*/
|
||||
export default class CalendarTSRange {
|
||||
/**
|
||||
* Construct a range with a given timezone for display purposes.
|
||||
*
|
||||
* @param {String} timeZone Desired timezone, e.g. 'America/Los_Angeles'
|
||||
*/
|
||||
constructor(timeZone) {
|
||||
this._start = {dateStr: null, timeStr: '', ts90k: null};
|
||||
this._end = {dateStr: null, timeStr: '', ts90k: null};
|
||||
// Don't need to keep timezone, but need parser and formatter
|
||||
this._timeFormatter = new TimeStamp90kFormatter(timeZone);
|
||||
this._timeParser = new Time90kParser(timeZone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a valid start date string is present.
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
hasStart() {
|
||||
return this.start.dateStr !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a valid end date string is present.
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
hasEnd() {
|
||||
return this.end.dateStr !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a valid start and end date string is present.
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
hasRange() {
|
||||
return this.hasStart() && this.hasEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the range's start component.
|
||||
*
|
||||
* @return {object} Object containing dateStr, timeStr, and ts90k components
|
||||
*/
|
||||
get start() {
|
||||
return this._start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the range's end component.
|
||||
*
|
||||
* @return {object} Object containing dateStr, timeStr, and ts90k components
|
||||
*/
|
||||
get end() {
|
||||
return this._end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the range's start component's ts90k property
|
||||
*
|
||||
* @return {object} timestamp in 90k units
|
||||
*/
|
||||
get startTime90k() {
|
||||
return this.start.ts90k;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the range's end component's ts90k property
|
||||
*
|
||||
* @return {object} timestamp in 90k units
|
||||
*/
|
||||
get endTime90k() {
|
||||
return this.end.ts90k;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the range has a defined start timestamp in 90k units.
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
get hasStartTime() {
|
||||
return this.startTime90k !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the calendar range in terms of a range over 90k timestamps.
|
||||
*
|
||||
* @return {Range90k} Range object or null if don't have start and end
|
||||
*/
|
||||
range90k() {
|
||||
return this.hasRange()
|
||||
? new Range90k(this.startTime90k, this.endTime90k)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function to update either start or end type range component.
|
||||
*
|
||||
* Strings are parsed to check if they are valid. Update only takes place
|
||||
* if they are. Parsing is in accordance with the installed Time90kParser
|
||||
* which means:
|
||||
* - HH:MM:ss:FFFFFZ format, where each componet may be empty to indicate 0
|
||||
* - YYYY-MM-DD format for the date
|
||||
*
|
||||
* NOTE: This function potentially modifies the content of the range
|
||||
* argument. This is on purpose and should reflect the new range values
|
||||
* upon succesful parsing!
|
||||
*
|
||||
* @param {object} range A range component
|
||||
* @param {String} dateStr Date string, if null range's value is re-used
|
||||
* @param {String} timeStr Time string, if null range's value is re-used
|
||||
* @param {Boolean} dateOnlyThenEndOfDay True if one should be added to date
|
||||
* which is only meaningful if there
|
||||
* is no time specified here, and also
|
||||
* not present in the range.
|
||||
* @return {Number} New timestamp if succesfully parsed, null otherwise
|
||||
*/
|
||||
_setRangeTime(range, dateStr, timeStr, dateOnlyThenEndOfDay) {
|
||||
dateStr = dateStr || range.dateStr;
|
||||
timeStr = timeStr || range.timeStr;
|
||||
const newTs90k = this._timeParser.parseDateTime90k(
|
||||
dateStr,
|
||||
timeStr,
|
||||
dateOnlyThenEndOfDay
|
||||
);
|
||||
if (newTs90k !== null) {
|
||||
range.dateStr = dateStr;
|
||||
range.timeStr = timeStr;
|
||||
range.ts90k = newTs90k;
|
||||
return newTs90k;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set start component of range from date and time strings.
|
||||
*
|
||||
* Uses _setRangeTime with appropriate dateOnlyThenEndOfDay value.
|
||||
*
|
||||
* @param {String} dateStr Date string
|
||||
* @param {String} timeStr Time string
|
||||
* @return {Number} New timestamp if succesfully parsed, null otherwise
|
||||
*/
|
||||
setStartDate(dateStr, timeStr = null) {
|
||||
return this._setRangeTime(this._start, dateStr, timeStr, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set time of start component of range time string.
|
||||
*
|
||||
* Uses _setRangeTime with appropriate dateOnlyThenEndOfDay value.
|
||||
*
|
||||
* @param {String} timeStr Time string
|
||||
* @return {Number} New timestamp if succesfully parsed, null otherwise
|
||||
*/
|
||||
setStartTime(timeStr) {
|
||||
return this._setRangeTime(this._start, null, timeStr, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set end component of range from date and time strings.
|
||||
*
|
||||
* Uses _setRangeTime with appropriate addOne value.
|
||||
*
|
||||
* @param {String} dateStr Date string
|
||||
* @param {String} timeStr Time string
|
||||
* @return {Number} New timestamp if succesfully parsed, null otherwise
|
||||
*/
|
||||
setEndDate(dateStr, timeStr = null) {
|
||||
return this._setRangeTime(this._end, dateStr, timeStr, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set time of end component of range time string.
|
||||
*
|
||||
* Uses _setRangeTime with appropriate addOne value.
|
||||
*
|
||||
* @param {String} timeStr Time string
|
||||
* @return {Number} New timestamp if succesfully parsed, null otherwise
|
||||
*/
|
||||
setEndTime(timeStr) {
|
||||
return this._setRangeTime(this._end, null, timeStr, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a timestamp in 90k units in the manner consistent with
|
||||
* what the parser of this module expects.
|
||||
*
|
||||
* @param {Number} ts90k Timestamp in 90k units
|
||||
* @return {String} Formatted string
|
||||
*/
|
||||
formatTimeStamp90k(ts90k) {
|
||||
return this._timeFormatter.formatTimeStamp90k(ts90k);
|
||||
}
|
||||
}
|
||||
132
ui-src/lib/models/Camera.js
Normal file
132
ui-src/lib/models/Camera.js
Normal file
@@ -0,0 +1,132 @@
|
||||
// vim: set et sw=2 ts=2:
|
||||
//
|
||||
// This file is part of Moonfire NVR, a security camera digital video recorder.
|
||||
// Copyright (C) 2018 Dolf Starreveld <dolf@starreveld.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations including
|
||||
// the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for all
|
||||
// of the code used other than OpenSSL. If you modify file(s) with this
|
||||
// exception, you may extend this exception to your version of the
|
||||
// file(s), but you are not obligated to do so. If you do not wish to do
|
||||
// so, delete this exception statement from your version. If you delete
|
||||
// this exception statement from all source files in the program, then
|
||||
// also delete it here.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import JsonWrapper from './JsonWrapper';
|
||||
import Range90k from './Range90k';
|
||||
|
||||
/**
|
||||
* Camera JSON wrapper.
|
||||
*/
|
||||
export default class Camera extends JsonWrapper {
|
||||
/**
|
||||
* Construct from JSON.
|
||||
*
|
||||
* @param {JSON} cameraJson JSON for single camera.
|
||||
*/
|
||||
constructor(cameraJson) {
|
||||
super(cameraJson);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get camera uuid.
|
||||
*
|
||||
* @return {String} Camera's uuid
|
||||
*/
|
||||
get uuid() {
|
||||
return this.json.uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get camera's short name.
|
||||
*
|
||||
* @return {String} Name of the camera
|
||||
*/
|
||||
get shortName() {
|
||||
return this.json.shortName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get camera's description.
|
||||
*
|
||||
* @return {String} Camera's description
|
||||
*/
|
||||
get description() {
|
||||
return this.json.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get maximimum amount of storage allowed to be used for camera's video
|
||||
* samples.
|
||||
*
|
||||
* @return {Number} Amount in bytes
|
||||
*/
|
||||
get retainBytes() {
|
||||
return this.json.retainBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Range90K object representing the range encompassing all available
|
||||
* video samples for the camera.
|
||||
*
|
||||
* This range does not mean every second of the range has video!
|
||||
*
|
||||
* @return {Range90k} The camera's available recordings range
|
||||
*/
|
||||
get range90k() {
|
||||
return new Range90k(
|
||||
this.json.minStartTime90k,
|
||||
this.json.maxEndTime90k,
|
||||
this.json.totalDuration90k
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total amount of storage currently taken up by the camera's video
|
||||
* samples.
|
||||
*
|
||||
* @return {Number} Amount in bytes
|
||||
*/
|
||||
get totalSampleFileBytes() {
|
||||
return this.json.totalSampleFileBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of the camera's days for which there are video samples.
|
||||
*
|
||||
* The result is a Map with dates as keys (in YYYY-MM-DD format) and each
|
||||
* value is a Range90k object for that day. Here too, the range does not
|
||||
* mean every second in the range has video, but presence of an entry for
|
||||
* a day does mean there is at least one (however short) video segment
|
||||
* available.
|
||||
*
|
||||
* @return {Map} Dates are keys, values are Range90K objects.
|
||||
*/
|
||||
get days() {
|
||||
return new Map(
|
||||
Object.entries(this.json.days).map(function(t) {
|
||||
let [k, v] = t;
|
||||
v = new Range90k(v.startTime90k, v.endTime90k, v.totalDuration90k);
|
||||
return [k, v];
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
80
ui-src/lib/models/JsonWrapper.js
Normal file
80
ui-src/lib/models/JsonWrapper.js
Normal file
@@ -0,0 +1,80 @@
|
||||
// vim: set et sw=2 ts=2:
|
||||
//
|
||||
// This file is part of Moonfire NVR, a security camera digital video recorder.
|
||||
// Copyright (C) 2018 Dolf Starreveld <dolf@starreveld.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations including
|
||||
// the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for all
|
||||
// of the code used other than OpenSSL. If you modify file(s) with this
|
||||
// exception, you may extend this exception to your version of the
|
||||
// file(s), but you are not obligated to do so. If you do not wish to do
|
||||
// so, delete this exception statement from your version. If you delete
|
||||
// this exception statement from all source files in the program, then
|
||||
// also delete it here.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* WeakMap that keeps our private data.
|
||||
*
|
||||
* @type {WeakMap}
|
||||
*/
|
||||
let _json = new WeakMap();
|
||||
|
||||
/**
|
||||
* Class to encapsulate recording JSON data.
|
||||
* *
|
||||
* The JSON is kept internally, but in a manner that does not allow direct
|
||||
* access. If access is needed, use the "json()" method. Sub-classes for
|
||||
* specific models shoudl provide the necessary getters instead.
|
||||
*/
|
||||
export default class JsonWrapper {
|
||||
/**
|
||||
* Accept JSON data to be encapsulated
|
||||
*
|
||||
* @param {object} jsonData JSON data
|
||||
*/
|
||||
constructor(jsonData) {
|
||||
_json.set(this, jsonData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get associated JSON object.
|
||||
*
|
||||
* Use of this should be avoided. Use functions to access the
|
||||
* data instead.
|
||||
*
|
||||
* @return {object} The JSON object.
|
||||
*/
|
||||
get json() {
|
||||
return _json.get(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @return {String} String version
|
||||
*/
|
||||
toString() {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
return this.json.toString();
|
||||
} else {
|
||||
return super.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
73
ui-src/lib/models/Range.js
Normal file
73
ui-src/lib/models/Range.js
Normal file
@@ -0,0 +1,73 @@
|
||||
// vim: set et sw=2 ts=2:
|
||||
//
|
||||
// This file is part of Moonfire NVR, a security camera digital video recorder.
|
||||
// Copyright (C) 2018 Dolf Starreveld <dolf@starreveld.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations including
|
||||
// the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for all
|
||||
// of the code used other than OpenSSL. If you modify file(s) with this
|
||||
// exception, you may extend this exception to your version of the
|
||||
// file(s), but you are not obligated to do so. If you do not wish to do
|
||||
// so, delete this exception statement from your version. If you delete
|
||||
// this exception statement from all source files in the program, then
|
||||
// also delete it here.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Class to represent ranges of values.
|
||||
*
|
||||
* The range has a "low", and "high" value property and is inclusive.
|
||||
* The "size" property returns the difference between high and low.
|
||||
*/
|
||||
export default class Range {
|
||||
/**
|
||||
* Create a range.
|
||||
*
|
||||
* @param {Number} low Low value (inclusive) in range.
|
||||
* @param {Number} high High value (inclusive) in range.
|
||||
*/
|
||||
constructor(low, high) {
|
||||
if (high < low) {
|
||||
console.log('Warning range swap: ' + low + ' - ' + high);
|
||||
[low, high] = [high, low];
|
||||
}
|
||||
this.low = low;
|
||||
this.high = high;
|
||||
}
|
||||
|
||||
/**
|
||||
* Size of the range.
|
||||
*
|
||||
* @return {Number} high - low
|
||||
*/
|
||||
get size() {
|
||||
return this.high - this.low;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if value is inside the range.
|
||||
*
|
||||
* @param {Number} value Value to test
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isInRange(value) {
|
||||
return value >= this.low && value <= this.high;
|
||||
}
|
||||
}
|
||||
109
ui-src/lib/models/Range90k.js
Normal file
109
ui-src/lib/models/Range90k.js
Normal file
@@ -0,0 +1,109 @@
|
||||
// vim: set et sw=2 ts=2:
|
||||
//
|
||||
// This file is part of Moonfire NVR, a security camera digital video recorder.
|
||||
// Copyright (C) 2018 Dolf Starreveld <dolf@starreveld.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations including
|
||||
// the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for all
|
||||
// of the code used other than OpenSSL. If you modify file(s) with this
|
||||
// exception, you may extend this exception to your version of the
|
||||
// file(s), but you are not obligated to do so. If you do not wish to do
|
||||
// so, delete this exception statement from your version. If you delete
|
||||
// this exception statement from all source files in the program, then
|
||||
// also delete it here.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import Range from './Range';
|
||||
|
||||
/**
|
||||
* WeakMap that keeps our private data.
|
||||
*
|
||||
* @type {WeakMap}
|
||||
*/
|
||||
let _range = new WeakMap();
|
||||
|
||||
/**
|
||||
* Subclass of Range to represent ranges over timestamps in 90k format.
|
||||
*
|
||||
* This mostly means added some getters with names that make more sense.
|
||||
*/
|
||||
export default class Range90k {
|
||||
/**
|
||||
* Create a range.
|
||||
*
|
||||
* @param {Number} low Low value (inclusive) in range.
|
||||
* @param {Number} high High value (inclusive) in range.
|
||||
*/
|
||||
constructor(low, high) {
|
||||
_range.set(this, new Range(low, high));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the range's start time.
|
||||
*
|
||||
* @return {Number} Number in 90k units
|
||||
*/
|
||||
get startTime90k() {
|
||||
return _range.get(this).low;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the range's end time.
|
||||
*
|
||||
* @return {Number} Number in 90k units
|
||||
*/
|
||||
get endTime90k() {
|
||||
return _range.get(this).high;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the range's duration.
|
||||
*
|
||||
* @return {Number} Number in 90k units
|
||||
*/
|
||||
get duration90k() {
|
||||
return _range.get(this).size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new range by trimming the current range against
|
||||
* another.
|
||||
*
|
||||
* The returned range will lie completely within the provided range.
|
||||
*
|
||||
* @param {Range90k} against Range the be used for limits
|
||||
* @return {Range90k} The trimmed range (always a new object)
|
||||
*/
|
||||
trimmed(against) {
|
||||
return new Range90k(
|
||||
Math.max(this.startTime90k, against.startTime90k),
|
||||
Math.min(this.endTime90k, against.endTime90k)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a copy of this range.
|
||||
*
|
||||
* @return {Range90k} A copy of this range object.
|
||||
*/
|
||||
clone() {
|
||||
return new Range90k(this.startTime90k, this.endTime90k);
|
||||
}
|
||||
}
|
||||
155
ui-src/lib/models/Recording.js
Normal file
155
ui-src/lib/models/Recording.js
Normal file
@@ -0,0 +1,155 @@
|
||||
// vim: set et sw=2 ts=2:
|
||||
//
|
||||
// This file is part of Moonfire NVR, a security camera digital video recorder.
|
||||
// Copyright (C) 2018 Dolf Starreveld <dolf@starreveld.com>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations including
|
||||
// the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for all
|
||||
// of the code used other than OpenSSL. If you modify file(s) with this
|
||||
// exception, you may extend this exception to your version of the
|
||||
// file(s), but you are not obligated to do so. If you do not wish to do
|
||||
// so, delete this exception statement from your version. If you delete
|
||||
// this exception statement from all source files in the program, then
|
||||
// also delete it here.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import JsonWrapper from './JsonWrapper';
|
||||
import Range90k from '../models/Range90k';
|
||||
|
||||
/**
|
||||
* Class to encapsulate recording JSON data.
|
||||
*/
|
||||
export default class Recording extends JsonWrapper {
|
||||
/**
|
||||
* Accept JSON data to be encapsulated
|
||||
*
|
||||
* @param {object} recordingJson JSON for a recording
|
||||
*/
|
||||
constructor(recordingJson) {
|
||||
super(recordingJson);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get recording's startId.
|
||||
*
|
||||
* @return {String} startId for recording
|
||||
*/
|
||||
get startId() {
|
||||
return this.json.startId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get recording's endId.
|
||||
*
|
||||
* @return {String} endId for recording
|
||||
*/
|
||||
get endId() {
|
||||
return this.json.endId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return start time of recording in 90k units.
|
||||
* @return {Number} Time in units of 90k parts of a second
|
||||
*/
|
||||
get startTime90k() {
|
||||
return this.json.startTime90k;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return end time of recording in 90k units.
|
||||
* @return {Number} Time in units of 90k parts of a second
|
||||
*/
|
||||
get endTime90k() {
|
||||
return this.json.endTime90k;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return duration of recording in 90k units.
|
||||
* @return {Number} Time in units of 90k parts of a second
|
||||
*/
|
||||
get duration90k() {
|
||||
const data = this.json;
|
||||
return data.endTime90k - data.startTime90k;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the range of the recording in 90k timestamp units,
|
||||
* optionally trimmed by another range.
|
||||
*
|
||||
* @param {Range90k} trimmedAgainst Optional range to trim against
|
||||
* @return {Range90k} Resulting range
|
||||
*/
|
||||
range90k(trimmedAgainst = null) {
|
||||
let result = new Range90k(this.startTime90k, this.endTime90k);
|
||||
return trimmedAgainst ? result.trimmed(trimmedAgainst) : result;
|
||||
}
|
||||
/**
|
||||
* Return duration of recording in seconds.
|
||||
* @return {Number} Time in units of seconds.
|
||||
*/
|
||||
get duration() {
|
||||
return this.duration90k / 90000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of bytes used by sample storage.
|
||||
*
|
||||
* @return {Number} Total bytes used
|
||||
*/
|
||||
get sampleFileBytes() {
|
||||
return this.json.sampleFileBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of video samples (frames) for the recording.
|
||||
*
|
||||
* @return {Number} Total bytes used
|
||||
*/
|
||||
get frameCount() {
|
||||
return this.json.videoSamples;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the has for the video samples.
|
||||
*
|
||||
* @return {String} Hash
|
||||
*/
|
||||
get videoSampleEntryHash() {
|
||||
return this.json.videoSampleEntrySha1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width of the frame(s) of the video samples.
|
||||
*
|
||||
* @return {Number} Width in pixels
|
||||
*/
|
||||
get videoSampleEntryWidth() {
|
||||
return this.json.videoSampleEntryWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the height of the frame(s) of the video samples.
|
||||
*
|
||||
* @return {Number} Height in pixels
|
||||
*/
|
||||
get videoSampleEntryHeight() {
|
||||
return this.json.videoSampleEntryHeight;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user