2018-12-19 15:05:10 +01:00
|
|
|
/**
|
|
|
|
* @author anthony-arnold [anthony.arnold@uqconnect.edu.au]
|
|
|
|
* @copyright Crown Copyright 2018
|
|
|
|
* @license Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2019-07-09 13:23:59 +02:00
|
|
|
import { fromBase64, toBase64 } from "../lib/Base64.mjs";
|
|
|
|
import { fromHex } from "../lib/Hex.mjs";
|
|
|
|
import Operation from "../Operation.mjs";
|
|
|
|
import OperationError from "../errors/OperationError.mjs";
|
|
|
|
import Utils from "../Utils.mjs";
|
|
|
|
import { isType, detectFileType } from "../lib/FileType.mjs";
|
2018-12-19 15:05:10 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* PlayMedia operation
|
|
|
|
*/
|
|
|
|
class PlayMedia extends Operation {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* PlayMedia constructor
|
|
|
|
*/
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
|
|
|
|
this.name = "Play Media";
|
2018-12-19 18:58:38 +01:00
|
|
|
this.module = "Default";
|
|
|
|
this.description = "Plays the input as audio or video depending on the type.<br><br>Tags: sound, movie, mp3, mp4, mov, webm, wav, ogg";
|
2018-12-19 15:05:10 +01:00
|
|
|
this.infoURL = "";
|
|
|
|
this.inputType = "string";
|
|
|
|
this.outputType = "byteArray";
|
|
|
|
this.presentType = "html";
|
|
|
|
this.args = [
|
|
|
|
{
|
|
|
|
"name": "Input format",
|
|
|
|
"type": "option",
|
|
|
|
"value": ["Raw", "Base64", "Hex"]
|
|
|
|
}
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {string} input
|
|
|
|
* @param {Object[]} args
|
|
|
|
* @returns {byteArray} The multimedia data as bytes.
|
|
|
|
*/
|
|
|
|
run(input, args) {
|
2018-12-19 18:58:38 +01:00
|
|
|
const [inputFormat] = args;
|
2018-12-19 15:05:10 +01:00
|
|
|
|
|
|
|
if (!input.length) return [];
|
|
|
|
|
|
|
|
// Convert input to raw bytes
|
|
|
|
switch (inputFormat) {
|
|
|
|
case "Hex":
|
|
|
|
input = fromHex(input);
|
|
|
|
break;
|
|
|
|
case "Base64":
|
|
|
|
// Don't trust the Base64 entered by the user.
|
|
|
|
// Unwrap it first, then re-encode later.
|
|
|
|
input = fromBase64(input, undefined, "byteArray");
|
|
|
|
break;
|
|
|
|
case "Raw":
|
|
|
|
default:
|
|
|
|
input = Utils.strToByteArray(input);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Determine file type
|
2018-12-26 19:40:27 +01:00
|
|
|
if (!isType(/^(audio|video)/, input)) {
|
2018-12-19 18:58:38 +01:00
|
|
|
throw new OperationError("Invalid or unrecognised file type");
|
2018-12-19 15:05:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Displays an audio or video element that may be able to play the media
|
|
|
|
* file.
|
2018-12-19 18:58:38 +01:00
|
|
|
*
|
2018-12-19 15:05:10 +01:00
|
|
|
* @param data {byteArray} Data containing an audio or video file.
|
|
|
|
* @returns {string} Markup to display a media player.
|
|
|
|
*/
|
|
|
|
async present(data) {
|
|
|
|
if (!data.length) return "";
|
|
|
|
|
2018-12-21 13:48:08 +01:00
|
|
|
const types = detectFileType(data);
|
|
|
|
const matches = /^audio|video/.exec(types[0].mime);
|
2018-12-19 15:05:10 +01:00
|
|
|
if (!matches) {
|
|
|
|
throw new OperationError("Invalid file type");
|
|
|
|
}
|
2018-12-21 13:48:08 +01:00
|
|
|
const dataURI = `data:${types[0].mime};base64,${toBase64(data)}`;
|
2018-12-19 15:05:10 +01:00
|
|
|
const element = matches[0];
|
|
|
|
|
2018-12-21 13:48:08 +01:00
|
|
|
let html = `<${element} src='${dataURI}' type='${types[0].mime}' controls>`;
|
2018-12-19 15:05:10 +01:00
|
|
|
html += "<p>Unsupported media type.</p>";
|
|
|
|
html += `</${element}>`;
|
|
|
|
return html;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default PlayMedia;
|