From 83f1902a8ec540c68f459f3afaf3d7c03389591a Mon Sep 17 00:00:00 2001 From: Sebastian Hildebrandt Date: Mon, 3 Jun 2019 20:06:19 +0200 Subject: [PATCH] graphics() added display vendor, refresh rate --- README.md | 8 +++- docs/graphics.html | 46 ++++++++++++++++-- lib/graphics.js | 117 ++++++++++++++++++++++++++++++++------------- lib/index.d.ts | 4 ++ lib/util.js | 10 ++++ 5 files changed, 147 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index f80201a..22956b1 100644 --- a/README.md +++ b/README.md @@ -251,8 +251,9 @@ I also created a nice little command line tool called [mmon][mmon-github-url] ( | | ...[0].bus | X | | X | X | | on which bus (e.g. PCIe) | | | ...[0].vram | X | | X | X | | VRAM size (in MB) | | | ...[0].vramDynamic | X | | X | X | | true if dynamicly allocated ram | -| | displays[] | X | | X | X | | monitor/display Array | -| | ...[0].model | X | | X | X | | monitor/display Model | +| | displays[] | X | | X | X | | monitor/display array | +| | ...[0].vendor | | | X | | | monitor/display vendor | +| | ...[0].model | X | | X | X | | monitor/display model | | | ...[0].main | X | | X | | | true if main monitor | | | ...[0].builtin | X | | X | | | true if built in monitor | | | ...[0].connection | X | | X | | | e.g. DisplayPort or HDMI | @@ -261,6 +262,9 @@ I also created a nice little command line tool called [mmon][mmon-github-url] ( | | ...[0].pixeldepth | X | | X | X | | color depth in bits | | | ...[0].resolutionx | X | | X | X | | pixel horizontal | | | ...[0].resolutiony | X | | X | X | | pixel vertical | +| | ...[0].currentResX | X | | X | X | | current pixel horizontal | +| | ...[0].currentResY | X | | X | X | | current pixel vertical | +| | ...[0].currentRefreshRate | X | | X | X | | current pixel vertical | #### 7. Operating System diff --git a/docs/graphics.html b/docs/graphics.html index 6fdf8fa..9403df1 100644 --- a/docs/graphics.html +++ b/docs/graphics.html @@ -143,7 +143,17 @@ X X - monitor/display Array + monitor/display array + + + + ...[0].vendor + + + X + + + monitor/display vendor @@ -153,7 +163,7 @@ X X - monitor/display Model + monitor/display model @@ -183,7 +193,7 @@ X - e.g. DisplayPort or HDMI + e.g. DisplayPort, HDMI @@ -235,6 +245,36 @@ pixel vertical + + + ...[0].currentResX + X + + X + X + + current pixel horizontal + + + + ...[0].currentResY + X + + X + X + + current pixel vertical + + + + ...[0].currentRefreshRate + X + + X + X + + current pixel vertical + diff --git a/lib/graphics.js b/lib/graphics.js index 7e0332c..bb00f27 100644 --- a/lib/graphics.js +++ b/lib/graphics.js @@ -30,14 +30,7 @@ const _sunos = (_platform === 'sunos'); let _resolutionx = 0; let _resolutiony = 0; let _pixeldepth = 0; - -function toInt(value) { - let result = parseInt(value, 10); - if (isNaN(result)) { - result = 0; - } - return result; -} +let _refreshrate = 0; function graphics(callback) { @@ -55,6 +48,7 @@ function graphics(callback) { vramDynamic: false }; let currentDisplay = { + vendor: '', model: '', main: false, builtin: false, @@ -63,7 +57,10 @@ function graphics(callback) { sizey: -1, pixeldepth: -1, resolutionx: -1, - resolutiony: -1 + resolutiony: -1, + currentResX: -1, + currentResY: -1, + currentRefreshRate: -1 }; for (let i = 0; i < lines.length; i++) { if ('' !== lines[i].trim()) { @@ -86,6 +83,7 @@ function graphics(callback) { if (Object.keys(currentDisplay).length > 0) {// just changed to Displays displays.push(currentDisplay); currentDisplay = { + vendor: '', model: '', main: false, builtin: false, @@ -94,7 +92,10 @@ function graphics(callback) { sizey: -1, pixeldepth: -1, resolutionx: -1, - resolutiony: -1 + resolutiony: -1, + currentResX: -1, + currentResY: -1, + currentRefreshRate: -1 }; } } @@ -115,6 +116,7 @@ function graphics(callback) { } if (3 === level) { // display controller level if (parts.length > 1 && '' === parts[1]) { + currentDisplay.vendor = ''; currentDisplay.model = parts[0].trim(); currentDisplay.main = false; currentDisplay.builtin = false; @@ -129,6 +131,8 @@ function graphics(callback) { let resolution = parts[1].split('x'); currentDisplay.resolutionx = (resolution.length > 1 ? parseInt(resolution[0]) : 0); currentDisplay.resolutiony = (resolution.length > 1 ? parseInt(resolution[1]) : 0); + currentDisplay.currentResX = currentDisplay.resolutionx; + currentDisplay.currentResY = currentDisplay.resolutiony; } if (parts.length > 1 && parts[0].replace(/ +/g, '').toLowerCase().indexOf('pixeldepth') !== -1) currentDisplay.pixeldepth = parseInt(parts[1]); // in BIT if (parts.length > 1 && parts[0].replace(/ +/g, '').toLowerCase().indexOf('framebufferdepth') !== -1) currentDisplay.pixeldepth = parseInt(parts[1]); // in BIT @@ -264,6 +268,7 @@ function graphics(callback) { // --> sizex // --> sizey let result = { + vendor: '', model: '', main: false, builtin: false, @@ -272,7 +277,10 @@ function graphics(callback) { sizey: -1, pixeldepth: -1, resolutionx: -1, - resolutiony: -1 + resolutiony: -1, + currentResX: -1, + currentResY: -1, + currentRefreshRate: -1 }; // find first "Detailed Timing Description" let start = 108; @@ -299,9 +307,13 @@ function graphics(callback) { if (model_raw.indexOf('0a') !== -1) { model_raw = model_raw.substr(0, model_raw.indexOf('0a')); } - result.model = model_raw.match(/.{1,2}/g).map(function (v) { - return String.fromCharCode(parseInt(v, 16)); - }).join(''); + try { + result.model = model_raw.match(/.{1,2}/g).map(function (v) { + return String.fromCharCode(parseInt(v, 16)); + }).join(''); + } catch (e) { + util.noop(); + } } else { result.model = ''; } @@ -311,6 +323,7 @@ function graphics(callback) { function parseLinesLinuxDisplays(lines, depth) { let displays = []; let currentDisplay = { + vendor: '', model: '', main: false, builtin: false, @@ -319,9 +332,13 @@ function graphics(callback) { sizey: -1, pixeldepth: -1, resolutionx: -1, - resolutiony: -1 + resolutiony: -1, + currentResX: -1, + currentResY: -1, + currentRefreshRate: -1 }; let is_edid = false; + let is_current = false; let edid_raw = ''; let start = 0; for (let i = 1; i < lines.length; i++) { // start with second line @@ -330,6 +347,7 @@ function graphics(callback) { if (currentDisplay.model || currentDisplay.main || currentDisplay.builtin || currentDisplay.connection || currentDisplay.sizex !== -1 || currentDisplay.pixeldepth !== -1 || currentDisplay.resolutionx !== -1) { // push last display to array displays.push(currentDisplay); currentDisplay = { + vendor: '', model: '', main: false, builtin: false, @@ -338,12 +356,15 @@ function graphics(callback) { sizey: -1, pixeldepth: -1, resolutionx: -1, - resolutiony: -1 + resolutiony: -1, + currentResX: -1, + currentResY: -1, + currentRefreshRate: -1 }; } let parts = lines[i].split(' '); currentDisplay.connection = parts[0]; - currentDisplay.main = (parts[2] === 'primary'); + currentDisplay.main = lines[i].toLowerCase().indexOf(' primary ') >= 0; currentDisplay.builtin = (parts[0].toLowerCase().indexOf('edp') >= 0); } @@ -354,6 +375,7 @@ function graphics(callback) { } else { // parsen EDID let edid_decoded = parseLinesLinuxEdid(edid_raw); + currentDisplay.vendor = edid_decoded.vendor; currentDisplay.model = edid_decoded.model; currentDisplay.resolutionx = edid_decoded.resolutionx; currentDisplay.resolutiony = edid_decoded.resolutiony; @@ -363,10 +385,26 @@ function graphics(callback) { is_edid = false; } } - if (lines[i].toLowerCase().indexOf('edid:') !== -1) { + if (lines[i].toLowerCase().indexOf('edid:') >= 0) { is_edid = true; start = lines[i].search(/\S|$/); } + if (lines[i].toLowerCase().indexOf('*current') >= 0) { + const parts1 = lines[i].split('('); + if (parts1 && parts1.length > 1 && parts1[0].indexOf('x') >= 0) { + const resParts = parts1[0].trim().split('x'); + currentDisplay.currentResolutionx = util.toInt(resParts[0]); + currentDisplay.currentResolutiony = util.toInt(resParts[1]); + } + is_current = true; + } + if (is_current && lines[i].toLowerCase().indexOf('clock') >= 0 && lines[i].toLowerCase().indexOf('hz') >= 0 && lines[i].toLowerCase().indexOf('v: height') >= 0) { + const parts1 = lines[i].split('clock'); + if (parts1 && parts1.length > 1 && parts1[1].toLowerCase().indexOf('hz') >= 0) { + currentDisplay.currentRefreshRate = util.toInt(parts1[1]); + } + is_current = false; + } } } @@ -407,6 +445,7 @@ function graphics(callback) { const parts = lines[0].replace('mode', '').replace(/"/g, '').trim().split('x'); if (parts.length === 2) { result.displays.push({ + vendor: '', model: util.getValue(lines, 'device_name', '='), main: true, builtin: false, @@ -415,7 +454,10 @@ function graphics(callback) { sizey: -1, pixeldepth: -1, resolutionx: parseInt(parts[0], 10), - resolutiony: parseInt(parts[1], 10) + resolutiony: parseInt(parts[1], 10), + currentResX: -1, + currentResY: -1, + currentRefreshRate: -1 }); } } @@ -473,24 +515,27 @@ function graphics(callback) { if (_windows) { // https://blogs.technet.microsoft.com/heyscriptingguy/2013/10/03/use-powershell-to-discover-multi-monitor-information/ try { - util.wmic('path win32_VideoController get AdapterCompatibility, AdapterDACType, name, PNPDeviceID, CurrentVerticalResolution, CurrentHorizontalResolution, CurrentNumberOfColors, AdapterRAM, CurrentBitsPerPixel, CurrentRefreshRate, MinRefreshRate, MaxRefreshRate, VideoMemoryType /value').then((stdout, error) => { + util.wmic('path win32_VideoController get /value').then((stdout, error) => { if (!error) { let csections = stdout.split(/\n\s*\n/); result.controllers = parseLinesWindowsControllers(csections); - util.wmic('path win32_desktopmonitor get Caption, MonitorManufacturer, MonitorType, ScreenWidth, ScreenHeight /value').then((stdout, error) => { + util.wmic('path win32_desktopmonitor get /value').then((stdout, error) => { let dsections = stdout.split(/\n\s*\n/); if (!error) { result.displays = parseLinesWindowsDisplays(dsections); if (result.controllers.length === 1 && result.displays.length === 1) { - if (_resolutionx && !result.displays[0].resolutionx) { - result.displays[0].resolutionx = _resolutionx; + if (_resolutionx) { + result.displays[0].currentResX = _resolutionx; } - if (_resolutiony && !result.displays[0].resolutiony) { - result.displays[0].resolutiony = _resolutiony; + if (_resolutiony) { + result.displays[0].currentResY = _resolutiony; } if (_pixeldepth) { result.displays[0].pixeldepth = _pixeldepth; } + if (_refreshrate && !result.displays[0].refreshrate) { + result.displays[0].currentRefreshRate = _refreshrate; + } } } if (callback) { @@ -519,15 +564,16 @@ function graphics(callback) { let lines = sections[i].trim().split('\r\n'); controllers.push({ - model: util.getValue(lines, 'name', '='), vendor: util.getValue(lines, 'AdapterCompatibility', '='), + model: util.getValue(lines, 'name', '='), bus: util.getValue(lines, 'PNPDeviceID', '=').startsWith('PCI') ? 'PCI' : '', vram: parseInt(util.getValue(lines, 'AdapterRAM', '='), 10) / 1024 / 1024, vramDynamic: (util.getValue(lines, 'VideoMemoryType', '=') === '2') }); - _resolutionx = toInt(util.getValue(lines, 'CurrentHorizontalResolution', '=')); - _resolutiony = toInt(util.getValue(lines, 'CurrentVerticalResolution', '=')); - _pixeldepth = toInt(util.getValue(lines, 'CurrentBitsPerPixel', '=')); + _resolutionx = util.toInt(util.getValue(lines, 'CurrentHorizontalResolution', '=')); + _resolutiony = util.toInt(util.getValue(lines, 'CurrentVerticalResolution', '=')); + _refreshrate = util.toInt(util.getValue(lines, 'CurrentRefreshRate', '=')); + _pixeldepth = util.toInt(util.getValue(lines, 'CurrentBitsPerPixel', '=')); } } } @@ -541,14 +587,19 @@ function graphics(callback) { if (sections[i].trim() !== '') { let lines = sections[i].trim().split('\r\n'); displays.push({ - model: util.getValue(lines, 'MonitorManufacturer', '='), + vendor: util.getValue(lines, 'MonitorManufacturer', '='), + model: util.getValue(lines, 'Name', '='), main: false, builtin: false, connection: '', - resolutionx: toInt(util.getValue(lines, 'ScreenWidth', '=')), - resolutiony: toInt(util.getValue(lines, 'ScreenHeight', '=')), sizex: -1, - sizey: -1 + sizey: -1, + pixeldepth: -1, + resolutionx: util.toInt(util.getValue(lines, 'ScreenWidth', '=')), + resolutiony: util.toInt(util.getValue(lines, 'ScreenHeight', '=')), + currentResX: -1, + currentResY: -1, + currentRefreshRate: -1 }); } } diff --git a/lib/index.d.ts b/lib/index.d.ts index 14dc36b..067f27d 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -167,6 +167,7 @@ export namespace Systeminformation { } interface GraphicsDisplayData { + vendor: string; model: string; main: boolean; builtin: boolean; @@ -176,6 +177,9 @@ export namespace Systeminformation { pixeldepth: number; resolutionx: number; resolutiony: number; + currentResX: number; + currentResY: number; + currentRefreshRate: number; } // 4. Operating System diff --git a/lib/util.js b/lib/util.js index dd79432..b0f7af6 100644 --- a/lib/util.js +++ b/lib/util.js @@ -38,6 +38,15 @@ const execOptsWin = { encoding: 'UTF-8' }; + +function toInt(value) { + let result = parseInt(value, 10); + if (isNaN(result)) { + result = 0; + } + return result; +} + function isFunction(functionToCheck) { let getType = {}; return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; @@ -397,6 +406,7 @@ function countUniqueLines(lines, startingWith) { } function noop() { } +exports.toInt = toInt; exports.execOptsWin = execOptsWin; exports.getCodepage = getCodepage; exports.execWin = execWin;