- 增加服务器参数设置对话框
- 优化服务器程序的错误捕捉与日志输出 - 优化翻译
This commit is contained in:
parent
66d57a3f4c
commit
d0aed6f101
BIN
Locales/ja.qm
BIN
Locales/ja.qm
Binary file not shown.
BIN
Locales/zh.qm
BIN
Locales/zh.qm
Binary file not shown.
BIN
Locales/zh_TW.qm
BIN
Locales/zh_TW.qm
Binary file not shown.
Binary file not shown.
@ -1,13 +1,13 @@
|
||||
[Server]
|
||||
ip = local
|
||||
port = 5055
|
||||
maxClient = 10
|
||||
[server]
|
||||
port = 5050
|
||||
maxclient = 5
|
||||
logger = true
|
||||
|
||||
[FFT]
|
||||
[fft]
|
||||
attack = 5
|
||||
decay = 5
|
||||
norspeed = 1
|
||||
peakthr = 10
|
||||
norspeed = 10
|
||||
fps = 35
|
||||
changeSpeed = 20
|
||||
changespeed = 20
|
||||
|
||||
|
||||
22
module.qml
22
module.qml
@ -1,13 +1,15 @@
|
||||
import NERvGear 1.0 as NVG
|
||||
import NERvGear.Private 1.0 as NVGP
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import "./qml"
|
||||
|
||||
NVG.Module {
|
||||
initialize: function () {
|
||||
console.log("Initializing ADV-Plugin.");
|
||||
Common.execute("../bin/ADVServer.exe", "-reboot");
|
||||
// Common.setWsocket(true);
|
||||
Common.execute(Common.serverEXE, "-reboot");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -18,6 +20,20 @@ NVG.Module {
|
||||
cleanup: function () {
|
||||
console.log("Cleaning up ADV-Plugin.");
|
||||
Common.setWsocket(false);
|
||||
Common.execute("../bin/ADVServer.exe", "-close");
|
||||
Common.execute(Common.serverEXE, "-close");
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Common
|
||||
onServerPreferencesOpen: {
|
||||
serverDialog.active = true;
|
||||
serverDialog.item.visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: serverDialog
|
||||
active: false
|
||||
sourceComponent: ServerPreferences { }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "top.mashiros.widget.advp",
|
||||
"version": "1.2.1",
|
||||
|
||||
"version": "1.3.0",
|
||||
|
||||
"title": {
|
||||
"en": "ADV Plugin",
|
||||
"zh": "音频可视化插件",
|
||||
@ -115,7 +115,7 @@
|
||||
"ja": "オーディナル・スケール- UI 下部"
|
||||
},
|
||||
"entry": "./styles/Preset_Ordinal_Scale_UI_bottom/Style.qml"
|
||||
},
|
||||
},
|
||||
{
|
||||
"location": "/preset/advp-style-preset/line",
|
||||
"catalog": "preset/widget",
|
||||
@ -189,4 +189,4 @@
|
||||
"entry": "Presets/Ordinal_Scale_UI_bottom/preset.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
166
qml/Common.qml
166
qml/Common.qml
@ -9,18 +9,41 @@ import NERvGear 1.0 as NVG
|
||||
Item {
|
||||
readonly property var styles: []
|
||||
readonly property var stylesURL: []
|
||||
readonly property var defaultServerCFG: {
|
||||
"server": {
|
||||
"port": 5050,
|
||||
"maxclient": 5,
|
||||
"logger": true
|
||||
},
|
||||
"fft": {
|
||||
"attack": 5,
|
||||
"decay": 5,
|
||||
"norspeed": 1,
|
||||
"peakthr": 10,
|
||||
"fps": 35,
|
||||
"changespeed": 20
|
||||
}
|
||||
}
|
||||
readonly property string iniFile: "../bin/advConfig.ini"
|
||||
readonly property string serverEXE: "../bin/ADVServer.exe"
|
||||
|
||||
property var serverCFG: defaultServerCFG
|
||||
property string wsIp: "localhost"
|
||||
property int wsPort: serverCFG.server.port
|
||||
|
||||
property int widgetsNum: 0
|
||||
property bool debug: false
|
||||
property bool rebootFlag: false
|
||||
|
||||
signal audioDataUpdated(var audioData)
|
||||
signal wsocketClosed()
|
||||
signal serverPreferencesOpen()
|
||||
|
||||
function execute(path, args) {
|
||||
path = NVG.Url.toLocalFile(Qt.resolvedUrl(path));
|
||||
NVG.SystemCall.execute(path, args);
|
||||
}
|
||||
|
||||
function openFile(fileUrl) {
|
||||
function readFile(fileUrl) {
|
||||
let request = new XMLHttpRequest();
|
||||
request.open("GET", fileUrl, false);
|
||||
request.send(null);
|
||||
@ -29,7 +52,14 @@ Item {
|
||||
return data;
|
||||
}
|
||||
|
||||
function parseINIString(data){
|
||||
function writeFile(fileUrl, text) {
|
||||
var request = new XMLHttpRequest();
|
||||
request.open("PUT", fileUrl, false);
|
||||
request.send(text);
|
||||
return request.status;
|
||||
}
|
||||
|
||||
function parseINIString(data) {
|
||||
let regex = {
|
||||
section: /\[\s*([^]*)\s*\]\s*$/,
|
||||
param: /^\s*([\w\.\-\_]+)\s*=\s*(.*?)\s*$/,
|
||||
@ -40,56 +70,113 @@ Item {
|
||||
let section = null;
|
||||
let match;
|
||||
lines.forEach(function(line){
|
||||
if(regex.comment.test(line)){
|
||||
return;
|
||||
}else if(regex.param.test(line)){
|
||||
match = line.match(regex.param);
|
||||
if(section){
|
||||
value[section][match[1]] = match[2];
|
||||
}else{
|
||||
value[match[1]] = match[2];
|
||||
}
|
||||
}else if(regex.section.test(line)){
|
||||
match = line.match(regex.section);
|
||||
value[match[1]] = {};
|
||||
section = match[1];
|
||||
}else if(line.length === 0 && section){
|
||||
section = null;
|
||||
};
|
||||
if (regex.comment.test(line)) {
|
||||
return;
|
||||
} else if (regex.param.test(line)) {
|
||||
match = line.match(regex.param);
|
||||
if (["true", "false"].indexOf(match[2]) > -1) {
|
||||
match[2] = Boolean(1 - ["true", "false"].indexOf(match[2]));
|
||||
} else if (/^\d+$/.test(match[2])) {
|
||||
match[2] = Number(match[2]);
|
||||
}
|
||||
if (section) {
|
||||
value[section][match[1]] = match[2];
|
||||
} else {
|
||||
value[match[1]] = match[2];
|
||||
}
|
||||
} else if (regex.section.test(line)) {
|
||||
match = line.match(regex.section);
|
||||
value[match[1]] = {};
|
||||
section = match[1];
|
||||
} else if(line.length === 0 && section) {
|
||||
section = null;
|
||||
};
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
function convertINIString(data) {
|
||||
let value = "";
|
||||
for (let section in data) {
|
||||
value += "[" + section + "]\n";
|
||||
for (let key in data[section]) {
|
||||
value += key + " = " + String(data[section][key]) + "\n";
|
||||
}
|
||||
value += "\n";
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function deepClone(obj) {
|
||||
let objClone = Array.isArray(obj) ? [] : {};
|
||||
if (obj && typeof obj === "object" && obj != null) {
|
||||
for (var key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
if (obj[key] && typeof obj[key] === "object") {
|
||||
objClone[key] = deepClone(obj[key]);
|
||||
} else {
|
||||
objClone[key] = obj[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return objClone;
|
||||
}
|
||||
|
||||
function isObjectValueEqual(a, b) {
|
||||
if (a === b)
|
||||
return true;
|
||||
let aProps = Object.getOwnPropertyNames(a);
|
||||
let bProps = Object.getOwnPropertyNames(b);
|
||||
if (aProps.length !== bProps.length)
|
||||
return false;
|
||||
for (let prop in a) {
|
||||
if (b.hasOwnProperty(prop)) {
|
||||
if (typeof a[prop] === 'object') {
|
||||
if (!isObjectValueEqual(a[prop], b[prop]))
|
||||
return false;
|
||||
} else if (a[prop] !== b[prop]) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: wsocket
|
||||
sourceComponent: WSocket {
|
||||
Component.onCompleted: {
|
||||
let ini_data = openFile("../bin/advConfig.ini");
|
||||
ini_data = ini_data.toLowerCase();
|
||||
let cfg = parseINIString(ini_data);
|
||||
if(cfg["server"]["ip"].toLowerCase() === "local") {
|
||||
wsIp = "localhost";
|
||||
} else {
|
||||
wsIp = cfg["server"]["ip"];
|
||||
}
|
||||
wsPort = cfg["server"]["port"];
|
||||
}}
|
||||
active: widgetsNum>0
|
||||
sourceComponent: WSocket {}
|
||||
active: false
|
||||
}
|
||||
|
||||
onWidgetsNumChanged: {
|
||||
wsocket.active = widgetsNum>0;
|
||||
}
|
||||
|
||||
function setWsocket(status) {
|
||||
wsocket.active = status;
|
||||
}
|
||||
|
||||
onWsocketClosed: {
|
||||
if (wsocket.active) {
|
||||
function rebootServer(force) {
|
||||
if (force || !debug && wsocket.active && rebootFlag) {
|
||||
console.log("Try to reboot ADVServer...");
|
||||
execute("../bin/ADVServer.exe", "-reboot");
|
||||
execute(serverEXE, "-reboot");
|
||||
wsocket.active = false;
|
||||
wsocket.active = true;
|
||||
rebootFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
onDebugChanged: {
|
||||
rebootServer();
|
||||
}
|
||||
|
||||
onRebootFlagChanged: {
|
||||
rebootServer();
|
||||
}
|
||||
|
||||
function parse_resource(resource_list, sort) {
|
||||
if (sort)
|
||||
resource_list.sort(function (x, y) {
|
||||
@ -120,5 +207,14 @@ Item {
|
||||
|
||||
Component.onCompleted: {
|
||||
updateStyleList();
|
||||
let ini_data = readFile(iniFile);
|
||||
if (ini_data) {
|
||||
ini_data = ini_data.toLowerCase();
|
||||
let cfg = parseINIString(ini_data);
|
||||
serverCFG = Object.assign(defaultServerCFG, cfg);
|
||||
} else {
|
||||
let ini_text = convertINIString(defaultServerCFG);
|
||||
writeFile(iniFile, ini_text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
qml/Main.qml
10
qml/Main.qml
@ -55,13 +55,19 @@ T.Widget {
|
||||
|
||||
menu: Menu {
|
||||
Action {
|
||||
text: qsTr("Settings") + "..."
|
||||
enabled: !styleDialog.active
|
||||
text: qsTr("Style Settings") + "..."
|
||||
onTriggered: {
|
||||
Common.updateStyleList();
|
||||
styleDialog.active = true;
|
||||
}
|
||||
}
|
||||
|
||||
Action {
|
||||
text: qsTr("Server Settings") + "..."
|
||||
onTriggered: {
|
||||
Common.serverPreferencesOpen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
|
||||
220
qml/ServerPreferences.qml
Normal file
220
qml/ServerPreferences.qml
Normal file
@ -0,0 +1,220 @@
|
||||
import QtQuick 2.12
|
||||
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import NERvGear 1.0 as NVG
|
||||
import NERvGear.Preferences 1.0 as P
|
||||
import NERvGear.Controls 1.0
|
||||
|
||||
import "."
|
||||
|
||||
|
||||
NVG.Window {
|
||||
title: qsTr("ADV-Server: Settings")
|
||||
visible: true
|
||||
minimumWidth: 480
|
||||
minimumHeight: 600
|
||||
width: minimumWidth
|
||||
height: minimumHeight
|
||||
|
||||
Page {
|
||||
id: cfg_page
|
||||
anchors.fill: parent
|
||||
|
||||
header: TitleBar {
|
||||
text: qsTr("Server Settings")
|
||||
standardButtons: Dialog.Save | Dialog.Reset
|
||||
|
||||
onAccepted: {
|
||||
let cfg = Object.assign(Common.deepClone(Common.serverCFG), rootPreference.save());
|
||||
|
||||
if (cfg.server.logger) {
|
||||
Common.debug = _debug.value;
|
||||
} else {
|
||||
Common.debug = false;
|
||||
}
|
||||
|
||||
if (!Common.isObjectValueEqual(cfg, Common.serverCFG)) {
|
||||
Common.setWsocket(false);
|
||||
Common.serverCFG = cfg;
|
||||
|
||||
let ini_text = Common.convertINIString(Common.serverCFG);
|
||||
Common.writeFile(Common.iniFile, ini_text);
|
||||
Common.rebootServer(true);
|
||||
Common.setWsocket(true);
|
||||
}
|
||||
|
||||
serverDialog.active = false;
|
||||
}
|
||||
|
||||
onReset: {
|
||||
rootPreference.load(Common.defaultServerCFG);
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
anchors.margins: 16
|
||||
anchors.topMargin: 0
|
||||
|
||||
Flickable {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
clip: true
|
||||
contentWidth: preferenceLayout.implicitWidth
|
||||
contentHeight: preferenceLayout.implicitHeight
|
||||
|
||||
ColumnLayout {
|
||||
id: preferenceLayout
|
||||
width: root.width
|
||||
|
||||
P.SwitchPreference {
|
||||
id: _debug
|
||||
Layout.fillWidth: true
|
||||
name: "debug"
|
||||
label: qsTr("Debug Mode")
|
||||
message: qsTr("Logging must be enabled and saved.")
|
||||
warning: value ? qsTr("This will disable the error recovery function!") : ""
|
||||
enabled: Common.serverCFG.server.logger
|
||||
defaultValue: Common.debug
|
||||
onPreferenceEdited: {
|
||||
Common.debug = value;
|
||||
}
|
||||
}
|
||||
|
||||
P.PreferenceGroup {
|
||||
id: rootPreference
|
||||
Layout.fillWidth: true
|
||||
|
||||
P.PreferenceGroup {
|
||||
Layout.fillWidth: true
|
||||
name: "server"
|
||||
Heading { text: qsTr("General") }
|
||||
|
||||
P.SpinPreference {
|
||||
name: "port"
|
||||
label: qsTr("Port")
|
||||
display: P.TextFieldPreference.ExpandLabel
|
||||
editable: true
|
||||
from: 1
|
||||
to: 65535
|
||||
value: String(value)
|
||||
defaultValue: Common.defaultServerCFG["server"]["port"]
|
||||
}
|
||||
|
||||
P.SpinPreference {
|
||||
name: "maxclient"
|
||||
label: qsTr("Max Number of Clients")
|
||||
message: qsTr("Maximum number of server connections\n(All ADV widgets share one connection).")
|
||||
display: P.TextFieldPreference.ExpandLabel
|
||||
editable: true
|
||||
from: 1
|
||||
to: 15
|
||||
value: String(value)
|
||||
defaultValue: Common.defaultServerCFG["server"]["maxclient"]
|
||||
}
|
||||
|
||||
P.SwitchPreference {
|
||||
id: _server_logger
|
||||
name: "logger"
|
||||
label: qsTr("Enable Logging")
|
||||
message: qsTr("Enable to output log file (ADV_Log.log).")
|
||||
defaultValue: Common.defaultServerCFG["server"]["logger"]
|
||||
}
|
||||
|
||||
P.ItemPreference {
|
||||
label: qsTr("Open Log File")
|
||||
Layout.fillWidth: true
|
||||
enabled: _debug.enabled
|
||||
select: function () {
|
||||
NVG.SystemCall.execute("explorer", NVG.Url.toLocalFile(Qt.resolvedUrl("../bin/ADV_Log.log")).replace(/\//g, '\\'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
P.PreferenceGroup {
|
||||
Layout.fillWidth: true
|
||||
name: "fft"
|
||||
Heading { text: qsTr("Data") }
|
||||
|
||||
P.SpinPreference {
|
||||
name: "attack"
|
||||
label: qsTr("Increase Speed")
|
||||
display: P.TextFieldPreference.ExpandLabel
|
||||
editable: true
|
||||
from: 1
|
||||
to: 200
|
||||
defaultValue: Common.defaultServerCFG["fft"]["attack"]
|
||||
}
|
||||
|
||||
P.SpinPreference {
|
||||
name: "decay"
|
||||
label: qsTr("Reduction Speed")
|
||||
display: P.TextFieldPreference.ExpandLabel
|
||||
editable: true
|
||||
from: 1
|
||||
to: 200
|
||||
defaultValue: Common.defaultServerCFG["fft"]["decay"]
|
||||
}
|
||||
|
||||
P.SpinPreference {
|
||||
name: "peakthr"
|
||||
label: qsTr("Peak Extra Increment")
|
||||
message: qsTr("Extra increment of data normalization peak.")
|
||||
display: P.TextFieldPreference.ExpandLabel
|
||||
editable: true
|
||||
from: 0
|
||||
to: 1000
|
||||
defaultValue: Common.defaultServerCFG["fft"]["peakthr"]
|
||||
}
|
||||
|
||||
P.SpinPreference {
|
||||
name: "norspeed"
|
||||
label: qsTr("Dynamic Normalization Factor")
|
||||
message: qsTr("Convergence speed of data normalization peak.")
|
||||
display: P.TextFieldPreference.ExpandLabel
|
||||
editable: true
|
||||
from: 1
|
||||
to: 100
|
||||
defaultValue: Common.defaultServerCFG["fft"]["norspeed"]
|
||||
}
|
||||
|
||||
P.SpinPreference {
|
||||
id: _fps
|
||||
name: "fps"
|
||||
label: qsTr("Transmission Rate")
|
||||
message: qsTr("Number of data sent per second.")
|
||||
display: P.TextFieldPreference.ExpandLabel
|
||||
editable: true
|
||||
from: 10
|
||||
to: 60
|
||||
defaultValue: Common.defaultServerCFG["fft"]["fps"]
|
||||
}
|
||||
|
||||
P.SpinPreference {
|
||||
name: "changespeed"
|
||||
label: qsTr("Change Speed")
|
||||
message: qsTr("Adjust the data change speed.")
|
||||
display: P.TextFieldPreference.ExpandLabel
|
||||
editable: true
|
||||
from: 1
|
||||
to: _fps.value - 1
|
||||
defaultValue: Common.defaultServerCFG["fft"]["changespeed"]
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
rootPreference.load(Common.serverCFG)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onClosing: {
|
||||
serverDialog.active = false;
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,7 @@ import "."
|
||||
|
||||
NVG.Window {
|
||||
id: window
|
||||
title: qsTr("ADV-Plugin: Settings")
|
||||
title: qsTr("ADV-Style: Settings")
|
||||
visible: true
|
||||
minimumWidth: 480
|
||||
minimumHeight: 600
|
||||
@ -26,7 +26,7 @@ NVG.Window {
|
||||
anchors.fill: parent
|
||||
|
||||
header: TitleBar {
|
||||
text: qsTr("Settings")
|
||||
text: qsTr("Style Settings")
|
||||
standardButtons: Dialog.Save | Dialog.Reset
|
||||
|
||||
onAccepted: {
|
||||
@ -82,7 +82,7 @@ NVG.Window {
|
||||
defaultValue: 0
|
||||
model: Common.styles
|
||||
}
|
||||
|
||||
|
||||
Heading {
|
||||
id: heading
|
||||
text: Common.styles[styleList.value] + " " + qsTr("Configuration")
|
||||
|
||||
@ -4,15 +4,12 @@ import "."
|
||||
|
||||
|
||||
WebSocket {
|
||||
property string wsIp: "localhost"
|
||||
property int wsPort: 5050
|
||||
|
||||
url: "ws://" + wsIp + ":" + wsPort
|
||||
url: "ws://" + Common.wsIp + ":" + Common.wsPort
|
||||
active: true
|
||||
|
||||
onStatusChanged: {
|
||||
if(status === WebSocket.Closed || status === WebSocket.Error) {
|
||||
Common.wsocketClosed();
|
||||
Common.rebootFlag = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user