AJA NTV2 SDK  18.1.0.2439
NTV2 SDK 18.1.0.2439
ntv2devicescanner.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
8 #include "ntv2devicescanner.h"
9 #include "ntv2devicefeatures.h"
10 #include "ntv2utils.h"
11 #include "ajabase/common/common.h"
12 #include "ajabase/system/debug.h"
13 #include "ajabase/system/lock.h"
14 #include <sstream>
15 #include "ajabase/system/info.h"
16 #include "ajabase/common/json.hpp"
17 #include <fstream>
18 #include "ajabase/system/file_io.h"
19 
20 using namespace std;
21 using json = nlohmann::json;
22 
23 
24 #define VDFAIL(__x__) AJA_sERROR (AJA_DebugUnit_VDev, AJAFUNC << ": " << __x__)
25 #define VDWARN(__x__) AJA_sWARNING(AJA_DebugUnit_VDev, AJAFUNC << ": " << __x__)
26 #define VDNOTE(__x__) AJA_sNOTICE (AJA_DebugUnit_VDev, AJAFUNC << ": " << __x__)
27 #define VDINFO(__x__) AJA_sINFO (AJA_DebugUnit_VDev, AJAFUNC << ": " << __x__)
28 #define VDDBUG(__x__) AJA_sDEBUG (AJA_DebugUnit_VDev, AJAFUNC << ": " << __x__)
29 
30 #define C2FAIL(__x__) AJA_sERROR (AJA_DebugUnit_CP2, AJAFUNC << ": " << __x__)
31 #define C2WARN(__x__) AJA_sWARNING(AJA_DebugUnit_CP2, AJAFUNC << ": " << __x__)
32 #define C2NOTE(__x__) AJA_sNOTICE (AJA_DebugUnit_CP2, AJAFUNC << ": " << __x__)
33 #define C2INFO(__x__) AJA_sINFO (AJA_DebugUnit_CP2, AJAFUNC << ": " << __x__)
34 #define C2DBUG(__x__) AJA_sDEBUG (AJA_DebugUnit_CP2, AJAFUNC << ": " << __x__)
35 
36 
37 #if !defined(NTV2_DEPRECATE_17_1)
38  bool CNTV2DeviceScanner::IsHexDigit (const char inChr)
39  { static const string sHexDigits("0123456789ABCDEFabcdef");
40  return sHexDigits.find(inChr) != string::npos;
41  }
42 
43  bool CNTV2DeviceScanner::IsDecimalDigit (const char inChr)
44  { static const string sDecDigits("0123456789");
45  return sDecDigits.find(inChr) != string::npos;
46  }
47 
48  bool CNTV2DeviceScanner::IsAlphaNumeric (const char inChr)
49  { static const string sLegalChars("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
50  return sLegalChars.find(inChr) != string::npos;
51  }
52 
53  bool CNTV2DeviceScanner::IsLegalDecimalNumber (const string & inStr, const size_t inMaxLength)
54  {
55  return aja::is_legal_decimal_number(inStr, inMaxLength);
56  }
57 
58  uint64_t CNTV2DeviceScanner::IsLegalHexSerialNumber (const string & inStr) // 0x3236333331375458
59  {
60  return aja::is_legal_hex_serial_number(inStr);
61  }
62 
63  bool CNTV2DeviceScanner::IsAlphaNumeric (const string & inStr)
64  {
65  for (size_t ndx(0); ndx < inStr.size(); ndx++)
66  if (!aja::is_alpha_numeric(inStr.at(ndx)))
67  return false;
68  return true;
69  }
70 #endif // !defined(NTV2_DEPRECATE_17_1)
71 
72 bool CNTV2DeviceScanner::IsLegalSerialNumber (const string & inStr)
73 {
74  if (inStr.length() != 8 && inStr.length() != 9)
75  return false;
76  return aja::is_alpha_numeric(inStr);
77 }
78 
81 
83 {
84  AJAAutoLock tmpLock(&sDevInfoListLock);
85  return sDevInfoList.size();
86 }
87 
89 {
90  if (inScanNow)
91  ScanHardware();
92 }
93 
94  #if !defined(NTV2_DEPRECATE_16_3)
95  CNTV2DeviceScanner::CNTV2DeviceScanner (bool inScanNow, UWord inDeviceMask)
96  {
97  (void)inDeviceMask;
98  if (inScanNow)
99  ScanHardware();
100  }
101  #endif // !defined(NTV2_DEPRECATE_16_3)
102 
104 {
105  AJAAutoLock tmpLock(&sDevInfoListLock);
106  return sDevInfoList;
107 }
108 
109 
111 {
112  AJAAutoLock tmpLock(&sDevInfoListLock);
113  sDevInfoList.clear();
114 
115  for (UWord boardNum(0); ; boardNum++)
116  {
117  CNTV2Card tmpDev(boardNum);
118  if (!tmpDev.IsOpen())
119  break;
120  const NTV2DeviceID deviceID (tmpDev.GetDeviceID());
121 
122  if (deviceID != DEVICE_ID_NOTFOUND)
123  {
124  ostringstream oss;
125  NTV2DeviceInfo info;
126  info.deviceIndex = boardNum;
127  info.deviceID = deviceID;
128  tmpDev.GetSerialNumberString(info.serialNumber);
129 
130  oss << ::NTV2DeviceIDToString (deviceID, tmpDev.IsSupported(kDeviceHasMicrophoneInput)) << " - " << boardNum;
131 
132  info.deviceIdentifier = oss.str();
133  SetDeviceAttributes(info, tmpDev);
134  SetAudioAttributes(info, tmpDev);
135  sDevInfoList.push_back(info);
136  }
137  tmpDev.Close();
138  } // boardNum loop
139 
140  GetVDevList(sDevInfoList); // For VKONA support
141  GetCP2DevList(sDevInfoList); // For CP2 support
142 } // ScanHardware
143 
144 bool CNTV2DeviceScanner::DeviceIDPresent (const NTV2DeviceID inDeviceID, const bool inRescan)
145 {
146  AJAAutoLock tmpLock(&sDevInfoListLock);
147  if (inRescan)
148  ScanHardware();
149 
150  for (NTV2DeviceInfoListConstIter iter(sDevInfoList.begin()); iter != sDevInfoList.end(); ++iter)
151  if (iter->deviceID == inDeviceID)
152  return true; // Found!
153  return false; // Not found
154 
155 } // DeviceIDPresent
156 
157 
158 bool CNTV2DeviceScanner::GetDeviceInfo (const ULWord inIndexNum, NTV2DeviceInfo & outDeviceInfo, const bool inRescan)
159 {
160  AJAAutoLock tmpLock(&sDevInfoListLock);
161  if (inRescan)
162  ScanHardware();
163 
164  for (NTV2DeviceInfoListConstIter iter(sDevInfoList.begin()); iter != sDevInfoList.end(); ++iter)
165  if (iter->deviceIndex == inIndexNum)
166  {outDeviceInfo = *iter; return true;} // Found!
167  return false; // No devices with this index number
168 }
169 
170 bool CNTV2DeviceScanner::GetDeviceInfoForSerial (const string & inSerialNum, NTV2DeviceInfo & outDeviceInfo, const bool inRescan)
171 {
172  AJAAutoLock tmpLock(&sDevInfoListLock);
173  if (inRescan)
174  ScanHardware();
175 
176  for (NTV2DeviceInfoListConstIter iter(sDevInfoList.begin()); iter != sDevInfoList.end(); ++iter)
177  if (iter->serialNumber == inSerialNum)
178  {outDeviceInfo = *iter; return true;} // Found!
179  return false; // No devices with this serial number
180 }
181 
182 bool CNTV2DeviceScanner::GetDeviceInfoForModel (const string & inModelName, NTV2DeviceInfo & outDeviceInfo, const bool inRescan)
183 {
184  AJAAutoLock tmpLock(&sDevInfoListLock);
185  if (inRescan)
186  ScanHardware();
187 
188  string nameSubString(inModelName); aja::lower(nameSubString);
189  for (NTV2DeviceInfoListConstIter iter(sDevInfoList.begin()); iter != sDevInfoList.end(); ++iter)
190  {
191  string devName(iter->deviceIdentifier); aja::lower(devName);
192  if (devName.find(nameSubString) != string::npos)
193  {outDeviceInfo = *iter; return true;} // Found!
194  }
195  if (nameSubString == "io4kplus") // special case Io4K+ / DNXIV
196  { // Io4K+ == DNXIV...
197  nameSubString = "avid dnxiv";
198  for (NTV2DeviceInfoListConstIter iter(sDevInfoList.begin()); iter != sDevInfoList.end(); ++iter)
199  {
200  string devName(iter->deviceIdentifier); aja::lower(devName);
201  if (devName.find(nameSubString) != string::npos)
202  {outDeviceInfo = *iter; return true;} // Found!
203  }
204  }
205  return false; // No devices with this model name
206 }
207 
208 bool CNTV2DeviceScanner::GetDeviceInfoForID (const NTV2DeviceID inID, NTV2DeviceInfo & outDeviceInfo, const bool inRescan)
209 {
210  AJAAutoLock tmpLock(&sDevInfoListLock);
211  if (inRescan)
212  ScanHardware();
213 
214  for (NTV2DeviceInfoListConstIter iter(sDevInfoList.begin()); iter != sDevInfoList.end(); ++iter)
215  if (iter->deviceID == inID)
216  {outDeviceInfo = *iter; return true;} // Found!
217  return false; // No devices with this device ID
218 }
219 
220 bool CNTV2DeviceScanner::GetDeviceAtIndex (const ULWord inDeviceIndexNumber, CNTV2Card & outDevice)
221 {
222  outDevice.Close();
223  AJAAutoLock tmpLock(&sDevInfoListLock);
224  ScanHardware();
225  for (NTV2DeviceInfoListConstIter iter(sDevInfoList.begin()); iter != sDevInfoList.end(); ++iter)
226  if (iter->deviceIndex == inDeviceIndexNumber)
227  {
228  if (iter->isVirtualDevice)
229  return outDevice.Open(iter->vdevUrl);
230  else
231  return outDevice.Open(UWord(inDeviceIndexNumber));
232  }
233  return false; // No devices with this index number
234 
235 } // GetDeviceAtIndex
236 
237 
239 {
240  outDevice.Close();
241  AJAAutoLock tmpLock(&sDevInfoListLock);
242  ScanHardware();
243  for (size_t ndx(0); ndx < sDevInfoList.size(); ndx++)
244  if (sDevInfoList.at(ndx).deviceID == inDeviceID)
245  {
246  if (sDevInfoList.at(ndx).isVirtualDevice)
247  return outDevice.Open(sDevInfoList.at(ndx).vdevUrl);
248  else
249  return outDevice.Open(UWord(ndx));
250  }
251  return false; // Not found
252 
253 } // GetFirstDeviceWithID
254 
255 
256 bool CNTV2DeviceScanner::GetFirstDeviceWithName (const string & inNameSubString, CNTV2Card & outDevice)
257 {
258  outDevice.Close();
259  AJAAutoLock tmpLock(&sDevInfoListLock);
260  ScanHardware();
261  string nameSubString(inNameSubString); aja::lower(nameSubString);
262  for (size_t ndx(0); ndx < sDevInfoList.size(); ndx++)
263  {
264  string deviceName(sDevInfoList.at(ndx).deviceIdentifier); aja::lower(deviceName);
265  if (deviceName.find(nameSubString) != string::npos)
266  {
267  if (sDevInfoList.at(ndx).isVirtualDevice)
268  {
269  bool ok (outDevice.Open(sDevInfoList.at(ndx).vdevUrl));
270  if (ok)
271  outDevice.setDeviceIndexNumber(UWord(sDevInfoList.at(ndx).deviceIndex)); // Patch _boardNumber
272  return ok;
273  }
274  return outDevice.Open(UWord(ndx));
275  }
276  }
277  if (nameSubString == "io4kplus")
278  { // Io4K+ == DNXIV...
279  nameSubString = "avid dnxiv";
280  for (size_t ndx(0); ndx < sDevInfoList.size(); ndx++)
281  {
282  string deviceName(sDevInfoList.at(ndx).deviceIdentifier); aja::lower(deviceName);
283  if (deviceName.find(nameSubString) != string::npos)
284  {
285  if (sDevInfoList.at(ndx).isVirtualDevice)
286  {
287  bool ok (outDevice.Open(sDevInfoList.at(ndx).vdevUrl));
288  if (ok)
289  outDevice.setDeviceIndexNumber(UWord(sDevInfoList.at(ndx).deviceIndex)); // Patch _boardNumber
290  return ok;
291  }
292  return outDevice.Open(UWord(ndx));
293  }
294  }
295  }
296  return false; // Not found
297 
298 } // GetFirstDeviceWithName
299 
300 bool CNTV2DeviceScanner::GetVirtualDeviceWithName (const string & inNameString, CNTV2Card & outDevice, const bool inRescan)
301 {
302  outDevice.Close();
303  AJAAutoLock tmpLock(&sDevInfoListLock);
304  if (inRescan)
305  ScanHardware();
306  string nameString(inNameString); aja::lower(nameString);
307  for (size_t ndx(0); ndx < sDevInfoList.size(); ndx++)
308  {
309  if (!sDevInfoList.at(ndx).isVirtualDevice)
310  continue;
311  string deviceName(sDevInfoList.at(ndx).vdevName); aja::lower(deviceName);
312  if (deviceName == nameString)
313  {
314  bool ok (outDevice.Open(sDevInfoList.at(ndx).vdevUrl));
315  if (ok)
316  outDevice.setDeviceIndexNumber(UWord(sDevInfoList.at(ndx).deviceIndex)); // Patch _boardNumber
317  return ok;
318  }
319  }
320  return false; // Not found
321 }
322 
323 bool CNTV2DeviceScanner::GetFirstDeviceWithSerial (const string & inSerialStr, CNTV2Card & outDevice)
324 {
325  outDevice.Close();
326  AJAAutoLock tmpLock(&sDevInfoListLock);
327  ScanHardware();
328  string searchSerialStr(inSerialStr); aja::lower(searchSerialStr);
329  for (size_t ndx(0); ndx < sDevInfoList.size(); ndx++)
330  {
331  string ser(sDevInfoList.at(ndx).serialNumber); aja::lower(ser);
332  if (ser.find(searchSerialStr) != string::npos)
333  {
334  if (sDevInfoList.at(ndx).isVirtualDevice)
335  return outDevice.Open(sDevInfoList.at(ndx).vdevUrl);
336  else
337  return outDevice.Open(UWord(ndx));
338  }
339  }
340  return false;
341 }
342 
343 
344 #if !defined(NTV2_DEPRECATE_17_5)
345 bool CNTV2DeviceScanner::GetDeviceWithSerial (const uint64_t inSerialNumber, CNTV2Card & outDevice)
346 {
347  const string serNumStr(::SerialNum64ToString(inSerialNumber));
348  return GetDeviceWithSerial(serNumStr, outDevice);
349 }
350 #endif // !defined(NTV2_DEPRECATE_17_5)
351 
352 bool CNTV2DeviceScanner::GetDeviceWithSerial (const string & inSerialNumber, CNTV2Card & outDevice)
353 {
354  outDevice.Close();
355  AJAAutoLock tmpLock(&sDevInfoListLock);
356  ScanHardware();
357  for (size_t ndx(0); ndx < sDevInfoList.size(); ndx++)
358  if (sDevInfoList.at(ndx).serialNumber == inSerialNumber)
359  {
360  if (sDevInfoList.at(ndx).isVirtualDevice)
361  return outDevice.Open(sDevInfoList.at(ndx).vdevUrl);
362  else
363  return outDevice.Open(UWord(ndx));
364  }
365  return false;
366 }
367 
368 
369 bool CNTV2DeviceScanner::GetFirstDeviceFromArgument (const string & inArgument, CNTV2Card & outDevice)
370 {
371  outDevice.Close();
372  string arg(inArgument); aja::strip(arg);
373  string larg(arg); aja::lower(larg);
374  if (arg.empty())
375  return false;
376 
377  // Special case: 'LIST' or '?' --- print an enumeration of available devices to stdout, then bail
378  { AJAAutoLock tmpLock(&sDevInfoListLock);
379  ScanHardware();
380  if (larg == "list" || larg == "?")
381  {
382  if (sDevInfoList.empty())
383  cout << "No devices detected" << endl;
384  else
385  cout << DEC(sDevInfoList.size()) << " available " << (sDevInfoList.size() == 1 ? "device:" : "devices:") << endl;
386  for (size_t ndx(0); ndx < sDevInfoList.size(); ndx++)
387  {
388  if (sDevInfoList.at(ndx).isVirtualDevice)
389  {
390  cout << DECN(ndx, 2) << " | " << setw(8) << "virtual";
391  if (!sDevInfoList.at(ndx).vdevName.empty())
392  cout << " | " << setw(10) << sDevInfoList.at(ndx).vdevName;
393  cout << " | " << sDevInfoList.at(ndx).vdevUrl << endl;
394  }
395  else
396  {
397  cout << DECN(ndx, 2) << " | " << setw(8) << "local";
398  const string serNum(sDevInfoList.at(ndx).serialNumber);
399  if (!serNum.empty())
400  cout << " | " << setw(10) << serNum;
401  cout << " | " << setw(16) << ::NTV2DeviceIDToString(sDevInfoList.at(ndx).deviceID);
402  cout << endl;
403  }
404  } // for each device
405  return false;
406  } // if 'list' or '?' specified
407  } // tmpLock scope
408  return outDevice.Open(arg); // Just throw arg "over the wall" and let Open deal with it
409 } // GetFirstDeviceFromArgument
410 
411 
413 { // Name that will find given device via CNTV2DeviceScanner::GetFirstDeviceFromArgument
414  if (!inDevice.IsOpen())
415  return string();
416  // Nub address 1st...
417  if (!inDevice.GetHostName().empty() && inDevice.IsRemote())
418  return inDevice.GetHostName(); // Nub host/device
419 
420  // Serial number 2nd...
421  string str;
422  if (inDevice.GetSerialNumberString(str))
423  return str;
424 
425  // Model name 3rd...
426  str = ::NTV2DeviceIDToString(inDevice.GetDeviceID(), false);
427  if (!str.empty() && str != "???")
428  return str;
429 
430  // Index number last...
431  ostringstream oss; oss << DEC(inDevice.GetIndexNumber());
432  return oss.str();
433 }
434 
435 
436 ostream & operator << (ostream & inOutStr, const NTV2DeviceInfoList & inList)
437 {
438  for (NTV2DeviceInfoListConstIter iter(inList.begin()); iter != inList.end(); ++iter)
439  inOutStr << " " << *iter;
440  return inOutStr;
441 
442 } // NTV2DeviceInfoList ostream operator <<
443 
444 
446 {
447  const NTV2DeviceInfo & first (*this);
448  size_t diffs (0);
449 
450  // 'memcmp' would be simpler, but because NTV2DeviceInfo has no constructor, the unfilled bytes in
451  // its "boardIdentifier" field are indeterminate, making it worthless for accurate comparisons.
452  // "boardSerialNumber" and boardNumber are the only required comparisons, but I also check boardType,
453  // boardID, and pciSlot for good measure...
454  if (first.deviceID != second.deviceID) diffs++;
455  if (first.deviceIndex != second.deviceIndex) diffs++;
456  if (first.serialNumber != second.serialNumber) diffs++;
457  if (first.pciSlot != second.pciSlot) diffs++;
458 
459  // Needs to be fixed now that deviceIdentifier is a std::string
460  //#if defined (AJA_DEBUG)
461  // if (::strncmp (first.deviceIdentifier.c_str (), second.deviceIdentifier.c_str (), first.deviceIdentifier.length ()))) diffs++;
462  // if (diffs)
463  // {cout << "## DEBUG: " << diffs << " diff(s):" << endl << "#### first ####" << endl << first << "#### second ####" << endl << second << endl;}
464  //#endif // AJA_DEBUG
465 
466  return diffs ? false : true;
467 
468 } // equality operator
469 
471 {
472  deviceID = DEVICE_ID_INVALID;
473  deviceIndex = 0;
474  pciSlot = 0;
475  deviceSerialNumber = 0;
476  serialNumber = "";
477  numVidInputs = 0;
478  numVidOutputs = 0;
479  numAnlgVidInputs = 0;
480  numAnlgVidOutputs = 0;
481  numHDMIVidInputs = 0;
482  numHDMIVidOutputs = 0;
483  numInputConverters = 0;
484  numOutputConverters = 0;
485  numUpConverters = 0;
486  numDownConverters = 0;
487  downConverterDelay = 0;
488  isoConvertSupport = false;
489  rateConvertSupport = false;
490  dvcproHDSupport = false;
491  qrezSupport = false;
492  hdvSupport = false;
493  quarterExpandSupport = false;
494  vidProcSupport = false;
495  dualLinkSupport = false;
496  colorCorrectionSupport = false;
497  programmableCSCSupport = false;
498  rgbAlphaOutputSupport = false;
499  breakoutBoxSupport = false;
500  procAmpSupport = false;
501  has2KSupport = false;
502  has4KSupport = false;
503  has8KSupport = false;
504  has3GLevelConversion = false;
505  proResSupport = false;
506  sdi3GSupport = false;
507  sdi12GSupport = false;
508  ipSupport = false;
509  biDirectionalSDI = false;
510  ltcInSupport = false;
511  ltcOutSupport = false;
512  ltcInOnRefPort = false;
513  stereoOutSupport = false;
514  stereoInSupport = false;
515  multiFormat = false;
516  numAudioStreams = 0;
517  numAnalogAudioInputChannels = 0;
518  numAESAudioInputChannels = 0;
519  numEmbeddedAudioInputChannels = 0;
520  numHDMIAudioInputChannels = 0;
521  numAnalogAudioOutputChannels = 0;
522  numAESAudioOutputChannels = 0;
523  numEmbeddedAudioOutputChannels = 0;
524  numHDMIAudioOutputChannels = 0;
525  numDMAEngines = 0;
526  numSerialPorts = 0;
527  pingLED = 0;
528  deviceIdentifier.clear();
529  audioSampleRateList.clear();
530  audioNumChannelsList.clear();
531  audioBitsPerSampleList.clear();
532  audioInSourceList.clear();
533  audioOutSourceList.clear();
534 }
535 
537 {
538  if (&info != this)
539  *this = info;
540 }
541 
542 
544  const NTV2DeviceInfoList & inNewList,
545  NTV2DeviceInfoList & outBoardsAdded,
546  NTV2DeviceInfoList & outBoardsRemoved)
547 {
548  NTV2DeviceInfoListConstIter oldIter (inOldList.begin ());
549  NTV2DeviceInfoListConstIter newIter (inNewList.begin ());
550 
551  outBoardsAdded.clear ();
552  outBoardsRemoved.clear ();
553 
554  while (true)
555  {
556  if (oldIter == inOldList.end () && newIter == inNewList.end ())
557  break; // Done -- exit
558 
559  if (oldIter != inOldList.end () && newIter != inNewList.end ())
560  {
561  const NTV2DeviceInfo & oldInfo (*oldIter), newInfo (*newIter);
562 
563  if (oldInfo != newInfo)
564  {
565  // Out with the old...
566  outBoardsRemoved.push_back (oldInfo);
567 
568  // In with the new...
569  if (newInfo.deviceID && newInfo.deviceID != NTV2DeviceID(0xFFFFFFFF))
570  outBoardsAdded.push_back (newInfo);
571  } // if mismatch
572 
573  ++oldIter;
574  ++newIter;
575  continue; // Move along
576 
577  } // if both valid
578 
579  if (oldIter != inOldList.end () && newIter == inNewList.end ())
580  {
581  outBoardsRemoved.push_back (*oldIter);
582  ++oldIter;
583  continue; // Move along
584  } // old is valid, new is not valid
585 
586  if (oldIter == inOldList.end () && newIter != inNewList.end ())
587  {
588  if (newIter->deviceID && newIter->deviceID != NTV2DeviceID(0xFFFFFFFF))
589  outBoardsAdded.push_back (*newIter);
590  ++newIter;
591  continue; // Move along
592  } // old is not valid, new is valid
593 
594  NTV2_ASSERT(false && "should never get here");
595 
596  } // loop til break
597 
598  // Return 'true' if there were any changes...
599  return !outBoardsAdded.empty () || !outBoardsRemoved.empty ();
600 
601 } // CompareDeviceInfoLists
602 
603 
604 ostream & operator << (ostream & inOutStr, const NTV2AudioSampleRateList & inList)
605 {
606  for (NTV2AudioSampleRateListConstIter iter (inList.begin ()); iter != inList.end (); ++iter)
607  inOutStr << " " << *iter;
608 
609  return inOutStr;
610 }
611 
612 
613 ostream & operator << (ostream & inOutStr, const NTV2AudioChannelsPerFrameList & inList)
614 {
615  for (NTV2AudioChannelsPerFrameListConstIter iter (inList.begin ()); iter != inList.end (); ++iter)
616  inOutStr << " " << *iter;
617 
618  return inOutStr;
619 }
620 
621 
622 ostream & operator << (ostream & inOutStr, const NTV2AudioSourceList & inList)
623 {
624  for (NTV2AudioSourceListConstIter iter(inList.begin()); iter != inList.end(); ++iter)
625  switch (*iter) // AudioSourceEnum
626  {
627  case kSourceSDI: return inOutStr << " SDI";
628  case kSourceAES: return inOutStr << " AES";
629  case kSourceADAT: return inOutStr << " ADAT";
630  case kSourceAnalog: return inOutStr << " Analog";
631  case kSourceNone: return inOutStr << " None";
632  case kSourceAll: return inOutStr << " All";
633  }
634  return inOutStr << " ???";
635 }
636 
637 
638 ostream & operator << (ostream & inOutStr, const NTV2AudioBitsPerSampleList & inList)
639 {
640  for (NTV2AudioBitsPerSampleListConstIter iter (inList.begin ()); iter != inList.end (); ++iter)
641  inOutStr << " " << *iter;
642 
643  return inOutStr;
644 }
645 
646 
647 ostream & operator << (ostream & inOutStr, const NTV2DeviceInfo & inInfo)
648 {
649  inOutStr << "Device Info for '" << inInfo.deviceIdentifier << "'" << endl
650  << " Device Index Number: " << inInfo.deviceIndex << endl
651  << " Device ID: 0x" << hex << inInfo.deviceID << dec << endl
652  << " Serial Number: " << inInfo.serialNumber << endl
653  << " PCI Slot: 0x" << hex << inInfo.pciSlot << dec << endl
654  << " Video Inputs: " << inInfo.numVidInputs << endl
655  << " Video Outputs: " << inInfo.numVidOutputs << endl
656  #if defined (_DEBUG)
657  << " Analog Video Inputs: " << inInfo.numAnlgVidInputs << endl
658  << " Analog Video Outputs: " << inInfo.numAnlgVidOutputs << endl
659  << " HDMI Video Inputs: " << inInfo.numHDMIVidInputs << endl
660  << " HDMI Video Outputs: " << inInfo.numHDMIVidOutputs << endl
661  << " Input Converters: " << inInfo.numInputConverters << endl
662  << " Output Converters: " << inInfo.numOutputConverters << endl
663  << " Up Converters: " << inInfo.numUpConverters << endl
664  << " Down Converters: " << inInfo.numDownConverters << endl
665  << " Down Converter Delay: " << inInfo.downConverterDelay << endl
666  << " DVCProHD: " << (inInfo.dvcproHDSupport ? "Y" : "N") << endl
667  << " Qrez: " << (inInfo.qrezSupport ? "Y" : "N") << endl
668  << " HDV: " << (inInfo.hdvSupport ? "Y" : "N") << endl
669  << " Quarter Expand: " << (inInfo.quarterExpandSupport ? "Y" : "N") << endl
670  << " ISO Convert: " << (inInfo.isoConvertSupport ? "Y" : "N") << endl
671  << " Rate Convert: " << (inInfo.rateConvertSupport ? "Y" : "N") << endl
672  << " VidProc: " << (inInfo.vidProcSupport ? "Y" : "N") << endl
673  << " Dual-Link: " << (inInfo.dualLinkSupport ? "Y" : "N") << endl
674  << " Color-Correction: " << (inInfo.colorCorrectionSupport ? "Y" : "N") << endl
675  << " Programmable CSC: " << (inInfo.programmableCSCSupport ? "Y" : "N") << endl
676  << " RGB Alpha Output: " << (inInfo.rgbAlphaOutputSupport ? "Y" : "N") << endl
677  << " Breakout Box: " << (inInfo.breakoutBoxSupport ? "Y" : "N") << endl
678  << " ProcAmp: " << (inInfo.procAmpSupport ? "Y" : "N") << endl
679  << " 2K: " << (inInfo.has2KSupport ? "Y" : "N") << endl
680  << " 4K: " << (inInfo.has4KSupport ? "Y" : "N") << endl
681  << " 8K: " << (inInfo.has8KSupport ? "Y" : "N") << endl
682  << " 3G Level Conversion: " << (inInfo.has3GLevelConversion ? "Y" : "N") << endl
683  << " ProRes: " << (inInfo.proResSupport ? "Y" : "N") << endl
684  << " SDI 3G: " << (inInfo.sdi3GSupport ? "Y" : "N") << endl
685  << " SDI 12G: " << (inInfo.sdi12GSupport ? "Y" : "N") << endl
686  << " IP: " << (inInfo.ipSupport ? "Y" : "N") << endl
687  << " SDI Bi-Directional: " << (inInfo.biDirectionalSDI ? "Y" : "N") << endl
688  << " LTC In: " << (inInfo.ltcInSupport ? "Y" : "N") << endl
689  << " LTC Out: " << (inInfo.ltcOutSupport ? "Y" : "N") << endl
690  << " LTC In on Ref Port: " << (inInfo.ltcInOnRefPort ? "Y" : "N") << endl
691  << " Stereo Out: " << (inInfo.stereoOutSupport ? "Y" : "N") << endl
692  << " Stereo In: " << (inInfo.stereoInSupport ? "Y" : "N") << endl
693  << " Audio Sample Rates: " << inInfo.audioSampleRateList << endl
694  << " AudioNumChannelsList: " << inInfo.audioNumChannelsList << endl
695  << " AudioBitsPerSampleList: " << inInfo.audioBitsPerSampleList << endl
696  << " AudioInSourceList: " << inInfo.audioInSourceList << endl
697  << " AudioOutSourceList: " << inInfo.audioOutSourceList << endl
698  << " Audio Streams: " << inInfo.numAudioStreams << endl
699  << " Analog Audio Input Channels: " << inInfo.numAnalogAudioInputChannels << endl
700  << " Analog Audio Output Channels: " << inInfo.numAnalogAudioOutputChannels << endl
701  << " AES Audio Input Channels: " << inInfo.numAESAudioInputChannels << endl
702  << " AES Audio Output Channels: " << inInfo.numAESAudioOutputChannels << endl
703  << " Embedded Audio Input Channels: " << inInfo.numEmbeddedAudioInputChannels << endl
704  << " Embedded Audio Output Channels: " << inInfo.numEmbeddedAudioOutputChannels << endl
705  << " HDMI Audio Input Channels: " << inInfo.numHDMIAudioInputChannels << endl
706  << " HDMI Audio Output Channels: " << inInfo.numHDMIAudioOutputChannels << endl
707  << " DMA Engines: " << inInfo.numDMAEngines << endl
708  << " Serial Ports: " << inInfo.numSerialPorts << endl
709  #endif // AJA_DEBUG
710  << "";
711 
712  return inOutStr;
713 
714 } // NTV2DeviceInfo ostream operator <<
715 
716 
717 ostream & operator << (ostream & inOutStr, const NTV2AudioPhysicalFormat & inFormat)
718 {
719  inOutStr << "AudioPhysicalFormat:" << endl
720  << " boardNumber: " << inFormat.boardNumber << endl
721  << " sampleRate: " << inFormat.sampleRate << endl
722  << " numChannels: " << inFormat.numChannels << endl
723  << " bitsPerSample: " << inFormat.bitsPerSample << endl
724  #if defined (DEBUG) || defined (AJA_DEBUG)
725  << " sourceIn: 0x" << hex << inFormat.sourceIn << dec << endl
726  << " sourceOut: 0x" << hex << inFormat.sourceOut << dec << endl
727  #endif // DEBUG or AJA_DEBUG
728  ;
729 
730  return inOutStr;
731 
732 } // AudioPhysicalFormat ostream operator <<
733 
734 
735 std::ostream & operator << (std::ostream & inOutStr, const NTV2AudioPhysicalFormatList & inList)
736 {
737  for (NTV2AudioPhysicalFormatListConstIter iter (inList.begin ()); iter != inList.end (); ++iter)
738  inOutStr << *iter;
739 
740  return inOutStr;
741 
742 } // AudioPhysicalFormatList ostream operator <<
743 
744 
745 // Private methods
746 
747 void CNTV2DeviceScanner::SetDeviceAttributes (NTV2DeviceInfo & devInfo, CNTV2DriverInterface & dev)
748 {
763  devInfo.hdvSupport = dev.IsSupported(kDeviceCanDoHDV);
780  devInfo.sdi3GSupport = wgtIDs.find(NTV2_Wgt3GSDIOut1) != wgtIDs.end();
782  devInfo.ipSupport = dev.IsSupported(kDeviceCanDoIP);
791  devInfo.procAmpSupport = false;
792 }
793 
794 void CNTV2DeviceScanner::SetAudioAttributes (NTV2DeviceInfo & info, CNTV2DriverInterface & dev)
795 {
796  // Start with empty lists...
797  info.audioSampleRateList.clear();
798  info.audioNumChannelsList.clear();
799  info.audioBitsPerSampleList.clear();
800  info.audioInSourceList.clear();
801  info.audioOutSourceList.clear();
802 
803 
805  {
806  ULWord audioControl;
807  dev.ReadRegister(kRegAud1Control, audioControl);
808 
809  //audioSampleRateList
810  info.audioSampleRateList.push_back(k48KHzSampleRate);
812  info.audioSampleRateList.push_back(k96KHzSampleRate);
813 
814  //audioBitsPerSampleList
816 
817  //audioInSourceList
818  info.audioInSourceList.push_back(kSourceSDI);
819  if (audioControl & BIT(21))
820  info.audioInSourceList.push_back(kSourceAES);
822  info.audioInSourceList.push_back(kSourceAnalog);
823 
824  //audioOutSourceList
825  info.audioOutSourceList.push_back(kSourceAll);
826 
827  //audioNumChannelsList
834 
836  }
837 
846 
847 } // SetAudioAttributes
848 
849 // Back door access to sDevInfoList
850 bool CNTV2DeviceScanner::PatchDeviceInfo (const UWord inDevIndex, CNTV2DriverInterface & dev) // STATIC
851 {
852  AJAAutoLock tmpLock(&sDevInfoListLock);
853  if (inDevIndex >= UWord(sDevInfoList.size()))
854  return false; // Bad index
855  if (!dev.IsOpen())
856  return false; // No device instance
857 
858  NTV2DeviceInfo & devInfo (sDevInfoList.at(inDevIndex));
859  NTV2DeviceID devID (dev.GetDeviceID());
860  if (!devID)
861  return false; // Bad device ID
862  if (devID == DEVICE_ID_INVALID)
863  return false; // Bad device ID
864 
865  if (devInfo.deviceID == devID)
866  return true; // Matching device IDs
867 
868  // Mismatched device IDs -- patch sDevInfoList entry...
869  VDNOTE(dev.GetDescription() << ": patched sDevInfoList[" << DEC(inDevIndex) << "]: device ID changed from '"
870  << ::NTV2DeviceIDToString(devInfo.deviceID) << "' to '"
871  << ::NTV2DeviceIDToString(devID) << "'");
872  devInfo.deviceID = devID;
873  SetDeviceAttributes (devInfo, dev);
874  SetAudioAttributes (devInfo, dev);
875  return true;
876 }
877 
878 bool CNTV2DeviceScanner::GetVDevList (NTV2DeviceInfoList & outVDevList)
879 {
880 #if defined(NTV2_PREVENT_PLUGIN_LOAD)
881  return false; // Plugin loading disabled, therefore no virtual devices
882 #else // else NTV2_PREVENT_PLUGIN_LOAD
883  string vdevPath (::NTV2GetVDevFolderPath());
884  if (vdevPath.empty())
885  return false;
886  ULWord vdIndex (ULWord(outVDevList.size()));
887  NTV2StringList vdevFiles;
888  AJAFileIO::ReadDirectory(vdevPath, "*.vdev", vdevFiles);
889  for (const auto & vdevFile : vdevFiles)
890  {
891  VDDBUG(vdevFile);
892  json vdevJson;
893  {
894  std::ifstream vf(vdevFile);
895  if (!vf.is_open())
896  {VDFAIL("Unable to open '" << vdevFile << "'"); return false;}
897  try
898  {
899  vdevJson = json::parse(vf);
900  }
901  catch (const json::parse_error& e)
902  {
903  VDFAIL("Invalid JSON at byte " << e.byte << " in '" << vdevFile << "': " << e.what() << ", exceptionID " << e.id);
904  return false;
905  }
906  }
907 
908  NTV2DeviceInfo newInfo;
909  newInfo.isVirtualDevice = true;
910  newInfo.deviceIndex = vdIndex;
911  newInfo.deviceID = DEVICE_ID_VKONA;
912  newInfo.deviceIdentifier = "";
913  newInfo.vdevName = "";
914  bool explicitlyDisabled(false);
915 
916  // EXPECTED JSON KEYS:
917  // "urlspec" [required] Specifies urlspec used to load the plugin.
918  // "name" [optional] Specifies a human-readable name for the device.
919  // If not specified, the .vdev file's base name is used instead.
920  // "disabled" [optional] Specify boolean 'true' to explicitly disable the device; 'false' retains device.
921  // If not specified, the device will always be considered enabled.
922  // "serial" [optional] If specified, must be a string containing the device's actual serial number.
923  // "devid" [optional] If specified, must be a string containing the NTV2DeviceID as a hexadecimal value.
924  if (vdevJson.size() > 32)
925  {VDFAIL("File '" << vdevFile << "': more than 32 keys"); continue;}
926  NTV2StringSet keys;
927  for (auto it(vdevJson.cbegin()); it != vdevJson.cend(); ++it)
928  if (keys.find(it.key()) == keys.end())
929  keys.insert(it.key());
931  NTV2StringList goodKeys, badKeys;
932  for (NTV2StringSetConstIter itKey(keys.begin()); itKey != keys.end(); ++itKey)
933  {
934  if (legalKeys.find(*itKey) == legalKeys.end())
935  badKeys.push_back(*itKey);
936  else
937  goodKeys.push_back(*itKey);
938  }
939  if (!badKeys.empty())
940  VDWARN("File '" << vdevFile << "': ignored " << DEC(badKeys.size()) << " unknown key(s): '" << aja::join(badKeys, "', '") << "'");
941  auto urlspecVal (vdevJson[kVDevJSON_URLSpec]), disabledVal (vdevJson[kVDevJSON_Disabled]),
942  serialVal (vdevJson[kVDevJSON_SerialNum]), devIDVal (vdevJson[kVDevJSON_DeviceID]);
943  if (urlspecVal.is_null())
944  {VDFAIL("File '" << vdevFile << "': missing required 'urlspec' parameter"); continue;}
945  if (disabledVal.is_boolean())
946  {
947  NTV2_ASSERT(!disabledVal.is_null());
948  explicitlyDisabled = disabledVal.get<bool>();
949  }
950  else if (!disabledVal.is_null())
951  {VDFAIL("File '" << vdevFile << "': invalid 'disabled' value -- expected boolean 'true' or 'false' value"); continue;}
952  if (explicitlyDisabled)
953  {VDINFO("File '" << vdevFile << "': explicitly 'disabled'"); continue;}
954  if (!serialVal.is_null())
955  {
956  if (!serialVal.is_string())
957  {VDFAIL("File '" << vdevFile << "': invalid 'serial' value -- expected string value"); continue;}
958  newInfo.serialNumber = serialVal.get<string>();
959  aja::strip(newInfo.serialNumber);
961  {VDFAIL("File '" << vdevFile << "': illegal 'serial' value '" << newInfo.serialNumber << "'"); continue;}
962  }
963  if (!devIDVal.is_null())
964  {
965  if (!devIDVal.is_string())
966  {VDFAIL("File '" << vdevFile << "': invalid 'devid' value -- expected string value"); continue;}
967  string id (devIDVal.get<string>());
968  aja::strip(id);
969  if (id.empty())
970  {VDFAIL("File '" << vdevFile << "': empty 'devid' value -- expected non-empty hex string value"); continue;}
971  aja::lower(id);
972  if (!aja::is_legal_hex_number(id, 8))
973  {VDFAIL("File '" << vdevFile << "': empty 'devid' value -- expected 8-hex-digit string value"); continue;}
974  if (id.find("0x") == 0)
975  id.erase(0,2);
976  NTV2DeviceID devid = NTV2DeviceID(aja::stoul(id, nullptr, 16));
977  const NTV2DeviceIDSet legalDevs(::NTV2GetSupportedDevices());
978  if (legalDevs.find(devid) == legalDevs.end())
979  {VDFAIL("File '" << vdevFile << "': 'devid' value 0x" << id << " (" << xHEX0N(devid,8) << ") is unsupported or unknown"); continue;}
980  newInfo.deviceID = devid;
981  }
982  newInfo.vdevUrl = urlspecVal.get<std::string>(); // we have the vdevUrl!
983 
984  NTV2DeviceSpecParser parser (newInfo.vdevUrl); // Check it
985  if (parser.Failed())
986  {VDFAIL("File '" << vdevFile << "': bad 'urlspec': " << newInfo.vdevUrl << "\n" << aja::join(parser.Errors(), "\n")); continue;}
987  if (newInfo.vdevUrl.find("://") == string::npos)
988  newInfo.vdevUrl = parser.Scheme() + "://" + newInfo.vdevUrl; //{VDFAIL("File '" << vdevFile << "': expected URL in 'urlspec': " << newInfo.vdevUrl); continue;}
989 
990  { // URLencode & append these URL params: &vdevfname= &vdevfpath= &vdevname= &vdevbasename=
991  newInfo.vdevUrl += parser.HasQueryParams() ? "&" : "?";
992  newInfo.vdevUrl += kQParamVDevFolderPath "=" + ::PercentEncode(vdevPath);
993  string fName (vdevFile);
994  fName.erase(fName.find(vdevPath), vdevPath.length()+1); // Remove everything up to file name
995  newInfo.vdevUrl += "&" kQParamVDevFileName "=" + ::PercentEncode(fName); // Remember file name
996  fName.erase(fName.length()-5, 5); // Lop off file name extension
997  if (newInfo.vdevName.empty())
998  newInfo.vdevName = fName; // Use file base name
999  newInfo.vdevUrl += "&" kQParamVDevName "=" + ::PercentEncode(newInfo.vdevName); // Remember name
1000  ostringstream oss; oss << DEC(newInfo.deviceIndex);
1001  newInfo.vdevUrl += "&" kQParamVDevIndex "=" + oss.str(); // Remember index number
1002  }
1003  if (!newInfo.vdevName.empty())
1004  { ostringstream oss; oss << newInfo.vdevName << " - " << newInfo.deviceIndex;
1005  newInfo.deviceIdentifier = oss.str();
1006  }
1007 
1008  outVDevList.push_back(newInfo);
1009  vdIndex++; // Now increment the device index number
1010  } // for each vdev file found
1011  return true;
1012 #endif // else NTV2_PREVENT_PLUGIN_LOAD
1013 } // GetVDevList
1014 
1015 bool CNTV2DeviceScanner::GetCP2DevList (NTV2DeviceInfoList & outVDevList)
1016 {
1017 #if defined(NTV2_PREVENT_PLUGIN_LOAD)
1018  return false; // Plugin loading disabled, therefore no virtual devices
1019 #else // else NTV2_PREVENT_PLUGIN_LOAD
1020  string vdevPath;
1022  if (pathInfo.GetValue(AJA_SystemInfoTag_Path_PersistenceStoreUser, vdevPath) != AJA_STATUS_SUCCESS)
1023  return false;
1024  }
1025  vdevPath += "virtualdevices";
1026  ULWord vdIndex = ULWord(outVDevList.size());
1027  NTV2StringList vdevFiles;
1028  AJAFileIO::ReadDirectory(vdevPath, "*.vdev", vdevFiles);
1029  for (const auto & vdevFile : vdevFiles)
1030  {
1031  json vdevJson;
1032  {
1033  std::ifstream vf(vdevFile);
1034  if (!vf.is_open())
1035  {C2FAIL("Unable to open '" << vdevFile << "'"); return false;}
1036  try
1037  {
1038  vdevJson = json::parse(vf);
1039  }
1040  catch (const json::parse_error& e)
1041  {
1042  C2FAIL("Invalid JSON at byte " << e.byte << " in '" << vdevFile << "': " << e.what() << ", exceptionID " << e.id);
1043  return false;
1044  }
1045  }
1046 
1047  NTV2DeviceInfo newVDev;
1048  newVDev.isVirtualDevice = true;
1049  newVDev.deviceIndex = vdIndex++;
1050  newVDev.deviceID = DEVICE_ID_SOFTWARE;
1051  newVDev.deviceIdentifier = "";
1052  newVDev.vdevName = "";
1053 
1054  // EXPECTED JSON KEYS:
1055  // "plugin" [required] Specifies name of plugin to be loaded.
1056  // "name" [optional] Specifies a human-readable name for the device.
1057  // "host" [optional] Specifies host to use in the plugin URL. Defaults to "localhost".
1058  string hostName;
1059  auto pluginVal (vdevJson["plugin"]), nameVal (vdevJson["name"]), hostVal (vdevJson["host"]), urlspecVal (vdevJson["urlspec"]);
1060  if (pluginVal.is_null())
1061  {C2FAIL("File: '" << vdevFile << "' missing required 'plugin' parameter"); continue;}
1062  if (!urlspecVal.is_null())
1063  C2WARN("File: '" << vdevFile << "' 'urlspec' parameter ignored");
1064 
1065  newVDev.vdevUrl = pluginVal.get<std::string>();
1066  if (!nameVal.is_null())
1067  {
1068  ostringstream oss;
1069  oss << nameVal.get<std::string>() << " - " << newVDev.deviceIndex;
1070  newVDev.deviceIdentifier = oss.str();
1071  newVDev.vdevName = nameVal.get<std::string>();
1072  }
1073 
1074  if (!hostVal.is_null())
1075  hostName = hostVal.get<std::string>();
1076  if (hostName.empty())
1077  hostName = "localhost";
1078  newVDev.vdevUrl += "://" + hostName + "/?";
1079 
1080  NTV2StringList params;
1081  for (auto it (vdevJson.begin()); it != vdevJson.end(); ++it)
1082  if (it.key() != "plugin" && it.key() != "name" && it.key() != "host")
1083  {
1084  auto paramValStr = to_string(it.value());
1085  aja::strip(paramValStr, "\"");
1086  params.push_back(it.key() + "=" + ::PercentEncode(paramValStr));
1087  }
1088 
1089  if (!newVDev.deviceIdentifier.empty())
1090  params.push_back("displayname=" + ::PercentEncode(newVDev.deviceIdentifier));
1091  const string queryStr(aja::join(params, "&"));
1092  if (!queryStr.empty())
1093  newVDev.vdevUrl += "?" + queryStr;
1094  outVDevList.push_back(newVDev);
1095  } // for each .vdev file found
1096  return true;
1097 #endif // else NTV2_PREVENT_PLUGIN_LOAD
1098 } // GetCP2DeviceList
bool programmableCSCSupport
Programmable color space converter?
#define VDINFO(__x__)
nlohmann::json json
The number of input converter widgets on the device.
virtual bool IsSupported(const NTV2BoolParamID inParamID)
#define C2WARN(__x__)
True if device can handle 2Kx1556 (film) video.
static bool GetFirstDeviceWithID(const NTV2DeviceID inDeviceID, CNTV2Card &outDevice)
Rescans the host, and returns an open CNTV2Card instance for the first AJA device found on the host t...
#define kQParamVDevIndex
Device index number for .vdev virtual device.
Definition: ntv2nubaccess.h:46
True if device supports 3D video output over dual-stream SDI.
Declares the AJALock class.
bool ipSupport
Supports IP IO?
The number of SDI-embedded input audio channels supported by the device.
True if audio system(s) support 2 or more audio channels.
The number of analog video outputs on the device.
UWord numAnalogAudioInputChannels
Total number of analog audio input channels.
True if device can do ISO conversion.
UWord numAnalogAudioOutputChannels
Total number of analog audio output channels.
static bool GetFirstDeviceWithSerial(const std::string &inSerialStr, CNTV2Card &outDevice)
Rescans the host, and returns an open CNTV2Card instance for the first AJA device whose serial number...
static bool GetVirtualDeviceWithName(const std::string &inNameString, CNTV2Card &outDevice, const bool inRescan=(!(0)))
Rescans the host, and returns an open CNTV2Card instance for the first virtual device with a matching...
static bool GetDeviceInfoForModel(const std::string &inModelName, NTV2DeviceInfo &outDeviceInfo, const bool inRescan=(0))
NTV2DeviceIDSet NTV2GetSupportedDevices(const NTV2DeviceKinds inKinds=NTV2_DEVICEKIND_ALL)
Returns an NTV2DeviceIDSet of devices supported by the SDK.
Definition: ntv2utils.cpp:7397
bool is_legal_hex_number(const std::string &inStr, size_t inMaxLength)
Definition: common.cpp:574
#define VDWARN(__x__)
I interrogate and control an AJA video/audio capture/playout device.
Definition: ntv2card.h:28
UWord numOutputConverters
Total number of output converters.
True if device can squeeze/stretch between 1920x1080/1280x1080 and 1280x720/960x720.
#define BIT(_x_)
Definition: ajatypes.h:496
UWord numAnlgVidInputs
Total number of analog video inputs.
True if device can do 3G level B to 3G level A conversion.
True if device supports an AJA breakout box.
The number of analog LTC outputs on the device.
The number of AES/EBU audio output channels on the device.
NTV2StringSet::const_iterator NTV2StringSetConstIter
Declares the AJADebug class.
NTV2AudioPhysicalFormatList::const_iterator NTV2AudioPhysicalFormatListConstIter
virtual UWord GetIndexNumber(void) const
static bool IsLegalDecimalNumber(const std::string &inStr, const size_t maxLen=2)
The number of independent Audio Systems on the device.
void setDeviceIndexNumber(const UWord num)
bool ltcInOnRefPort
Supports LTC on reference input?
#define kQParamVDevName
Base name of .vdev file.
Definition: ntv2nubaccess.h:44
static AJAStatus ReadDirectory(const std::string &directory, const std::string &filePattern, std::vector< std::string > &fileContainer)
Definition: file_io.cpp:805
UWord numVidOutputs
Total number of video outputs – analog, digital, whatever.
virtual bool Close(void)
Closes me, releasing host resources that may have been allocated in a previous Open call...
std::string NTV2GetVDevFolderPath(const bool inAddTrailingPathDelim=false)
Definition: ntv2utils.cpp:7383
static bool PatchDeviceInfo(const UWord inDevIndex, CNTV2DriverInterface &dev)
One-stop shop for parsing device specifications. (New in SDK 16.3) I do very little in the way of val...
virtual bool Open(const UWord inDeviceIndex)
Opens a local/physical AJA device so it can be monitored/controlled.
static bool DeviceIDPresent(const NTV2DeviceID inDeviceID, const bool inRescan=(0))
True if device has SFP connectors.
UWord numEmbeddedAudioInputChannels
Total number of embedded (SDI) audio input channels.
Definition: lock.h:28
True if device can do video processing.
bool has2KSupport
Supports 2K formats?
Definition: json.hpp:5362
static bool GetDeviceInfoForSerial(const std::string &inSerialNum, NTV2DeviceInfo &outDeviceInfo, const bool inRescan=(0))
True if device can handle QRez.
#define false
uint32_t ULWord
Definition: ajatypes.h:236
The number of DMA engines on the device.
UWord numHDMIAudioInputChannels
Total number of HDMI audio input channels.
ULWord pciSlot
PCI slot (if applicable and/or known)
#define kQParamVDevFolderPath
Path to folder containing .vdev files.
Definition: ntv2nubaccess.h:43
#define NTV2_ASSERT(_expr_)
Definition: ajatypes.h:489
The number of SDI video outputs on the device.
unsigned long stoul(const std::string &str, std::size_t *idx, int base)
Definition: common.cpp:143
virtual bool IsRemote(void) const
NTV2AudioSampleRateList audioSampleRateList
My supported audio sample rates.
NTV2AudioSourceList audioInSourceList
My supported audio input sources (AES, ADAT, etc.)
True if device can read LTC (Linear TimeCode) from its reference input.
UWord numAnlgVidOutputs
Total number of analog video outputs.
True if device SDI connectors are bi-directional.
std::string PercentEncode(const std::string &inStr)
static AJALock sDevInfoListLock
static bool GetFirstDeviceWithName(const std::string &inNameSubString, CNTV2Card &outDevice)
Rescans the host, and returns an open CNTV2Card instance for the first AJA device whose device identi...
UWord numDMAEngines
Total number of DMA engines.
bool ltcOutSupport
Supports LTC output?
bool proResSupport
Supports ProRes?
I&#39;m the base class that undergirds the platform-specific derived classes (from which CNTV2Card is ult...
True if device has CSCs capable of splitting the key (alpha) and YCbCr (fill) from RGB frame buffers ...
True if device has at least one programmable color space converter widget.
True if device supports 3D video input over dual-stream SDI.
bool breakoutBoxSupport
Can support a breakout box?
NTV2DeviceID
Identifies a specific AJA NTV2 device model number. The NTV2DeviceID is actually the PROM part number...
Definition: ntv2enums.h:20
The highest bit number of the LED bits in the Global Control Register on the device.
std::vector< AudioBitsPerSampleEnum > NTV2AudioBitsPerSampleList
UWord numHDMIVidOutputs
Total number of HDMI outputs.
True if device can handle quarter-sized frames (pixel-halving and line-halving during input...
bool ltcInSupport
Accepts LTC input?
virtual bool IsOpen(void) const
CNTV2DeviceScanner(const bool inScanNow=(!(0)))
std::string to_string(bool val)
Definition: common.cpp:180
Invalid or "not found".
Definition: ntv2enums.h:101
static bool GetFirstDeviceFromArgument(const std::string &inArgument, CNTV2Card &outDevice)
Rescans the host, and returns an open CNTV2Card instance for the AJA device that matches a command li...
NTV2AudioChannelsPerFrameList::const_iterator NTV2AudioChannelsPerFrameListConstIter
std::set< std::string > NTV2StringSet
#define VDDBUG(__x__)
NTV2AudioBitsPerSampleList::const_iterator NTV2AudioBitsPerSampleListConstIter
#define kVDevJSON_SerialNum
Running VDEV&#39;s serial number (expects string value)
Definition: ntv2nubaccess.h:51
static bool GetDeviceWithSerial(const std::string &inSerialNumber, CNTV2Card &outDevice)
Rescans the host, and returns an open CNTV2Card instance for the first AJA device whose serial number...
True if device can squeeze/stretch between 1920x1080 and 1440x1080.
bool has4KSupport
Supports 4K formats?
Declares the AJAFileIO class.
virtual bool GetSerialNumberString(std::string &outSerialNumberString)
Answers with a string that contains my human-readable serial number.
Definition: ntv2card.cpp:229
std::string serialNumber
Unique device serial number (new in SDK 17.5)
virtual bool ReadRegister(const ULWord inRegNum, ULWord &outValue, const ULWord inMask=0xFFFFFFFF, const ULWord inShift=0)
Reads all or part of the 32-bit contents of a specific register (real or virtual) on the AJA device...
std::vector< NTV2DeviceInfo > NTV2DeviceInfoList
I am an ordered list of NTV2DeviceInfo structs.
The number of up-converters on the device.
bool is_alpha_numeric(const char inChr)
Definition: common.cpp:521
AudioChannelsPerFrameEnum numChannels
static size_t GetNumDevices(void)
#define VDFAIL(__x__)
#define kVDevJSON_DeviceID
Running VDEV&#39;s device ID (expects string value containing 32-bit hexadecimal value) ...
Definition: ntv2nubaccess.h:52
bool has8KSupport
Supports 8K formats?
static bool IsHexDigit(const char inChr)
bool sdi12GSupport
Supports 12G?
UWord numUpConverters
Total number of up-converters.
std::set< ULWord > ULWordSet
A collection of unique ULWord (uint32_t) values.
Software device that doesn&#39;t emulate one of the above devices.
Definition: ntv2enums.h:84
NTV2DeviceInfoList::const_iterator NTV2DeviceInfoListConstIter
bool colorCorrectionSupport
Supports color correction?
#define kVDevJSON_URLSpec
URLspec for VDEV (expects string value)
Definition: ntv2nubaccess.h:49
static NTV2DeviceInfoList GetDeviceInfoList(void)
True if device has 12G SDI connectors.
#define kQParamVDevFileName
.vdev file name (with extension)
Definition: ntv2nubaccess.h:45
UWord numAESAudioInputChannels
Total number of AES audio input channels.
static bool CompareDeviceInfoLists(const NTV2DeviceInfoList &inOldList, const NTV2DeviceInfoList &inNewList, NTV2DeviceInfoList &outDevicesAdded, NTV2DeviceInfoList &outDevicesRemoved)
True if audio system(s) support 6 or more audio channels.
virtual NTV2DeviceID GetDeviceID(void)
bool biDirectionalSDI
Supports Bi-directional SDI.
static bool GetDeviceAtIndex(const ULWord inDeviceIndexNumber, CNTV2Card &outDevice)
Rescans the host, and returns an open CNTV2Card instance for the AJA device having the given zero-bas...
uint64_t is_legal_hex_serial_number(const std::string &inStr)
Definition: common.cpp:540
std::vector< AudioChannelsPerFrameEnum > NTV2AudioChannelsPerFrameList
Declares the CNTV2DeviceScanner class.
virtual std::string GetDescription(void) const
ULWord deviceIndex
Device index number – this will be phased out someday.
The number of HDMI video outputs on the device.
UWord numHDMIVidInputs
Total number of HDMI inputs.
ostream & operator<<(ostream &inOutStr, const NTV2DeviceInfoList &inList)
The number of SDI-embedded output audio channels supported by the device.
std::vector< AudioSampleRateEnum > NTV2AudioSampleRateList
UWord numVidInputs
Total number of video inputs – analog, digital, whatever.
std::string NTV2DeviceIDToString(const NTV2DeviceID inValue, const bool inForRetailDisplay=false)
Definition: ntv2utils.cpp:4608
bool operator==(const NTV2DeviceInfo &rhs) const
True if device supports 10-bit RGB input/output over 2-wire SDI.
std::string & strip(std::string &str, const std::string &ws)
Definition: common.cpp:461
UWord numDownConverters
Total number of down-converters.
#define kVDevJSON_Disabled
VDEV is disabled if value is true (expects boolean value)
Definition: ntv2nubaccess.h:50
The number of analog audio output channels on the device.
NTV2AudioChannelsPerFrameList audioNumChannelsList
My supported number of audio channels per frame.
#define DEC(__x__)
static bool GetDeviceInfo(const ULWord inDeviceIndexNumber, NTV2DeviceInfo &outDeviceInfo, const bool inRescan=(0))
The number of analog LTC inputs on the device.
The number of analog video inputs on the device.
Declares numerous NTV2 utility functions.
UWord numSerialPorts
Total number of serial ports.
virtual ULWord GetNumSupported(const NTV2NumericParamID inParamID)
Declares the AJASystemInfo class.
static void ScanHardware(void)
The number of output converter widgets on the device.
True if device has any analog inputs or outputs.
#define C2FAIL(__x__)
True if the device can handle 4K/UHD video.
The number of RS-422 serial ports on the device.
std::string vdevName
bool is_legal_decimal_number(const std::string &inStr, size_t inMaxLength)
Definition: common.cpp:526
uint16_t UWord
Definition: ajatypes.h:234
bool stereoOutSupport
Supports stereo output?
UWord numAudioStreams
Maximum number of independent audio streams.
static bool GetDeviceInfoForID(const NTV2DeviceID inID, NTV2DeviceInfo &outDeviceInfo, const bool inRescan=(0))
#define VDNOTE(__x__)
static NTV2DeviceInfoList sDevInfoList
#define xHEX0N(__x__, __n__)
The number of HDMI audio input channels on the device.
static bool IsAlphaNumeric(const char inStr)
static bool IsLegalSerialNumber(const std::string &inStr)
static std::string GetDeviceRefName(CNTV2Card &inDevice)
virtual ULWordSet GetSupportedItems(const NTV2EnumsID inEnumsID)
UWord numInputConverters
Total number of input converters.
True if device has any LUTs.
AudioBitsPerSampleEnum bitsPerSample
The down-converter delay on the device.
bool dualLinkSupport
Supports dual-link?
static uint64_t IsLegalHexSerialNumber(const std::string &inStr)
std::string vdevUrl
static bool IsDecimalDigit(const char inChr)
NTV2AudioSampleRateList::const_iterator NTV2AudioSampleRateListConstIter
Private include file for all ajabase sources.
UWord numEmbeddedAudioOutputChannels
Total number of embedded (SDI) audio output channels.
The number of analog audio input channels on the device.
True if audio system(s) support 8 or more audio channels.
True if device has a microphone input connector.
std::string SerialNum64ToString(const uint64_t &inSerNum)
Definition: ntv2utils.cpp:7893
std::string join(const std::vector< std::string > &parts, const std::string &delim)
Definition: common.cpp:468
std::set< NTV2DeviceID > NTV2DeviceIDSet
A set of NTV2DeviceIDs.
Definition: ntv2utils.h:1098
bool stereoInSupport
Supports stereo input?
bool rgbAlphaOutputSupport
Supports RGB alpha channel?
UWord numHDMIAudioOutputChannels
Total number of HDMI audio output channels.
std::vector< std::string > NTV2StringList
NTV2AudioBitsPerSampleList audioBitsPerSampleList
My supported audio bits-per-sample.
NTV2DeviceID deviceID
Device ID/species (e.g., DEVICE_ID_KONA3G, DEVICE_ID_IOXT, etc.)
std::vector< NTV2AudioPhysicalFormat > NTV2AudioPhysicalFormatList
I am an ordered list of NTV2AudioPhysicalFormat structs.
std::string & lower(std::string &str)
Definition: common.cpp:436
#define DECN(__x__, __n__)
Identifies the NTV2AudioWidgetID enumerated type.
std::vector< AudioSourceEnum > NTV2AudioSourceList
True if device supports 8K video formats.
bool has3GLevelConversion
Supports 3G Level Conversion?
The number of HDMI audio output channels on the device.
The number of SDI video inputs on the device.
bool multiFormat
Supports multiple video formats?
AudioSampleRateEnum sampleRate
True if device can can accommodate Apple ProRes-compressed video in its frame buffers.
virtual std::string GetHostName(void) const
NTV2AudioSourceList::const_iterator NTV2AudioSourceListConstIter
Declares device capability functions.
NTV2AudioSourceList audioOutSourceList
My supported audio output destinations (AES, etc.)
The number of AES/EBU audio input channels on the device.
The number of down-converters on the device.
UWord numAESAudioOutputChannels
Total number of AES audio output channels.
True if Audio System(s) support a 96kHz sample rate.
bool sdi3GSupport
Supports 3G?
std::string deviceIdentifier
Device name as seen in Control Panel, Watcher, Cables, etc.
True if device can do frame rate conversion.
The number of HDMI video inputs on the device.
True if device can simultaneously handle different video formats on more than one SDI input or output...