Merge pull request #10427 from ctrlaltdavid/21334

Fix erroneous "did not start playing recording" messages
This commit is contained in:
Brad Hefta-Gaub 2017-05-16 20:54:27 -07:00 committed by GitHub
commit b0d2de7bc0
2 changed files with 118 additions and 59 deletions

View file

@ -14,6 +14,7 @@
var APP_NAME = "PLAYBACK",
HIFI_RECORDER_CHANNEL = "HiFi-Recorder-Channel",
RECORDER_COMMAND_ERROR = "error",
HIFI_PLAYER_CHANNEL = "HiFi-Player-Channel",
PLAYER_COMMAND_PLAY = "play",
PLAYER_COMMAND_STOP = "stop",
@ -47,9 +48,17 @@
searchState = SEARCH_IDLE,
otherPlayersPlaying,
otherPlayersPlayingCounts,
pauseCount;
pauseCount,
isDestroyLater = false,
destroy;
function onUpdateTimestamp() {
if (isDestroyLater) {
destroy();
return;
}
userData.timestamp = Date.now();
Entities.editEntity(entityID, { userData: JSON.stringify(userData) });
EntityViewer.queryOctree(); // Keep up to date ready for find().
@ -69,12 +78,14 @@
if (sender !== scriptUUID) {
message = JSON.parse(message);
index = otherPlayersPlaying.indexOf(message.entity);
if (index !== -1) {
otherPlayersPlayingCounts[index] += 1;
} else {
otherPlayersPlaying.push(message.entity);
otherPlayersPlayingCounts.push(1);
if (message.playing !== undefined) {
index = otherPlayersPlaying.indexOf(message.entity);
if (index !== -1) {
otherPlayersPlayingCounts[index] += 1;
} else {
otherPlayersPlaying.push(message.entity);
otherPlayersPlayingCounts.push(1);
}
}
}
}
@ -83,10 +94,11 @@
// Create a new persistence entity (even if already have one but that should never occur).
var properties;
log("Create recording " + filename);
log("Create recording entity for " + filename);
if (updateTimestampTimer !== null) {
Script.clearInterval(updateTimestampTimer); // Just in case.
if (updateTimestampTimer !== null) { // Just in case.
Script.clearInterval(updateTimestampTimer);
updateTimestampTimer = null;
}
searchState = SEARCH_IDLE;
@ -114,6 +126,7 @@
return true;
}
log("Could not create recording entity for " + filename);
return false;
}
@ -224,7 +237,7 @@
return result;
}
function destroy() {
destroy = function () {
// Delete current persistence entity.
if (entityID !== null) { // Just in case.
Entities.deleteEntity(entityID);
@ -233,7 +246,13 @@
}
if (updateTimestampTimer !== null) { // Just in case.
Script.clearInterval(updateTimestampTimer);
updateTimestampTimer = null;
}
};
function destroyLater() {
// Schedules a call to destroy() when timer threading suits.
isDestroyLater = true;
}
function setUp() {
@ -254,6 +273,7 @@
create: create,
find: find,
destroy: destroy,
destroyLater: destroyLater,
setUp: setUp,
tearDown: tearDown
};
@ -261,41 +281,78 @@
Player = (function () {
// Recording playback functions.
var isPlayingRecording = false,
var userID = null,
isPlayingRecording = false,
recordingFilename = "",
autoPlayTimer = null,
autoPlay,
playRecording;
function play(recording, position, orientation) {
function error(message) {
// Send error message to user.
Messages.sendMessage(HIFI_RECORDER_CHANNEL, JSON.stringify({
command: RECORDER_COMMAND_ERROR,
user: userID,
message: message
}));
}
function play(user, recording, position, orientation) {
var errorMessage;
if (autoPlayTimer) { // Cancel auto-play.
// FIXME: Once in a while Script.clearTimeout() fails.
// [DEBUG] [hifi.scriptengine] [3748] [agent] stopTimer -- not in _timerFunctionMap QObject(0x0)
Script.clearTimeout(autoPlayTimer);
autoPlayTimer = null;
}
userID = user;
if (Entity.create(recording, position, orientation)) {
log("Play new recording " + recordingFilename);
isPlayingRecording = true;
log("Play recording " + recording);
isPlayingRecording = true; // Immediate feedback.
recordingFilename = recording;
playRecording(recordingFilename, position, orientation);
playRecording(recordingFilename, position, orientation, true);
} else {
log("Could not create entity to play new recording " + recordingFilename);
errorMessage = "Could not persist recording " + recording.slice(4); // Remove leading "atp:".
log(errorMessage);
error(errorMessage);
autoPlayTimer = Script.setTimeout(autoPlay, AUTOPLAY_ERROR_INTERVAL); // Resume auto-play later.
}
}
function autoPlay() {
autoPlay = function () {
var recording,
AUTOPLAY_SEARCH_DELTA = 1000;
// Random delay to help reduce collisions between AC scripts.
Script.setTimeout(function () {
// Guard against Script.clearTimeout() in play() not always working.
if (isPlayingRecording) {
return;
}
recording = Entity.find();
if (recording) {
log("Play persisted recording " + recordingFilename);
playRecording(recording.recording, recording.position, recording.orientation);
log("Play persisted recording " + recording.recording);
userID = null;
autoPlayTimer = null;
isPlayingRecording = true; // Immediate feedback.
recordingFilename = recording.recording;
playRecording(recording.recording, recording.position, recording.orientation, false);
} else {
autoPlayTimer = Script.setTimeout(autoPlay, AUTOPLAY_SEARCH_INTERVAL); // Try again soon.
}
}, Math.random() * AUTOPLAY_SEARCH_DELTA);
}
};
playRecording = function (recording, position, orientation) {
playRecording = function (recording, position, orientation, isManual) {
Recording.loadRecording(recording, function (success) {
var errorMessage;
if (success) {
Users.disableIgnoreRadius();
@ -310,15 +367,22 @@
Recording.setPlayerLoop(true);
Recording.setPlayerUseSkeletonModel(true);
isPlayingRecording = true;
recordingFilename = recording;
Recording.setPlayerTime(0.0);
Recording.startPlaying();
UserActivityLogger.logAction("playRecordingAC_play_recording");
} else {
log("Failed to load recording " + recording);
if (isManual) {
// Delete persistence entity if manual play request.
Entity.destroyLater(); // Schedule for deletion; works around timer threading issues.
}
errorMessage = "Could not load recording " + recording.slice(4); // Remove leading "atp:".
log(errorMessage);
error(errorMessage);
isPlayingRecording = false;
recordingFilename = "";
autoPlayTimer = Script.setTimeout(autoPlay, AUTOPLAY_ERROR_INTERVAL); // Try again later.
}
});
@ -374,7 +438,15 @@
recording: Player.recording(),
entity: Entity.id()
}));
heartbeatTimer = Script.setTimeout(sendHeartbeat, HEARTBEAT_INTERVAL);
}
function onHeartbeatTimer() {
sendHeartbeat();
heartbeatTimer = Script.setTimeout(onHeartbeatTimer, HEARTBEAT_INTERVAL);
}
function startHeartbeat() {
onHeartbeatTimer();
}
function stopHeartbeat() {
@ -394,7 +466,7 @@
switch (message.command) {
case PLAYER_COMMAND_PLAY:
if (!Player.isPlaying()) {
Player.play(message.recording, message.position, message.orientation);
Player.play(sender, message.recording, message.position, message.orientation);
} else {
log("Didn't start playing " + message.recording + " because already playing " + Player.recording());
}
@ -418,7 +490,7 @@
Messages.subscribe(HIFI_PLAYER_CHANNEL);
Player.autoPlay();
sendHeartbeat();
startHeartbeat();
UserActivityLogger.logAction("playRecordingAC_script_load");
}

View file

@ -275,6 +275,7 @@
Player = (function () {
var HIFI_RECORDER_CHANNEL = "HiFi-Recorder-Channel",
RECORDER_COMMAND_ERROR = "error",
HIFI_PLAYER_CHANNEL = "HiFi-Player-Channel",
PLAYER_COMMAND_PLAY = "play",
PLAYER_COMMAND_STOP = "stop",
@ -283,7 +284,6 @@
playerIsPlayings = [], // True if AC player script is playing a recording.
playerRecordings = [], // Assignment client mappings of recordings being played.
playerTimestamps = [], // Timestamps of last heartbeat update from player script.
playerStartupTimeouts = [], // Timers that check that recording has started playing.
updateTimer,
UPDATE_INTERVAL = 5000; // Must be > player's HEARTBEAT_INTERVAL.
@ -304,7 +304,6 @@
playerIsPlayings.splice(i, 1);
playerRecordings.splice(i, 1);
playerTimestamps.splice(i, 1);
playerStartupTimeouts.splice(i, 1);
}
}
@ -315,8 +314,7 @@
}
function playRecording(recording, position, orientation) {
var index,
CHECK_PLAYING_TIMEOUT = 10000;
var index;
// Optional function parameters.
if (position === undefined) {
@ -340,26 +338,9 @@
position: position,
orientation: orientation
}));
playerStartupTimeouts[index] = Script.setTimeout(function () {
if ((!playerIsPlayings[index] || playerRecordings[index] !== recording) && playerStartupTimeouts[index]) {
error("Didn't start playing recording "
+ recording.slice(4) + "!"); // Remove leading "atp:" from recording.
}
playerStartupTimeouts[index] = null;
}, CHECK_PLAYING_TIMEOUT);
}
function stopPlayingRecording(playerID) {
var index;
// Cancel check that recording started playing.
index = playerIDs.indexOf(playerID);
if (index !== -1 && playerStartupTimeouts[index] !== null) {
// Cannot clearTimeout() without program log error, so just set null.
playerStartupTimeouts[index] = null;
}
Messages.sendMessage(HIFI_PLAYER_CHANNEL, JSON.stringify({
player: playerID,
command: PLAYER_COMMAND_STOP
@ -376,15 +357,21 @@
message = JSON.parse(message);
index = playerIDs.indexOf(sender);
if (index === -1) {
index = playerIDs.length;
playerIDs[index] = sender;
if (message.command === RECORDER_COMMAND_ERROR) {
if (message.user === MyAvatar.sessionUUID) {
error(message.message);
}
} else {
index = playerIDs.indexOf(sender);
if (index === -1) {
index = playerIDs.length;
playerIDs[index] = sender;
}
playerIsPlayings[index] = message.playing;
playerRecordings[index] = message.recording;
playerTimestamps[index] = Date.now();
Dialog.updatePlayerDetails(playerIsPlayings, playerRecordings, playerIDs);
}
playerIsPlayings[index] = message.playing;
playerRecordings[index] = message.recording;
playerTimestamps[index] = Date.now();
Dialog.updatePlayerDetails(playerIsPlayings, playerRecordings, playerIDs);
}
function reset() {
@ -392,7 +379,6 @@
playerIsPlayings = [];
playerRecordings = [];
playerTimestamps = [];
playerStartupTimeouts = [];
Dialog.updatePlayerDetails(playerIsPlayings, playerRecordings, playerIDs);
}
@ -529,6 +515,7 @@
break;
case STOP_PLAYING_RECORDING_ACTION:
// Stop the specified player.
log("Unload recording " + message.value);
Player.stopPlayingRecording(message.value);
break;
case LOAD_RECORDING_ACTION: