AJA NTV2 SDK  17.5.0.1242
NTV2 SDK 17.5.0.1242
infoimpl.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
9 #include "ajabase/system/info.h"
10 #include <sstream>
11 #include <cstdlib>
12 #include <stdexcept>
13 #include <unistd.h>
14 
15 std::string aja_cmd(const char* cmd)
16 {
17 #if 0
18  const int maxbufsize = 256;
19  char buffer[maxbufsize];
20  std::string result = "";
21  FILE* pipe = popen(cmd, "r");
22  if (!pipe)
23  {
24  throw std::runtime_error("popen() failed!");
25  }
26 
27  try
28  {
29  while (!feof(pipe))
30  {
31  if (fgets(buffer, maxbufsize, pipe) != NULL)
32  {
33  try
34  {
35  result += buffer;
36  }
37  catch (...)
38  {
39  pclose(pipe);
40  throw;
41  }
42  }
43  }
44  }
45  catch (...)
46  {
47  pclose(pipe);
48  throw;
49  }
50  pclose(pipe);
51  return result;
52 #else
53  throw std::runtime_error("aja_cmd() failed!");
54  return "";
55 #endif
56 }
57 
58 std::string aja_procfs(const char* procfs_file, const char* value_key)
59 {
60  // cat /proc/cpuinfo outputs something like:
61  // vendor_id : GenuineIntel
62  // model name : Intel(R) Xeon(R) CPU X5650 @ 2.67GHz
63  // ...
64  // so use grep to get the lines matching key
65  // use head to only select the first line returned
66  // use cut to get just the part after ':'
67  // use xargs to remove leading and trailing spaces
68  // use tr to remove linefeeds
69  // use tr to remove repeated spaces
70  std::ostringstream oss;
71  oss << "cat /proc/" << procfs_file << " | grep '" << value_key << "' | head -n 1 | cut -d ':' -f 2 | xargs | tr -d '\n' | tr -s ' '";
72 
73  return aja_cmd(oss.str().c_str());
74 }
75 
76 std::string aja_uptime()
77 {
78  // Centos6 / Redhat 6 does not have the uptime -s command so
79  // first try using /proc/uptime
80 
81  std::string out;
82  std::ostringstream oss;
83  oss << "date -d \"`cut -f1 -d. /proc/uptime` seconds ago\" \"+%Y-%m-%d %H:%M:%S\"";
84  out = aja_cmd(oss.str().c_str());
85  out = aja::strip(out);
86 
87  if (out.empty())
88  {
89  out = aja_cmd("uptime -s 2>/dev/null");
90  out = aja::strip(out);
91  }
92 
93  return out;
94 }
95 
96 std::string aja_productname()
97 {
98  std::string out;
99  out = aja_cmd("lsb_release -d -s 2>/dev/null");
100  out = aja::strip(out);
101  out = aja::strip(out, "\"");
102 
103  if (out.empty())
104  {
105  AJAFileIO f;
106 
107  if (f.FileExists("/etc/redhat-release"))
108  {
109  out = aja_cmd("cat /etc/redhat-release 2>/dev/null");
110  }
111  else if(f.FileExists("/etc/os-release"))
112  {
113  out = aja_cmd("cat /etc/os-release 2>/dev/null | grep 'PRETTY_NAME' | head -n 1 | cut -d '=' -f 2 | tr -d '\"' | tr -d '\n'");
114  }
115  }
116 
117  out = aja::strip(out);
118  return out;
119 }
120 
121 std::string aja_osversion()
122 {
123  std::string out;
124  out = aja_cmd("lsb_release -r -s 2>/dev/null");
125 
126  if (out.empty())
127  {
128  AJAFileIO f;
129 
130  if(f.FileExists("/etc/os-release"))
131  {
132  out = aja_cmd("cat /etc/os-release 2>/dev/null | grep 'VERSION_ID' | head -n 1 | cut -d '=' -f 2 | tr -d '\"' | tr -d '\n'");
133  }
134  }
135 
136  out = aja::strip(out);
137  return out;
138 }
139 
140 void get_vendor_and_device(std::map<std::string, std::string>& inDevicePart,
141  std::vector<std::string>& outFoundDevices)
142 {
143  if (inDevicePart.size() >= 2)
144  {
145  std::string vend;
146  std::string device;
147 
148  if (inDevicePart.find("SVendor") != inDevicePart.end())
149  vend = inDevicePart.at("SVendor");
150  else if (inDevicePart.find("Vendor") != inDevicePart.end())
151  vend = inDevicePart.at("Vendor");
152 
153  if (inDevicePart.find("SDevice") != inDevicePart.end())
154  device = inDevicePart.at("SDevice");
155  else if (inDevicePart.find("Device") != inDevicePart.end())
156  device = inDevicePart.at("Device");
157 
158  outFoundDevices.push_back(vend + " " + device);
159  }
160 }
161 
162 std::string aja_getgputype()
163 {
164  std::string out;
165  out = aja_cmd("lspci -vmm | grep VGA -A 4");
166 
167  // The following are some real world lspci results the code has been tested against and a few made up samples
168 
169  // CentOS 7 running under VirtualBox
170  //out = "Class:\tVGA compatible controller\nVendor:\tInnoTek Systemberatung GmbH\nDevice:\tVirtualBox Graphics Adapter\n\nSlot:\t00:03.0";
171  // Ubuntu 18.04 with NVIDIA Quadro K600
172  //out = "Class:\tVGA compatible controller\nVendor:\tNVIDIA Corporation\nDevice:\tGK107GL [Quadro K600]\nSVendor:\tNVIDIA Corporation\nSDevice:\tGK107GL [Quadro K600]";
173  // Ubuntu 18.04 with 2x NVIDIA Quadro K600
174  //out = "Class:\tVGA compatible controller\nVendor:\tNVIDIA Corporation\nDevice:\tGK107GL [Quadro K600]\nSVendor:\tNVIDIA Corporation\nSDevice:\tGK107GL [Quadro K600]\n--\nClass:\tVGA compatible controller\nVendor:\tNVIDIA Corporation\nDevice:\tGK107GL [Quadro K600]\nSVendor:\tNVIDIA Corporation\nSDevice:\tGK107GL [Quadro K600]";
175  // CentOS 7 running as a VM (not sure which hypervisor)
176  //out = "Class:\tVGA compatible controller\nVendor:\tVendor 1234\nDevice:\t Device 1111\nSVendor:\tRed Hat, Inc.\nSDevice:\tDevice 1100";
177  // If no VGA found or lspci fails
178  //out = "";
179  // VGA found but no vendor or device keys
180  //out = "Class:\tVGA compatible controller\nPhySlot:\t1\nRev:\t02";
181  // VGA found but a value contains colons
182  //out = "Class:\tVGA compatible controller\nVendor:\tFake vendor with : colon in name, twice : end\nDevice:\tGeneric:VGA";
183 
184  std::ostringstream oss;
185  std::vector<std::string> lines = aja::split(out, '\n');
186  if (lines.empty() == false)
187  {
188  std::vector<std::string>::iterator it;
189  std::vector<std::string> foundDevices;
190  std::map<std::string, std::string> deviceParts;
191  for(it=lines.begin();it!=lines.end();++it)
192  {
193  if (*it == "--" || *it == "")
194  {
195  if (deviceParts.size() >= 2)
196  {
197  get_vendor_and_device(deviceParts, foundDevices);
198  deviceParts.clear();
199  }
200  continue;
201  }
202 
203  std::vector<std::string> cols = aja::split(*it, ':');
204  if (cols.size() > 1)
205  {
206  std::string key = aja::strip(cols.at(0));
207  std::string val = cols.at(1);
208  // handle any values that contain colons by concating back together
209  for(size_t i=2;i<cols.size();++i)
210  {
211  val = val + ":" + cols.at(i);
212  }
213  val = aja::strip(val);
214 
215  if (key == "Class")
216  {
217  deviceParts.clear();
218  continue;
219  }
220  else if (key == "Vendor" || key == "Device" ||
221  key == "SVendor" || key == "SDevice")
222  {
223  deviceParts[key] = val;
224  }
225  }
226  }
227 
228  if (deviceParts.size() >= 2)
229  {
230  get_vendor_and_device(deviceParts, foundDevices);
231  deviceParts.clear();
232  }
233 
234  for(size_t i=0;i<foundDevices.size();++i)
235  {
236  if (i != 0)
237  {
238  oss << ", ";
239  }
240  oss << foundDevices.at(i);
241  }
242  }
243  return oss.str();
244 }
245 
247 {
248  mMemoryUnits = units;
249 }
250 
252 {
253 
254 }
255 
256 AJAStatus
258 {
260 
261 #if 0
262  static char tmp_buf[4096];
263 
264  if (sections & AJA_SystemInfoSection_System)
265  {
266  mValueMap[int(AJA_SystemInfoTag_System_Model)] = aja_cmd("uname -m | tr -d '\n'");
267  gethostname(tmp_buf, sizeof(tmp_buf));
270 
271  ret = AJA_STATUS_SUCCESS;
272  }
273 
274  if (sections & AJA_SystemInfoSection_OS)
275  {
278  mValueMap[int(AJA_SystemInfoTag_OS_VersionBuild)] = aja_cmd("uname -v | tr -d '\n'");
279  mValueMap[int(AJA_SystemInfoTag_OS_KernelVersion)] = aja_cmd("uname -r | tr -d '\n'");
280 
281  ret = AJA_STATUS_SUCCESS;
282  }
283 
284  if (sections & AJA_SystemInfoSection_CPU)
285  {
286  mValueMap[int(AJA_SystemInfoTag_CPU_Type)] = aja_procfs("cpuinfo", "model name");
287  long int numProcs = sysconf(_SC_NPROCESSORS_ONLN);
288  std::ostringstream num_cores;
289  num_cores << numProcs;
290  mValueMap[int(AJA_SystemInfoTag_CPU_NumCores)] = num_cores.str();
291 
292  ret = AJA_STATUS_SUCCESS;
293  }
294 
295  if (sections & AJA_SystemInfoSection_Mem)
296  {
297  std::string memTotalStr = aja_procfs("meminfo", "MemTotal");
298  int64_t memtotalbytes=0;
299  if (memTotalStr.find(" kB") != std::string::npos)
300  {
301  // convert from kilobytes to bytes
302  aja::replace(memTotalStr, " kB", "");
303  std::istringstream(memTotalStr) >> memtotalbytes;
304  memtotalbytes *= 1024;
305  }
306  else
307  {
308  // assume it is in bytes?
309  std::istringstream(memTotalStr) >> memtotalbytes;
310  }
311 
312  std::string memFreeStr = aja_procfs("meminfo", "MemFree");
313  int64_t memfreebytes=0;
314  if (memFreeStr.find(" kB") != std::string::npos)
315  {
316  // convert from kilobytes to bytes
317  aja::replace(memFreeStr, " kB", "");
318  std::istringstream(memFreeStr) >> memfreebytes;
319  memfreebytes *= 1024;
320  }
321  else
322  {
323  // assume it is in bytes?
324  std::istringstream(memFreeStr) >> memfreebytes;
325  }
326 
327  std::string unitsLabel;
328  double divisor = 1.0;
329  switch(mMemoryUnits)
330  {
331  default:
333  unitsLabel = "B";
334  break;
336  unitsLabel = "KB";
337  divisor = 1024.0;
338  break;
340  unitsLabel = "MB";
341  divisor = 1048576.0;
342  break;
344  unitsLabel = "GB";
345  divisor = 1073741824.0;
346  break;
347  }
348 
349  int64_t memusedbytes = memtotalbytes - memfreebytes;
350 
351  std::ostringstream t,u,f;
352  t << int64_t(memtotalbytes / divisor) << " " << unitsLabel;
353  u << int64_t(memusedbytes / divisor) << " " << unitsLabel;
354  f << int64_t(memfreebytes / divisor) << " " << unitsLabel;
355 
356  mValueMap[int(AJA_SystemInfoTag_Mem_Total)] = t.str();
357  mValueMap[int(AJA_SystemInfoTag_Mem_Used)] = u.str();
358  mValueMap[int(AJA_SystemInfoTag_Mem_Free)] = f.str();
359 
360  ret = AJA_STATUS_SUCCESS;
361  } // end if (sections & AJA_SystemInfoSection_Mem)
362 
363  if (sections & AJA_SystemInfoSection_GPU)
364  {
366 
367  ret = AJA_STATUS_SUCCESS;
368  }
369 
370  if (sections & AJA_SystemInfoSection_Path)
371  {
372  const char* homePath = getenv("HOME");
373  if (homePath != NULL)
374  {
377  mValueMap[int(AJA_SystemInfoTag_Path_PersistenceStoreUser)].append("/.aja/config/");
378  }
379 
380  mValueMap[int(AJA_SystemInfoTag_Path_PersistenceStoreSystem)] = "/opt/aja/config/";
381 
382  mValueMap[int(AJA_SystemInfoTag_Path_Applications)] = "/opt/aja/bin/";
383  mValueMap[int(AJA_SystemInfoTag_Path_Utilities)] = "/opt/aja/bin/";
384  mValueMap[int(AJA_SystemInfoTag_Path_Firmware)] = "/opt/aja/firmware/";
385 
386  ret = AJA_STATUS_SUCCESS;
387  }
388 
389 #endif
390  return ret;
391 }
AJA_SystemInfoSection_Path
@ AJA_SystemInfoSection_Path
Definition: info.h:61
info.h
Declares the AJASystemInfo class.
AJA_SystemInfoMemoryUnit_Megabytes
@ AJA_SystemInfoMemoryUnit_Megabytes
Definition: info.h:23
AJA_SystemInfoSection_CPU
@ AJA_SystemInfoSection_CPU
Definition: info.h:57
aja::strip
std::string & strip(std::string &str, const std::string &ws)
Definition: common.cpp:461
NULL
#define NULL
Definition: ntv2caption608types.h:19
AJA_STATUS_SUCCESS
@ AJA_STATUS_SUCCESS
Definition: types.h:381
aja::split
void split(const std::string &str, const char delim, std::vector< std::string > &elems)
Definition: common.cpp:350
AJA_SystemInfoTag_Path_Firmware
@ AJA_SystemInfoTag_Path_Firmware
Definition: info.h:50
AJASystemInfoImpl::mMemoryUnits
int mMemoryUnits
Definition: infoimpl.h:26
AJA_SystemInfoTag_OS_KernelVersion
@ AJA_SystemInfoTag_OS_KernelVersion
Definition: info.h:38
aja_procfs
std::string aja_procfs(const char *procfs_file, const char *value_key)
Definition: infoimpl.cpp:58
AJA_SystemInfoTag_Path_Applications
@ AJA_SystemInfoTag_Path_Applications
Definition: info.h:48
AJASystemInfoImpl::~AJASystemInfoImpl
virtual ~AJASystemInfoImpl()
Definition: infoimpl.cpp:251
get_vendor_and_device
void get_vendor_and_device(std::map< std::string, std::string > &inDevicePart, std::vector< std::string > &outFoundDevices)
Definition: infoimpl.cpp:140
AJA_SystemInfoMemoryUnit_Kilobytes
@ AJA_SystemInfoMemoryUnit_Kilobytes
Definition: info.h:22
AJA_SystemInfoTag_CPU_Type
@ AJA_SystemInfoTag_CPU_Type
Definition: info.h:39
aja_productname
std::string aja_productname()
Definition: infoimpl.cpp:96
AJAStatus
AJAStatus
Definition: types.h:378
aja_cmd
std::string aja_cmd(const char *cmd)
Definition: infoimpl.cpp:15
AJA_SystemInfoTag_CPU_NumCores
@ AJA_SystemInfoTag_CPU_NumCores
Definition: info.h:40
aja::replace
std::string & replace(std::string &str, const std::string &from, const std::string &to)
Definition: common.cpp:110
AJA_STATUS_FAIL
@ AJA_STATUS_FAIL
Definition: types.h:382
AJA_SystemInfoTag_System_Name
@ AJA_SystemInfoTag_System_Name
Definition: info.h:33
aja_osversion
std::string aja_osversion()
Definition: infoimpl.cpp:121
AJASystemInfoImpl::mValueMap
std::map< int, std::string > mValueMap
Definition: infoimpl.h:24
AJA_SystemInfoTag_System_BootTime
@ AJA_SystemInfoTag_System_BootTime
Definition: info.h:34
AJA_SystemInfoTag_OS_Version
@ AJA_SystemInfoTag_OS_Version
Definition: info.h:36
AJA_SystemInfoTag_Mem_Used
@ AJA_SystemInfoTag_Mem_Used
Definition: info.h:42
AJA_SystemInfoSection_GPU
@ AJA_SystemInfoSection_GPU
Definition: info.h:58
AJA_SystemInfoTag_Path_PersistenceStoreUser
@ AJA_SystemInfoTag_Path_PersistenceStoreUser
Definition: info.h:46
AJASystemInfoSections
AJASystemInfoSections
Definition: info.h:55
AJASystemInfoImpl::AJASystemInfoImpl
AJASystemInfoImpl(int units)
Definition: infoimpl.cpp:246
AJA_SystemInfoTag_Path_PersistenceStoreSystem
@ AJA_SystemInfoTag_Path_PersistenceStoreSystem
Definition: info.h:47
file_io.h
Declares the AJAFileIO class.
AJA_SystemInfoMemoryUnit_Gigabytes
@ AJA_SystemInfoMemoryUnit_Gigabytes
Definition: info.h:24
AJA_SystemInfoTag_OS_ProductName
@ AJA_SystemInfoTag_OS_ProductName
Definition: info.h:35
AJAFileIO::FileExists
static bool FileExists(const std::wstring &fileName)
Definition: file_io.cpp:97
AJA_SystemInfoSection_OS
@ AJA_SystemInfoSection_OS
Definition: info.h:60
AJA_SystemInfoTag_Path_Utilities
@ AJA_SystemInfoTag_Path_Utilities
Definition: info.h:49
AJA_SystemInfoTag_Path_UserHome
@ AJA_SystemInfoTag_Path_UserHome
Definition: info.h:45
AJASystemInfoImpl::Rescan
virtual AJAStatus Rescan(AJASystemInfoSections sections)
Definition: infoimpl.cpp:257
AJA_SystemInfoSection_Mem
@ AJA_SystemInfoSection_Mem
Definition: info.h:59
AJA_SystemInfoTag_Mem_Free
@ AJA_SystemInfoTag_Mem_Free
Definition: info.h:43
AJAFileIO
Definition: file_io.h:64
AJA_SystemInfoTag_GPU_Type
@ AJA_SystemInfoTag_GPU_Type
Definition: info.h:44
aja_getgputype
std::string aja_getgputype()
Definition: infoimpl.cpp:162
AJA_SystemInfoTag_OS_VersionBuild
@ AJA_SystemInfoTag_OS_VersionBuild
Definition: info.h:37
AJA_SystemInfoMemoryUnit_Bytes
@ AJA_SystemInfoMemoryUnit_Bytes
Definition: info.h:21
AJA_SystemInfoSection_System
@ AJA_SystemInfoSection_System
Definition: info.h:62
AJA_SystemInfoTag_Mem_Total
@ AJA_SystemInfoTag_Mem_Total
Definition: info.h:41
infoimpl.h
Declares the AJASystemInfoImpl class.
AJA_SystemInfoTag_System_Model
@ AJA_SystemInfoTag_System_Model
Definition: info.h:31
aja_uptime
std::string aja_uptime()
Definition: infoimpl.cpp:76