AJA NTV2 SDK  18.1.0.2149
NTV2 SDK 18.1.0.2149
ntv2signalrouter.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
7 #include "ntv2signalrouter.h"
8 #include "ntv2routingexpert.h"
9 #include "ntv2debug.h"
10 #include "ntv2utils.h"
11 #include "ntv2devicefeatures.hh"
12 #include "ntv2registerexpert.h"
13 #include "ajabase/system/debug.h"
14 #include "ajabase/common/common.h"
15 #include <memory.h>
16 #include <stdio.h>
17 #include <assert.h>
18 #include <algorithm>
19 
20 using namespace std;
21 
22 // Logging helpers
23 #define HEX16(__x__) "0x" << hex << setw(16) << setfill('0') << uint64_t(__x__) << dec
24 #define INSTP(_p_) HEX16(uint64_t(_p_))
25 #define SRiFAIL(__x__) AJA_sERROR (AJA_DebugUnit_RoutingGeneric, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
26 #define SRiWARN(__x__) AJA_sWARNING(AJA_DebugUnit_RoutingGeneric, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
27 #define SRiNOTE(__x__) AJA_sNOTICE (AJA_DebugUnit_RoutingGeneric, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
28 #define SRiINFO(__x__) AJA_sINFO (AJA_DebugUnit_RoutingGeneric, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
29 #define SRiDBG(__x__) AJA_sDEBUG (AJA_DebugUnit_RoutingGeneric, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
30 #define SRFAIL(__x__) AJA_sERROR (AJA_DebugUnit_RoutingGeneric, AJAFUNC << ": " << __x__)
31 #define SRWARN(__x__) AJA_sWARNING(AJA_DebugUnit_RoutingGeneric, AJAFUNC << ": " << __x__)
32 #define SRNOTE(__x__) AJA_sNOTICE (AJA_DebugUnit_RoutingGeneric, AJAFUNC << ": " << __x__)
33 #define SRINFO(__x__) AJA_sINFO (AJA_DebugUnit_RoutingGeneric, AJAFUNC << ": " << __x__)
34 #define SRDBG(__x__) AJA_sDEBUG (AJA_DebugUnit_RoutingGeneric, AJAFUNC << ": " << __x__)
35 
36 static NTV2StringList & Tokenize (const string & inString, NTV2StringList & outTokens, const string & inDelimiters = " ", bool inTrimEmpty = false)
37 {
38  string::size_type pos (0), lastPos (0);
39  outTokens.clear ();
40  while (true)
41  {
42  pos = inString.find_first_of (inDelimiters, lastPos);
43  if (pos == string::npos)
44  {
45  pos = inString.length ();
46  if (pos != lastPos || !inTrimEmpty)
47  outTokens.push_back (NTV2StringList::value_type (inString.data () + lastPos, NTV2StringList::size_type(pos - lastPos)));
48  break;
49  }
50  else
51  {
52  if (pos != lastPos || !inTrimEmpty)
53  outTokens.push_back (NTV2StringList::value_type (inString.data () + lastPos, NTV2StringList::size_type(pos - lastPos)));
54  }
55  lastPos = pos + 1;
56  }
57  return outTokens;
58 }
59 
61 
62 bool CNTV2SignalRouter::AddConnection (const NTV2InputXptID inSignalInput, const NTV2OutputXptID inSignalOutput)
63 {
64  mConnections.insert (NTV2SignalConnection (inSignalInput, inSignalOutput));
65  SRiDBG(NTV2InputCrosspointIDToString(inSignalInput) << ", " << NTV2OutputCrosspointIDToString(inSignalOutput) << ": " << *this);
66  return true;
67 }
68 
69 
70 bool CNTV2SignalRouter::HasInput (const NTV2InputXptID inSignalInput) const
71 {
72  return mConnections.find (inSignalInput) != mConnections.end ();
73 }
74 
75 
77 {
78  NTV2XptConnectionsConstIter it(mConnections.find(inSignalInput));
79  return it != mConnections.end() ? it->second : NTV2_XptBlack;
80 }
81 
82 
83 bool CNTV2SignalRouter::HasConnection (const NTV2InputXptID inSignalInput, const NTV2OutputXptID inSignalOutput) const
84 {
85  NTV2XptConnectionsConstIter iter (mConnections.find (inSignalInput));
86  if (iter == mConnections.end())
87  return false;
88  return iter->second == inSignalOutput;
89 }
90 
91 
92 bool CNTV2SignalRouter::RemoveConnection (const NTV2InputXptID inSignalInput, const NTV2OutputXptID inSignalOutput)
93 {
94  NTV2XptConnectionsIter iter (mConnections.find (inSignalInput));
95  if (iter == mConnections.end())
96  return false; // Not in map
97  if (iter->second != inSignalOutput)
98  return false; // No match
99  mConnections.erase (iter);
100  return true;
101 }
102 
103 
104 static const ULWord sSignalRouterRegMasks[] = { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 };
105 static const ULWord sSignalRouterRegShifts[] = { 0, 8, 16, 24 };
106 
107 
109 {
110  Reset();
111  for (NTV2InputXptIDSetConstIter it(inInputs.begin()); it != inInputs.end(); ++it)
112  {
113  uint32_t regNum(0), maskNdx(0);
115  NTV2RegisterReadsConstIter iter (::FindFirstMatchingRegisterNumber(regNum, inRegReads));
116  if (iter == inRegReads.end())
117  continue;
118 
119  NTV2_ASSERT(iter->registerNumber == regNum);
120  NTV2_ASSERT(iter->registerMask == 0xFFFFFFFF);
121  NTV2_ASSERT(iter->registerShift == 0);
122  NTV2_ASSERT(maskNdx < 4);
123  const uint32_t regValue (iter->registerValue & sSignalRouterRegMasks[maskNdx]);
124  const NTV2OutputXptID outputXpt (NTV2OutputXptID(regValue >> sSignalRouterRegShifts[maskNdx]));
125  if (outputXpt != NTV2_XptBlack)
126  mConnections.insert(NTV2SignalConnection (*it, outputXpt));
127  } // for each NTV2InputXptID
128  return true;
129 }
130 
131 
133 {
134  outRegWrites.clear ();
135 
136  for (NTV2XptConnectionsConstIter iter (mConnections.begin ()); iter != mConnections.end (); ++iter)
137  {
138  const NTV2InputXptID inputXpt(iter->first);
139  const NTV2OutputXptID outputXpt(iter->second);
140  uint32_t regNum(0), ndx(999);
141 
142  if (!CNTV2RegisterExpert::GetCrosspointSelectGroupRegisterInfo (inputXpt, regNum, ndx) || !regNum || ndx > 3)
143  {
144  outRegWrites.clear();
145  return false;
146  }
147 
148  const NTV2RegInfo regInfo (regNum, outputXpt, sSignalRouterRegMasks[ndx], sSignalRouterRegShifts[ndx]);
149  try
150  {
151  outRegWrites.push_back (regInfo);
152  }
153  catch (const bad_alloc &)
154  {
155  outRegWrites.clear ();
156  return false;
157  }
158  }
159  SRiDBG(outRegWrites);
160  return true;
161 }
162 
163 
165  NTV2XptConnections & outChanged, NTV2XptConnections & outMissing) const
166 {
167  outNew.clear(); outChanged.clear(); outMissing.clear();
168  // Check that my connections are also in RHS:
169  for (NTV2XptConnectionsConstIter it(mConnections.begin()); it != mConnections.end(); ++it)
170  {
171  const NTV2SignalConnection & connection (*it);
172  const NTV2InputXptID inputXpt(connection.first);
173  const NTV2OutputXptID outputXpt(connection.second);
174  if (inRHS.HasConnection(inputXpt, outputXpt))
175  ;
176  else if (inRHS.HasInput(inputXpt))
177  outChanged.insert(NTV2Connection(inputXpt, inRHS.GetConnectedOutput(inputXpt))); // Connection changed from this
178  else
179  outNew.insert(connection); // Connection is new in me, not in RHS
180  }
181 
182  // Check that RHS' connections are also in me...
183  const NTV2XptConnections connectionsRHS(inRHS.GetConnections());
184  for (NTV2XptConnectionsConstIter it(connectionsRHS.begin()); it != connectionsRHS.end(); ++it)
185  {
186  const NTV2SignalConnection & connectionRHS (*it);
187  const NTV2InputXptID inputXpt(connectionRHS.first);
188  const NTV2OutputXptID outputXpt(connectionRHS.second);
189  NTV2XptConnectionsConstIter pFind (mConnections.find(inputXpt));
190  if (pFind == mConnections.end()) // If not found in me...
191  outMissing.insert(connectionRHS); // ...in RHS, but missing in me
192  else if (pFind->second != outputXpt) // If output xpt differs...
193  outChanged.insert(connectionRHS); // ...then 'connection' is changed (in RHS, not in me)
194  }
195 
196  return outNew.empty() && outChanged.empty() && outMissing.empty(); // Return true if identical
197 }
198 
199 
200 ostream & CNTV2SignalRouter::Print (ostream & oss, const bool inForRetailDisplay) const
201 {
202  if (inForRetailDisplay)
203  {
204  oss << mConnections.size() << " routing entries:" << endl;
205  for (NTV2XptConnectionsConstIter iter (mConnections.begin()); iter != mConnections.end(); ++iter)
206  oss << ::NTV2InputCrosspointIDToString(iter->first, inForRetailDisplay)
207  << " <== " << ::NTV2OutputCrosspointIDToString(iter->second, inForRetailDisplay) << endl;
208  }
209  else
210  oss << mConnections;
211  return oss;
212 }
213 
214 
215 bool CNTV2SignalRouter::PrintCode (string & outCode, const PrintCodeConfig & inConfig) const
216 {
217  return ToCodeString(outCode, mConnections, inConfig);
218 
219 } // PrintCode
220 
221 
222 bool CNTV2SignalRouter::ToCodeString (string & outCode, const NTV2XptConnections & inConnections,
223  const PrintCodeConfig & inConfig)
224 {
225  ostringstream oss;
226 
227  outCode.clear ();
228 
229  if (inConfig.mShowComments)
230  {
231  oss << inConfig.mPreCommentText << DEC(inConnections.size()) << " routing ";
232  oss << ((inConnections.size () == 1) ? "entry:" : "entries:");
233  oss << inConfig.mPostCommentText << inConfig.mLineBreakText;
234  }
235 
236  if (inConfig.mShowDeclarations)
237  {
238  if (inConfig.mUseRouter)
239  oss << inConfig.mPreClassText << "CNTV2SignalRouter" << inConfig.mPostClassText
240  << "\t"<< inConfig.mPreVariableText << inConfig.mRouterVarName<< inConfig.mPostVariableText;
241  else
242  oss << inConfig.mPreClassText << "CNTV2Card" << inConfig.mPostClassText
243  << "\t" << inConfig.mPreVariableText << inConfig.mDeviceVarName<< inConfig.mPostVariableText;
244  oss << ";" << inConfig.mLineBreakText;
245  }
246 
247  const string varName (inConfig.mUseRouter ? inConfig.mRouterVarName : inConfig.mDeviceVarName);
248  const string variableNameText (inConfig.mPreVariableText + varName + inConfig.mPostVariableText);
249  const string funcName (inConfig.mUseRouter ? "AddConnection" : "Connect");
250  const string functionCallText (inConfig.mPreFunctionText + funcName + inConfig.mPostFunctionText);
251  for (NTV2XptConnectionsConstIter iter (inConnections.begin ()); iter != inConnections.end (); ++iter)
252  {
253  const string inXptStr (inConfig.mPreXptText + ::NTV2InputCrosspointIDToString(iter->first, false) + inConfig.mPostXptText);
254  const string outXptStr (inConfig.mPreXptText + ::NTV2OutputCrosspointIDToString(iter->second, false) + inConfig.mPostXptText);
255 
256  oss << variableNameText << "." << functionCallText << " (" << inXptStr << ", " << outXptStr << ");";
257 
258  if (inConfig.mShowComments)
259  {
260  NTV2XptConnectionsConstIter pNew(inConfig.mNew.find(iter->first));
261  NTV2XptConnectionsConstIter pChanged(inConfig.mChanged.find(iter->first));
262  if (pNew != inConfig.mNew.end() && pNew->second == iter->second)
263  oss << inConfig.mFieldBreakText << inConfig.mPreCommentText << "New" << inConfig.mPostCommentText;
264  else if (pChanged != inConfig.mChanged.end() && pChanged->second != iter->second)
265  oss << inConfig.mFieldBreakText << inConfig.mPreCommentText << "Changed from "
266  << ::NTV2OutputCrosspointIDToString(pChanged->second, false) << inConfig.mPostCommentText;
267  }
268  oss << inConfig.mLineBreakText;
269  } // for each connection
270 
271  if (inConfig.mShowComments)
272  for (NTV2XptConnectionsConstIter pGone(inConfig.mMissing.begin()); pGone != inConfig.mMissing.end(); ++pGone)
273  if (inConnections.find(pGone->first) == inConnections.end())
274  {
275  if (inConfig.mUseRouter)
276  oss << inConfig.mPreCommentText << varName << "." << "RemoveConnection" << " ("
277  << ::NTV2InputCrosspointIDToString(pGone->first, false)
278  << ", " << ::NTV2OutputCrosspointIDToString(pGone->second, false)
279  << ");" << inConfig.mPostCommentText
280  << inConfig.mFieldBreakText << inConfig.mPreCommentText << "Deleted" << inConfig.mPostCommentText
281  << inConfig.mLineBreakText;
282  else
283  oss << inConfig.mPreCommentText << varName << "." << "Disconnect" << " ("
284  << ::NTV2InputCrosspointIDToString(pGone->first, false)
285  << ");" << inConfig.mPostCommentText << inConfig.mFieldBreakText
286  << inConfig.mPreCommentText
287  << "From " << ::NTV2OutputCrosspointIDToString(pGone->second, false)
288  << inConfig.mPostCommentText << inConfig.mLineBreakText;
289  }
290 
291  outCode = oss.str();
292  return true;
293 }
294 
295 
296 bool CNTV2SignalRouter::Initialize (void) // STATIC
297 {
300  return pExpert ? true : false;
301 } // Initialize
302 
303 
304 bool CNTV2SignalRouter::Deinitialize (void) // STATIC
305 {
307 }
308 
309 
310 bool CNTV2SignalRouter::IsInitialized (void) // STATIC
311 {
314  return pExpert ? true : false;
315 }
316 
317 
319 {
322  return pExpert ? pExpert->InputXptToString(inInputXpt) : string();
323 }
324 
325 
327 {
330  return pExpert ? pExpert->OutputXptToString(inOutputXpt) : string();
331 }
332 
333 
335 {
338  return pExpert ? pExpert->StringToInputXpt(inStr) : NTV2_INPUT_CROSSPOINT_INVALID;
339 }
340 
341 
343 {
346  return pExpert ? pExpert->StringToOutputXpt(inStr) : NTV2_OUTPUT_CROSSPOINT_INVALID;
347 }
348 
349 
350 bool CNTV2SignalRouter::GetWidgetIDs (const NTV2DeviceID inDeviceID, NTV2WidgetIDSet & outWidgets) // STATIC
351 {
352  outWidgets.clear();
353  for (NTV2WidgetID widgetID(NTV2WidgetID(NTV2_WIDGET_FIRST)); NTV2_IS_VALID_WIDGET(widgetID); widgetID = NTV2WidgetID(widgetID+1))
354  if (::NTV2DeviceCanDoWidget (inDeviceID, widgetID))
355  outWidgets.insert(widgetID);
356  return !outWidgets.empty();
357 }
358 
359 
360 bool CNTV2SignalRouter::GetWidgetsForInput (const NTV2InputXptID inInputXpt, NTV2WidgetIDSet & outWidgetIDs) // STATIC
361 {
362  outWidgetIDs.clear();
365  return pExpert ? pExpert->GetWidgetsForInput(inInputXpt, outWidgetIDs) : false;
366 }
367 
368 
369 bool CNTV2SignalRouter::GetWidgetForInput (const NTV2InputXptID inInputXpt, NTV2WidgetID & outWidgetID, const NTV2DeviceID inDeviceID) // STATIC
370 {
371  outWidgetID = NTV2_WIDGET_INVALID;
372  NTV2WidgetIDSet wgts;
373  if (!GetWidgetsForInput(inInputXpt, wgts))
374  return false;
375  if (inDeviceID == DEVICE_ID_NOTFOUND)
376  outWidgetID = *(wgts.begin());
377  else
378  for (NTV2WidgetIDSetConstIter it(wgts.begin()); it != wgts.end(); ++it)
379  if (::NTV2DeviceCanDoWidget(inDeviceID, *it))
380  {
381  outWidgetID = *it;
382  break;
383  }
384  return outWidgetID != NTV2_WIDGET_INVALID;
385 }
386 
387 
388 bool CNTV2SignalRouter::GetWidgetsForOutput (const NTV2OutputXptID inOutputXpt, NTV2WidgetIDSet & outWidgetIDs) // STATIC
389 {
390  outWidgetIDs.clear();
393  return pExpert ? pExpert->GetWidgetsForOutput(inOutputXpt, outWidgetIDs) : false;
394 }
395 
396 
397 bool CNTV2SignalRouter::GetWidgetForOutput (const NTV2OutputXptID inOutputXpt, NTV2WidgetID & outWidgetID, const NTV2DeviceID inDeviceID) // STATIC
398 {
399  outWidgetID = NTV2_WIDGET_INVALID;
400  NTV2WidgetIDSet wgts;
401  {
403  if (!GetWidgetsForOutput(inOutputXpt, wgts))
404  return false;
405  }
406  if (inDeviceID == DEVICE_ID_NOTFOUND)
407  outWidgetID = *(wgts.begin());
408  else
409  for (NTV2WidgetIDSetConstIter it(wgts.begin()); it != wgts.end(); ++it)
410  if (::NTV2DeviceCanDoWidget(inDeviceID, *it))
411  {
412  outWidgetID = *it;
413  break;
414  }
415  return outWidgetID != NTV2_WIDGET_INVALID;
416 }
417 
418 
419 bool CNTV2SignalRouter::GetWidgetInputs (const NTV2WidgetID inWidgetID, NTV2InputXptIDSet & outInputs) // STATIC
420 {
421  outInputs.clear();
423  return pExpert ? pExpert->GetWidgetInputs(inWidgetID, outInputs) : false;
424 }
425 
426 
427 bool CNTV2SignalRouter::GetAllWidgetInputs (const NTV2DeviceID inDeviceID, NTV2InputXptIDSet & outInputs) // STATIC
428 {
429  outInputs.clear();
430  NTV2WidgetIDSet widgetIDs;
431  if (!GetWidgetIDs (inDeviceID, widgetIDs))
432  return false; // Fail
433 
434  for (NTV2WidgetIDSetConstIter iter(widgetIDs.begin()); iter != widgetIDs.end (); ++iter)
435  {
436  NTV2InputXptIDSet inputs;
437  CNTV2SignalRouter::GetWidgetInputs (*iter, inputs);
438  for (NTV2InputXptIDSetConstIter it(inputs.begin()); it != inputs.end(); ++it)
439  {
440  if (WidgetIDToType(*iter) == NTV2WidgetType_FrameStore)
441  if (!::NTV2DeviceCanDo425Mux(inDeviceID))
442  if (!::NTV2DeviceCanDo8KVideo(inDeviceID))
443  if (::NTV2InputCrosspointIDToString(*it, false).find("DS2") != string::npos) // is DS2 input?
444  continue; // do not include FrameStore DS2 inputs for IP25G
445  outInputs.insert(*it);
446  }
447  }
448  return true;
449 }
450 
451 
452 bool CNTV2SignalRouter::GetAllRoutingRegInfos (const NTV2InputXptIDSet & inInputs, NTV2RegisterWrites & outRegInfos) // STATIC
453 {
454  outRegInfos.clear();
455 
456  set<uint32_t> regNums;
457  uint32_t regNum(0), maskNdx(0);
458  for (NTV2InputXptIDSetConstIter it(inInputs.begin()); it != inInputs.end(); ++it)
460  if (regNums.find(regNum) == regNums.end())
461  regNums.insert(regNum);
462  for (set<uint32_t>::const_iterator iter(regNums.begin()); iter != regNums.end(); ++iter)
463  outRegInfos.push_back(NTV2RegInfo(*iter));
464 
465  return true;
466 }
467 
468 
469 bool CNTV2SignalRouter::GetWidgetOutputs (const NTV2WidgetID inWidgetID, NTV2OutputXptIDSet & outOutputs) // STATIC
470 {
471  outOutputs.clear();
473  return pExpert ? pExpert->GetWidgetOutputs(inWidgetID, outOutputs) : false;
474 }
475 
476 bool CNTV2SignalRouter::GetAllWidgetOutputs (const NTV2DeviceID inDeviceID, NTV2OutputXptIDSet & outOutputs) // STATIC
477 {
478  outOutputs.clear();
479  NTV2WidgetIDSet widgetIDs;
480  if (!GetWidgetIDs (inDeviceID, widgetIDs))
481  return false; // Fail
482 
483  for (NTV2WidgetIDSetConstIter iter(widgetIDs.begin()); iter != widgetIDs.end (); ++iter)
484  {
485  NTV2OutputXptIDSet outputs;
486  CNTV2SignalRouter::GetWidgetOutputs (*iter, outputs);
487  for (NTV2OutputXptIDSetConstIter it(outputs.begin()); it != outputs.end(); ++it)
488  {
489  if (WidgetIDToType(*iter) == NTV2WidgetType_FrameStore)
490  if (!::NTV2DeviceCanDo425Mux(inDeviceID))
491  if (!::NTV2DeviceCanDo8KVideo(inDeviceID))
492  if (::NTV2OutputCrosspointIDToString(*it, false).find("DS2") != string::npos) // is DS2 output?
493  continue; // do not include FrameStore DS2 outputs for IP25G
494  outOutputs.insert(*it);
495  }
496  }
497  return true;
498 }
499 
501 {
503  return pExpert ? pExpert->IsRGBOnlyInputXpt(inInputXpt) : false;
504 }
505 
507 {
509  return pExpert ? pExpert->IsYUVOnlyInputXpt(inInputXpt) : false;
510 }
511 
513 {
515  return pExpert ? pExpert->IsKeyInputXpt(inInputXpt) : false;
516 }
517 
519 {
521  if (pExpert)
522  return pExpert->WidgetIDToChannel(inWidgetID);
523  return NTV2_CHANNEL_INVALID;
524 }
525 
527 {
529  if (pExpert)
530  return pExpert->WidgetIDFromTypeAndChannel(inWidgetType, inChannel);
531  return NTV2_WIDGET_INVALID;
532 }
533 
535 {
537  if (pExpert)
538  return pExpert->WidgetIDToType(inWidgetID);
539  return NTV2WidgetType_Invalid;
540 }
541 
543 {
545  return pExpert ? pExpert->IsSDIWidget(inWidgetType) : false;
546 }
547 
549 {
551  return pExpert ? pExpert->IsSDIInWidget(inWidgetType) : false;
552 }
553 
555 {
557  return pExpert ? pExpert->IsSDIOutWidget(inWidgetType) : false;
558 }
559 
561 {
563  return pExpert ? pExpert->Is3GSDIWidget(inWidgetType) : false;
564 }
565 
567 {
569  return pExpert ? pExpert->Is12GSDIWidget(inWidgetType) : false;
570 }
571 
573 {
575  return pExpert ? pExpert->IsDualLinkWidget(inWidgetType) : false;
576 }
577 
579 {
581  return pExpert ? pExpert->IsDualLinkInWidget(inWidgetType) : false;
582 }
583 
585 {
587  return pExpert ? pExpert->IsDualLinkOutWidget(inWidgetType) : false;
588 }
589 
591 {
593  return pExpert ? pExpert->IsHDMIWidget(inWidgetType) : false;
594 }
595 
597 {
599  return pExpert ? pExpert->IsHDMIInWidget(inWidgetType) : false;
600 }
601 
603 {
605  return pExpert ? pExpert->IsHDMIOutWidget(inWidgetType) : false;
606 }
607 
608 bool CNTV2SignalRouter::GetConnectionsFromRegs (const NTV2InputXptIDSet & inInputXptIDs, const NTV2RegisterReads & inRegValues, NTV2XptConnections & outConnections)
609 {
610  outConnections.clear();
611  for (NTV2InputXptIDSetConstIter it(inInputXptIDs.begin()); it != inInputXptIDs.end(); ++it)
612  {
613  uint32_t regNum(0), maskNdx(0);
615  NTV2RegisterReadsConstIter iter (::FindFirstMatchingRegisterNumber(regNum, inRegValues));
616  if (iter == inRegValues.end())
617  continue;
618 
619  if (iter->registerNumber != regNum)
620  return false; // Register numbers must match here
621  if (iter->registerMask != 0xFFFFFFFF)
622  return false; // Mask must be 0xFFFFFFFF
623  if (iter->registerShift)
624  return false; // Shift must be zero
625  NTV2_ASSERT(maskNdx < 4);
626  const uint32_t regValue (iter->registerValue & sSignalRouterRegMasks[maskNdx]);
627  const NTV2OutputXptID outputXpt (NTV2OutputXptID(regValue >> sSignalRouterRegShifts[maskNdx]));
628  if (outputXpt != NTV2_XptBlack)
629  outConnections.insert(NTV2SignalConnection (*it, outputXpt));
630  } // for each NTV2InputXptID
631  return true;
632 }
633 
634 
636  const NTV2XptConnections & inRHS,
637  NTV2XptConnections & outNew,
638  NTV2XptConnections & outMissing)
639 {
640  outNew.clear(); outMissing.clear();
641  // Check that LHS connections are also in RHS:
642  for (NTV2XptConnectionsConstIter it(inLHS.begin()); it != inLHS.end(); ++it)
643  {
644  const NTV2SignalConnection & LHSconnection(*it);
645  const NTV2InputXptID inputXpt(LHSconnection.first);
646  const NTV2OutputXptID outputXpt(LHSconnection.second);
647  NTV2XptConnectionsConstIter RHSit(inRHS.find(inputXpt));
648  if (RHSit == inRHS.end())
649  outMissing.insert(LHSconnection); // LHSConnection's inputXpt missing from RHS
650  else if (RHSit->second == outputXpt)
651  ; // LHS's input xpt connected to same output xpt as RHS
652  else
653  {
654  outMissing.insert(LHSconnection); // LHS connection missing from RHS
655  outNew.insert(*RHSit); // RHS connection is new
656  }
657  }
658 
659  // Check that RHS connections are also in LHS...
660  for (NTV2XptConnectionsConstIter it(inRHS.begin()); it != inRHS.end(); ++it)
661  {
662  const NTV2SignalConnection & connectionRHS (*it);
663  const NTV2InputXptID inputXpt(connectionRHS.first);
664  const NTV2OutputXptID outputXpt(connectionRHS.second);
665  NTV2XptConnectionsConstIter LHSit(inLHS.find(inputXpt));
666  if (LHSit == inLHS.end()) // If RHS input xpt not in LHS...
667  outNew.insert(connectionRHS); // ...then RHS connection is new
668  else if (LHSit->second != outputXpt) // Else if output xpt changed...
669  // Should've already been handled in previous for loop
670  NTV2_ASSERT(outMissing.find(LHSit->first) != outMissing.end() && outNew.find(LHSit->first) != outNew.end());
671  }
672 
673  return outNew.empty() && outMissing.empty(); // Return true if identical
674 }
675 
676 
677 bool CNTV2SignalRouter::CreateFromString (const string & inString, NTV2XptConnections & outConnections) // STATIC
678 {
679  NTV2StringList lines;
680  string stringToParse(inString); aja::strip(aja::lower(stringToParse));
681  aja::replace(stringToParse, " ", "");
682  aja::replace(stringToParse, "\t", "");
683  aja::replace(stringToParse, "&lt;","<"); // in case uuencoded
684 
685  outConnections.clear();
686  if (Tokenize(stringToParse, lines, "\n\r", true).empty()) // Split the string at line breaks
687  {
688  SRWARN("No lines resulted from input string '" << stringToParse << "'");
689  return true; // Nothing there
690  }
691 
692  if (lines.front().find("<==") != string::npos)
693  {
694 // SRDBG(lines.size() << " lines");
695  for (NTV2StringListConstIter pEachLine(lines.begin()); pEachLine != lines.end(); ++pEachLine)
696  {
697 // SRDBG(" line '" << *pEachLine << "'");
698  size_t pos (pEachLine->find("<=="));
699  if (pos == string::npos)
700  {SRFAIL("Parse error: '<==' missing in line '" << *pEachLine << "'"); return false;}
701  string leftPiece (pEachLine->substr(0, pos)); aja::strip(leftPiece);
702  string rightPiece (pEachLine->substr(pos + 3, pEachLine->length())); aja::strip(rightPiece);
703  NTV2InputXptID inputXpt (StringToNTV2InputCrosspointID(leftPiece));
704  NTV2OutputXptID outputXpt (StringToNTV2OutputCrosspointID(rightPiece));
705  //SRDBG(" L'" << leftPiece << "', R'" << rightPiece << "'");
706  if (inputXpt == NTV2_INPUT_CROSSPOINT_INVALID)
707  {SRFAIL("Parse error: invalid input crosspoint from '" << leftPiece << "' from line '" << *pEachLine << "'"); return false;}
708  if (outConnections.find(inputXpt) != outConnections.end())
709  SRWARN("Overwriting " << ::NTV2InputCrosspointIDToString(inputXpt) << "-" << ::NTV2OutputCrosspointIDToString(outConnections[inputXpt])
710  << " with " << ::NTV2InputCrosspointIDToString(inputXpt) << "-" << ::NTV2OutputCrosspointIDToString(outputXpt));
711  outConnections.insert(NTV2Connection(inputXpt, outputXpt));
712  } // for each line
713  }
714  else if (lines.front().find("connect(") != string::npos)
715  {
716  for (NTV2StringListConstIter pLine(lines.begin()); pLine != lines.end(); ++pLine)
717  {
718  string line(*pLine); aja::strip(line);
719  if (line.empty())
720  continue;
721  if (line.find("//") == 0) // starts with "//"
722  continue;
723 // SRDBG(" line '" << line << "'");
724  size_t openParenPos(line.find("(")), closedParenPos(line.find(");"));
725  if (openParenPos == string::npos || closedParenPos == string::npos || openParenPos > closedParenPos)
726  {SRFAIL("Parse error: '(' or ');' missing in line '" << line << "'"); return false;}
727  string remainder(line.substr(openParenPos+1, closedParenPos - openParenPos - 1));
728  NTV2StringList xptNames;
729  aja::split(remainder, ',', xptNames);
730  if (xptNames.size() < 2 || xptNames.size() > 2)
731  {SRFAIL("Parse error: " << DEC(xptNames.size()) << " 'Connect' parameter(s) found, expected 2"); return false;}
732  NTV2InputXptID inputXpt (StringToNTV2InputCrosspointID(xptNames.at(0)));
733  NTV2OutputXptID outputXpt (StringToNTV2OutputCrosspointID(xptNames.at(1)));
734  //SRDBG(" L'" << xptNames.at(0) << "', R'" << xptNames.at(1) << "'");
735  if (inputXpt == NTV2_INPUT_CROSSPOINT_INVALID)
736  {SRFAIL("Parse error: invalid input crosspoint from '" << xptNames.at(0) << "' from line '" << *pLine << "'"); return false;}
737  if (outputXpt == NTV2_OUTPUT_CROSSPOINT_INVALID)
738  {SRFAIL("Parse error: invalid output crosspoint from '" << xptNames.at(1) << "' from line '" << *pLine << "'"); return false;}
739  if (outConnections.find(inputXpt) != outConnections.end())
740  SRWARN("Overwriting " << ::NTV2InputCrosspointIDToString(inputXpt) << "-" << ::NTV2OutputCrosspointIDToString(outConnections[inputXpt])
741  << " with " << ::NTV2InputCrosspointIDToString(inputXpt) << "-" << ::NTV2OutputCrosspointIDToString(outputXpt));
742  outConnections.insert(NTV2Connection(inputXpt, outputXpt));
743  } // for each line
744  }
745  else
746  {SRFAIL("Unable to parse '" << lines.front() << "' -- expected '.contains(' or '<=='"); return false;}
747  SRINFO(DEC(outConnections.size()) << " connection(s) created from input string");
748  return true;
749 }
750 
751 
752 bool CNTV2SignalRouter::CreateFromString (const string & inString, CNTV2SignalRouter & outRouter) // STATIC
753 {
755  outRouter.Reset();
756  if (!CreateFromString(inString, connections))
757  return false;
758  return outRouter.ResetFrom(connections);
759 }
760 
761 bool CNTV2SignalRouter::CreateFromString (const string & inString, NTV2PossibleConnections & outConnections) // STATIC
762 {
763  NTV2StringList lines;
764  string stringToParse(inString); aja::strip(aja::lower(stringToParse));
765  aja::replace(stringToParse, " ", "");
766  aja::replace(stringToParse, "\t", "");
767  aja::replace(stringToParse, "&lt;","<"); // in case uuencoded
768 
769  outConnections.clear();
770  if (Tokenize(stringToParse, lines, "\n\r", true).empty()) // Split the string at line breaks
771  {
772  SRWARN("No lines resulted from input string '" << stringToParse << "'");
773  return true; // Nothing there
774  }
775 
776  if (lines.front().find("<==") != string::npos)
777  {
778  //cout << lines.size() << " lines" << endl;
779  for (size_t lineNum(0); lineNum < lines.size(); lineNum++)
780  {
781  const string & line (lines.at(lineNum));
782  //cout << " line '" << line << "'" << endl;
783  size_t pos (line.find("<=="));
784  if (pos == string::npos)
785  {SRFAIL("Parse error: '<==' missing in line '" << line << "'"); return false;}
786  string leftPiece (line.substr(0, pos)); aja::strip(leftPiece);
787  string rightPiece (line.substr(pos + 3, line.length())); aja::strip(rightPiece);
788  //cout << " L'" << leftPiece << "', R'" << rightPiece << "'" << endl;
789  NTV2InputXptID inputXpt (StringToNTV2InputCrosspointID(leftPiece));
790  if (inputXpt == NTV2_INPUT_CROSSPOINT_INVALID)
791  {SRFAIL("Parse error: invalid input crosspoint from '" << leftPiece << "' from line '" << line << "'"); return false;}
793  if (rightPiece.find(",") != string::npos)
794  {
795  NTV2StringList rtPieces(aja::split(rightPiece, ","));
796  for (size_t n(0); n < rtPieces.size(); n++)
797  {
798  string s(rtPieces.at(n));
799  outputXpt = StringToNTV2OutputCrosspointID(aja::strip(s));
800  if (!NTV2_IS_VALID_OutputCrosspointID(outputXpt))
801  {SRWARN("Skipped invalid output crosspoint from '" << s << "' in line '" << line << "'"); continue;}
802  outConnections.insert(NTV2Connection(inputXpt, outputXpt));
803  }
804  }
805  else
806  {
807  outputXpt = StringToNTV2OutputCrosspointID(rightPiece);
808  if (!NTV2_IS_VALID_OutputCrosspointID(outputXpt))
809  {SRWARN("Skipped invalid output crosspoint from '" << rightPiece << "' in line '" << line << "'"); continue;}
810  outConnections.insert(NTV2Connection(inputXpt, outputXpt));
811  }
812  } // for each line
813  }
814  else
815  {SRFAIL("Unable to parse '" << lines.front() << "' -- expected '<=='"); return false;}
816  SRINFO(DEC(outConnections.size()) << " potential connection(s) created from input string");
817  //cout << "Success! Imported " << outConnections.size() << " connections:" << endl << outConnections << endl;
818  return true;
819 }
820 
822 
823 
824 
826 
827 NTV2InputXptID GetFrameStoreInputXptFromChannel (const NTV2Channel inChannel, const bool inIsBInput)
828 {
833  if (NTV2_IS_VALID_CHANNEL (inChannel))
834  return inIsBInput ? gFrameBufferBInputs [inChannel] : gFrameBufferInputs [inChannel];
835  else
837 }
838 
839 
840 NTV2InputXptID GetCSCInputXptFromChannel (const NTV2Channel inChannel, const bool inIsKeyInput)
841 {
846  if (NTV2_IS_VALID_CHANNEL(inChannel))
847  return inIsKeyInput ? gCSCKeyInput[inChannel] : gCSCVideoInput[inChannel];
848  else
850 }
851 
852 
854 {
857  return NTV2_IS_VALID_CHANNEL(inLUT) ? gLUTInput[inLUT] : NTV2_INPUT_CROSSPOINT_INVALID;
858 }
859 
860 
861 NTV2InputXptID GetDLInInputXptFromChannel (const NTV2Channel inChannel, const bool inLinkB)
862 {
867  if (NTV2_IS_VALID_CHANNEL(inChannel))
868  return inLinkB ? gDLBInputs[inChannel] : gDLInputs[inChannel];
869  else
871 }
872 
874 {
877  if (NTV2_IS_VALID_CHANNEL(inChannel))
878  return gDLOutInputs[inChannel];
879  else
881 }
882 
883 
884 NTV2OutputXptID GetCSCOutputXptFromChannel (const NTV2Channel inChannel, const bool inIsKey, const bool inIsRGB)
885 {
892  if (NTV2_IS_VALID_CHANNEL(inChannel))
893  {
894  if (inIsKey)
895  return gCSCKeyOutputs[inChannel];
896  else
897  return inIsRGB ? gCSCRGBOutputs[inChannel] : gCSCYUVOutputs[inChannel];
898  }
899  else
901 }
902 
904 {
907  return NTV2_IS_VALID_CHANNEL(inLUT) ? gLUTRGBOutputs[inLUT] : NTV2_OUTPUT_CROSSPOINT_INVALID;
908 }
909 
910 NTV2OutputXptID GetFrameStoreOutputXptFromChannel (const NTV2Channel inChannel, const bool inIsRGB, const bool inIs425)
911 {
920  if (NTV2_IS_VALID_CHANNEL(inChannel))
921  if (inIs425)
922  return inIsRGB ? gFrameBufferRGB425Outputs[inChannel] : gFrameBufferYUV425Outputs[inChannel];
923  else
924  return inIsRGB ? gFrameBufferRGBOutputs[inChannel] : gFrameBufferYUVOutputs[inChannel];
925  else
927 }
928 
929 
930 NTV2OutputXptID GetInputSourceOutputXpt (const NTV2InputSource inInputSource, const bool inIsSDI_DS2, const bool inIsHDMI_RGB, const UWord inHDMI_Quadrant)
931 {
932  static const NTV2OutputXptID gHDMIInputOutputs [4][4] = { { NTV2_XptHDMIIn1, NTV2_XptHDMIIn1Q2, NTV2_XptHDMIIn1Q3, NTV2_XptHDMIIn1Q4 },
936  static const NTV2OutputXptID gHDMIInputRGBOutputs [4][4] = { { NTV2_XptHDMIIn1RGB, NTV2_XptHDMIIn1Q2RGB, NTV2_XptHDMIIn1Q3RGB, NTV2_XptHDMIIn1Q4RGB },
940 
941  if (NTV2_INPUT_SOURCE_IS_SDI (inInputSource))
943  else if (NTV2_INPUT_SOURCE_IS_HDMI (inInputSource))
944  {
945  NTV2Channel channel = ::NTV2InputSourceToChannel (inInputSource);
946  if (inHDMI_Quadrant < 4)
947  return inIsHDMI_RGB ? gHDMIInputRGBOutputs [channel][inHDMI_Quadrant] : gHDMIInputOutputs [channel][inHDMI_Quadrant];
948  else
950  }
951  else if (NTV2_INPUT_SOURCE_IS_ANALOG (inInputSource))
952  return NTV2_XptAnalogIn;
953  else
955 }
956 
957 
958 NTV2OutputXptID GetSDIInputOutputXptFromChannel (const NTV2Channel inChannel, const bool inIsDS2)
959 {
960  static const NTV2OutputXptID gSDIInputOutputs [] = { NTV2_XptSDIIn1, NTV2_XptSDIIn2, NTV2_XptSDIIn3, NTV2_XptSDIIn4,
964  if (NTV2_IS_VALID_CHANNEL(inChannel))
965  return inIsDS2 ? gSDIInputDS2Outputs[inChannel] : gSDIInputOutputs[inChannel];
966  else
968 }
969 
970 NTV2OutputXptID GetDLOutOutputXptFromChannel(const NTV2Channel inChannel, const bool inIsLinkB)
971 {
976  if (NTV2_IS_VALID_CHANNEL(inChannel))
977  return inIsLinkB ? gDLOutDS2Outputs[inChannel] : gDLOutOutputs[inChannel];
978  else
980 }
981 
983 {
986  if (NTV2_IS_VALID_CHANNEL(inChannel))
987  return gDLInOutputs[inChannel];
988  else
990 }
991 
992 
993 NTV2InputXptID GetOutputDestInputXpt (const NTV2OutputDestination inOutputDest, const bool inIsSDI_DS2, const UWord inHDMI_Quadrant)
994 {
996  if (NTV2_OUTPUT_DEST_IS_SDI(inOutputDest))
997  return ::GetSDIOutputInputXpt (::NTV2OutputDestinationToChannel(inOutputDest), inIsSDI_DS2);
998  else if (NTV2_OUTPUT_DEST_IS_HDMI(inOutputDest))
999  return inHDMI_Quadrant > 3 ? NTV2_XptHDMIOutInput : gHDMIOutputInputs[inHDMI_Quadrant];
1000  else if (NTV2_OUTPUT_DEST_IS_ANALOG(inOutputDest))
1001  return NTV2_XptAnalogOutInput;
1002  else
1004 }
1005 
1006 
1007 NTV2InputXptID GetSDIOutputInputXpt (const NTV2Channel inChannel, const bool inIsDS2)
1008 {
1013  if (NTV2_IS_VALID_CHANNEL (inChannel))
1014  return inIsDS2 ? gSDIOutputDS2Inputs [inChannel] : gSDIOutputInputs [inChannel];
1015  else
1017 }
1018 
1019 
1020 NTV2OutputXptID GetMixerOutputXptFromChannel (const NTV2Channel inChannel, const bool inIsKey)
1021 {
1026  if (NTV2_IS_VALID_CHANNEL(inChannel))
1027  return inIsKey ? gMixerKeyYUVOutputs[inChannel] : gMixerVidYUVOutputs[inChannel];
1028  else
1030 }
1031 
1032 
1033 NTV2InputXptID GetMixerFGInputXpt (const NTV2Channel inChannel, const bool inIsKey)
1034 {
1039  if (NTV2_IS_VALID_CHANNEL(inChannel))
1040  return inIsKey ? gMixerFGKeyInputs[inChannel] : gMixerFGVideoInputs[inChannel];
1041  else
1043 }
1044 
1045 
1046 NTV2InputXptID GetMixerBGInputXpt (const NTV2Channel inChannel, const bool inIsKey)
1047 {
1052  if (NTV2_IS_VALID_CHANNEL(inChannel))
1053  return inIsKey ? gMixerBGKeyInputs[inChannel] : gMixerBGVideoInputs[inChannel];
1054  else
1056 }
1057 
1058 NTV2InputXptID GetTSIMuxInputXptFromChannel (const NTV2Channel inChannel, const bool inLinkB)
1059 {
1064  if (NTV2_IS_VALID_CHANNEL(inChannel))
1065  return inLinkB ? gDLBInputs[inChannel] : gDLInputs[inChannel];
1066  else
1068 }
1069 
1070 NTV2OutputXptID GetTSIMuxOutputXptFromChannel (const NTV2Channel inChannel, const bool inLinkB, const bool inIsRGB)
1071 {
1080  if (NTV2_IS_VALID_CHANNEL(inChannel))
1081  {
1082  if (inLinkB)
1083  return inIsRGB ? gMuxBRGBOutputs[inChannel] : gMuxBYUVOutputs[inChannel];
1084  else
1085  return inIsRGB ? gMuxARGBOutputs[inChannel] : gMuxAYUVOutputs[inChannel];
1086  }
1087  else
1089 }
1091 
1092 
1093 // static
1094 bool CNTV2SignalRouter::GetRouteROMInfoFromReg (const ULWord inRegNum, const ULWord inRegVal,
1095  NTV2InputXptID & outInputXpt, NTV2OutputXptIDSet & outOutputXpts, const bool inAppendOutputXpts)
1096 {
1097  static const ULWord firstROMReg(kRegFirstValidXptROMRegister);
1098  static const ULWord firstInpXpt(NTV2_FIRST_INPUT_CROSSPOINT);
1099  if (!inAppendOutputXpts)
1100  outOutputXpts.clear();
1101  outInputXpt = NTV2_INPUT_CROSSPOINT_INVALID;
1102  if (inRegNum < uint32_t(kRegFirstValidXptROMRegister))
1103  return false;
1104  if (inRegNum >= uint32_t(kRegInvalidValidXptROMRegister))
1105  return false;
1106 
1107  const ULWord regOffset(inRegNum - firstROMReg);
1108  const ULWord bitOffset((regOffset % 4) * 32);
1109  outInputXpt = NTV2InputXptID(firstInpXpt + regOffset / 4UL); // 4 regs per inputXpt
1110  if (!inRegVal)
1111  return true; // No bits set
1112 
1114  NTV2_ASSERT(pExpert);
1115  for (UWord bitNdx(0); bitNdx < 32; bitNdx++)
1116  if (inRegVal & ULWord(1UL << bitNdx))
1117  {
1118  const NTV2OutputXptID yuvOutputXpt (NTV2OutputXptID((bitOffset + bitNdx) & 0x0000007F));
1119  const NTV2OutputXptID rgbOutputXpt (NTV2OutputXptID(yuvOutputXpt | 0x80));
1120  if (pExpert && pExpert->IsOutputXptValid(yuvOutputXpt))
1121  outOutputXpts.insert(yuvOutputXpt);
1122  if (pExpert && pExpert->IsOutputXptValid(rgbOutputXpt))
1123  outOutputXpts.insert(rgbOutputXpt);
1124  }
1125  return true;
1126 }
1127 
1128 // static
1130 {
1131  outConnections.clear();
1132  for (NTV2RegReadsConstIter iter(inROMRegs.begin()); iter != inROMRegs.end(); ++iter)
1133  {
1134  if (iter->registerNumber < kRegFirstValidXptROMRegister || iter->registerNumber >= kRegInvalidValidXptROMRegister)
1135  continue; // Skip -- not a ROM reg
1137  NTV2OutputXptIDSet outputXpts;
1138  if (GetRouteROMInfoFromReg (iter->registerNumber, iter->registerValue, inputXpt, outputXpts, true))
1139  for (NTV2OutputXptIDSetConstIter it(outputXpts.begin()); it != outputXpts.end(); ++it)
1140  outConnections.insert(NTV2Connection(inputXpt, *it));
1141  }
1142  return !outConnections.empty();
1143 }
1144 
1145 // static
1147 {
1148  outROMRegs.clear();
1149  for (uint32_t regNum(kRegFirstValidXptROMRegister); regNum < kRegInvalidValidXptROMRegister; regNum++)
1150  outROMRegs.push_back(NTV2RegInfo(regNum));
1151  return true;
1152 }
1153 
1154 
1156 
1157 ostream & operator << (ostream & oss, const CNTV2SignalRouter & inObj)
1158 {
1159  return inObj.Print(oss);
1160 }
1161 
1162 
1163 ostream & operator << (ostream & oss, const NTV2OutputXptIDSet & inObj)
1164 {
1165  NTV2OutputXptIDSetConstIter iter(inObj.begin());
1166  while (iter != inObj.end())
1167  {
1168  oss << ::NTV2OutputCrosspointIDToString(*iter, false);
1169  if (++iter == inObj.end())
1170  break;
1171  oss << ", ";
1172  }
1173  return oss;
1174 }
1175 
1176 ostream & operator << (ostream & oss, const NTV2InputXptIDSet & inObj)
1177 {
1178  NTV2InputXptIDSetConstIter iter(inObj.begin());
1179  while (iter != inObj.end())
1180  {
1181  oss << ::NTV2InputCrosspointIDToString(*iter, false);
1182  if (++iter == inObj.end())
1183  break;
1184  oss << ", ";
1185  }
1186  return oss;
1187 }
1188 
1190 {
1191  registerNum = inRHS.registerNumber;
1192  mask = inRHS.registerMask;
1193  shift = inRHS.registerShift;
1194  value = inRHS.registerValue;
1195  return *this;
1196 }
1197 
1198 ostream & operator << (ostream & inOutStream, const NTV2WidgetIDSet & inObj)
1199 {
1200  for (NTV2WidgetIDSetConstIter iter (inObj.begin ()); iter != inObj.end (); )
1201  {
1202  inOutStream << ::NTV2WidgetIDToString (*iter, true);
1203  if (++iter != inObj.end ())
1204  inOutStream << ",";
1205  }
1206  return inOutStream;
1207 }
1208 
1209 ostream & operator << (ostream & oss, const NTV2XptConnection & inObj)
1210 {
1211  oss << ::NTV2InputCrosspointIDToString(inObj.first) << " <== " << ::NTV2OutputCrosspointIDToString(inObj.second);
1212  return oss;
1213 }
1214 
1215 ostream & operator << (ostream & oss, const NTV2XptConnections & inObj)
1216 {
1217  for (NTV2XptConnectionsConstIter it(inObj.begin()); it != inObj.end(); )
1218  {
1219  oss << *it;
1220  if (++it != inObj.end())
1221  oss << endl;
1222  }
1223  return oss;
1224 }
1225 
1226 ostream & operator << (ostream & oss, const NTV2PossibleConnections & inObj)
1227 {
1228  if (inObj.empty())
1229  return oss;
1231  for (NTV2PossibleConnectionsConstIter it(inObj.begin()); it != inObj.end(); )
1232  {
1233  if (ixpt != it->first)
1234  {
1235  ixpt = it->first;
1236  oss << ::NTV2InputCrosspointIDToString(ixpt) << " <== ";
1237  }
1238  oss << ::NTV2OutputCrosspointIDToString(it->second);
1239  if (++it == inObj.end())
1240  break;
1241  if (ixpt == it->first)
1242  oss << ", ";
1243  else
1244  oss << endl;
1245  }
1246  return oss;
1247 }
1248 
NTV2Channel NTV2InputSourceToChannel(const NTV2InputSource inInputSource)
Converts a given NTV2InputSource to its equivalent NTV2Channel value.
Definition: ntv2utils.cpp:5049
NTV2XptConnections::const_iterator NTV2XptConnectionsConstIter
Everything needed to call CNTV2Card::ReadRegister or CNTV2Card::WriteRegister functions.
static bool Deinitialize(void)
Explicitly deinitializes and deallocates the Routing Expert singleton.
static bool IsKeyInputXpt(const NTV2InputXptID inInputXpt)
NTV2OutputXptID GetDLInOutputXptFromChannel(const NTV2Channel inChannel)
static const ULWord sSignalRouterRegShifts[]
NTV2InputXptIDSet::const_iterator NTV2InputXptIDSetConstIter
A const iterator for iterating over an NTV2InputXptIDSet.
std::string mPostCommentText
Comment postfix text.
#define SRINFO(__x__)
Declares the AJAMemory class.
std::string NTV2WidgetIDToString(const NTV2WidgetID inValue, const bool inCompactDisplay=false)
Definition: ntv2utils.cpp:6164
virtual void Reset(void)
Resets me, erasing any/all existing connections.
ULWord registerMask
My register mask value to use in a ReadRegister or WriteRegister call.
NTV2RegWritesConstIter NTV2RegReadsConstIter
A handy const (read-only) iterator for iterating over the contents of an NTV2RegisterReads instance...
static bool GetPossibleConnections(const NTV2RegReads &inROMRegisters, NTV2PossibleConnections &outConnections)
Answers with the implemented crosspoint connections as obtained from the given ROM registers...
virtual bool AddConnection(const NTV2InputXptID inSignalInput, const NTV2OutputXptID inSignalOutput=NTV2_XptBlack)
Adds a connection between a widget&#39;s signal input (sink) and another widget&#39;s signal output (source)...
NTV2OutputXptID GetDLOutOutputXptFromChannel(const NTV2Channel inChannel, const bool inIsLinkB)
Declares CNTV2SignalRouter class.
static bool GetConnectionsFromRegs(const NTV2InputXptIDSet &inInputXptIDs, const NTV2RegisterReads &inRegValues, NTV2XptConnections &outConnections)
Converts a set of crosspoint registers into a set of crosspoint connections.
virtual bool HasConnection(const NTV2InputXptID inSignalInput, const NTV2OutputXptID inSignalOutput) const
Answers true if I contain a connection between the specified input (signal sink) and output (signal s...
NTV2OutputDestination
Identifies a specific video output destination.
Definition: ntv2enums.h:1326
Declares the AJADebug class.
ostream & operator<<(ostream &oss, const CNTV2SignalRouter &inObj)
NTV2OutputXptID GetLUTOutputXptFromChannel(const NTV2Channel inLUT)
static bool IsHDMIOutWidgetType(const NTV2WidgetType inWidgetType)
NTV2InputXptID GetDLOutInputXptFromChannel(const NTV2Channel inChannel)
NTV2StringList::const_iterator NTV2StringListConstIter
bool NTV2DeviceCanDo425Mux(const NTV2DeviceID inDeviceID)
virtual bool GetRegisterWrites(NTV2RegisterWrites &outRegWrites) const
Returns a sequence of NTV2RegInfo values that can be written to an NTV2 device using its WriteRegiste...
static std::string NTV2InputCrosspointIDToString(const NTV2InputXptID inInputXpt)
Returns a string containing the most compact human-readable form for a given input crosspoint...
if(!(riid==IID_IUnknown) &&!(riid==IID_IClassFactory))
Definition: dllentry.cpp:196
static bool Initialize(void)
Explicitly allocates and initializes the Routing Expert singleton.
I am a reference-counted pointer template class. I am intended to be a proxy for an underlying object...
Definition: ajarefptr.h:89
std::string mFieldBreakText
Text to use for field breaks.
static bool CompareConnections(const NTV2XptConnections &inLHS, const NTV2XptConnections &inRHS, NTV2XptConnections &outNew, NTV2XptConnections &outRemoved)
Compares two sets of crosspoint connections.
static bool GetWidgetOutputs(const NTV2WidgetID inWidgetID, NTV2OutputXptIDSet &outOutputs)
Returns the output crosspoints known to be "owned" by the given widget.
static bool IsSDIOutputWidgetType(const NTV2WidgetType inWidgetType)
NTV2XptConnections mNew
Optional, to show new connections.
static bool Is12GSDIWidgetType(const NTV2WidgetType inWidgetType)
Definition: json.hpp:5362
std::string mRouterVarName
Name to use for CNTV2SignalRouter variable.
virtual NTV2XptConnections GetConnections(void) const
NTV2InputXptID GetMixerFGInputXpt(const NTV2Channel inChannel, const bool inIsKey)
std::pair< NTV2InputXptID, NTV2OutputXptID > NTV2Connection
This links an NTV2InputXptID and an NTV2OutputXptID.
uint32_t ULWord
Definition: ajatypes.h:236
NTV2Channel
These enum values are mostly used to identify a specific widget_framestore. They&#39;re also commonly use...
Definition: ntv2enums.h:1359
NTV2OutputXptIDSet::const_iterator NTV2OutputXptIDSetConstIter
A const iterator for iterating over an NTV2OutputXptIDSet.
This class is a collection of widget input-to-output connections that can be applied all-at-once to a...
static bool CreateFromString(const std::string &inString, NTV2XptConnections &outConnections)
Decodes a given string into a map of crosspoint connections.
NTV2WidgetType
Definition: ntv2enums.h:3050
#define NTV2_OUTPUT_DEST_IS_HDMI(_dest_)
Definition: ntv2enums.h:1346
std::string mDeviceVarName
Name to use for CNTV2Card variable.
static bool IsInitialized(void)
#define NTV2_ASSERT(_expr_)
Definition: ajatypes.h:489
NTV2RegWritesConstIter NTV2RegisterReadsConstIter
Declares RoutingExpert class used by CNTV2SignalRouter.
NTV2Channel NTV2OutputDestinationToChannel(const NTV2OutputDestination inOutputDest)
Converts a given NTV2OutputDestination to its equivalent NTV2Channel value.
Definition: ntv2utils.cpp:5157
bool mShowDeclarations
If true, show variable declarations in the generated code.
std::string NTV2InputCrosspointIDToString(const NTV2InputCrosspointID inValue, const bool inForRetailDisplay=false)
Definition: ntv2utils.cpp:5816
unsigned int n
Definition: pstream.cpp:148
#define true
static bool GetRouteROMInfoFromReg(const ULWord inROMRegNum, const ULWord inROMRegValue, NTV2InputXptID &outInputXpt, NTV2OutputXptIDSet &outOutputXpts, const bool inAppendOutputXpts=false)
Answers with the NTV2InputXptID and NTV2OutputXptIDSet for the given ROM register value...
NTV2InputXptID GetFrameStoreInputXptFromChannel(const NTV2Channel inChannel, const bool inIsBInput)
ULWord registerValue
My register value to use in a ReadRegister or WriteRegister call.
NTV2DeviceID
Identifies a specific AJA NTV2 device model number. The NTV2DeviceID is actually the PROM part number...
Definition: ntv2enums.h:20
ULWord registerNumber
My register number to use in a ReadRegister or WriteRegister call.
bool NTV2DeviceCanDoWidget(const NTV2DeviceID inDeviceID, const NTV2WidgetID inWidgetID)
Invalid or "not found".
Definition: ntv2enums.h:100
#define NTV2_INPUT_SOURCE_IS_HDMI(_inpSrc_)
Definition: ntv2enums.h:1283
NTV2InputXptID GetLUTInputXptFromChannel(const NTV2Channel inLUT)
static bool GetAllRoutingRegInfos(const NTV2InputXptIDSet &inInputs, NTV2RegisterWrites &outRegInfos)
Returns all routing registers for the given set of input crosspoints.
NTV2XptConnections mChanged
Optional, to show changed connections.
std::set< NTV2WidgetID > NTV2WidgetIDSet
A collection of distinct NTV2WidgetID values.
virtual NTV2OutputXptID GetConnectedOutput(const NTV2InputXptID inSignalInput) const
bool mUseRouter
If true, use calls to CNTV2SignalRouter instead of CNTV2Card.
std::string mPostClassText
Class postfix text.
void split(const std::string &str, const char delim, std::vector< std::string > &elems)
Definition: common.cpp:350
static NTV2StringList & Tokenize(const string &inString, NTV2StringList &outTokens, const string &inDelimiters=" ", bool inTrimEmpty=false)
NTV2InputXptID GetMixerBGInputXpt(const NTV2Channel inChannel, const bool inIsKey)
std::string mPreFunctionText
Function name prefix text.
NTV2OutputXptID GetTSIMuxOutputXptFromChannel(const NTV2Channel inChannel, const bool inLinkB, const bool inIsRGB)
NTV2RegWrites NTV2RegisterReads
NTV2OutputXptID GetInputSourceOutputXpt(const NTV2InputSource inInputSource, const bool inIsSDI_DS2, const bool inIsHDMI_RGB, const UWord inHDMI_Quadrant)
ULWord registerShift
My register shift value to use in a ReadRegister or WriteRegister call.
virtual bool HasInput(const NTV2InputXptID inSignalInput) const
Answers true if I contain a connection that involves the given input (signal sink).
static bool IsRGBOnlyInputXpt(const NTV2InputXptID inInputXpt)
static NTV2InputXptID StringToNTV2InputCrosspointID(const std::string &inStr)
Returns a string containing the most compact human-readable form for a given input crosspoint...
std::pair< NTV2InputXptID, NTV2OutputXptID > NTV2SignalConnection
NTV2XptConnections connections
Definition: ntv2vcam.cpp:1011
std::string mPreXptText
Crosspoint variable prefix text.
#define SRiDBG(__x__)
static const ULWord sSignalRouterRegMasks[]
static bool GetCrosspointSelectGroupRegisterInfo(const NTV2InputCrosspointID inInputXpt, uint32_t &outXptRegNum, uint32_t &outMaskIndex)
Answers with the crosspoint select register and mask information for a given widget input...
static bool ToCodeString(std::string &outCode, const NTV2XptConnections &inConnections, const PrintCodeConfig &inConfig=PrintCodeConfig())
Converts the given map of crosspoint connections into source code.
NTV2InputXptID GetCSCInputXptFromChannel(const NTV2Channel inChannel, const bool inIsKeyInput)
std::string mPostXptText
Crosspoint variable postfix text.
Declares NTV2DeviceCanDo... and NTV2DeviceGetNum... functions. This module is included at compile tim...
static bool Is3GSDIWidgetType(const NTV2WidgetType inWidgetType)
NTV2RoutingEntry & operator=(const NTV2RegInfo &inRHS)
Assigns an NTV2RegInfo to me.
NTV2InputXptID GetDLInInputXptFromChannel(const NTV2Channel inChannel, const bool inLinkB)
static NTV2WidgetID WidgetIDFromTypeAndChannel(const NTV2WidgetType inWidgetType, const NTV2Channel inChannel)
#define NTV2_OUTPUT_DEST_IS_ANALOG(_dest_)
Definition: ntv2enums.h:1347
#define NTV2_IS_VALID_OutputCrosspointID(__s__)
Definition: ntv2enums.h:2740
NTV2PossibleConnections::const_iterator NTV2PossibleConnectionsConstIter
#define NTV2_OUTPUT_DEST_IS_SDI(_dest_)
Definition: ntv2enums.h:1348
#define NTV2_IS_VALID_CHANNEL(__x__)
Definition: ntv2enums.h:1373
static bool GetAllWidgetInputs(const NTV2DeviceID inDeviceID, NTV2InputXptIDSet &outInputs)
Returns all supported widget input crosspoints for the given device.
static bool IsDualLinkInWidgetType(const NTV2WidgetType inWidgetType)
NTV2InputSource
Identifies a specific video input source.
Definition: ntv2enums.h:1264
virtual bool PrintCode(std::string &outCode, const PrintCodeConfig &inConfig=PrintCodeConfig()) const
Prints me as source code to the given output stream.
Originally 0x01. Changed to 0x00 in SDK 17.1.
Definition: ntv2enums.h:2757
static bool DisposeInstance(void)
std::string mPostVariableText
Variable postfix text.
std::string & strip(std::string &str, const std::string &ws)
Definition: common.cpp:461
NTV2WidgetIDSet::const_iterator NTV2WidgetIDSetConstIter
An iterator for iterating over a read-only NTV2WidgetIDSet.
std::string mPreVariableText
Variable prefix text.
static bool GetWidgetForOutput(const NTV2OutputXptID inOutputXpt, NTV2WidgetID &outWidgetID, const NTV2DeviceID inDeviceID=DEVICE_ID_NOTFOUND)
Returns the widget that "owns" the specified output crosspoint.
#define DEC(__x__)
static bool GetWidgetForInput(const NTV2InputXptID inInputXpt, NTV2WidgetID &outWidgetID, const NTV2DeviceID inDeviceID=DEVICE_ID_NOTFOUND)
Returns the widget that "owns" the specified input crosspoint.
Declares numerous NTV2 utility functions.
virtual std::ostream & Print(std::ostream &inOutStream, const bool inForRetailDisplay=false) const
Prints me in a human-readable format to the given output stream.
std::set< NTV2InputXptID > NTV2InputXptIDSet
A collection of distinct NTV2InputXptID values.
std::string mPreCommentText
Comment prefix text.
virtual bool RemoveConnection(const NTV2InputXptID inSignalInput, const NTV2OutputXptID inSignalOutput)
Removes the connection between the specified input (signal sink) and output (signal source)...
NTV2InputXptID GetTSIMuxInputXptFromChannel(const NTV2Channel inChannel, const bool inLinkB)
static AJALock gRoutingExpertLock
virtual bool Compare(const CNTV2SignalRouter &inRHS, NTV2XptConnections &outNew, NTV2XptConnections &outChanged, NTV2XptConnections &outMissing) const
Compares me with another routing, and returns three connection mappings as a result of the comparison...
static bool GetWidgetIDs(const NTV2DeviceID inDeviceID, NTV2WidgetIDSet &outWidgets)
Returns the widget IDs supported by the given device.
static bool IsDualLinkOutWidgetType(const NTV2WidgetType inWidgetType)
virtual bool ResetFromRegisters(const NTV2InputXptIDSet &inInputXpts, const NTV2RegisterReads &inRegReads)
Resets me, erasing any/all existing connections, then rebuilding my connections from the given regist...
std::string mPreClassText
Class prefix text.
NTV2WidgetID
Definition: ntv2enums.h:2912
static bool MakeRouteROMRegisters(NTV2RegReads &outROMRegisters)
Prepares an initialized, zeroed NTV2RegReads that&#39;s prepared to read all ROM registers from a device...
bool NTV2DeviceCanDo8KVideo(const NTV2DeviceID inDeviceID)
uint16_t UWord
Definition: ajatypes.h:234
std::string mPostFunctionText
Function name postfix text.
NTV2OutputXptID GetFrameStoreOutputXptFromChannel(const NTV2Channel inChannel, const bool inIsRGB, const bool inIs425)
static RoutingExpertPtr GetInstance(const bool inCreateIfNecessary=true)
std::string mLineBreakText
Text to use for line breaks.
static bool GetWidgetsForOutput(const NTV2OutputXptID inOutputXpt, NTV2WidgetIDSet &outWidgetIDs)
Returns the widgets that "own" the specified output crosspoint.
#define NTV2_INPUT_SOURCE_IS_ANALOG(_inpSrc_)
Definition: ntv2enums.h:1284
bool mShowComments
If true, show comments in the generated code.
static bool IsDualLinkWidgetType(const NTV2WidgetType inWidgetType)
static bool IsSDIWidgetType(const NTV2WidgetType inWidgetType)
NTV2OutputXptID GetCSCOutputXptFromChannel(const NTV2Channel inChannel, const bool inIsKey, const bool inIsRGB)
std::pair< NTV2InputXptID, NTV2OutputXptID > NTV2XptConnection
enum NTV2InputCrosspointID NTV2InputXptID
NTV2InputXptID GetSDIOutputInputXpt(const NTV2Channel inChannel, const bool inIsDS2)
std::multimap< NTV2InputXptID, NTV2OutputXptID > NTV2PossibleConnections
A map of zero or more one-to-many possible NTV2InputXptID to NTV2OutputXptID connections.
static bool IsHDMIWidgetType(const NTV2WidgetType inWidgetType)
Private include file for all ajabase sources.
NTV2OutputXptID GetMixerOutputXptFromChannel(const NTV2Channel inChannel, const bool inIsKey)
NTV2XptConnections mMissing
Optional, to show deleted connections.
std::string NTV2OutputCrosspointIDToString(const NTV2OutputCrosspointID inValue, const bool inForRetailDisplay=false)
Definition: ntv2utils.cpp:5959
static bool GetWidgetsForInput(const NTV2InputXptID inInputXpt, NTV2WidgetIDSet &outWidgetIDs)
Returns the widgets that "own" the specified input crosspoint.
std::map< NTV2InputXptID, NTV2OutputXptID > NTV2XptConnections
virtual bool ResetFrom(const NTV2XptConnections &inConnections)
Resets me, replacing any/all existing connections with the given connections.
std::vector< std::string > NTV2StringList
static std::string NTV2OutputCrosspointIDToString(const NTV2OutputXptID inOutputXpt)
Returns a string containing the most compact human-readable form for a given output crosspoint...
static bool IsYUVOnlyInputXpt(const NTV2InputXptID inInputXpt)
std::vector< NTV2RegInfo > NTV2RegisterWrites
static NTV2Channel WidgetIDToChannel(const NTV2WidgetID inWidgetID)
#define NTV2_INPUT_SOURCE_IS_SDI(_inpSrc_)
Definition: ntv2enums.h:1285
std::string & lower(std::string &str)
Definition: common.cpp:436
#define SRFAIL(__x__)
NTV2RegWrites NTV2RegReads
An ordered sequence of zero or more NTV2RegInfo structs intended for ReadRegister.
#define NTV2_IS_VALID_WIDGET(__w__)
Definition: ntv2enums.h:3048
#define SRWARN(__x__)
static NTV2WidgetType WidgetIDToType(const NTV2WidgetID inWidgetID)
static bool GetAllWidgetOutputs(const NTV2DeviceID inDeviceID, NTV2OutputXptIDSet &outOutputs)
Returns all supported widget output crosspoints for the given device.
std::string & replace(std::string &str, const std::string &from, const std::string &to)
Definition: common.cpp:110
NTV2OutputXptID GetSDIInputOutputXptFromChannel(const NTV2Channel inChannel, const bool inIsDS2)
static NTV2OutputXptID StringToNTV2OutputCrosspointID(const std::string &inStr)
Returns the output crosspoint that corresponds to the given string.
std::set< NTV2OutputXptID > NTV2OutputXptIDSet
A collection of distinct NTV2OutputXptID values.
static bool GetWidgetInputs(const NTV2WidgetID inWidgetID, NTV2InputXptIDSet &outInputs)
Returns the input crosspoints known to be "owned" by the given widget.
enum NTV2OutputCrosspointID NTV2OutputXptID
NTV2InputXptID GetOutputDestInputXpt(const NTV2OutputDestination inOutputDest, const bool inIsSDI_DS2, const UWord inHDMI_Quadrant)
#define NTV2_WIDGET_FIRST
Identifies firmware widgets that logically can have zero or more signal inputs (identified by NTV2Inp...
Definition: ntv2enums.h:2911
Declares the CNTV2RegisterExpert class.
NTV2RegReadsConstIter FindFirstMatchingRegisterNumber(const uint32_t inRegNum, const NTV2RegReads &inRegInfos)
Returns a const iterator to the first entry in the NTV2RegInfo collection with a matching register nu...
static bool IsHDMIInWidgetType(const NTV2WidgetType inWidgetType)
static bool IsSDIInputWidgetType(const NTV2WidgetType inWidgetType)