From a6bf9d7b9070c3995756a8f3ec3b4043b735147c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 28 Aug 2014 11:42:39 -0700 Subject: [PATCH] Handle URL recordings + some safety checks --- examples/PlayRecordingOnAC.js | 5 ++- examples/Recorder.js | 8 +++-- libraries/avatars/src/Recorder.cpp | 57 +++++++++++++++++++++++++----- libraries/avatars/src/Recorder.h | 7 ++-- 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/examples/PlayRecordingOnAC.js b/examples/PlayRecordingOnAC.js index a68e60a6fa..9af5dd6f95 100644 --- a/examples/PlayRecordingOnAC.js +++ b/examples/PlayRecordingOnAC.js @@ -12,6 +12,7 @@ var filename = "http://your.recording.url"; var playFromCurrentLocation = true; +var loop = true; Avatar.faceModelURL = "http://public.highfidelity.io/models/heads/EvilPhilip_v7.fst"; Avatar.skeletonModelURL = "http://public.highfidelity.io/models/skeletons/Philip_Carl_Body_A-Pose.fst"; @@ -30,7 +31,9 @@ function update(event) { return; } if (count == 0) { - Avatar.startPlaying(playFromCurrentLocation); + Avatar.setPlayFromCurrentLocation(playFromCurrentLocation); + Avatar.setLoop(loop); + Avatar.startPlaying(); Avatar.play(); Vec3.print("Playing from ", Avatar.position); diff --git a/examples/Recorder.js b/examples/Recorder.js index cf4b422926..dad8db8cb4 100644 --- a/examples/Recorder.js +++ b/examples/Recorder.js @@ -161,12 +161,16 @@ function mousePressEvent(event) { } else if (saveIcon === toolBar.clicked(clickedOverlay)) { if (!MyAvatar.isRecording()) { recordingFile = Window.save("Save recording to file", ".", "*.rec"); - MyAvatar.saveRecording(recordingFile); + if (recordingFile != "") { + MyAvatar.saveRecording(recordingFile); + } } } else if (loadIcon === toolBar.clicked(clickedOverlay)) { if (!MyAvatar.isRecording()) { recordingFile = Window.browse("Load recorcding from file", ".", "*.rec"); - MyAvatar.loadRecording(recordingFile); + if (recordingFile != "") { + MyAvatar.loadRecording("https://s3-us-west-1.amazonaws.com/highfidelity-public/ozan/bartender.rec"); + } } } else { diff --git a/libraries/avatars/src/Recorder.cpp b/libraries/avatars/src/Recorder.cpp index 69cde6560e..15ac6ede6c 100644 --- a/libraries/avatars/src/Recorder.cpp +++ b/libraries/avatars/src/Recorder.cpp @@ -10,7 +10,9 @@ // #include +#include +#include #include #include #include @@ -57,6 +59,25 @@ Recording::~Recording() { delete _audio; } +int Recording::getLength() const { + if (_timestamps.isEmpty()) { + return 0; + } + return _timestamps.last(); +} + +qint32 Recording::getFrameTimestamp(int i) const { + if (i >= _timestamps.size()) { + return getLength(); + } + return _timestamps[i]; +} + +const RecordingFrame& Recording::getFrame(int i) const { + assert(i < _timestamps.size()); + return _frames[i]; +} + void Recording::addFrame(int timestamp, RecordingFrame &frame) { _timestamps << timestamp; _frames << frame; @@ -492,18 +513,38 @@ void writeRecordingToFile(RecordingPointer recording, QString filename) { } RecordingPointer readRecordingFromFile(RecordingPointer recording, QString filename) { - qDebug() << "Reading recording from " << filename << "."; + QElapsedTimer timer; + timer.start(); if (!recording) { recording.reset(new Recording()); } - QElapsedTimer timer; - QFile file(filename); - if (!file.open(QIODevice::ReadOnly)){ - return recording; + QByteArray byteArray; + QUrl url(filename); + if (url.scheme() == "http" || url.scheme() == "https" || url.scheme() == "ftp") { + qDebug() << "Downloading recording at" << url; + NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url)); + QEventLoop loop; + QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); + loop.exec(); + if (reply->error() != QNetworkReply::NoError) { + qDebug() << "Error while downloading recording: " << reply->error(); + reply->deleteLater(); + return recording; + } + byteArray = reply->readAll(); + reply->deleteLater(); + } else { + qDebug() << "Reading recording from " << filename << "."; + QFile file(filename); + if (!file.open(QIODevice::ReadOnly)){ + return recording; + } + byteArray = file.readAll(); + file.close(); } - timer.start(); - QDataStream fileStream(&file); + QDataStream fileStream(byteArray); fileStream >> recording->_timestamps; RecordingFrame baseFrame; @@ -603,7 +644,7 @@ RecordingPointer readRecordingFromFile(RecordingPointer recording, QString filen recording->addAudioPacket(audioArray); - qDebug() << "Read " << file.size() << " bytes in " << timer.elapsed() << " ms."; + qDebug() << "Read " << byteArray.size() << " bytes in " << timer.elapsed() << " ms."; return recording; } diff --git a/libraries/avatars/src/Recorder.h b/libraries/avatars/src/Recorder.h index 1f41672749..447c3eabe8 100644 --- a/libraries/avatars/src/Recorder.h +++ b/libraries/avatars/src/Recorder.h @@ -81,11 +81,11 @@ public: ~Recording(); bool isEmpty() const { return _timestamps.isEmpty(); } - int getLength() const { return _timestamps.last(); } // in ms + int getLength() const; // in ms int getFrameNumber() const { return _frames.size(); } - qint32 getFrameTimestamp(int i) const { return _timestamps[i]; } - const RecordingFrame& getFrame(int i) const { return _frames[i]; } + qint32 getFrameTimestamp(int i) const; + const RecordingFrame& getFrame(int i) const; Sound* getAudio() const { return _audio; } protected: @@ -97,7 +97,6 @@ private: QVector _timestamps; QVector _frames; - bool _stereo; Sound* _audio; friend class Recorder;