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 
22 #include "libmythbase/compat.h"
23 
24 #include "Link.h"
25 #include "Ingredients.h"
26 #include "Root.h"
27 #include "BaseClasses.h"
28 #include "ParseNode.h"
29 #include "ASN1Codes.h"
30 #include "Actions.h"
31 #include "Engine.h"
32 #include "Logging.h"
33 
35 {
37 }
38 
40 {
41  MHIngredient::Initialise(p, engine);
42  // The link condition is encoded differently in the binary and text representations.
43  MHParseNode *pLinkCond = p->GetNamedArg(C_LINK_CONDITION);
44 
45  if (pLinkCond) // Only in binary.
46  {
47  m_eventSource.Initialise(pLinkCond->GetArgN(0), engine); // Event source
48  m_nEventType = (enum EventType)pLinkCond->GetArgN(1)->GetEnumValue(); // Event type
49  // The event data is optional and type-dependent.
50  if (pLinkCond->GetArgCount() >= 3)
51  {
52  MHParseNode *pEventData = pLinkCond->GetArgN(2);
53 
54  switch (pEventData->m_nNodeType)
55  {
57  m_eventData.m_fBoolVal = pEventData->GetBoolValue();
59  break;
60  case MHParseNode::PNInt:
61  m_eventData.m_nIntVal = pEventData->GetIntValue();
62  m_eventData.m_Type = MHUnion::U_Int;
63  break;
65  pEventData->GetStringValue(m_eventData.m_strVal);
67  break;
68  default:
69  MHParseNode::Failure("Unknown type of event data");
70  }
71  }
72  }
73  else // Only in text.
74  {
75  MHParseNode *pEventSource = p->GetNamedArg(P_EVENT_SOURCE); // Event source
76 
77  if (! pEventSource)
78  {
79  MHParseNode::Failure("Missing :EventSource");
80  }
81  else
82  {
83  m_eventSource.Initialise(pEventSource->GetArgN(0), engine);
84  }
85 
86  MHParseNode *pEventType = p->GetNamedArg(P_EVENT_TYPE); // Event type
87 
88  if (! pEventType)
89  {
90  MHParseNode::Failure("Missing :EventType");
91  }
92  else
93  {
94  m_nEventType = (enum EventType)pEventType->GetArgN(0)->GetEnumValue();
95  }
96 
97  MHParseNode *pEventData = p->GetNamedArg(P_EVENT_DATA); // Event data - optional
98 
99  if (pEventData)
100  {
101  MHParseNode *pEventDataArg = pEventData->GetArgN(0);
102 
103  switch (pEventDataArg->m_nNodeType)
104  {
105  case MHParseNode::PNBool:
106  m_eventData.m_fBoolVal = pEventDataArg->GetBoolValue();
107  m_eventData.m_Type = MHUnion::U_Bool;
108  break;
109  case MHParseNode::PNInt:
110  m_eventData.m_nIntVal = pEventDataArg->GetIntValue();
111  m_eventData.m_Type = MHUnion::U_Int;
112  break;
114  pEventDataArg->GetStringValue(m_eventData.m_strVal);
116  break;
117  default:
118  MHParseNode::Failure("Unknown type of event data");
119  }
120  }
121  }
122 
123  MHParseNode *pLinkEffect = p->GetNamedArg(C_LINK_EFFECT);
124 
125  if (pLinkEffect)
126  {
127  m_linkEffect.Initialise(pLinkEffect, engine);
128  }
129 }
130 
131 static const std::array<const QString,33> rchEventType
132 {
133  "IsAvailable",
134  "ContentAvailable",
135  "IsDeleted",
136  "IsRunning",
137  "IsStopped",
138  "UserInput",
139  "AnchorFired",
140  "TimerFired",
141  "AsyncStopped",
142  "InteractionCompleted",
143  "TokenMovedFrom",
144  "TokenMovedTo",
145  "StreamEvent",
146  "StreamPlaying",
147  "StreamStopped",
148  "CounterTrigger",
149  "HighlightOn",
150  "HighlightOff",
151  "CursorEnter",
152  "CursorLeave",
153  "IsSelected",
154  "IsDeselected",
155  "TestEvent",
156  "FirstItemPresented",
157  "LastItemPresented",
158  "HeadItems",
159  "TailItems",
160  "ItemSelected",
161  "ItemDeselected",
162  "EntryFieldFull",
163  "EngineEvent",
164  "FocusMoved",
165  "SliderValueChanged"
166 };
167 
168 // Look up the event type. Returns zero if it doesn't match.
169 int MHLink::GetEventType(const QString& str)
170 {
171  for (size_t i = 0; i < rchEventType.size(); i++)
172  {
173  if (str.compare(rchEventType[i], Qt::CaseInsensitive) == 0)
174  {
175  return (i + 1); // Numbered from 1
176  }
177  }
178 
179  return 0;
180 }
181 
183 {
184  if (ev > 0 && ev <= rchEventType.size())
185  {
186  return rchEventType[ev-1];
187  }
188  return QString("Unknown event %1").arg(ev);
189 }
190 
191 void MHLink::PrintMe(FILE *fd, int nTabs) const
192 {
193  PrintTabs(fd, nTabs);
194  fprintf(fd, "{:Link");
195  MHIngredient::PrintMe(fd, nTabs + 1);
196  PrintTabs(fd, nTabs + 1);
197  fprintf(fd, ":EventSource ");
198  m_eventSource.PrintMe(fd, nTabs + 1);
199  fprintf(fd, "\n");
200  MHASSERT(m_nEventType > 0 && m_nEventType <= rchEventType.size());
201  PrintTabs(fd, nTabs + 1);
202  fprintf(fd, ":EventType %s\n", qPrintable(rchEventType[m_nEventType-1]));
203 
204  // The event data is optional and its format depends on the event type.
205  switch (m_eventData.m_Type)
206  {
207  case MHUnion::U_Bool:
208  PrintTabs(fd, nTabs + 1);
209  fprintf(fd, ":EventData %s\n", m_eventData.m_fBoolVal ? "true" : "false");
210  break;
211  case MHUnion::U_Int:
212  PrintTabs(fd, nTabs + 1);
213  fprintf(fd, ":EventData %d\n", m_eventData.m_nIntVal);
214  break;
215  case MHUnion::U_String:
216  PrintTabs(fd, nTabs + 1);
217  fprintf(fd, ":EventData");
218  m_eventData.m_strVal.PrintMe(fd, nTabs);
219  fprintf(fd, "\n");
220  break;
221  default:
222  break; // None and others
223  }
224 
225  PrintTabs(fd, nTabs + 1);
226  fprintf(fd, ":LinkEffect (\n");
227  m_linkEffect.PrintMe(fd, nTabs + 2);
228  PrintTabs(fd, nTabs + 1);
229  fprintf(fd, ")\n");
230  PrintTabs(fd, nTabs);
231  fprintf(fd, "}\n");
232 }
233 
234 // Activation.
236 {
237  if (m_fRunning)
238  {
239  return;
240  }
241 
242  MHIngredient::Activation(engine);
243  m_fRunning = true;
244  engine->AddLink(this);
245  engine->EventTriggered(this, EventIsRunning);
246 }
247 
249 {
250  if (! m_fRunning)
251  {
252  return;
253  }
254 
255  engine->RemoveLink(this);
257 }
258 
259 // Activate or deactivate the link.
260 void MHLink::Activate(bool fActivate, MHEngine *engine)
261 {
262  if (fActivate)
263  {
264  if (! m_fRunning)
265  {
266  Activation(engine);
267  }
268  }
269  else
270  {
271  if (m_fRunning)
272  {
273  Deactivation(engine);
274  }
275  }
276 }
277 
278 // Check this link to see if the event matches the requirements. If the link does not specify
279 // any event data the link fires whatever the value of the data.
280 void MHLink::MatchEvent(const MHObjectRef &sourceRefRef, enum EventType ev, const MHUnion &evData, MHEngine *engine)
281 {
282  if (m_fRunning && m_nEventType == ev && sourceRefRef.Equal(m_eventSource, engine)) // Source and event type match.
283  {
284  bool fMatch = false;
285 
286  switch (m_eventData.m_Type)
287  {
288  case MHUnion::U_None:
289  fMatch = true;
290  break; // No data specified - always matches.
291  case MHUnion::U_Bool:
292  fMatch = evData.m_Type == MHUnion::U_Bool && evData.m_fBoolVal == m_eventData.m_fBoolVal;
293  break;
294  case MHUnion::U_Int:
295  fMatch = evData.m_Type == MHUnion::U_Int && evData.m_nIntVal == m_eventData.m_nIntVal;
296  break;
297  case MHUnion::U_String:
298  fMatch = evData.m_Type == MHUnion::U_String && evData.m_strVal.Equal(m_eventData.m_strVal);
299  break;
300  default:
301  fMatch = false;
302  break;
303  }
304 
305  // Fire the link
306  if (fMatch)
307  {
308  MHLOG(MHLogLinks, QString("Link fired - %1").arg(m_ObjectReference.Printable()));
309  engine->AddActions(m_linkEffect);
310  }
311  }
312 }
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
P_EVENT_SOURCE
@ P_EVENT_SOURCE
Definition: ASN1Codes.h:296
MHObjectRef::Initialise
void Initialise(MHParseNode *p, MHEngine *engine)
Definition: BaseClasses.cpp:278
MHRoot::Deactivation
virtual void Deactivation(MHEngine *engine)
Definition: Root.cpp:86
MHLogLinks
@ MHLogLinks
Definition: freemheg.h:76
ASN1Codes.h
MHEngine
Definition: Engine.h:72
MHParseNode::GetIntValue
int GetIntValue()
Definition: ParseNode.cpp:170
MHIngredient::Initialise
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Ingredients.cpp:49
MHUnion::m_nIntVal
int m_nIntVal
Definition: BaseClasses.h:302
MHUnion::U_Int
@ U_Int
Definition: BaseClasses.h:298
MHEngine::AddLink
void AddLink(MHLink *pLink)
Definition: Engine.cpp:712
EventIsRunning
@ EventIsRunning
Definition: Root.h:33
Actions.h
mythburn.FILE
int FILE
Definition: mythburn.py:139
MHOctetString::PrintMe
void PrintMe(FILE *fd, int nTabs) const
Definition: BaseClasses.cpp:154
MHUnion::m_fBoolVal
bool m_fBoolVal
Definition: BaseClasses.h:303
MHObjectRef::Equal
bool Equal(const MHObjectRef &objr, MHEngine *engine) const
Definition: BaseClasses.cpp:331
MHRoot::m_fRunning
bool m_fRunning
Definition: Root.h:252
MHRoot::m_ObjectReference
MHObjectRef m_ObjectReference
Definition: Root.h:247
MHASSERT
#define MHASSERT(f)
Definition: Logging.h:30
P_EVENT_TYPE
@ P_EVENT_TYPE
Definition: ASN1Codes.h:297
MHEngine::EventTriggered
void EventTriggered(MHRoot *pSource, enum EventType ev)
Definition: Engine.h:94
MHUnion
Definition: BaseClasses.h:283
hardwareprofile.config.p
p
Definition: config.py:33
ParseNode.h
compat.h
C_LINK_CONDITION
@ C_LINK_CONDITION
Definition: ASN1Codes.h:98
EventType
EventType
Definition: Root.h:33
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:107
MHLOG
#define MHLOG(__level, __text)
Definition: Logging.h:36
MHUnion::U_None
enum MHUnion::UnionTypes U_None
Engine.h
Ingredients.h
C_LINK_EFFECT
@ C_LINK_EFFECT
Definition: ASN1Codes.h:99
MHParseNode::GetArgCount
int GetArgCount()
Definition: ParseNode.cpp:60
MHEngine::AddActions
void AddActions(const MHActionSequence &actions)
Definition: Engine.cpp:723
MHParseNode::GetBoolValue
bool GetBoolValue()
Definition: ParseNode.cpp:192
Root.h
MHActionSequence::Initialise
virtual void Initialise(MHParseNode *p, MHEngine *engine)
Definition: Actions.cpp:67
MHParseNode::Failure
static void Failure(const char *p)
Definition: ParseNode.cpp:43
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_String
@ U_String
Definition: BaseClasses.h:298
MHParseNode::GetEnumValue
int GetEnumValue()
Definition: ParseNode.cpp:181
MHParseNode::GetStringValue
void GetStringValue(MHOctetString &str)
Definition: ParseNode.cpp:203
MHParseNode::PNString
@ PNString
Definition: ParseNode.h:41
MHOctetString::Equal
bool Equal(const MHOctetString &str) const
Definition: BaseClasses.h:123
Logging.h
MHEngine::RemoveLink
void RemoveLink(MHLink *pLink)
Definition: Engine.cpp:717
MHUnion::m_strVal
MHOctetString m_strVal
Definition: BaseClasses.h:304
MHParseNode::PNInt
@ PNInt
Definition: ParseNode.h:41
MHObjectRef::PrintMe
void PrintMe(FILE *fd, int nTabs) const
Definition: BaseClasses.cpp:299
MHUnion::U_Bool
@ U_Bool
Definition: BaseClasses.h:298
P_EVENT_DATA
@ P_EVENT_DATA
Definition: ASN1Codes.h:298
MHObjectRef::Printable
QString Printable() const
Definition: BaseClasses.cpp:313