"use strict"; //// EZrecord.js//// Created by David Rowe on June 24th, 2017.// Copyright 2017 High Fidelity, Inc.// Copyright 2023 Overte e.V.//// Distributed under the Apache License, Version 2.0.// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// (function () { var APP_NAME = "EZRECORD", APP_ICON_INACTIVE = "icons/tablet-icons/avatar-record-i.svg", APP_ICON_ACTIVE = "icons/tablet-icons/avatar-record-a.svg", SHORTCUT_KEY = "r", // Alt modifier is assumed. tablet, button, RecordingIndicator, Recorder; function log(message) { print(APP_NAME + ": " + message); } function logDetails() { return { current_domain: location.placename }; } RecordingIndicator = (function () { // Displays "recording" overlay. var hmdOverlay, HMD_FONT_SIZE = 0.08, desktopOverlay, DESKTOP_FONT_SIZE = 24; function show() { // Create both overlays in case user switches desktop/HMD mode. var screenSize = Controller.getViewportDimensions(), recordingText = "REC", // Unicode circle \u25cf doesn't render in HMD. CAMERA_JOINT_INDEX = -7; if (HMD.active) { // 3D overlay attached to avatar. hmdOverlay = Entities.addEntity({ "type": "Text", "text": recordingText, "dimensions": { "x": 3 * HMD_FONT_SIZE, "y": HMD_FONT_SIZE, "z": 0.01 }, "parentID": MyAvatar.sessionUUID, "parentJointIndex": CAMERA_JOINT_INDEX, "localPosition": { "x": 0.95, "y": 0.95, "z": -2.0 }, "color": { "red": 255, "green": 0, "blue": 0 }, "alpha": 0.9, "unlit": true, "lineHeight": HMD_FONT_SIZE, "backgroundAlpha": 0, "ignorePickIntersection": true, "billboardMode": "full", "renderLayer": "front", "visible": true },"local"); } else { // 2D overlay on desktop. desktopOverlay = Overlays.addOverlay("text", { text: recordingText, width: 3 * DESKTOP_FONT_SIZE, height: DESKTOP_FONT_SIZE, x: screenSize.x - 4 * DESKTOP_FONT_SIZE, y: DESKTOP_FONT_SIZE, font: { size: DESKTOP_FONT_SIZE }, color: { red: 255, green: 8, blue: 8 }, alpha: 1.0, backgroundAlpha: 0, visible: true }); } } function hide() { if (desktopOverlay) { Overlays.deleteOverlay(desktopOverlay); } if (hmdOverlay) { Entities.deleteEntity(hmdOverlay); } } return { show: show, hide: hide }; }()); Recorder = (function () { var IDLE = 0, COUNTING_DOWN = 1, RECORDING = 2, recordingState = IDLE, countdownTimer, countdownSeconds, COUNTDOWN_SECONDS = 3, tickSound, startRecordingSound, finishRecordingSound, TICK_SOUND = "../system/assets/sounds/countdown-tick.wav", START_RECORDING_SOUND = "../system/assets/sounds/start-recording.wav", FINISH_RECORDING_SOUND = "../system/assets/sounds/finish-recording.wav", START_RECORDING_SOUND_DURATION = 1200, SOUND_VOLUME = 0.2; function playSound(sound) { Audio.playSound(sound, { position: MyAvatar.position, localOnly: true, volume: SOUND_VOLUME }); } function isRecording() { return recordingState === COUNTING_DOWN || recordingState === RECORDING; } function startRecording() { if (recordingState !== IDLE) { return; } log("Start countdown"); countdownSeconds = COUNTDOWN_SECONDS; playSound(tickSound); countdownTimer = Script.setInterval(function () { countdownSeconds -= 1; if (countdownSeconds <= 0) { Script.clearInterval(countdownTimer); playSound(startRecordingSound); log("Start recording"); Script.setTimeout(function () { // Delay start so that start beep is not included in recorded sound. Recording.startRecording(); RecordingIndicator.show(); }, START_RECORDING_SOUND_DURATION); recordingState = RECORDING; } else { playSound(tickSound); } }, 1000); recordingState = COUNTING_DOWN; } function cancelRecording() { log("Cancel recording"); if (recordingState === COUNTING_DOWN) { Script.clearInterval(countdownTimer); } else { Recording.stopRecording(); RecordingIndicator.hide(); } recordingState = IDLE; } function finishRecording() { playSound(finishRecordingSound); Recording.stopRecording(); RecordingIndicator.hide(); var filename = (new Date()).toISOString(); // yyyy-mm-ddThh:mm:ss.sssZ filename = filename.replace(/[\-:]|\.\d*Z$/g, "").replace("T", "-") + ".hfr"; // yyyymmmdd-hhmmss.hfr filename = Recording.getDefaultRecordingSaveDirectory() + filename; log("Finish recording: " + filename); Recording.saveRecording(filename); recordingState = IDLE; UserActivityLogger.logAction("ezrecord_finish_recording", logDetails()); } function stopRecording() { if (recordingState === COUNTING_DOWN) { cancelRecording(); } else if (recordingState === RECORDING) { finishRecording(); } } function setUp() { tickSound = SoundCache.getSound(Script.resolvePath(TICK_SOUND)); startRecordingSound = SoundCache.getSound(Script.resolvePath(START_RECORDING_SOUND)); finishRecordingSound = SoundCache.getSound(Script.resolvePath(FINISH_RECORDING_SOUND)); } function tearDown() { if (recordingState !== IDLE) { cancelRecording(); } } return { isRecording: isRecording, startRecording: startRecording, stopRecording: stopRecording, setUp: setUp, tearDown: tearDown }; }()); function toggleRecording() { if (Recorder.isRecording()) { Recorder.stopRecording(); } else { Recorder.startRecording(); } button.editProperties({ isActive: Recorder.isRecording() }); } function onKeyPressEvent(event) { if (event.isAlt && event.text === SHORTCUT_KEY && !event.isControl && !event.isMeta && !event.isAutoRepeat) { toggleRecording(); } } function onButtonClicked() { toggleRecording(); } function setUp() { tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); if (!tablet) { return; } Recorder.setUp(); // tablet/toolbar button. button = tablet.addButton({ icon: APP_ICON_INACTIVE, activeIcon: APP_ICON_ACTIVE, text: APP_NAME, isActive: false }); if (button) { button.clicked.connect(onButtonClicked); } Controller.keyPressEvent.connect(onKeyPressEvent); UserActivityLogger.logAction("ezrecord_run_script", logDetails()); } function tearDown() { Controller.keyPressEvent.disconnect(onKeyPressEvent); Recorder.tearDown(); if (!tablet) { return; } if (button) { button.clicked.disconnect(onButtonClicked); tablet.removeButton(button); button = null; } tablet = null; } setUp(); Script.scriptEnding.connect(tearDown);}());
"use strict";
//
// EZrecord.js
//
// Created by David Rowe on June 24th, 2017.
// Copyright 2017 High Fidelity, Inc.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
(function () {
var APP_NAME = "EZRECORD",
APP_ICON_INACTIVE = "icons/tablet-icons/avatar-record-i.svg",
APP_ICON_ACTIVE = "icons/tablet-icons/avatar-record-a.svg",
SHORTCUT_KEY = "r", // Alt modifier is assumed.
tablet,
button,
RecordingIndicator,
Recorder;
function log(message) {
print(APP_NAME + ": " + message);
}
function logDetails() {
return {
current_domain: location.placename
};
}
RecordingIndicator = (function () {
// Displays "recording" overlay.
var hmdOverlay,
HMD_FONT_SIZE = 0.08,
desktopOverlay,
DESKTOP_FONT_SIZE = 24;
function show() {
// Create both overlays in case user switches desktop/HMD mode.
var screenSize = Controller.getViewportDimensions(),
recordingText = "REC", // Unicode circle \u25cf doesn't render in HMD.
CAMERA_JOINT_INDEX = -7;
if (HMD.active) {
// 3D overlay attached to avatar.
hmdOverlay = Entities.addEntity({
"type": "Text",
"text": recordingText,
"dimensions": { "x": 3 * HMD_FONT_SIZE, "y": HMD_FONT_SIZE, "z": 0.01 },
"parentID": MyAvatar.sessionUUID,
"parentJointIndex": CAMERA_JOINT_INDEX,
"localPosition": { "x": 0.95, "y": 0.95, "z": -2.0 },
"color": { "red": 255, "green": 0, "blue": 0 },
"alpha": 0.9,
"unlit": true,
"lineHeight": HMD_FONT_SIZE,
"backgroundAlpha": 0,
"ignorePickIntersection": true,
"billboardMode": "full",
"renderLayer": "front",
"visible": true
},"local");
} else {
// 2D overlay on desktop.
desktopOverlay = Overlays.addOverlay("text", {
text: recordingText,
width: 3 * DESKTOP_FONT_SIZE,
height: DESKTOP_FONT_SIZE,
x: screenSize.x - 4 * DESKTOP_FONT_SIZE,
y: DESKTOP_FONT_SIZE,
font: { size: DESKTOP_FONT_SIZE },
color: { red: 255, green: 8, blue: 8 },
alpha: 1.0,
backgroundAlpha: 0,
visible: true
});
}
}
function hide() {
if (desktopOverlay) {
Overlays.deleteOverlay(desktopOverlay);
}
if (hmdOverlay) {
Entities.deleteEntity(hmdOverlay);
}
}
return {
show: show,
hide: hide
};
}());
Recorder = (function () {
var IDLE = 0,
COUNTING_DOWN = 1,
RECORDING = 2,
recordingState = IDLE,
countdownTimer,
countdownSeconds,
COUNTDOWN_SECONDS = 3,
tickSound,
startRecordingSound,
finishRecordingSound,
TICK_SOUND = "../system/assets/sounds/countdown-tick.wav",
START_RECORDING_SOUND = "../system/assets/sounds/start-recording.wav",
FINISH_RECORDING_SOUND = "../system/assets/sounds/finish-recording.wav",
START_RECORDING_SOUND_DURATION = 1200,
SOUND_VOLUME = 0.2;
function playSound(sound) {
Audio.playSound(sound, {
position: MyAvatar.position,
localOnly: true,
volume: SOUND_VOLUME
});
}
function isRecording() {
return recordingState === COUNTING_DOWN || recordingState === RECORDING;
}
function startRecording() {
if (recordingState !== IDLE) {
return;
}
log("Start countdown");
countdownSeconds = COUNTDOWN_SECONDS;
playSound(tickSound);
countdownTimer = Script.setInterval(function () {
countdownSeconds -= 1;
if (countdownSeconds <= 0) {
Script.clearInterval(countdownTimer);
playSound(startRecordingSound);
log("Start recording");
Script.setTimeout(function () {
// Delay start so that start beep is not included in recorded sound.
Recording.startRecording();
RecordingIndicator.show();
}, START_RECORDING_SOUND_DURATION);
recordingState = RECORDING;
} else {
playSound(tickSound);
}
}, 1000);
recordingState = COUNTING_DOWN;
}
function cancelRecording() {
log("Cancel recording");
if (recordingState === COUNTING_DOWN) {
Script.clearInterval(countdownTimer);
} else {
Recording.stopRecording();
RecordingIndicator.hide();
}
recordingState = IDLE;
}
function finishRecording() {
playSound(finishRecordingSound);
Recording.stopRecording();
RecordingIndicator.hide();
var filename = (new Date()).toISOString(); // yyyy-mm-ddThh:mm:ss.sssZ
filename = filename.replace(/[\-:]|\.\d*Z$/g, "").replace("T", "-") + ".hfr"; // yyyymmmdd-hhmmss.hfr
filename = Recording.getDefaultRecordingSaveDirectory() + filename;
log("Finish recording: " + filename);
Recording.saveRecording(filename);
recordingState = IDLE;
UserActivityLogger.logAction("ezrecord_finish_recording", logDetails());
}
function stopRecording() {
if (recordingState === COUNTING_DOWN) {
cancelRecording();
} else if (recordingState === RECORDING) {
finishRecording();
}
}
function setUp() {
tickSound = SoundCache.getSound(Script.resolvePath(TICK_SOUND));
startRecordingSound = SoundCache.getSound(Script.resolvePath(START_RECORDING_SOUND));
finishRecordingSound = SoundCache.getSound(Script.resolvePath(FINISH_RECORDING_SOUND));
}
function tearDown() {
if (recordingState !== IDLE) {
cancelRecording();
}
}
return {
isRecording: isRecording,
startRecording: startRecording,
stopRecording: stopRecording,
setUp: setUp,
tearDown: tearDown
};
}());
function toggleRecording() {
if (Recorder.isRecording()) {
Recorder.stopRecording();
} else {
Recorder.startRecording();
}
button.editProperties({ isActive: Recorder.isRecording() });
}
function onKeyPressEvent(event) {
if (event.isAlt && event.text === SHORTCUT_KEY && !event.isControl && !event.isMeta && !event.isAutoRepeat) {
toggleRecording();
}
}
function onButtonClicked() {
toggleRecording();
}
function setUp() {
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
if (!tablet) {
return;
}
Recorder.setUp();
// tablet/toolbar button.
button = tablet.addButton({
icon: APP_ICON_INACTIVE,
activeIcon: APP_ICON_ACTIVE,
text: APP_NAME,
isActive: false
});
if (button) {
button.clicked.connect(onButtonClicked);
}
Controller.keyPressEvent.connect(onKeyPressEvent);
UserActivityLogger.logAction("ezrecord_run_script", logDetails());
}
function tearDown() {
Controller.keyPressEvent.disconnect(onKeyPressEvent);
Recorder.tearDown();
if (!tablet) {
return;
}
if (button) {
button.clicked.disconnect(onButtonClicked);
tablet.removeButton(button);
button = null;
}
tablet = null;
}
setUp();
Script.scriptEnding.connect(tearDown);
}());