diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index ce373f4d33..681cc58cb3 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -644,7 +644,7 @@ void AudioMixer::run() { QJsonObject audioGroupObject = settingsObject[AUDIO_GROUP_KEY].toObject(); // check the payload to see if we have asked for dynamicJitterBuffer support - const QString DYNAMIC_JITTER_BUFFER_JSON_KEY = "dynamic-jitter-buffer"; + const QString DYNAMIC_JITTER_BUFFER_JSON_KEY = "dynamic_jitter_buffer"; _streamSettings._dynamicJitterBuffers = audioGroupObject[DYNAMIC_JITTER_BUFFER_JSON_KEY].toBool(); if (_streamSettings._dynamicJitterBuffers) { qDebug() << "Enable dynamic jitter buffers."; @@ -653,21 +653,21 @@ void AudioMixer::run() { } bool ok; - const QString DESIRED_JITTER_BUFFER_FRAMES_KEY = "static-desired-jitter-buffer-frames"; + const QString DESIRED_JITTER_BUFFER_FRAMES_KEY = "static_desired_jitter_buffer_frames"; _streamSettings._staticDesiredJitterBufferFrames = audioGroupObject[DESIRED_JITTER_BUFFER_FRAMES_KEY].toString().toInt(&ok); if (!ok) { _streamSettings._staticDesiredJitterBufferFrames = DEFAULT_STATIC_DESIRED_JITTER_BUFFER_FRAMES; } qDebug() << "Static desired jitter buffer frames:" << _streamSettings._staticDesiredJitterBufferFrames; - const QString MAX_FRAMES_OVER_DESIRED_JSON_KEY = "max-frames-over-desired"; + const QString MAX_FRAMES_OVER_DESIRED_JSON_KEY = "max_frames_over_desired"; _streamSettings._maxFramesOverDesired = audioGroupObject[MAX_FRAMES_OVER_DESIRED_JSON_KEY].toString().toInt(&ok); if (!ok) { _streamSettings._maxFramesOverDesired = DEFAULT_MAX_FRAMES_OVER_DESIRED; } qDebug() << "Max frames over desired:" << _streamSettings._maxFramesOverDesired; - const QString USE_STDEV_FOR_DESIRED_CALC_JSON_KEY = "use-stdev-for-desired-calc"; + const QString USE_STDEV_FOR_DESIRED_CALC_JSON_KEY = "use_stdev_for_desired_calc"; _streamSettings._useStDevForJitterCalc = audioGroupObject[USE_STDEV_FOR_DESIRED_CALC_JSON_KEY].toBool(); if (_streamSettings._useStDevForJitterCalc) { qDebug() << "Using Philip's stdev method for jitter calc if dynamic jitter buffers enabled"; @@ -675,28 +675,28 @@ void AudioMixer::run() { qDebug() << "Using Fred's max-gap method for jitter calc if dynamic jitter buffers enabled"; } - const QString WINDOW_STARVE_THRESHOLD_JSON_KEY = "window-starve-threshold"; + const QString WINDOW_STARVE_THRESHOLD_JSON_KEY = "window_starve_threshold"; _streamSettings._windowStarveThreshold = audioGroupObject[WINDOW_STARVE_THRESHOLD_JSON_KEY].toString().toInt(&ok); if (!ok) { _streamSettings._windowStarveThreshold = DEFAULT_WINDOW_STARVE_THRESHOLD; } qDebug() << "Window A starve threshold:" << _streamSettings._windowStarveThreshold; - const QString WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES_JSON_KEY = "window-seconds-for-desired-calc-on-too-many-starves"; + const QString WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES_JSON_KEY = "window_seconds_for_desired_calc_on_too_many_starves"; _streamSettings._windowSecondsForDesiredCalcOnTooManyStarves = audioGroupObject[WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES_JSON_KEY].toString().toInt(&ok); if (!ok) { _streamSettings._windowSecondsForDesiredCalcOnTooManyStarves = DEFAULT_WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES; } qDebug() << "Window A length:" << _streamSettings._windowSecondsForDesiredCalcOnTooManyStarves << "seconds"; - const QString WINDOW_SECONDS_FOR_DESIRED_REDUCTION_JSON_KEY = "window-seconds-for-desired-reduction"; + const QString WINDOW_SECONDS_FOR_DESIRED_REDUCTION_JSON_KEY = "window_seconds_for_desired_reduction"; _streamSettings._windowSecondsForDesiredReduction = audioGroupObject[WINDOW_SECONDS_FOR_DESIRED_REDUCTION_JSON_KEY].toString().toInt(&ok); if (!ok) { _streamSettings._windowSecondsForDesiredReduction = DEFAULT_WINDOW_SECONDS_FOR_DESIRED_REDUCTION; } qDebug() << "Window B length:" << _streamSettings._windowSecondsForDesiredReduction << "seconds"; - const QString REPETITION_WITH_FADE_JSON_KEY = "repetition-with-fade"; + const QString REPETITION_WITH_FADE_JSON_KEY = "repetition_with_fade"; _streamSettings._repetitionWithFade = audioGroupObject[REPETITION_WITH_FADE_JSON_KEY].toBool(); if (_streamSettings._repetitionWithFade) { qDebug() << "Repetition with fade enabled"; @@ -704,13 +704,13 @@ void AudioMixer::run() { qDebug() << "Repetition with fade disabled"; } - const QString PRINT_STREAM_STATS_JSON_KEY = "print-stream-stats"; + const QString PRINT_STREAM_STATS_JSON_KEY = "print_stream_stats"; _printStreamStats = audioGroupObject[PRINT_STREAM_STATS_JSON_KEY].toBool(); if (_printStreamStats) { qDebug() << "Stream stats will be printed to stdout"; } - const QString FILTER_KEY = "enable-filter"; + const QString FILTER_KEY = "enable_filter"; if (audioGroupObject[FILTER_KEY].isBool()) { _enableFilter = audioGroupObject[FILTER_KEY].toBool(); } @@ -718,7 +718,7 @@ void AudioMixer::run() { qDebug() << "Filter enabled"; } - const QString UNATTENUATED_ZONE_KEY = "unattenuated-zone"; + const QString UNATTENUATED_ZONE_KEY = "unattenuated_zone"; QString unattenuatedZoneString = audioGroupObject[UNATTENUATED_ZONE_KEY].toString(); if (!unattenuatedZoneString.isEmpty()) { @@ -742,7 +742,7 @@ void AudioMixer::run() { << QString("%1, %2, %3").arg(destinationCenter.x).arg(destinationCenter.y).arg(destinationCenter.z); } - const QString ATTENATION_PER_DOULING_IN_DISTANCE = "attenuation-per-doubling-in-distance"; + const QString ATTENATION_PER_DOULING_IN_DISTANCE = "attenuation_per_doubling_in_distance"; if (audioGroupObject[ATTENATION_PER_DOULING_IN_DISTANCE].isString()) { bool ok = false; float attenuation = audioGroupObject[ATTENATION_PER_DOULING_IN_DISTANCE].toString().toFloat(&ok); diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 86d4da684b..24e9a5b63b 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -4,9 +4,9 @@ "label": "Metaverse Registration", "settings": [ { - "name": "access-token", + "name": "access_token", "label": "Access Token", - "help": "This is an access token generated on the My Tokens page of your High Fidelity account.
Generate a token with the 'domains' scope and paste it here.
This is required to associate this domain-server with a domain in your account." + "help": "This is an access token generated on the My Tokens page of your High Fidelity account.
Generate a token with the 'domains' scope and paste it here.
This is required to associate this domain-server with a domain in your account." }, { "name": "id", @@ -20,12 +20,12 @@ "label": "Security", "settings": [ { - "name": "http-username", + "name": "http_username", "label": "HTTP Username", "help": "Username used for basic HTTP authentication." }, { - "name": "http-password", + "name": "http_password", "label": "HTTP Password", "type": "password", "help": "Password used for basic HTTP authentication. Leave this blank if you do not want to change it.", @@ -39,20 +39,20 @@ "assignment-types": [0], "settings": [ { - "name": "enable-filter", + "name": "enable_filter", "type": "checkbox", "label": "Enable Positional Filter", "help": "positional audio stream uses lowpass filter", "default": true }, { - "name": "unattenuated-zone", + "name": "unattenuated_zone", "label": "Unattenuated Zone", "help": "Boxes for source and listener (corner x, corner y, corner z, size x, size y, size z, corner x, corner y, corner z, size x, size y, size z)", "placeholder": "no zone" }, { - "name": "attenuation-per-doubling-in-distance", + "name": "attenuation_per_doubling_in_distance", "label": "Attenuattion per doubling in distance", "help": "Factor between 0.0 and 1.0 (0.0: No attenuation, 1.0: extreme attenuation)", "placeholder": "0.18", @@ -60,7 +60,7 @@ "advanced": true }, { - "name": "dynamic-jitter-buffer", + "name": "dynamic_jitter_buffer", "type": "checkbox", "label": "Dynamic Jitter Buffers", "help": "dynamically buffer client audio based on perceived jitter in packet receipt timing", @@ -68,7 +68,7 @@ "advanced": true }, { - "name": "static-desired-jitter-buffer-frames", + "name": "static_desired_jitter_buffer_frames", "label": "Static Desired Jitter Buffer Frames", "help": "If dynamic jitter buffers is disabled, this determines the target number of frames maintained by the AudioMixer's jitter buffers", "placeholder": "1", @@ -76,7 +76,7 @@ "advanced": true }, { - "name": "max-frames-over-desired", + "name": "max_frames_over_desired", "label": "Max Frames Over Desired", "help": "The highest number of frames an AudioMixer's ringbuffer can exceed the desired jitter buffer frames by", "placeholder": "10", @@ -84,7 +84,7 @@ "advanced": true }, { - "name": "use-stdev-for-desired-calc", + "name": "use_stdev_for_desired_calc", "type": "checkbox", "label": "Use Stdev for Desired Jitter Frames Calc:", "help": "use Philip's method (stdev of timegaps) to calculate desired jitter frames (otherwise Fred's max timegap method is used)", @@ -92,7 +92,7 @@ "advanced": true }, { - "name": "window-starve-threshold", + "name": "window_starve_threshold", "label": "Window Starve Threshold", "help": "If this many starves occur in an N-second window (N is the number in the next field), then the desired jitter frames will be re-evaluated using Window A.", "placeholder": "3", @@ -100,7 +100,7 @@ "advanced": true }, { - "name": "window-seconds-for-desired-calc-on-too-many-starves", + "name": "window_seconds_for_desired_calc_on_too_many_starves", "label": "Timegaps Window (A) Seconds:", "help": "Window A contains a history of timegaps. Its max timegap is used to re-evaluate the desired jitter frames when too many starves occur within it.", "placeholder": "50", @@ -108,7 +108,7 @@ "advanced": true }, { - "name": "window-seconds-for-desired-reduction", + "name": "window_seconds_for_desired_reduction", "label": "Timegaps Window (B) Seconds:", "help": "Window B contains a history of timegaps. Its max timegap is used as a ceiling for the desired jitter frames value.", "placeholder": "10", @@ -116,7 +116,7 @@ "advanced": true }, { - "name": "repetition-with-fade", + "name": "repetition_with_fade", "type": "checkbox", "label": "Repetition with Fade:", "help": "dropped frames and mixing during starves repeat the last frame, eventually fading to silence", @@ -124,7 +124,7 @@ "advanced": true }, { - "name": "print-stream-stats", + "name": "print_stream_stats", "type": "checkbox", "label": "Print Stream Stats:", "help": "audio upstream and downstream stats of each agent printed to audio-mixer stdout", diff --git a/domain-server/resources/web/css/style.css b/domain-server/resources/web/css/style.css index a75b1a23ae..60f493593a 100644 --- a/domain-server/resources/web/css/style.css +++ b/domain-server/resources/web/css/style.css @@ -73,4 +73,4 @@ span.port { #small-save-button { width: 100%; margin-bottom: 15px; -} \ No newline at end of file +} diff --git a/domain-server/resources/web/js/bootbox.min.js b/domain-server/resources/web/js/bootbox.min.js new file mode 100644 index 0000000000..a7ea24fe7a --- /dev/null +++ b/domain-server/resources/web/js/bootbox.min.js @@ -0,0 +1,6 @@ +/** + * bootbox.js v4.3.0 + * + * http://bootboxjs.com/license.txt + */ +!function(a,b){"use strict";"function"==typeof define&&define.amd?define(["jquery"],b):"object"==typeof exports?module.exports=b(require("jquery")):a.bootbox=b(a.jQuery)}(this,function a(b,c){"use strict";function d(a){var b=q[o.locale];return b?b[a]:q.en[a]}function e(a,c,d){a.stopPropagation(),a.preventDefault();var e=b.isFunction(d)&&d(a)===!1;e||c.modal("hide")}function f(a){var b,c=0;for(b in a)c++;return c}function g(a,c){var d=0;b.each(a,function(a,b){c(a,b,d++)})}function h(a){var c,d;if("object"!=typeof a)throw new Error("Please supply an object of options");if(!a.message)throw new Error("Please specify a message");return a=b.extend({},o,a),a.buttons||(a.buttons={}),a.backdrop=a.backdrop?"static":!1,c=a.buttons,d=f(c),g(c,function(a,e,f){if(b.isFunction(e)&&(e=c[a]={callback:e}),"object"!==b.type(e))throw new Error("button with key "+a+" must be an object");e.label||(e.label=a),e.className||(e.className=2>=d&&f===d-1?"btn-primary":"btn-default")}),a}function i(a,b){var c=a.length,d={};if(1>c||c>2)throw new Error("Invalid argument length");return 2===c||"string"==typeof a[0]?(d[b[0]]=a[0],d[b[1]]=a[1]):d=a[0],d}function j(a,c,d){return b.extend(!0,{},a,i(c,d))}function k(a,b,c,d){var e={className:"bootbox-"+a,buttons:l.apply(null,b)};return m(j(e,d,c),b)}function l(){for(var a={},b=0,c=arguments.length;c>b;b++){var e=arguments[b],f=e.toLowerCase(),g=e.toUpperCase();a[f]={label:d(g)}}return a}function m(a,b){var d={};return g(b,function(a,b){d[b]=!0}),g(a.buttons,function(a){if(d[a]===c)throw new Error("button key "+a+" is not allowed (options are "+b.join("\n")+")")}),a}var n={dialog:"",header:"",footer:"",closeButton:"",form:"
",inputs:{text:"",textarea:"",email:"",select:"",checkbox:"
",date:"",time:"",number:"",password:""}},o={locale:"en",backdrop:!0,animate:!0,className:null,closeButton:!0,show:!0,container:"body"},p={};p.alert=function(){var a;if(a=k("alert",["ok"],["message","callback"],arguments),a.callback&&!b.isFunction(a.callback))throw new Error("alert requires callback property to be a function when provided");return a.buttons.ok.callback=a.onEscape=function(){return b.isFunction(a.callback)?a.callback():!0},p.dialog(a)},p.confirm=function(){var a;if(a=k("confirm",["cancel","confirm"],["message","callback"],arguments),a.buttons.cancel.callback=a.onEscape=function(){return a.callback(!1)},a.buttons.confirm.callback=function(){return a.callback(!0)},!b.isFunction(a.callback))throw new Error("confirm requires a callback");return p.dialog(a)},p.prompt=function(){var a,d,e,f,h,i,k;if(f=b(n.form),d={className:"bootbox-prompt",buttons:l("cancel","confirm"),value:"",inputType:"text"},a=m(j(d,arguments,["title","callback"]),["cancel","confirm"]),i=a.show===c?!0:a.show,a.message=f,a.buttons.cancel.callback=a.onEscape=function(){return a.callback(null)},a.buttons.confirm.callback=function(){var c;switch(a.inputType){case"text":case"textarea":case"email":case"select":case"date":case"time":case"number":case"password":c=h.val();break;case"checkbox":var d=h.find("input:checked");c=[],g(d,function(a,d){c.push(b(d).val())})}return a.callback(c)},a.show=!1,!a.title)throw new Error("prompt requires a title");if(!b.isFunction(a.callback))throw new Error("prompt requires a callback");if(!n.inputs[a.inputType])throw new Error("invalid prompt type");switch(h=b(n.inputs[a.inputType]),a.inputType){case"text":case"textarea":case"email":case"date":case"time":case"number":case"password":h.val(a.value);break;case"select":var o={};if(k=a.inputOptions||[],!k.length)throw new Error("prompt with select requires options");g(k,function(a,d){var e=h;if(d.value===c||d.text===c)throw new Error("given options in wrong format");d.group&&(o[d.group]||(o[d.group]=b("").attr("label",d.group)),e=o[d.group]),e.append("")}),g(o,function(a,b){h.append(b)}),h.val(a.value);break;case"checkbox":var q=b.isArray(a.value)?a.value:[a.value];if(k=a.inputOptions||[],!k.length)throw new Error("prompt with checkbox requires options");if(!k[0].value||!k[0].text)throw new Error("given options in wrong format");h=b("
"),g(k,function(c,d){var e=b(n.inputs[a.inputType]);e.find("input").attr("value",d.value),e.find("label").append(d.text),g(q,function(a,b){b===d.value&&e.find("input").prop("checked",!0)}),h.append(e)})}return a.placeholder&&h.attr("placeholder",a.placeholder),a.pattern&&h.attr("pattern",a.pattern),f.append(h),f.on("submit",function(a){a.preventDefault(),a.stopPropagation(),e.find(".btn-primary").click()}),e=p.dialog(a),e.off("shown.bs.modal"),e.on("shown.bs.modal",function(){h.focus()}),i===!0&&e.modal("show"),e},p.dialog=function(a){a=h(a);var c=b(n.dialog),d=c.find(".modal-dialog"),f=c.find(".modal-body"),i=a.buttons,j="",k={onEscape:a.onEscape};if(g(i,function(a,b){j+="",k[a]=b.callback}),f.find(".bootbox-body").html(a.message),a.animate===!0&&c.addClass("fade"),a.className&&c.addClass(a.className),"large"===a.size&&d.addClass("modal-lg"),"small"===a.size&&d.addClass("modal-sm"),a.title&&f.before(n.header),a.closeButton){var l=b(n.closeButton);a.title?c.find(".modal-header").prepend(l):l.css("margin-top","-10px").prependTo(f)}return a.title&&c.find(".modal-title").html(a.title),j.length&&(f.after(n.footer),c.find(".modal-footer").html(j)),c.on("hidden.bs.modal",function(a){a.target===this&&c.remove()}),c.on("shown.bs.modal",function(){c.find(".btn-primary:first").focus()}),c.on("escape.close.bb",function(a){k.onEscape&&e(a,c,k.onEscape)}),c.on("click",".modal-footer button",function(a){var d=b(this).data("bb-handler");e(a,c,k[d])}),c.on("click",".bootbox-close-button",function(a){e(a,c,k.onEscape)}),c.on("keyup",function(a){27===a.which&&c.trigger("escape.close.bb")}),b(a.container).append(c),c.modal({backdrop:a.backdrop,keyboard:!1,show:!1}),a.show&&c.modal("show"),c},p.setDefaults=function(){var a={};2===arguments.length?a[arguments[0]]=arguments[1]:a=arguments[0],b.extend(o,a)},p.hideAll=function(){return b(".bootbox").modal("hide"),p};var q={br:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Sim"},cs:{OK:"OK",CANCEL:"Zrušit",CONFIRM:"Potvrdit"},da:{OK:"OK",CANCEL:"Annuller",CONFIRM:"Accepter"},de:{OK:"OK",CANCEL:"Abbrechen",CONFIRM:"Akzeptieren"},el:{OK:"Εντάξει",CANCEL:"Ακύρωση",CONFIRM:"Επιβεβαίωση"},en:{OK:"OK",CANCEL:"Cancel",CONFIRM:"OK"},es:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Aceptar"},et:{OK:"OK",CANCEL:"Katkesta",CONFIRM:"OK"},fi:{OK:"OK",CANCEL:"Peruuta",CONFIRM:"OK"},fr:{OK:"OK",CANCEL:"Annuler",CONFIRM:"D'accord"},he:{OK:"אישור",CANCEL:"ביטול",CONFIRM:"אישור"},id:{OK:"OK",CANCEL:"Batal",CONFIRM:"OK"},it:{OK:"OK",CANCEL:"Annulla",CONFIRM:"Conferma"},ja:{OK:"OK",CANCEL:"キャンセル",CONFIRM:"確認"},lt:{OK:"Gerai",CANCEL:"Atšaukti",CONFIRM:"Patvirtinti"},lv:{OK:"Labi",CANCEL:"Atcelt",CONFIRM:"Apstiprināt"},nl:{OK:"OK",CANCEL:"Annuleren",CONFIRM:"Accepteren"},no:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},pl:{OK:"OK",CANCEL:"Anuluj",CONFIRM:"Potwierdź"},pt:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Confirmar"},ru:{OK:"OK",CANCEL:"Отмена",CONFIRM:"Применить"},sv:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},tr:{OK:"Tamam",CANCEL:"İptal",CONFIRM:"Onayla"},zh_CN:{OK:"OK",CANCEL:"取消",CONFIRM:"确认"},zh_TW:{OK:"OK",CANCEL:"取消",CONFIRM:"確認"}};return p.init=function(c){return a(c||b)},p}); \ No newline at end of file diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index 3313bce06d..fa05b1cce9 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -4,9 +4,7 @@ var Settings = { var viewHelpers = { getFormGroup: function(groupName, setting, values, isAdvanced, isLocked) { - setting_id = groupName + "_" + setting.name - - console.log(setting.name + " in " + groupName + " is " + isLocked) + setting_name = groupName + "." + setting.name form_group = "
" @@ -26,22 +24,21 @@ var viewHelpers = { if (setting.type === 'checkbox') { form_group += "" form_group += "
" - form_group += ""; form_group += "
" } else { input_type = _.has(setting, 'type') ? setting.type : "text" - form_group += ""; - form_group += "" + setting.label + ""; + form_group += "" form_group += "" + setting.help + "" } - form_group += "
" return form_group } @@ -89,6 +86,10 @@ $(document).ready(function(){ $(this).blur() }) + + $('#settings-form').on('click', '#choose-domain-btn', function(){ + chooseFromHighFidelityDomains($(this)) + }) var panelsSource = $('#panels-template').html() Settings.panelsTemplate = _.template(panelsSource) @@ -108,16 +109,24 @@ function reloadSettings() { $('.nav-stacked').html(Settings.sidebarTemplate(data)) $('#panels').html(Settings.panelsTemplate(data)) - Settings.initialValues = form2js('settings-form', "_", false, cleanupFormValues, true); + Settings.initialValues = form2js('settings-form', ".", false, cleanupFormValues, true); // add tooltip to locked settings $('label.locked').tooltip({ placement: 'right', title: 'This setting is in the master config file and cannot be changed' }) + + appendDomainSelectionModal() }); } +function appendDomainSelectionModal() { + var metaverseInput = $("[name='metaverse.id']"); + var chooseButton = $(""); + metaverseInput.after(chooseButton); +} + var SETTINGS_ERROR_MESSAGE = "There was a problem saving domain settings. Please try again!"; $('body').on('click', '.save-button', function(e){ @@ -127,7 +136,9 @@ $('body').on('click', '.save-button', function(e){ }); // grab a JSON representation of the form via form2js - var formJSON = form2js('settings-form', "_", false, cleanupFormValues, true); + var formJSON = form2js('settings-form', ".", false, cleanupFormValues, true); + + console.log(formJSON); // re-enable all inputs $("input").each(function(){ @@ -162,13 +173,13 @@ function badgeSidebarForDifferences(changedInput) { var panelParentID = changedInput.closest('.panel').attr('id') // get a JSON representation of that section - var rootJSON = form2js(panelParentID, "_", false, cleanupFormValues, true); + var rootJSON = form2js(panelParentID, ".", false, cleanupFormValues, true); var panelJSON = rootJSON[panelParentID] var badgeValue = 0 for (var setting in panelJSON) { - if (panelJSON[setting] != Settings.initialValues[panelParentID][ setting]) { + if (panelJSON[setting] != Settings.initialValues[panelParentID][setting]) { badgeValue += 1 } } @@ -208,7 +219,7 @@ function showRestartModal() { function cleanupFormValues(node) { if (node.type && node.type === 'checkbox') { - return { name: node.id, value: node.checked ? true : false }; + return { name: node.name, value: node.checked ? true : false }; } else { return false; } @@ -220,4 +231,71 @@ function showAlertMessage(message, isSuccess) { alertBox.addClass(isSuccess ? 'alert-success' : 'alert-danger'); alertBox.html(message); alertBox.fadeIn(); +} + +function chooseFromHighFidelityDomains(clickedButton) { + // setup the modal to help user pick their domain + if (Settings.initialValues.metaverse.access_token) { + + // add a spinner to the choose button + clickedButton.html("Loading domains...") + clickedButton.attr('disabled', 'disabled') + + // get a list of user domains from data-web + data_web_domains_url = "https://data.highfidelity.io/api/v1/domains?access_token=" + $.getJSON(data_web_domains_url + Settings.initialValues.metaverse.access_token, function(data){ + + modal_buttons = { + cancel: { + label: 'Cancel', + className: 'btn-default' + } + } + + if (data.data.domains.length) { + // setup a select box for the returned domains + modal_body = "

Choose the High Fidelity domain you want this domain-server to represent.
This will set your domain ID on the settings page.

" + domain_select = $("") + _.each(data.data.domains, function(domain){ + domain_select.append("") + }) + modal_body += "" + domain_select[0].outerHTML + modal_buttons["success"] = { + label: 'Choose domain', + callback: function() { + domainID = $('#domain-name-select').val() + // set the domain ID on the form + $("[name='metaverse.id']").val(domainID).change(); + } + } + } else { + modal_buttons["success"] = { + label: 'Create new domain', + callback: function() { + window.open("https://data.highfidelity.io/domains", '_blank'); + } + } + modal_body = "

You do not have any domains in your High Fidelity account." + + "

Go to your domains page to create a new one. Once your domain is created re-open this dialog to select it.

" + } + + + bootbox.dialog({ + title: "Choose matching domain", + message: modal_body, + buttons: modal_buttons + }) + + // remove the spinner from the choose button + clickedButton.html("Choose from my domains") + clickedButton.removeAttr('disabled') + }) + + } else { + bootbox.alert({ + message: "You must have an access token to query your High Fidelity domains.

" + + "Please follow the instructions on the settings page to add an access token.", + title: "Access token required" + }) + } } \ No newline at end of file diff --git a/domain-server/resources/web/settings/index.shtml b/domain-server/resources/web/settings/index.shtml index 2f0cdf6537..18b1f40d60 100644 --- a/domain-server/resources/web/settings/index.shtml +++ b/domain-server/resources/web/settings/index.shtml @@ -75,6 +75,7 @@ + \ No newline at end of file diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 4f048a2ec9..fb475f681d 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -81,6 +81,11 @@ DomainServer::DomainServer(int argc, char* argv[]) : void DomainServer::restart() { qDebug() << "domain-server is restarting."; + + // make sure all static instances are reset + LimitedNodeList::getInstance()->reset(); + AccountManager::getInstance(true); + exit(DomainServer::EXIT_CODE_REBOOT); } @@ -1396,8 +1401,8 @@ bool DomainServer::isAuthenticatedRequest(HTTPConnection* connection, const QUrl const QByteArray HTTP_COOKIE_HEADER_KEY = "Cookie"; const QString ADMIN_USERS_CONFIG_KEY = "admin-users"; const QString ADMIN_ROLES_CONFIG_KEY = "admin-roles"; - const QString BASIC_AUTH_USERNAME_KEY_PATH = "security.http-username"; - const QString BASIC_AUTH_PASSWORD_KEY_PATH = "security.http-password"; + const QString BASIC_AUTH_USERNAME_KEY_PATH = "security.http_username"; + const QString BASIC_AUTH_PASSWORD_KEY_PATH = "security.http_password"; const QByteArray UNAUTHENTICATED_BODY = "You do not have permission to access this domain-server."; diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index fc36a97a25..b5d7df65cf 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -39,6 +39,28 @@ DomainServerSettingsManager::DomainServerSettingsManager() : void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList) { _configMap.loadMasterAndUserConfig(argumentList); + + // for now we perform a temporary transition from http-username and http-password to http_username and http_password + const QVariant* oldUsername = valueForKeyPath(_configMap.getUserConfig(), "security.http-username"); + const QVariant* oldPassword = valueForKeyPath(_configMap.getUserConfig(), "security.http-password"); + + if (oldUsername || oldPassword) { + QVariantMap& settingsMap = *reinterpret_cast(_configMap.getUserConfig()["security"].data()); + + // remove old keys, move to new format + if (oldUsername) { + settingsMap["http_username"] = oldUsername->toString(); + settingsMap.remove("http-username"); + } + + if (oldPassword) { + settingsMap["http_password"] = oldPassword->toString(); + settingsMap.remove("http-password"); + } + + // save the updated settings + persistToFile(); + } } const QString SETTINGS_PATH = "/settings.json"; diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 88e4bad7b2..f79b66b539 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include #include @@ -25,9 +27,14 @@ const bool VERBOSE_HTTP_REQUEST_DEBUGGING = false; -AccountManager& AccountManager::getInstance() { - static AccountManager sharedInstance; - return sharedInstance; +AccountManager& AccountManager::getInstance(bool forceReset) { + static std::auto_ptr sharedInstance(new AccountManager()); + + if (forceReset) { + sharedInstance.reset(new AccountManager()); + } + + return *sharedInstance; } Q_DECLARE_METATYPE(OAuthAccessToken) diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index edccab0b75..8d1a127408 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -42,7 +42,7 @@ const QByteArray ACCESS_TOKEN_AUTHORIZATION_HEADER = "Authorization"; class AccountManager : public QObject { Q_OBJECT public: - static AccountManager& getInstance(); + static AccountManager& getInstance(bool forceReset = false); void authenticatedRequest(const QString& path, QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation, diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index d42cab6210..2c8e968375 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -35,29 +35,32 @@ const char SOLO_NODE_TYPES[2] = { const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://data.highfidelity.io"); -LimitedNodeList* LimitedNodeList::_sharedInstance = NULL; +std::auto_ptr LimitedNodeList::_sharedInstance; LimitedNodeList* LimitedNodeList::createInstance(unsigned short socketListenPort, unsigned short dtlsPort) { - if (!_sharedInstance) { - NodeType::init(); + NodeType::init(); + + if (_sharedInstance.get()) { + qDebug() << "LimitedNodeList called with existing instance." << + "Releasing auto_ptr, deleting existing instance and creating a new one."; - _sharedInstance = new LimitedNodeList(socketListenPort, dtlsPort); - - // register the SharedNodePointer meta-type for signals/slots - qRegisterMetaType(); - } else { - qDebug("LimitedNodeList createInstance called with existing instance."); + delete _sharedInstance.release(); } + + _sharedInstance = std::auto_ptr(new LimitedNodeList(socketListenPort, dtlsPort)); + + // register the SharedNodePointer meta-type for signals/slots + qRegisterMetaType(); - return _sharedInstance; + return _sharedInstance.get(); } LimitedNodeList* LimitedNodeList::getInstance() { - if (!_sharedInstance) { + if (!_sharedInstance.get()) { qDebug("LimitedNodeList getInstance called before call to createInstance. Returning NULL pointer."); } - return _sharedInstance; + return _sharedInstance.get(); } diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 337d66616e..b34845719c 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -14,6 +14,7 @@ #include #include +#include #ifndef _WIN32 #include // not on windows, not needed for mac or windows @@ -118,7 +119,7 @@ signals: void nodeKilled(SharedNodePointer); void publicSockAddrChanged(const HifiSockAddr& publicSockAddr); protected: - static LimitedNodeList* _sharedInstance; + static std::auto_ptr _sharedInstance; LimitedNodeList(unsigned short socketListenPort, unsigned short dtlsListenPort); LimitedNodeList(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 7ae9f9ba00..3a1ed79f77 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -24,30 +24,31 @@ #include "SharedUtil.h" #include "UUID.h" -NodeList* NodeList::_sharedInstance = NULL; - NodeList* NodeList::createInstance(char ownerType, unsigned short socketListenPort, unsigned short dtlsPort) { - if (!_sharedInstance) { - NodeType::init(); + + NodeType::init(); + + if (_sharedInstance.get()) { + qDebug() << "NodeList called with existing instance." << + "Releasing auto_ptr, deleting existing instance and creating a new one."; - _sharedInstance = new NodeList(ownerType, socketListenPort, dtlsPort); - LimitedNodeList::_sharedInstance = _sharedInstance; - - // register the SharedNodePointer meta-type for signals/slots - qRegisterMetaType(); - } else { - qDebug("NodeList createInstance called with existing instance."); + delete _sharedInstance.release(); } - - return _sharedInstance; + + _sharedInstance = std::auto_ptr(new NodeList(ownerType, socketListenPort, dtlsPort)); + + // register the SharedNodePointer meta-type for signals/slots + qRegisterMetaType(); + + return static_cast(_sharedInstance.get()); } NodeList* NodeList::getInstance() { - if (!_sharedInstance) { + if (!_sharedInstance.get()) { qDebug("NodeList getInstance called before call to createInstance. Returning NULL pointer."); } - return _sharedInstance; + return static_cast(_sharedInstance.get()); } NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned short dtlsListenPort) : diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index d17e56fd48..8293d0a05a 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -84,8 +84,6 @@ public slots: signals: void limitOfSilentDomainCheckInsReached(); private: - static NodeList* _sharedInstance; - NodeList(char ownerType, unsigned short socketListenPort, unsigned short dtlsListenPort); NodeList(NodeList const&); // Don't implement, needed to avoid copies of singleton void operator=(NodeList const&); // Don't implement, needed to avoid copies of singleton