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 "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 char *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 char *str)
170 {
171  for (int i = 0; i < (int)(sizeof(rchEventType) / sizeof(rchEventType[0])); i++)
172  {
173  if (strcasecmp(str, rchEventType[i]) == 0)
174  {
175  return (i + 1); // Numbered from 1
176  }
177  }
178 
179  return 0;
180 }
181 
183 {
184  if (ev > 0 && ev <= (int)(sizeof(rchEventType) / sizeof(rchEventType[0])))
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 <= (int)(sizeof(rchEventType) / sizeof(rchEventType[0])));
201  PrintTabs(fd, nTabs + 1);
202  fprintf(fd, ":EventType %s\n", 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 }
bool m_fBoolVal
Definition: BaseClasses.h:293
static void Failure(const char *p)
Definition: ParseNode.cpp:43
int m_nIntVal
Definition: BaseClasses.h:292
void PrintMe(FILE *fd, int nTabs) const override
#define P_EVENT_TYPE
Definition: ASN1Codes.h:292
void PrintMe(FILE *fd, int nTabs) const
enum NodeType m_nNodeType
Definition: ParseNode.h:46
virtual void Activation(MHEngine *engine)
Definition: Root.cpp:69
QString Printable() const
virtual void Deactivation(MHEngine *engine)
Definition: Root.cpp:85
enum MHUnion::UnionTypes U_None
void AddLink(MHLink *pLink)
Definition: Engine.cpp:713
#define C_LINK_CONDITION
Definition: ASN1Codes.h:95
void RemoveLink(MHLink *pLink)
Definition: Engine.cpp:718
virtual void Initialise(MHParseNode *p, MHEngine *engine)
Definition: Actions.cpp:67
void PrintTabs(FILE *fd, int n)
Definition: ParseNode.cpp:34
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Ingredients.cpp:49
int GetIntValue()
Definition: ParseNode.cpp:170
void EventTriggered(MHRoot *pSource, enum EventType ev)
Definition: Engine.h:93
bool Equal(const MHOctetString &str) const
Definition: BaseClasses.h:120
void GetStringValue(MHOctetString &str)
Definition: ParseNode.cpp:203
MHParseNode * GetNamedArg(int nTag)
Definition: ParseNode.cpp:110
void PrintMe(FILE *fd, int nTabs) const
#define MHASSERT(f)
Definition: Logging.h:30
bool m_fRunning
Definition: Root.h:208
MHObjectRef m_ObjectReference
Definition: Root.h:203
bool Equal(const MHObjectRef &objr, MHEngine *engine) const
int FILE
Definition: mythburn.py:110
int GetEnumValue()
Definition: ParseNode.cpp:181
MHOctetString m_StrVal
Definition: BaseClasses.h:294
#define MHLOG(__level, __text)
Definition: Logging.h:36
int GetArgCount()
Definition: ParseNode.cpp:60
bool GetBoolValue()
Definition: ParseNode.cpp:192
#define P_EVENT_DATA
Definition: ASN1Codes.h:293
void Initialise(MHParseNode *p, MHEngine *engine)
#define P_EVENT_SOURCE
Definition: ASN1Codes.h:291
virtual void PrintMe(FILE *fd, int nTabs) const
Definition: Actions.cpp:468
#define C_LINK_EFFECT
Definition: ASN1Codes.h:96
MHParseNode * GetArgN(int n)
Definition: ParseNode.cpp:78
EventType
Definition: Root.h:33
void AddActions(const MHActionSequence &actions)
Definition: Engine.cpp:724