Merge branch 'tablet-ui' of github.com:highfidelity/hifi into tablet-imporove-dialogs

This commit is contained in:
Dante Ruiz 2017-03-10 19:33:51 +00:00
commit 78da936344
23 changed files with 99 additions and 1304 deletions

View file

@ -241,6 +241,7 @@ void AudioMixer::sendStatsPacket() {
statsObject["avg_streams_per_frame"] = (float)_stats.sumStreams / (float)_numStatFrames;
statsObject["avg_listeners_per_frame"] = (float)_stats.sumListeners / (float)_numStatFrames;
statsObject["avg_listeners_(silent)_per_frame"] = (float)_stats.sumListenersSilent / (float)_numStatFrames;
statsObject["silent_packets_per_frame"] = (float)_numSilentPackets / (float)_numStatFrames;

View file

@ -106,6 +106,7 @@ void AudioMixerSlave::mix(const SharedNodePointer& node) {
sendMixPacket(node, *data, encodedBuffer);
} else {
++stats.sumListenersSilent;
sendSilentPacket(node, *data);
}
@ -221,17 +222,19 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) {
stats.mixTime += mixTime.count();
#endif
// use the per listener AudioLimiter to render the mixed data...
listenerData->audioLimiter.render(_mixSamples, _bufferSamples, AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
// check for silent audio after the peak limiter has converted the samples
// check for silent audio before limiting
// limiting uses a dither and can only guarantee abs(sample) <= 1
bool hasAudio = false;
for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; ++i) {
if (_bufferSamples[i] != 0) {
if (_mixSamples[i] != 0.0f) {
hasAudio = true;
break;
}
}
// use the per listener AudioLimiter to render the mixed data
listenerData->audioLimiter.render(_mixSamples, _bufferSamples, AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
return hasAudio;
}

View file

@ -14,6 +14,7 @@
void AudioMixerStats::reset() {
sumStreams = 0;
sumListeners = 0;
sumListenersSilent = 0;
totalMixes = 0;
hrtfRenders = 0;
hrtfSilentRenders = 0;
@ -28,6 +29,7 @@ void AudioMixerStats::reset() {
void AudioMixerStats::accumulate(const AudioMixerStats& otherStats) {
sumStreams += otherStats.sumStreams;
sumListeners += otherStats.sumListeners;
sumListenersSilent += otherStats.sumListenersSilent;
totalMixes += otherStats.totalMixes;
hrtfRenders += otherStats.hrtfRenders;
hrtfSilentRenders += otherStats.hrtfSilentRenders;

View file

@ -19,6 +19,7 @@
struct AudioMixerStats {
int sumStreams { 0 };
int sumListeners { 0 };
int sumListenersSilent { 0 };
int totalMixes { 0 };

View file

@ -66,8 +66,6 @@ TabletModalWindow {
signal canceled();
Component.onCompleted: {
console.log("Helper " + helper + " drives " + drives);
fileDialogItem.keyboardEnabled = HMD.active;
// HACK: The following lines force the model to initialize properly such that the go-up button
@ -459,6 +457,7 @@ TabletModalWindow {
bottomMargin: hifi.dimensions.contentSpacing.y + currentSelection.controlHeight - currentSelection.height
}
headerVisible: !selectDirectory
onClicked: navigateToRow(row);
onDoubleClicked: navigateToRow(row);
focus: true
Keys.onReturnPressed: navigateToCurrentRow();

View file

@ -81,6 +81,10 @@ void HMDScriptingInterface::closeTablet() {
_showTablet = false;
}
void HMDScriptingInterface::openTablet() {
_showTablet = true;
}
QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine) {
glm::vec3 hudIntersection;
auto instance = DependencyManager::get<HMDScriptingInterface>();

View file

@ -76,6 +76,8 @@ public:
Q_INVOKABLE void closeTablet();
Q_INVOKABLE void openTablet();
signals:
bool shouldShowHandControllersChanged();

View file

@ -1052,7 +1052,12 @@ void AudioClient::handleAudioInput() {
auto packetType = _shouldEchoToServer ?
PacketType::MicrophoneAudioWithEcho : PacketType::MicrophoneAudioNoEcho;
if (_lastInputLoudness == 0) {
// if the _inputGate closed in this last frame, then we don't actually want
// to send a silent packet, instead, we want to go ahead and encode and send
// the output from the input gate (eventually, this could be crossfaded)
// and allow the codec to properly encode down to silent/zero. If we still
// have _lastInputLoudness of 0 in our NEXT frame, we will send a silent packet
if (_lastInputLoudness == 0 && !_inputGate.closedInLastFrame()) {
packetType = PacketType::SilentAudioFrame;
}
Transform audioTransform;

View file

@ -58,7 +58,6 @@ void AudioNoiseGate::removeDCOffset(int16_t* samples, int numSamples) {
}
}
void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) {
//
// Impose Noise Gate
@ -77,8 +76,7 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) {
// NOISE_GATE_FRAMES_TO_AVERAGE: How many audio frames should we average together to compute noise floor.
// More means better rejection but also can reject continuous things like singing.
// NUMBER_OF_NOISE_SAMPLE_FRAMES: How often should we re-evaluate the noise floor?
float loudness = 0;
int thisSample = 0;
int samplesOverNoiseGate = 0;
@ -142,11 +140,13 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) {
_sampleCounter = 0;
}
if (samplesOverNoiseGate > NOISE_GATE_WIDTH) {
_isOpen = true;
_framesToClose = NOISE_GATE_CLOSE_FRAME_DELAY;
} else {
if (--_framesToClose == 0) {
_closedInLastFrame = !_isOpen;
_isOpen = false;
}
}

View file

@ -24,6 +24,7 @@ public:
void removeDCOffset(int16_t* samples, int numSamples);
bool clippedInLastFrame() const { return _didClipInLastFrame; }
bool closedInLastFrame() const { return _closedInLastFrame; }
float getMeasuredFloor() const { return _measuredFloor; }
float getLastLoudness() const { return _lastLoudness; }
@ -40,6 +41,7 @@ private:
float _sampleFrames[NUMBER_OF_NOISE_SAMPLE_FRAMES];
int _sampleCounter;
bool _isOpen;
bool _closedInLastFrame { false };
int _framesToClose;
};

View file

@ -136,9 +136,10 @@ int InboundAudioStream::parseData(ReceivedMessage& message) {
break;
}
case SequenceNumberStats::Early: {
// Packet is early; write droppable silent samples for each of the skipped packets.
// NOTE: we assume that each dropped packet contains the same number of samples
// as the packet we just received.
// Packet is early. Treat the packets as if all the packets between the last
// OnTime packet and this packet were lost. If we're using a codec this will
// also result in allowing the codec to interpolate lost data. Then
// fall through to the "on time" logic to actually handle this packet
int packetsDropped = arrivalInfo._seqDiffFromExpected;
lostAudioData(packetsDropped);
@ -147,7 +148,8 @@ int InboundAudioStream::parseData(ReceivedMessage& message) {
case SequenceNumberStats::OnTime: {
// Packet is on time; parse its data to the ringbuffer
if (message.getType() == PacketType::SilentAudioFrame) {
// FIXME - Some codecs need to know about these silent frames... and can produce better output
// If we recieved a SilentAudioFrame from our sender, we might want to drop
// some of the samples in order to catch up to our desired jitter buffer size.
writeDroppableSilentFrames(networkFrames);
} else {
// note: PCM and no codec are identical
@ -158,7 +160,12 @@ int InboundAudioStream::parseData(ReceivedMessage& message) {
parseAudioData(message.getType(), afterProperties);
} else {
qDebug(audio) << "Codec mismatch: expected" << _selectedCodecName << "got" << codecInPacket << "writing silence";
writeDroppableSilentFrames(networkFrames);
// Since the data in the stream is using a codec that we aren't prepared for,
// we need to let the codec know that we don't have data for it, this will
// allow the codec to interpolate missing data and produce a fade to silence.
lostAudioData(1);
// inform others of the mismatch
auto sendingNode = DependencyManager::get<NodeList>()->nodeWithUUID(message.getSourceID());
emit mismatchedAudioCodec(sendingNode, _selectedCodecName, codecInPacket);
@ -240,6 +247,25 @@ int InboundAudioStream::parseAudioData(PacketType type, const QByteArray& packet
int InboundAudioStream::writeDroppableSilentFrames(int silentFrames) {
// We can't guarentee that all clients have faded the stream down
// to silence and encoded that silence before sending us a
// SilentAudioFrame. If the encoder has truncated the stream it will
// leave the decoder holding some unknown loud state. To handle this
// case we will call the decoder's lostFrame() method, which indicates
// that it should interpolate from its last known state down toward
// silence.
if (_decoder) {
// FIXME - We could potentially use the output from the codec, in which
// case we might get a cleaner fade toward silence. NOTE: The below logic
// attempts to catch up in the event that the jitter buffers have grown.
// The better long term fix is to use the output from the decode, detect
// when it actually reaches silence, and then delete the silent portions
// of the jitter buffers. Or petentially do a cross fade from the decode
// output to silence.
QByteArray decodedBuffer;
_decoder->lostFrame(decodedBuffer);
}
// calculate how many silent frames we should drop.
int silentSamples = silentFrames * _numChannels;
int samplesPerFrame = _ringBuffer.getNumFrameSamples();

View file

@ -434,6 +434,7 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
auto rootContext = getRootContext();
rootContext->setContextProperty("urlHandler", new UrlHandler());
rootContext->setContextProperty("resourceDirectoryUrl", QUrl::fromLocalFile(PathUtils::resourcesPath()));
rootContext->setContextProperty("pathToFonts", "../../");
}
static uvec2 clampSize(const uvec2& size, uint32_t maxDimension) {

View file

@ -287,7 +287,8 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr
QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_SOURCE_URL)));
}
gotoHomeScreen();
// force to the tablet to go to the homescreen
loadHomeScreen(true);
QMetaObject::invokeMethod(_qmlTabletRoot, "setUsername", Q_ARG(const QVariant&, QVariant(getUsername())));
@ -305,6 +306,9 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr
}
}
void TabletProxy::gotoHomeScreen() {
loadHomeScreen(false);
}
void TabletProxy::gotoMenuScreen(const QString& submenu) {
QObject* root = nullptr;
@ -388,8 +392,8 @@ void TabletProxy::popFromStack() {
}
}
void TabletProxy::gotoHomeScreen() {
if (_state != State::Home) {
void TabletProxy::loadHomeScreen(bool forceOntoHomeScreen) {
if (_state != State::Home && ( _state != State::Uninitialized || forceOntoHomeScreen)) {
if (!_toolbarMode && _qmlTabletRoot) {
auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader");
QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen()), Qt::DirectConnection);

View file

@ -202,6 +202,7 @@ protected slots:
void desktopWindowClosed();
protected:
void removeButtonsFromHomeScreen();
void loadHomeScreen(bool forceOntoHomeScreen);
void addButtonsToToolbar();
void removeButtonsFromToolbar();

View file

@ -72,6 +72,9 @@ tablet.screenChanged.connect(onScreenChanged);
AudioDevice.muteToggled.connect(onMuteToggled);
Script.scriptEnding.connect(function () {
if (onAudioScreen) {
tablet.gotoHomeScreen();
}
button.clicked.disconnect(onClicked);
tablet.screenChanged.disconnect(onScreenChanged);
AudioDevice.muteToggled.disconnect(onMuteToggled);

View file

@ -18,13 +18,14 @@ var button;
var buttonName = "GOTO";
var toolBar = null;
var tablet = null;
var onGotoScreen = false;
function onAddressBarShown(visible) {
button.editProperties({isActive: visible});
}
function onClicked(){
DialogsManager.toggleAddressBar();
onGotoScreen = !onGotoScreen;
}
if (Settings.getValue("HUDUIEnabled")) {
@ -49,6 +50,9 @@ button.clicked.connect(onClicked);
DialogsManager.addressBarShown.connect(onAddressBarShown);
Script.scriptEnding.connect(function () {
if (onGotoScreen) {
DialogsManager.toggleAddressBar();
}
button.clicked.disconnect(onClicked);
if (tablet) {
tablet.removeButton(button);

View file

@ -48,6 +48,9 @@
}, POLL_RATE);
Script.scriptEnding.connect(function () {
if (enabled) {
Menu.closeInfoView('InfoView_html/help.html');
}
button.clicked.disconnect(onClicked);
Script.clearInterval(interval);
if (tablet) {

View file

@ -121,6 +121,7 @@ function onClick() {
if (onMarketplaceScreen) {
// for toolbar-mode: go back to home screen, this will close the window.
tablet.gotoHomeScreen();
onMarketplaceScreen = false;
} else {
var entity = HMD.tabletID;
Entities.editEntity(entity, {textures: JSON.stringify({"tex.close": HOME_BUTTON_TEXTURE})});
@ -140,6 +141,9 @@ tablet.screenChanged.connect(onScreenChanged);
Entities.canWriteAssetsChanged.connect(onCanWriteAssetsChanged);
Script.scriptEnding.connect(function () {
if (onMarketplaceScreen) {
tablet.gotoHomeScreen();
}
tablet.removeButton(marketplaceButton);
tablet.screenChanged.disconnect(onScreenChanged);
Entities.canWriteAssetsChanged.disconnect(onCanWriteAssetsChanged);

View file

@ -48,6 +48,9 @@ var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-
tablet.screenChanged.connect(onScreenChanged);
Script.scriptEnding.connect(function () {
if (onMenuScreen) {
tablet.gotoHomeScreen();
}
button.clicked.disconnect(onClicked);
tablet.removeButton(button);
tablet.screenChanged.disconnect(onScreenChanged);

View file

@ -696,6 +696,9 @@ function clearLocalQMLDataAndClosePAL() {
}
function shutdown() {
if (onPalScreen) {
tablet.gotoHomeScreen();
}
button.clicked.disconnect(onTabletButtonClicked);
tablet.removeButton(button);
tablet.screenChanged.disconnect(onTabletScreenChanged);

View file

@ -191,12 +191,12 @@ function resetButtons(pathStillSnapshot, pathAnimatedSnapshot, notify) {
if (clearOverlayWhenMoving) {
MyAvatar.setClearOverlayWhenMoving(true); // not until after the share dialog
}
HMD.openTablet();
}
function processingGif() {
// show hud
Reticle.visible = reticleVisible;
button.clicked.disconnect(onClicked);
buttonConnected = false;
// show overlays if they were on
@ -211,8 +211,10 @@ Window.snapshotShared.connect(snapshotShared);
Window.processingGif.connect(processingGif);
Script.scriptEnding.connect(function () {
button.clicked.disconnect(onClicked);
buttonConnected = false;
if (buttonConnected) {
button.clicked.disconnect(onClicked);
buttonConnected = false;
}
if (tablet) {
tablet.removeButton(button);
}

View file

@ -114,6 +114,9 @@
tablet.screenChanged.connect(onScreenChanged);
function cleanup() {
if (onUsersScreen) {
tablet.gotoHomeScreen();
}
button.clicked.disconnect(onClicked);
tablet.removeButton(button);
}

File diff suppressed because it is too large Load diff