mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into controllers
This commit is contained in:
commit
a82c2d66ed
28 changed files with 861 additions and 32 deletions
|
@ -102,7 +102,7 @@ endif()
|
|||
|
||||
# link required hifi libraries
|
||||
link_hifi_libraries(shared octree environment gpu gl procedural model render
|
||||
fbx networking model-networking entities avatars
|
||||
recording fbx networking model-networking entities avatars
|
||||
audio audio-client animation script-engine physics
|
||||
render-utils entities-renderer ui auto-updater
|
||||
controllers plugins display-plugins input-plugins )
|
||||
|
|
|
@ -1027,10 +1027,7 @@ void Application::initializeUi() {
|
|||
foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) {
|
||||
QString name = inputPlugin->getName();
|
||||
if (name == KeyboardMouseDevice::NAME) {
|
||||
auto kbm = static_cast<KeyboardMouseDevice*>(inputPlugin.data());
|
||||
// FIXME incredibly evil.... _keyboardMouseDevice is now owned by
|
||||
// both a QSharedPointer and a std::shared_ptr
|
||||
_keyboardMouseDevice = std::shared_ptr<KeyboardMouseDevice>(kbm);
|
||||
_keyboardMouseDevice = std::dynamic_pointer_cast<KeyboardMouseDevice>(inputPlugin);
|
||||
}
|
||||
}
|
||||
updateInputModes();
|
||||
|
@ -4645,7 +4642,7 @@ DisplayPlugin* Application::getActiveDisplayPlugin() {
|
|||
updateDisplayMode();
|
||||
Q_ASSERT(_displayPlugin);
|
||||
}
|
||||
return _displayPlugin.data();
|
||||
return _displayPlugin.get();
|
||||
}
|
||||
|
||||
const DisplayPlugin* Application::getActiveDisplayPlugin() const {
|
||||
|
@ -4685,10 +4682,10 @@ void Application::updateDisplayMode() {
|
|||
bool first = true;
|
||||
foreach(auto displayPlugin, displayPlugins) {
|
||||
addDisplayPluginToMenu(displayPlugin, first);
|
||||
QObject::connect(displayPlugin.data(), &DisplayPlugin::requestRender, [this] {
|
||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::requestRender, [this] {
|
||||
paintGL();
|
||||
});
|
||||
QObject::connect(displayPlugin.data(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) {
|
||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) {
|
||||
resizeGL();
|
||||
});
|
||||
|
||||
|
@ -4814,12 +4811,14 @@ void Application::updateInputModes() {
|
|||
foreach(auto inputPlugin, inputPlugins) {
|
||||
QString name = inputPlugin->getName();
|
||||
QAction* action = menu->getActionForOption(name);
|
||||
if (action->isChecked() && !_activeInputPlugins.contains(inputPlugin)) {
|
||||
_activeInputPlugins.append(inputPlugin);
|
||||
newInputPlugins.append(inputPlugin);
|
||||
} else if (!action->isChecked() && _activeInputPlugins.contains(inputPlugin)) {
|
||||
_activeInputPlugins.removeOne(inputPlugin);
|
||||
removedInputPlugins.append(inputPlugin);
|
||||
|
||||
auto it = std::find(std::begin(_activeInputPlugins), std::end(_activeInputPlugins), inputPlugin);
|
||||
if (action->isChecked() && it == std::end(_activeInputPlugins)) {
|
||||
_activeInputPlugins.push_back(inputPlugin);
|
||||
newInputPlugins.push_back(inputPlugin);
|
||||
} else if (!action->isChecked() && it != std::end(_activeInputPlugins)) {
|
||||
_activeInputPlugins.erase(it);
|
||||
removedInputPlugins.push_back(inputPlugin);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -206,7 +206,7 @@ namespace controller {
|
|||
void ScriptingInterface::updateMaps() {
|
||||
QVariantMap newHardware;
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
auto devices = userInputMapper->getDevices();
|
||||
const auto& devices = userInputMapper->getDevices();
|
||||
for (const auto& deviceMapping : devices) {
|
||||
auto deviceID = deviceMapping.first;
|
||||
if (deviceID != userInputMapper->getStandardDeviceID()) {
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace controller {
|
|||
void setSensorToWorldMat(glm::mat4 sensorToWorldMat) { _sensorToWorldMat = sensorToWorldMat; }
|
||||
glm::mat4 getSensorToWorldMat() { return _sensorToWorldMat; }
|
||||
|
||||
DevicesMap getDevices() { return _registeredDevices; }
|
||||
const DevicesMap& getDevices() { return _registeredDevices; }
|
||||
uint16 getStandardDeviceID() const { return STANDARD_DEVICE; }
|
||||
InputDevice::Pointer getStandardDevice() { return _registeredDevices[getStandardDeviceID()]; }
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ InputPluginList getInputPlugins() {
|
|||
|
||||
InputPluginList result;
|
||||
for (int i = 0; PLUGIN_POOL[i]; ++i) {
|
||||
InputPlugin * plugin = PLUGIN_POOL[i];
|
||||
InputPlugin* plugin = PLUGIN_POOL[i];
|
||||
if (plugin->isSupported()) {
|
||||
plugin->init();
|
||||
result.push_back(InputPluginPointer(plugin));
|
||||
|
|
|
@ -7,9 +7,8 @@
|
|||
//
|
||||
#pragma once
|
||||
|
||||
#include <QList>
|
||||
#include <QVector>
|
||||
#include <QSharedPointer>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
class DisplayPlugin;
|
||||
class InputPlugin;
|
||||
|
@ -17,8 +16,8 @@ class Plugin;
|
|||
class PluginContainer;
|
||||
class PluginManager;
|
||||
|
||||
using DisplayPluginPointer = QSharedPointer<DisplayPlugin>;
|
||||
using DisplayPluginList = QVector<DisplayPluginPointer>;
|
||||
using InputPluginPointer = QSharedPointer<InputPlugin>;
|
||||
using InputPluginList = QVector<InputPluginPointer>;
|
||||
using DisplayPluginPointer = std::shared_ptr<DisplayPlugin>;
|
||||
using DisplayPluginList = std::vector<DisplayPluginPointer>;
|
||||
using InputPluginPointer = std::shared_ptr<InputPlugin>;
|
||||
using InputPluginList = std::vector<InputPluginPointer>;
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
//
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "Forward.h"
|
||||
|
||||
class PluginManager : public QObject {
|
||||
|
|
48
libraries/recording/src/recording/Clip.cpp
Normal file
48
libraries/recording/src/recording/Clip.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Clip.h"
|
||||
|
||||
#include "Frame.h"
|
||||
|
||||
#include "impl/FileClip.h"
|
||||
#include "impl/BufferClip.h"
|
||||
|
||||
using namespace recording;
|
||||
|
||||
Clip::Pointer Clip::fromFile(const QString& filePath) {
|
||||
return std::make_shared<FileClip>(filePath);
|
||||
}
|
||||
|
||||
void Clip::toFile(Clip::Pointer clip, const QString& filePath) {
|
||||
// FIXME
|
||||
}
|
||||
|
||||
Clip::Pointer Clip::duplicate() {
|
||||
Clip::Pointer result = std::make_shared<BufferClip>();
|
||||
|
||||
float currentPosition = position();
|
||||
seek(0);
|
||||
|
||||
Frame::Pointer frame = nextFrame();
|
||||
while (frame) {
|
||||
result->appendFrame(frame);
|
||||
}
|
||||
|
||||
seek(currentPosition);
|
||||
return result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
Clip::Pointer Clip::fromIODevice(QIODevice * device) {
|
||||
return std::make_shared<IOClip>(device);
|
||||
}
|
||||
|
||||
void Clip::fromIODevice(Clip::Pointer clip, QIODevice * device) {
|
||||
}
|
||||
#endif
|
48
libraries/recording/src/recording/Clip.h
Normal file
48
libraries/recording/src/recording/Clip.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Recording_Clip_h
|
||||
#define hifi_Recording_Clip_h
|
||||
|
||||
#include "Forward.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class QIODevice;
|
||||
|
||||
namespace recording {
|
||||
|
||||
class Clip : public QObject {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<Clip>;
|
||||
|
||||
Clip(QObject* parent = nullptr) : QObject(parent) {}
|
||||
virtual ~Clip() {}
|
||||
|
||||
Pointer duplicate();
|
||||
|
||||
virtual void seek(float offset) = 0;
|
||||
virtual float position() const = 0;
|
||||
|
||||
virtual FramePointer peekFrame() const = 0;
|
||||
virtual FramePointer nextFrame() = 0;
|
||||
virtual void skipFrame() = 0;
|
||||
virtual void appendFrame(FramePointer) = 0;
|
||||
|
||||
|
||||
static Pointer fromFile(const QString& filePath);
|
||||
static void toFile(Pointer clip, const QString& filePath);
|
||||
|
||||
protected:
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
9
libraries/recording/src/recording/Deck.cpp
Normal file
9
libraries/recording/src/recording/Deck.cpp
Normal file
|
@ -0,0 +1,9 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Deck.h"
|
37
libraries/recording/src/recording/Deck.h
Normal file
37
libraries/recording/src/recording/Deck.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Recording_Deck_h
|
||||
#define hifi_Recording_Deck_h
|
||||
|
||||
#include "Forward.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class QIODevice;
|
||||
|
||||
namespace recording {
|
||||
|
||||
class Deck : public QObject {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<Deck>;
|
||||
|
||||
Deck(QObject* parent = nullptr) : QObject(parent) {}
|
||||
virtual ~Deck();
|
||||
|
||||
// Place a clip on the deck for recording or playback
|
||||
void queueClip(ClipPointer clip, float timeOffset = 0.0f);
|
||||
void play(float timeOffset = 0.0f);
|
||||
void reposition(float timeOffsetDelta);
|
||||
void setPlaybackSpeed(float rate);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -15,14 +15,28 @@
|
|||
|
||||
namespace recording {
|
||||
|
||||
using FrameType = uint16_t;
|
||||
|
||||
struct Frame;
|
||||
|
||||
using FramePointer = std::shared_ptr<Frame>;
|
||||
|
||||
// A recording of some set of state from the application, usually avatar
|
||||
// data + audio for a single person
|
||||
class Clip;
|
||||
|
||||
// An interface for interacting with clips, creating them by recording or
|
||||
// playing them back. Also serialization to and from files / network sources
|
||||
using ClipPointer = std::shared_ptr<Clip>;
|
||||
|
||||
// An interface for playing back clips
|
||||
class Deck;
|
||||
|
||||
using DeckPointer = std::shared_ptr<Deck>;
|
||||
|
||||
// An interface for recording a single clip
|
||||
class Recorder;
|
||||
|
||||
using RecorderPointer = std::shared_ptr<Recorder>;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
103
libraries/recording/src/recording/Frame.cpp
Normal file
103
libraries/recording/src/recording/Frame.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Frame.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <QtCore/QMap>
|
||||
|
||||
using namespace recording;
|
||||
|
||||
// FIXME move to shared
|
||||
template <typename Key, typename Value>
|
||||
class Registry {
|
||||
public:
|
||||
using ForwardMap = QMap<Value, Key>;
|
||||
using BackMap = QMap<Key, Value>;
|
||||
static const Key INVALID_KEY = static_cast<Key>(-1);
|
||||
|
||||
Key registerValue(const Value& value) {
|
||||
Locker lock(_mutex);
|
||||
Key result = INVALID_KEY;
|
||||
if (_forwardMap.contains(value)) {
|
||||
result = _forwardMap[value];
|
||||
} else {
|
||||
_forwardMap[value] = result = _nextKey++;
|
||||
_backMap[result] = value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Key getKey(const Value& value) {
|
||||
Locker lock(_mutex);
|
||||
Key result = INVALID_KEY;
|
||||
if (_forwardMap.contains(value)) {
|
||||
result = _forwardMap[value];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ForwardMap getKeysByValue() {
|
||||
Locker lock(_mutex);
|
||||
ForwardMap result = _forwardMap;
|
||||
return result;
|
||||
}
|
||||
|
||||
BackMap getValuesByKey() {
|
||||
Locker lock(_mutex);
|
||||
BackMap result = _backMap;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
using Mutex = std::mutex;
|
||||
using Locker = std::unique_lock<Mutex>;
|
||||
|
||||
Mutex _mutex;
|
||||
|
||||
ForwardMap _forwardMap;
|
||||
BackMap _backMap;
|
||||
Key _nextKey { 0 };
|
||||
};
|
||||
|
||||
static Registry<FrameType, QString> frameTypes;
|
||||
static QMap<FrameType, Frame::Handler> handlerMap;
|
||||
using Mutex = std::mutex;
|
||||
using Locker = std::unique_lock<Mutex>;
|
||||
static Mutex mutex;
|
||||
static std::once_flag once;
|
||||
|
||||
|
||||
|
||||
FrameType Frame::registerFrameType(const QString& frameTypeName) {
|
||||
Locker lock(mutex);
|
||||
std::call_once(once, [&] {
|
||||
auto headerType = frameTypes.registerValue("com.highfidelity.recording.Header");
|
||||
Q_ASSERT(headerType == Frame::TYPE_HEADER);
|
||||
});
|
||||
return frameTypes.registerValue(frameTypeName);
|
||||
}
|
||||
|
||||
QMap<QString, FrameType> Frame::getFrameTypes() {
|
||||
return frameTypes.getKeysByValue();
|
||||
}
|
||||
|
||||
QMap<FrameType, QString> Frame::getFrameTypeNames() {
|
||||
return frameTypes.getValuesByKey();
|
||||
}
|
||||
|
||||
Frame::Handler Frame::registerFrameHandler(FrameType type, Handler handler) {
|
||||
Locker lock(mutex);
|
||||
Handler result;
|
||||
if (handlerMap.contains(type)) {
|
||||
result = handlerMap[type];
|
||||
}
|
||||
handlerMap[type] = handler;
|
||||
return result;
|
||||
}
|
40
libraries/recording/src/recording/Frame.h
Normal file
40
libraries/recording/src/recording/Frame.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Recording_Frame_h
|
||||
#define hifi_Recording_Frame_h
|
||||
|
||||
#include "Forward.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
namespace recording {
|
||||
|
||||
struct Frame {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<Frame>;
|
||||
using Handler = std::function<void(Frame::Pointer frame)>;
|
||||
|
||||
static const FrameType TYPE_INVALID = 0xFFFF;
|
||||
static const FrameType TYPE_HEADER = 0x0;
|
||||
FrameType type { TYPE_INVALID };
|
||||
float timeOffset { 0 };
|
||||
QByteArray data;
|
||||
|
||||
static FrameType registerFrameType(const QString& frameTypeName);
|
||||
static QMap<QString, FrameType> getFrameTypes();
|
||||
static QMap<FrameType, QString> getFrameTypeNames();
|
||||
static Handler registerFrameHandler(FrameType type, Handler handler);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
62
libraries/recording/src/recording/Recorder.cpp
Normal file
62
libraries/recording/src/recording/Recorder.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Recorder.h"
|
||||
|
||||
#include <NumericalConstants.h>
|
||||
|
||||
#include "impl/BufferClip.h"
|
||||
#include "Frame.h"
|
||||
|
||||
using namespace recording;
|
||||
|
||||
void Recorder::start() {
|
||||
if (!_recording) {
|
||||
_recording = true;
|
||||
if (!_clip) {
|
||||
_clip = std::make_shared<BufferClip>();
|
||||
}
|
||||
_timer.start();
|
||||
emit recordingStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Recorder::stop() {
|
||||
if (!_recording) {
|
||||
_recording = false;
|
||||
_elapsed = _timer.elapsed();
|
||||
emit recordingStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool Recorder::isRecording() {
|
||||
return _recording;
|
||||
}
|
||||
|
||||
void Recorder::clear() {
|
||||
_clip.reset();
|
||||
}
|
||||
|
||||
void Recorder::recordFrame(FrameType type, QByteArray frameData) {
|
||||
if (!_recording || !_clip) {
|
||||
return;
|
||||
}
|
||||
|
||||
Frame::Pointer frame = std::make_shared<Frame>();
|
||||
frame->type = type;
|
||||
frame->data = frameData;
|
||||
frame->timeOffset = (float)(_elapsed + _timer.elapsed()) / MSECS_PER_SECOND;
|
||||
_clip->appendFrame(frame);
|
||||
}
|
||||
|
||||
ClipPointer Recorder::getClip() {
|
||||
auto result = _clip;
|
||||
_clip.reset();
|
||||
return result;
|
||||
}
|
||||
|
55
libraries/recording/src/recording/Recorder.h
Normal file
55
libraries/recording/src/recording/Recorder.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Recording_Recorder_h
|
||||
#define hifi_Recording_Recorder_h
|
||||
|
||||
#include "Forward.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QElapsedTimer>
|
||||
|
||||
namespace recording {
|
||||
|
||||
// An interface for interacting with clips, creating them by recording or
|
||||
// playing them back. Also serialization to and from files / network sources
|
||||
class Recorder : public QObject {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<Recorder>;
|
||||
|
||||
Recorder(QObject* parent = nullptr) : QObject(parent) {}
|
||||
virtual ~Recorder();
|
||||
|
||||
// Start recording frames
|
||||
void start();
|
||||
// Stop recording
|
||||
void stop();
|
||||
// Test if recording is active
|
||||
bool isRecording();
|
||||
// Erase the currently recorded content
|
||||
void clear();
|
||||
|
||||
void recordFrame(FrameType type, QByteArray frameData);
|
||||
|
||||
// Return the currently recorded content
|
||||
ClipPointer getClip();
|
||||
|
||||
signals:
|
||||
void recordingStateChanged();
|
||||
|
||||
private:
|
||||
QElapsedTimer _timer;
|
||||
ClipPointer _clip;
|
||||
quint64 _elapsed;
|
||||
bool _recording { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
74
libraries/recording/src/recording/impl/BufferClip.cpp
Normal file
74
libraries/recording/src/recording/impl/BufferClip.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "BufferClip.h"
|
||||
|
||||
#include "../Frame.h"
|
||||
|
||||
using namespace recording;
|
||||
|
||||
|
||||
void BufferClip::seek(float offset) {
|
||||
Locker lock(_mutex);
|
||||
auto itr = std::lower_bound(_frames.begin(), _frames.end(), offset,
|
||||
[](Frame::Pointer a, float b)->bool{
|
||||
return a->timeOffset < b;
|
||||
}
|
||||
);
|
||||
_frameIndex = itr - _frames.begin();
|
||||
}
|
||||
|
||||
float BufferClip::position() const {
|
||||
Locker lock(_mutex);
|
||||
float result = std::numeric_limits<float>::max();
|
||||
if (_frameIndex < _frames.size()) {
|
||||
result = _frames[_frameIndex]->timeOffset;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FramePointer BufferClip::peekFrame() const {
|
||||
Locker lock(_mutex);
|
||||
FramePointer result;
|
||||
if (_frameIndex < _frames.size()) {
|
||||
result = _frames[_frameIndex];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FramePointer BufferClip::nextFrame() {
|
||||
Locker lock(_mutex);
|
||||
FramePointer result;
|
||||
if (_frameIndex < _frames.size()) {
|
||||
result = _frames[_frameIndex];
|
||||
++_frameIndex;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void BufferClip::appendFrame(FramePointer newFrame) {
|
||||
auto currentPosition = position();
|
||||
seek(newFrame->timeOffset);
|
||||
{
|
||||
Locker lock(_mutex);
|
||||
_frames.insert(_frames.begin() + _frameIndex, newFrame);
|
||||
}
|
||||
seek(currentPosition);
|
||||
}
|
||||
|
||||
void BufferClip::skipFrame() {
|
||||
Locker lock(_mutex);
|
||||
if (_frameIndex < _frames.size()) {
|
||||
++_frameIndex;
|
||||
}
|
||||
}
|
||||
|
||||
void BufferClip::reset() {
|
||||
Locker lock(_mutex);
|
||||
_frameIndex = 0;
|
||||
}
|
47
libraries/recording/src/recording/impl/BufferClip.h
Normal file
47
libraries/recording/src/recording/impl/BufferClip.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Recording_Impl_BufferClip_h
|
||||
#define hifi_Recording_Impl_BufferClip_h
|
||||
|
||||
#include "../Clip.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace recording {
|
||||
|
||||
class BufferClip : public Clip {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<BufferClip>;
|
||||
|
||||
BufferClip(QObject* parent = nullptr) : Clip(parent) {}
|
||||
virtual ~BufferClip() {}
|
||||
|
||||
virtual void seek(float offset) override;
|
||||
virtual float position() const override;
|
||||
|
||||
virtual FramePointer peekFrame() const override;
|
||||
virtual FramePointer nextFrame() override;
|
||||
virtual void skipFrame() override;
|
||||
virtual void appendFrame(FramePointer) override;
|
||||
|
||||
private:
|
||||
using Mutex = std::mutex;
|
||||
using Locker = std::unique_lock<Mutex>;
|
||||
|
||||
virtual void reset() override;
|
||||
|
||||
std::vector<FramePointer> _frames;
|
||||
mutable Mutex _mutex;
|
||||
mutable size_t _frameIndex { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
105
libraries/recording/src/recording/impl/FileClip.cpp
Normal file
105
libraries/recording/src/recording/impl/FileClip.cpp
Normal file
|
@ -0,0 +1,105 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/04
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "FileClip.h"
|
||||
|
||||
#include "../Frame.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace recording;
|
||||
|
||||
static const qint64 MINIMUM_FRAME_SIZE = sizeof(FrameType) + sizeof(float) + sizeof(uint16_t) + 1;
|
||||
|
||||
FileClip::FileClip(const QString& fileName, QObject* parent) : Clip(parent), _file(fileName) {
|
||||
auto size = _file.size();
|
||||
_map = _file.map(0, size, QFile::MapPrivateOption);
|
||||
|
||||
auto current = _map;
|
||||
auto end = current + size;
|
||||
// Read all the frame headers
|
||||
while (end - current < MINIMUM_FRAME_SIZE) {
|
||||
FrameHeader header;
|
||||
memcpy(&(header.type), current, sizeof(FrameType));
|
||||
current += sizeof(FrameType);
|
||||
memcpy(&(header.timeOffset), current, sizeof(FrameType));
|
||||
current += sizeof(float);
|
||||
memcpy(&(header.size), current, sizeof(uint16_t));
|
||||
current += sizeof(uint16_t);
|
||||
header.fileOffset = current - _map;
|
||||
if (end - current < header.size) {
|
||||
break;
|
||||
}
|
||||
|
||||
_frameHeaders.push_back(header);
|
||||
}
|
||||
}
|
||||
|
||||
FileClip::~FileClip() {
|
||||
Locker lock(_mutex);
|
||||
_file.unmap(_map);
|
||||
_map = nullptr;
|
||||
}
|
||||
|
||||
void FileClip::seek(float offset) {
|
||||
Locker lock(_mutex);
|
||||
auto itr = std::lower_bound(_frameHeaders.begin(), _frameHeaders.end(), offset,
|
||||
[](const FrameHeader& a, float b)->bool {
|
||||
return a.timeOffset < b;
|
||||
}
|
||||
);
|
||||
_frameIndex = itr - _frameHeaders.begin();
|
||||
}
|
||||
|
||||
float FileClip::position() const {
|
||||
Locker lock(_mutex);
|
||||
float result = std::numeric_limits<float>::max();
|
||||
if (_frameIndex < _frameHeaders.size()) {
|
||||
result = _frameHeaders[_frameIndex].timeOffset;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FramePointer FileClip::readFrame(uint32_t frameIndex) const {
|
||||
FramePointer result;
|
||||
if (frameIndex < _frameHeaders.size()) {
|
||||
result = std::make_shared<Frame>();
|
||||
const FrameHeader& header = _frameHeaders[frameIndex];
|
||||
result->type = header.type;
|
||||
result->timeOffset = header.timeOffset;
|
||||
result->data.insert(0, reinterpret_cast<char*>(_map)+header.fileOffset, header.size);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FramePointer FileClip::peekFrame() const {
|
||||
Locker lock(_mutex);
|
||||
return readFrame(_frameIndex);
|
||||
}
|
||||
|
||||
FramePointer FileClip::nextFrame() {
|
||||
Locker lock(_mutex);
|
||||
auto result = readFrame(_frameIndex);
|
||||
if (_frameIndex < _frameHeaders.size()) {
|
||||
++_frameIndex;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void FileClip::skipFrame() {
|
||||
++_frameIndex;
|
||||
}
|
||||
|
||||
void FileClip::reset() {
|
||||
_frameIndex = 0;
|
||||
}
|
||||
|
||||
void FileClip::appendFrame(FramePointer) {
|
||||
throw std::runtime_error("File clips are read only");
|
||||
}
|
||||
|
62
libraries/recording/src/recording/impl/FileClip.h
Normal file
62
libraries/recording/src/recording/impl/FileClip.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_Recording_Impl_FileClip_h
|
||||
#define hifi_Recording_Impl_FileClip_h
|
||||
|
||||
#include "../Clip.h"
|
||||
|
||||
#include <QtCore/QFile>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace recording {
|
||||
|
||||
class FileClip : public Clip {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<FileClip>;
|
||||
|
||||
FileClip(const QString& file, QObject* parent = nullptr);
|
||||
virtual ~FileClip();
|
||||
|
||||
virtual void seek(float offset) override;
|
||||
virtual float position() const override;
|
||||
|
||||
virtual FramePointer peekFrame() const override;
|
||||
virtual FramePointer nextFrame() override;
|
||||
virtual void appendFrame(FramePointer) override;
|
||||
virtual void skipFrame() override;
|
||||
|
||||
private:
|
||||
using Mutex = std::mutex;
|
||||
using Locker = std::unique_lock<Mutex>;
|
||||
|
||||
virtual void reset() override;
|
||||
|
||||
struct FrameHeader {
|
||||
FrameType type;
|
||||
float timeOffset;
|
||||
uint16_t size;
|
||||
quint64 fileOffset;
|
||||
};
|
||||
|
||||
using FrameHeaders = std::vector<FrameHeader>;
|
||||
|
||||
FramePointer readFrame(uint32_t frameIndex) const;
|
||||
|
||||
mutable Mutex _mutex;
|
||||
QFile _file;
|
||||
uint32_t _frameIndex { 0 };
|
||||
uchar* _map;
|
||||
FrameHeaders _frameHeaders;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -646,13 +646,14 @@ QScriptValue ScriptEngine::evaluate(const QString& sourceCode, const QString& fi
|
|||
}
|
||||
|
||||
void ScriptEngine::run() {
|
||||
// TODO: can we add a short circuit for _stoppingAllScripts here? What does it mean to not start running if
|
||||
// we're in the process of stopping?
|
||||
|
||||
if (_stoppingAllScripts) {
|
||||
return; // bail early - avoid setting state in init(), as evaluate() will bail too
|
||||
}
|
||||
|
||||
if (!_isInitialized) {
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
_isRunning = true;
|
||||
_isFinished = false;
|
||||
if (_wantSignals) {
|
||||
|
|
|
@ -132,8 +132,7 @@ int main(int argc, char** argv) {
|
|||
inputPlugin->activate();
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
if (name == KeyboardMouseDevice::NAME) {
|
||||
auto keyboardMouseDevice = static_cast<KeyboardMouseDevice*>(inputPlugin.data()); // TODO: this seems super hacky
|
||||
userInputMapper->registerDevice(std::shared_ptr<InputDevice>(keyboardMouseDevice));
|
||||
userInputMapper->registerDevice(std::dynamic_pointer_cast<KeyboardMouseDevice>(inputPlugin));
|
||||
}
|
||||
inputPlugin->pluginUpdate(0, false);
|
||||
}
|
||||
|
|
10
tests/recording/CMakeLists.txt
Normal file
10
tests/recording/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
# Declare dependencies
|
||||
macro (setup_testcase_dependencies)
|
||||
# link in the shared libraries
|
||||
link_hifi_libraries(shared recording)
|
||||
|
||||
copy_dlls_beside_windows_executable()
|
||||
endmacro ()
|
||||
|
||||
setup_hifi_testcase()
|
19
tests/recording/src/Constants.h
Normal file
19
tests/recording/src/Constants.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef hifi_Constants_h
|
||||
#define hifi_Constants_h
|
||||
|
||||
static const QString HEADER_NAME = "com.highfidelity.recording.Header";
|
||||
static const QString TEST_NAME = "com.highfidelity.recording.Test";
|
||||
|
||||
#endif // hifi_FrameTests_h
|
||||
|
||||
|
29
tests/recording/src/FrameTests.cpp
Normal file
29
tests/recording/src/FrameTests.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "FrameTests.h"
|
||||
#include "Constants.h"
|
||||
#include "../QTestExtensions.h"
|
||||
|
||||
#include <recording/Frame.h>
|
||||
|
||||
QTEST_MAIN(FrameTests)
|
||||
|
||||
void FrameTests::registerFrameTypeTest() {
|
||||
auto result = recording::Frame::registerFrameType(TEST_NAME);
|
||||
QCOMPARE(result, (recording::FrameType)1);
|
||||
auto forwardMap = recording::Frame::getFrameTypes();
|
||||
QCOMPARE(forwardMap.count(TEST_NAME), 1);
|
||||
QCOMPARE(forwardMap[TEST_NAME], result);
|
||||
QCOMPARE(forwardMap[HEADER_NAME], recording::Frame::TYPE_HEADER);
|
||||
auto backMap = recording::Frame::getFrameTypeNames();
|
||||
QCOMPARE(backMap.count(result), 1);
|
||||
QCOMPARE(backMap[result], TEST_NAME);
|
||||
QCOMPARE(backMap[recording::Frame::TYPE_HEADER], HEADER_NAME);
|
||||
}
|
||||
|
21
tests/recording/src/FrameTests.h
Normal file
21
tests/recording/src/FrameTests.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_FrameTests_h
|
||||
#define hifi_FrameTests_h
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
class FrameTests : public QObject {
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void registerFrameTypeTest();
|
||||
};
|
||||
|
||||
#endif // hifi_FrameTests_h
|
25
tests/recording/src/RecorderTests.cpp
Normal file
25
tests/recording/src/RecorderTests.cpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "RecorderTests.h"
|
||||
#include "Constants.h"
|
||||
#include "../QTestExtensions.h"
|
||||
|
||||
#include <recording/Recorder.h>
|
||||
|
||||
QTEST_MAIN(RecorderTests)
|
||||
|
||||
void RecorderTests::recorderTest() {
|
||||
//auto recorder = std::make_shared<recording::Recorder>();
|
||||
//QCOMPARE(recoreder.isRecording(), false);
|
||||
//recorder.start();
|
||||
//QCOMPARE(recoreder.isRecording(), true);
|
||||
//recorder.stop();
|
||||
//QCOMPARE(recoreder.isRecording(), false);
|
||||
}
|
||||
|
21
tests/recording/src/RecorderTests.h
Normal file
21
tests/recording/src/RecorderTests.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/11/05
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef hifi_RecorderTests_h
|
||||
#define hifi_RecorderTests_h
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
class RecorderTests : public QObject {
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void recorderTest();
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue