VulpesOS/gaia/tv_apps/fling-player/js/casting_message.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

220 lines
6 KiB
JavaScript
Executable file

/* global mDBG */
(function(exports) {
'use strict';
/**
* This object parses and process the message casted
* between receiver and controller.
*
* The message casted is in JSON and shall carry properties below:
* - seq: Number. The sequence of message sent. Increased by 1 when sending
* one new message. The message sequences from controller and receiver
* shall be independent to each other.
* - type: String. Indicate the message type.
* - other extra properties depending on the type
*
* For example, the message of loading request from a controller may be like:
* {
* 'seq': 3,
* 'type': 'load',
* 'url': 'http://www.example.com/foo.ogg'
* }
*/
var castingMessage = {};
castingMessage.type = Object.freeze({
/**
* Represent the device info.
* The extra message properties:
* - displayName: String. The device display name
*/
'device-info': {
name: 'device-info',
sanitizeMsg: function (msg) {
if (msg.displayName !== undefined &&
typeof msg.displayName != 'string'
) {
throw new Error('Ilegal display name = ' + msg.displayName +
' in casting message of type = ' + this.name);
}
return msg;
}
},
/**
* Represent acknowledgement of message receiving.
* The extra message properties:
* - error: String. Present if there is error
*/
ack: {
name: 'ack',
sanitizeMsg: function (msg) {
if (msg.error !== null &&
msg.error !== undefined &&
typeof msg.error != 'string'
) {
throw new Error('Ilegal error = ' + msg.error +
' in casting message of type = ' + this.name);
}
return msg;
}
},
/**
* Represent video playing status. The extra message properties:
* - time: Number. The current video time
* - status: String. Describe status, could be
* - buffering: Video buffering
* - loaded: The media's metadata has finished loading;
* all attributes now contain as much useful information
* as they're going to.
* - buffered: Video buffered and ready to play
* - playing: Video is playing
* - seeked: Video seeking is done
* - stopped: Video is not playing (maybe ended or paused).
* - error: Error on playing.
* When error occurs, one more extra message properties:
* - error: String. The error code.
*/
status: {
name: 'status',
sanitizeMsg: function (msg) {
if (typeof msg.time != 'number' || (msg.time >= 0) === false) {
throw new Error('Ilegal time = ' + msg.time +
' in casting message of type = ' + this.name);
}
var validStatus = [
'buffering', 'loaded', 'buffered',
'playing', 'seeked', 'stopped', 'error'
];
if (validStatus.indexOf(msg.status) < 0) {
throw new Error('Ilegal status = ' + msg.status +
' in casting message of type = ' + this.name);
}
if (msg.status == 'error' && typeof msg.error != 'string') {
throw new Error('Ilegal error = ' + msg.error +
' in casting message of type = ' + this.name);
}
return msg;
}
},
/**
* Request to load and play video. The extra message properties:
* - url : String. The video url.
*/
load: {
name: 'load',
sanitizeMsg: function (msg) {
if (typeof msg.url != 'string' || !msg.url) {
throw new Error('Ilegal url = ' + msg.url +
' in casting message of type = ' + this.name);
}
return msg;
}
},
/**
* Request to play video
*/
play: {
name: 'play'
},
/**
* Request to pause video
*/
pause: {
name: 'pause'
},
/**
* Request to seek on video. The extra message properties:
* - time: Number. The time to seek.
*/
seek: {
name: 'seek',
sanitizeMsg: function (msg) {
if (typeof msg.time != 'number' || (msg.time >= 0) === false) {
throw new Error('Ilegal time in casting message of type = ' +
this.name, msg.time);
}
return msg;
}
}
});
/**
* Validate and make sure the message format, datatype.
*
* @param {Object} content the message content to sanitize
* @return {Object} Sanitized message
*/
castingMessage.sanitizeMsg = function (content) {
mDBG.log('castingMessage#sanitizeMsg');
mDBG.log('Sanitize message content:', content);
if (this.type[content.type]) {
if (typeof content.seq == 'number' && content.seq >= 0) {
if (typeof this.type[content.type].sanitizeMsg == 'function') {
content = this.type[content.type].sanitizeMsg(content);
}
} else {
throw new Error('Missing sequence of casting message : ' +
JSON.stringify(content));
}
} else {
throw new Error('Unknown type of casting message : ' + content.type);
}
return content;
};
/**
* @param {String} txt the message txt sent from controller
* @return {Array.<Object>} the parsed messages
*/
castingMessage.parse = function (txt) {
mDBG.log('castingMessage#parse');
mDBG.log('Parsing : ', txt);
var data = '[' + txt.replace(/}{/g, '},{') + ']';
mDBG.log('Transformed : ', data);
var msgs = JSON.parse(data);
mDBG.log('JSON Parsed : ', msgs);
var results = [];
msgs.forEach((m) => {
try {
results.push(this.sanitizeMsg(m));
} catch (e) {
mDBG.error(e);
}
});
mDBG.log('Sanitized : ', results);
return results;
};
/**
* @param {Object} content the message content being sent.
* @return {String} the messsage txt to sent
*/
castingMessage.stringify = function (content) {
return JSON.stringify(this.sanitizeMsg(content));
};
exports.castingMessage = castingMessage;
})(window);