MythTV  master
Link.cpp
Go to the documentation of this file.
1 /* Link.cpp
2 
3  Copyright (C) David C. J. Matthews 2004, 2008 dm at prolingua.co.uk
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU General Public License
7  as published by the Free Software Foundation; either version 2
8  of the License, or (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18  Or, point your browser to http://www.gnu.org/copyleft/gpl.html
19 
20 */
21 #include "Link.h"
22 
23 #include <array>
24 #include <cstdio>
25 
26 #include <QString>
27 
28 #include "Ingredients.h"
29 #include "Root.h"
30 #include "BaseClasses.h"
31 #include "ParseNode.h"
32 #include "ASN1Codes.h"
33 #include "Actions.h"
34 #include "Engine.h"
35 #include "Logging.h"
36 
38 {
40 }
41 
43 {
44  MHIngredient::Initialise(p, engine);
45  // The link condition is encoded differently in the binary and text representations.
46  MHParseNode *pLinkCond = p->GetNamedArg(C_LINK_CONDITION);
47 
48  if (pLinkCond) // Only in binary.
49  {
50  m_eventSource.Initialise(pLinkCond->GetArgN(0), engine); // Event source
51  m_nEventType = (enum EventType)pLinkCond->GetArgN(1)->GetEnumValue(); // Event type
52  // The event data is optional and type-dependent.
53  if (pLinkCond->GetArgCount() >= 3)
54  {
55  MHParseNode *pEventData = pLinkCond->GetArgN(2);
56 
57  switch (pEventData->m_nNodeType)
58  {
60  m_eventData.m_fBoolVal = pEventData->GetBoolValue();
62  break;
63  case MHParseNode::PNInt:
64  m_eventData.m_nIntVal = pEventData->GetIntValue();
65  m_eventData.m_Type = MHUnion::U_Int;
66  break;
68  pEventData->GetStringValue(m_eventData.m_strVal);
70  break;
71  default:
72  MHParseNode::Failure("Unknown type of event data");
73  }
74  }
75  }
76  else // Only in text.
77  {
78  MHParseNode *pEventSource = p->GetNamedArg(P_EVENT_SOURCE); // Event source
79 
80  if (! pEventSource)
81  {
82  MHParseNode::Failure("Missing :EventSource");
83  }
84  else
85  {
86  m_eventSource.Initialise(pEventSource->GetArgN(0), engine);
87  }
88 
89  MHParseNode *pEventType = p->GetNamedArg(P_EVENT_TYPE); // Event type
90 
91  if (! pEventType)
92  {
93  MHParseNode::Failure("Missing :EventType");
94  }
95  else
96  {
97  m_nEventType = (enum EventType)pEventType->GetArgN(0)->GetEnumValue();
98  }
99 
100  MHParseNode *pEventData = p->GetNamedArg(P_EVENT_DATA); // Event data - optional
101 
102  if (pEventData)
103  {
104  MHParseNode *pEventDataArg = pEventData->GetArgN(0);
105 
106  switch (pEventDataArg->m_nNodeType)
107  {
108  case MHParseNode::PNBool:
109  m_eventData.m_fBoolVal = pEventDataArg->GetBoolValue();
110  m_eventData.m_Type = MHUnion::U_Bool;
111  break;
112  case MHParseNode::PNInt:
113  m_eventData.m_nIntVal = pEventDataArg->GetIntValue();
114  m_eventData.m_Type = MHUnion::U_Int;
115  break;
117  pEventDataArg->GetStringValue(m_eventData.m_strVal);
119  break;
120  default:
121  MHParseNode::Failure("Unknown type of event data");
122  }
123  }
124  }
125 
126  MHParseNode *pLinkEffect = p->GetNamedArg(C_LINK_EFFECT);
127 
128  if (pLinkEffect)
129  {
130  m_linkEffect.Initialise(pLinkEffect, engine);
131  }
132 }
133 
134 static const std::array<const QString,33> rchEventType
135 {
136  "IsAvailable",
137  "ContentAvailable",
138  "IsDeleted",
139  "IsRunning",
140  "IsStopped",
141  "UserInput",
142  "AnchorFired",
143  "TimerFired",
144  "AsyncStopped",
145  "InteractionCompleted",
146  "TokenMovedFrom",
147  "TokenMovedTo",
148  "StreamEvent",
149  "StreamPlaying",
150  "StreamStopped",
151  "CounterTrigger",
152  "HighlightOn",
153  "HighlightOff",
154  "CursorEnter",
155  "CursorLeave",
156  "IsSelected",
157  "IsDeselected",
158  "TestEvent",
159  "FirstItemPresented",
160  "LastItemPresented",
161  "HeadItems",
162  "TailItems",
163  "ItemSelected",
164  "ItemDeselected",
165  "EntryFieldFull",
166  "EngineEvent",
167  "FocusMoved",
168  "SliderValueChanged"
169 };
170 
171 // Look up the event type. Returns zero if it doesn't match.
172 int MHLink::GetEventType(const QString& str)
173 {
174  for (size_t i = 0; i < rchEventType.size(); i++)
175  {
176  if (str.compare(rchEventType[i], Qt::CaseInsensitive) == 0)
177  {
178  return (i + 1); // Numbered from 1
179  }
180  }
181 
182  return 0;
183 }
184 
186 {
187  if (ev > 0 && ev <= rchEventType.size())
188  {
189  return rchEventType[ev-1];
190  }
191  return QString("Unknown event %1").arg(ev);
192 }
193 
194 void MHLink::PrintMe(FILE *fd, int nTabs) const
195 {
196  PrintTabs(fd, nTabs);
197  fprintf(fd, "{:Link");
198  MHIngredient::PrintMe(fd, nTabs + 1);
199  PrintTabs(fd, nTabs + 1);
200  fprintf(fd, ":EventSource ");
201  m_eventSource.PrintMe(fd, nTabs + 1);
202  fprintf(fd, "\n");
203  MHASSERT(m_nEventType > 0 && m_nEventType <= rchEventType.size());
204  PrintTabs(fd, nTabs + 1);
205  fprintf(fd, ":EventType %s\n", qPrintable(rchEventType[m_nEventType-1]));
206 
207  // The event data is optional and its format depends on the event type.
208  switch (m_eventData.m_Type)
209  {
210  case MHUnion::U_Bool:
211  PrintTabs(fd, nTabs + 1);
212  fprintf(fd, ":EventData %s\n", m_eventData.m_fBoolVal ? "true" : "false");
213  break;
214  case MHUnion::U_Int:
215  PrintTabs(fd, nTabs + 1);
216  fprintf(fd, ":EventData %d\n", m_eventData.m_nIntVal);
217  break;
218  case MHUnion::U_String:
219  PrintTabs(fd, nTabs + 1);
220  fprintf(fd, ":EventData");
221  m_eventData.m_strVal.PrintMe(fd, nTabs);
222  fprintf(fd, "\n");
223  break;
224  default:
225  break; // None and others
226  }
227 
228  PrintTabs(fd, nTabs + 1);
229  fprintf(fd, ":LinkEffect (\n");
230  m_linkEffect.PrintMe(fd, nTabs + 2);
231  PrintTabs(fd, nTabs + 1);
232  fprintf(fd, ")\n");
233  PrintTabs(fd, nTabs);
234  fprintf(fd, "}\n");
235 }
236 
237 // Activation.
239 {
240  if (m_fRunning)
241  {
242  return;
243  }
244 
245  MHIngredient::Activation(engine);
246  m_fRunning = true;
247  engine->AddLink(this);
248  engine->EventTriggered(this, EventIsRunning);
249 }
250 
252 {
253  if (! m_fRunning)
254  {
255  return;
256  }
257 
258  engine->RemoveLink(this);
260 }
261 
262 // Activate or deactivate the link.
263 void MHLink::Activate(bool fActivate, MHEngine *engine)
264 {
265  if (fActivate)
266  {
267  if (! m_fRunning)
268  {
269  Activation(engine);
270  }
271  }
272  else
273  {
274  if (m_fRunning)
275  {
276  Deactivation(engine);
277  }
278  }
279 }
280 
281 // Check this link to see if the event matches the requirements. If the link does not specify
282 // any event data the link fires whatever the value of the data.
283 void MHLink::MatchEvent(const MHObjectRef &sourceRefRef, enum EventType ev, const MHUnion &evData, MHEngine *engine)
284 {
285  if (m_fRunning && m_nEventType == ev && sourceRefRef.Equal(m_eventSource, engine)) // Source and event type match.
286  {
287  bool fMatch = false;
288 
289  switch (m_eventData.m_Type)
290  {
291  case MHUnion::U_None:
292  fMatch = true;
293  break; // No data specified - always matches.
294  case MHUnion::U_Bool:
295  fMatch = evData.m_Type == MHUnion::U_Bool && evData.m_fBoolVal == m_eventData.m_fBoolVal;
296  break;
297  case MHUnion::U_Int:
298  fMatch = evData.m_Type == MHUnion::U_Int && evData.m_nIntVal == m_eventData.m_nIntVal;
299  break;
300  case MHUnion::U_String:
301  fMatch = evData.m_Type == MHUnion::U_String && evData.m_strVal.Equal(m_eventData.m_strVal);
302  break;
303  default:
304  fMatch = false;
305  break;
306  }
307 
308  // Fire the link
309  if (fMatch)
310  {
311  MHLOG(MHLogLinks, QString("Link fired - %1").arg(m_ObjectReference.Printable()));
312  engine->AddActions(m_linkEffect);
313  }
314  }
315 }
MHRoot::Activation
virtual void Activation(MHEngine *engine)
Definition: Root.cpp:70
MHObjectRef
Definition: BaseClasses.h:153
MHParseNode::m_nNodeType
enum NodeType m_nNodeType
Definition: ParseNode.h:46
MHObjectRef::Initialise
void Initialise(MHParseNode *p, MHEngine *engine)
Definition: BaseClasses.cpp:263
MHRoot::Deactivation
virtual void Deactivation(MHEngine *engine)
Definition: Root.cpp:86
ASN1Codes.h
MHEngine
Definition: Engine.h:72
MHParseNode::GetIntValue
int GetIntValue()
Definition: ParseNode.cpp:170
MHParseNode::PNString
@ PNString
Definition: ParseNode.h:41
MHIngredient::Initialise
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Ingredients.cpp:50
MHUnion::m_nIntVal
int m_nIntVal
Definition: BaseClasses.h:302
MHUnion::U_String
@ U_String
Definition: BaseClasses.h:298
C_LINK_EFFECT
@ C_LINK_EFFECT
Definition: ASN1Codes.h:99
MHEngine::AddLink
void AddLink(MHLink *pLink)
Definition: Engine.cpp:724
Actions.h
mythburn.FILE
int FILE
Definition: mythburn.py:139
MHOctetString::PrintMe
void PrintMe(FILE *fd, int nTabs) const
Definition: BaseClasses.cpp:142
MHUnion::m_fBoolVal
bool m_fBoolVal
Definition: BaseClasses.h:303
MHObjectRef::Equal
bool Equal(const MHObjectRef &objr, MHEngine *engine) const
Definition: BaseClasses.cpp:316
MHRoot::m_fRunning
bool m_fRunning
Definition: Root.h:253
MHUnion::U_Int
@ U_Int
Definition: BaseClasses.h:298
MHRoot::m_ObjectReference
MHObjectRef m_ObjectReference
Definition: Root.h:248
MHASSERT
#define MHASSERT(f)
Definition: Logging.h:30
MHEngine::EventTriggered
void EventTriggered(MHRoot *pSource, enum EventType ev)
Definition: Engine.h:94
MHUnion
Definition: BaseClasses.h:283
EventType
EventType
Definition: Root.h:33
hardwareprofile.config.p
p
Definition: config.py:33
ParseNode.h
PrintTabs
void PrintTabs(FILE *fd, int n)
Definition: ParseNode.cpp:34
MHParseNode::GetArgN
MHParseNode * GetArgN(int n)
Definition: ParseNode.cpp:78
MHIngredient::PrintMe
void PrintMe(FILE *fd, int nTabs) const override
Definition: Ingredients.cpp:108
EventIsRunning
@ EventIsRunning
Definition: Root.h:34
MHLOG
#define MHLOG(__level, __text)
Definition: Logging.h:36
P_EVENT_SOURCE
@ P_EVENT_SOURCE
Definition: ASN1Codes.h:296
MHUnion::U_None
enum MHUnion::UnionTypes U_None
Engine.h
Ingredients.h
MHParseNode::GetArgCount
int GetArgCount()
Definition: ParseNode.cpp:60
MHEngine::AddActions
void AddActions(const MHActionSequence &actions)
Definition: Engine.cpp:735
P_EVENT_TYPE
@ P_EVENT_TYPE
Definition: ASN1Codes.h:297
MHParseNode::GetBoolValue
bool GetBoolValue()
Definition: ParseNode.cpp:192
Root.h
MHActionSequence::Initialise
virtual void Initialise(MHParseNode *p, MHEngine *engine)
Definition: Actions.cpp:67
MHLogLinks
@ MHLogLinks
Definition: freemheg.h:76
MHParseNode::Failure
static void Failure(const char *p)
Definition: ParseNode.cpp:43
P_EVENT_DATA
@ P_EVENT_DATA
Definition: ASN1Codes.h:298
MHParseNode::PNBool
@ PNBool
Definition: ParseNode.h:41
BaseClasses.h
MHParseNode
Definition: ParseNode.h:38
MHActionSequence::PrintMe
virtual void PrintMe(FILE *fd, int nTabs) const
Definition: Actions.cpp:456
MHUnion::U_Bool
@ U_Bool
Definition: BaseClasses.h:298
MHParseNode::GetEnumValue
int GetEnumValue()
Definition: ParseNode.cpp:181
C_LINK_CONDITION
@ C_LINK_CONDITION
Definition: ASN1Codes.h:98
MHParseNode::GetStringValue
void GetStringValue(MHOctetString &str)
Definition: ParseNode.cpp:203
MHOctetString::Equal
bool Equal(const MHOctetString &str) const
Definition: BaseClasses.h:123
Logging.h
MHEngine::RemoveLink
void RemoveLink(MHLink *pLink)
Definition: Engine.cpp:729
MHParseNode::PNInt
@ PNInt
Definition: ParseNode.h:41
MHUnion::m_strVal
MHOctetString m_strVal
Definition: BaseClasses.h:304
MHObjectRef::PrintMe
void PrintMe(FILE *fd, int nTabs) const
Definition: BaseClasses.cpp:284
MHObjectRef::Printable
QString Printable() const
Definition: BaseClasses.cpp:298