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{
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;
64 m_eventData.m_nIntVal = pEventData->GetIntValue();
66 break;
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 {
109 m_eventData.m_fBoolVal = pEventDataArg->GetBoolValue();
111 break;
113 m_eventData.m_nIntVal = pEventDataArg->GetIntValue();
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
134static 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.
172int 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
194void 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;
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
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.
263void 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.
283void 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;
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}
@ P_EVENT_DATA
Definition: ASN1Codes.h:298
@ P_EVENT_TYPE
Definition: ASN1Codes.h:297
@ P_EVENT_SOURCE
Definition: ASN1Codes.h:296
@ C_LINK_CONDITION
Definition: ASN1Codes.h:98
@ C_LINK_EFFECT
Definition: ASN1Codes.h:99
#define MHASSERT(f)
Definition: Logging.h:30
#define MHLOG(__level, __text)
Definition: Logging.h:36
void PrintTabs(FILE *fd, int n)
Definition: ParseNode.cpp:34
EventType
Definition: Root.h:34
@ EventIsRunning
Definition: Root.h:34
virtual void PrintMe(FILE *fd, int nTabs) const
Definition: Actions.cpp:456
virtual void Initialise(MHParseNode *p, MHEngine *engine)
Definition: Actions.cpp:67
void AddLink(MHLink *pLink)
Definition: Engine.cpp:718
void RemoveLink(MHLink *pLink)
Definition: Engine.cpp:723
void EventTriggered(MHRoot *pSource, enum EventType ev)
Definition: Engine.h:94
void AddActions(const MHActionSequence &actions)
Definition: Engine.cpp:729
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Ingredients.cpp:50
void PrintMe(FILE *fd, int nTabs) const override
bool Equal(const MHObjectRef &objr, MHEngine *engine) const
QString Printable() const
void PrintMe(FILE *fd, int nTabs) const
void Initialise(MHParseNode *p, MHEngine *engine)
void PrintMe(FILE *fd, int nTabs) const
bool Equal(const MHOctetString &str) const
Definition: BaseClasses.h:123
MHParseNode * GetArgN(int n)
Definition: ParseNode.cpp:78
static void Failure(const char *p)
Definition: ParseNode.cpp:43
int GetEnumValue()
Definition: ParseNode.cpp:181
void GetStringValue(MHOctetString &str)
Definition: ParseNode.cpp:203
int GetArgCount()
Definition: ParseNode.cpp:60
bool GetBoolValue()
Definition: ParseNode.cpp:192
enum NodeType m_nNodeType
Definition: ParseNode.h:46
int GetIntValue()
Definition: ParseNode.cpp:170
virtual void Activation(MHEngine *engine)
Definition: Root.cpp:70
MHObjectRef m_ObjectReference
Definition: Root.h:248
virtual void Deactivation(MHEngine *engine)
Definition: Root.cpp:86
bool m_fRunning
Definition: Root.h:253
bool m_fBoolVal
Definition: BaseClasses.h:303
int m_nIntVal
Definition: BaseClasses.h:302
enum MHUnion::UnionTypes U_None
MHOctetString m_strVal
Definition: BaseClasses.h:304
@ MHLogLinks
Definition: freemheg.h:82
int FILE
Definition: mythburn.py:138