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