MHEG5  18.9.0
MHEG5 Documentation
mh5link.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2004 Ocean Blue Software Ltd
4  * Copyright © 2000 Koninklijke Philips Electronics N.V
5  *
6  * This file is part of a DTVKit Software Component
7  * You are permitted to copy, modify or distribute this file subject to the terms
8  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
9  *
10  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
11  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
12  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
13  *
14  * If you or your organisation is not a member of DTVKit then you have access
15  * to this source code outside of the terms of the licence agreement
16  * and you are expected to delete this and any associated files immediately.
17  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
18  *******************************************************************************/
32 /*---includes for this file--------------------------------------------------*/
33 #include "mh5link.h"
34 #include "mh5memory.h" /* for constructor */
35 #include "mh5object.h" /* for actions */
36 #include "mh5variable.h" /* for actions */
37 #include "mh5streamevent.h"
38 #include "mh5queue.h"
39 #include "mh5debug.h"
40 
41 #ifdef MH5PRINTOUT
42 #include <string.h>
43 #endif /* #ifdef MH5PRINTOUT */
44 
45 #ifdef TRACING
46 #include "mh5eventtokens.h"
47 #endif
48 
49 /*---constant definitions for this file--------------------------------------*/
50 #define MAX_REG_STRINGS 32
51 
52 
53 /*---local typedef structs for this file-------------------------------------*/
54 
55 typedef struct s_LinkString
56 {
59 } S_LinkString;
60 
61 /*---local (static) variable declarations for this file----------------------*/
62 
63 /* Linked list of Link objects that are currently active. This list is checked
64  * when processing events to see whether any Links fire.
65  */
67 unsigned int existsLinkCount[MHEG5LASTEVENT + 1];
68 
69 static S_LinkString registeredStrings[MAX_REG_STRINGS];
70 static int numberRegistered;
71 
72 static const char htext_top[] = "rec://htext/top";
73 static const char htext_bot[] = "rec://htext/bot";
74 
75 /*---local function definitions----------------------------------------------*/
76 
77 /*---global function definitions---------------------------------------------*/
78 
84 /*
85  Debug
86  */
87 #ifdef MH5PRINTOUT
88 
89 void MHEG5linkPrint(MHEG5Link *link, char *out)
90 {
91  MHEG5ingredientPrint(&link->ingredient, out);
92  MHEG5indent(out);
93  MHEG_PRINT(out, ":EventSource ");
94  if (link->sourcegid.len)
95  {
96  MHEG_PRINT(out, "(");
97  MHEG5stringPrint(*((MHEG5String *)&link->sourcegid), out);
98  MHEG_PRINT(out, " ");
99  MHEG5intPrint(link->source, out);
100  MHEG_PRINT(out, ")");
101  }
102  else
103  MHEG5intPrint(link->source, out);
104  MHEG5newLine(out);
105  MHEG5indent(out);
106  MHEG_PRINT(out, ":EventType ");
107  MHEG5eventPrint(link->eventType, out);
108  MHEG5newLine(out);
109  MHEG5indent(out);
110  if (link->eventData.type != MHEG5NONE)
111  {
112  MHEG_PRINT(out, ":EventData ");
113  MHEG5genericPrint(link->eventData, out, 0);
114  MHEG5newLine(out);
115  MHEG5indent(out);
116  }
117  MHEG_PRINT(out, ":LinkEffect (");
118  MHEG5newLine(out);
119  MHEG5actionPrint(link->linkEffect, out);
120  MHEG5indent(out);
121  MHEG_PRINT(out, ")");
122  MHEG5newLine(out);
123 }
124 
125 #endif
126 
128 {
129  int i;
130  MHEG5EventType et;
131  for (et = MHEG5NONEEVENT; et != (MHEG5LASTEVENT + 1); et++)
132  {
133  activeLinksHead[et] = 0;
134  existsLinkCount[et] = 0;
135  }
136  /* null string */
137  registeredStrings[0].str.len = 0;
138  registeredStrings[0].str.data = NULL;
139  registeredStrings[0].numLinks = 0;
140  /* hypertext top and bottom event strings */
141  registeredStrings[HTEXT_TOP_STR].str.len = 15;
142  registeredStrings[HTEXT_TOP_STR].str.data = (MHEG5Byte *)htext_top;
143  registeredStrings[HTEXT_TOP_STR].numLinks = 0;
144  registeredStrings[HTEXT_BOT_STR].str.len = 15;
145  registeredStrings[HTEXT_BOT_STR].str.data = (MHEG5Byte *)htext_bot;
146  registeredStrings[HTEXT_BOT_STR].numLinks = 0;
147  for (i = 3; i != MAX_REG_STRINGS; i++)
148  {
149  registeredStrings[i].str.len = 0;
150  registeredStrings[i].str.data = NULL;
151  registeredStrings[i].numLinks = 0;
152  }
153  numberRegistered = 3;
154 }
155 
157 {
158  int i;
159  if (s.len == 0)
160  {
161  registeredStrings[0].numLinks++;
162  return 0;
163  }
164  for (i = 1; i != MAX_REG_STRINGS; i++)
165  {
166  if ((registeredStrings[i].str.len == s.len) &&
167  (memcmp(registeredStrings[i].str.data, s.data, s.len) == 0))
168  {
169  MHEG5stringDestruct( &s );
170  registeredStrings[i].numLinks++;
171  return i;
172  }
173  else if (registeredStrings[i].str.len == 0)
174  {
175  if (i == numberRegistered)
176  {
177  numberRegistered++;
178  }
179  registeredStrings[i].numLinks = 1;
180  registeredStrings[i].str.len = s.len;
181  registeredStrings[i].str.data = s.data;
182  return i;
183  }
184  }
185  return -1;
186 }
187 
189 {
190  int i;
191  if (s.len == 0)
192  {
193  return 0;
194  }
195  for (i = 1; i != numberRegistered; i++)
196  {
197  if ((registeredStrings[i].str.len == s.len) &&
198  (memcmp(registeredStrings[i].str.data, s.data, s.len) == 0))
199  {
200  return i;
201  }
202  }
203  return -1;
204 }
205 
207 {
208  return registeredStrings[i].str;
209 }
210 
211 static void LNK_FreeString( MHEG5Int ndx )
212 {
213  int i = numberRegistered - 1;
214  if (registeredStrings[ndx].numLinks)
215  {
216  registeredStrings[ndx].numLinks--;
217  }
218  if ((ndx > HTEXT_BOT_STR) &&
219  registeredStrings[ndx].str.len &&
220  !registeredStrings[ndx].numLinks)
221  {
222  MHEG5stringDestruct( &registeredStrings[ndx].str );
223  }
224  if (ndx == i)
225  {
226  while ((i != HTEXT_BOT_STR) && !registeredStrings[i].str.len)
227  i--;
228  numberRegistered = i + 1;
229  }
230 }
231 
233 {
234  MHEG5String eventName;
235  if (link->eventData.type == (U16BIT)MHEG5INT)
236  {
237  eventName = LNK_GetString((int)link->eventData.value.i );
238  }
239  else
240  {
241  assert( link->eventData.type == (U16BIT)MHEG5NONE );
242  eventName.data = NULL;
243  }
244  return eventName.data;
245 }
246 
253 {
254  assert(link);
255 
257 
258  link->eventData.indirect = MHEG5FALSE;
259  link->eventData.type = MHEG5NONE;
260 }
261 
270 {
271  MHEG5String name;
272  assert(link);
273 
274  assert( existsLinkCount[link->eventType] > 0 );
275  existsLinkCount[link->eventType]--;
276 
278 
279  if (link->eventData.indirect)
280  {
281  LNK_FreeString( link->eventData.value.i );
282  }
283 
285 
286  if (link->sourcegid.len)
287  {
288  name.len = link->sourcegid.len;
289  name.data = link->sourcegid.ptr.name;
290  MHEG5stringDestruct( &name );
291  }
292  //TRACE(TEVNTS,("link %d, src:%d", link->ingredient.root.id,link->source ))
293 }
294 
295 /*
296  Internal behaviours
297  */
298 /*
299  no special Prepare Function
300  */
302 {
303  assert(link);
304 
306 
308 }
309 
310 /*
311  freeMem of Link
312  */
314 {
315  assert(link);
317 
319 }
320 
321 /*
322  Activation
323  Execute the following sequence of actions:
324  1. Apply the Activation behaviour as inherited from the base class.
325  2. Make the Link object receptive to events that fulfil its LinkCondition.
326  3. Set the RunningStatus of the Link to True.
327  4. Generate an IsRunning event.
328  */
330 {
331  assert(link);
332 
333  if (!link->ingredient.root.runningStatus)
334  {
336  {
337  MHEG5linkPrepare( link );
338  }
339  /* Could call the base class activation behaviour, but */
340  /* MHEG5ingredientActivate(&link->ingredient); <- does nothing, so don't bother */
341 
343 
344  #ifdef TRACING
345  if (!(mheg_trace_debug & TACTIONS))
346  {
347  TRACE(TEVNTS, ("link %d, src:%d typ:%s", link->ingredient.root.id, link->source, MHEG5eventToString(link->eventType)))
348  }
349  #endif
350 
351 #ifndef NDEBUG
352  /* Debug checking whether link is already in the list */
353  {
354  MHEG5Link *listItem = activeLinksHead[link->eventType];
355  while (listItem != 0)
356  {
357  assert(listItem != link);
358  listItem = listItem->nextActiveLink;
359  }
360  }
361 #endif
362 
363  /* Add this Link to the list of currently active Link objects
364  */
365  link->nextActiveLink = activeLinksHead[link->eventType];
366  activeLinksHead[link->eventType] = link;
367 
368  MHEG5sendSync((MHEG5Root *) link, MHEG5ISRUNNING, 0);
369 
370  if (link->eventType == MHEG5STREAMEVENT)
371  {
372  /* Notify stream event manager than the link became active
373  */
374  MHEG5notifyLinkActive(link);
375  }
376  }
377 }
378 
379 /*
380  Deactivation
381  Execute the following sequence of actions:
382  1. Put the Link object in an inactive state so that it is not receptive to events.
383  2. Apply the Deactivation behaviour as inherited from the base class.
384  */
386 {
387  assert(link);
388 
389  if (link->ingredient.root.runningStatus)
390  {
391  if (link->eventType == MHEG5STREAMEVENT)
392  {
393  /* Notify stream event manager than the link became inactive
394  */
396  }
397 
398  #ifdef TRACING
399  if (!(mheg_trace_debug & TACTIONS))
400  {
401  TRACE(TEVNTS, ("link %d, src:%d typ:%s", link->ingredient.root.id, link->source, MHEG5eventToString(link->eventType)))
402  }
403  #endif
404 
405  /* Remove this Link from the list of currently active Link objects
406  */
407  if (activeLinksHead[link->eventType] == link)
408  {
409  /* This is the first item in the linked list. Remove from
410  * the head of the list.
411  */
412  activeLinksHead[link->eventType] = link->nextActiveLink;
413  }
414  else
415  {
416  MHEG5Link *listItem = activeLinksHead[link->eventType];
417 
418  if (listItem != 0)
419  {
420  while (listItem->nextActiveLink != 0)
421  {
422  if (listItem->nextActiveLink == link)
423  {
424  /* Found the Link - route the nextActiveLink pointer
425  * round it.
426  */
427  listItem->nextActiveLink = link->nextActiveLink;
428  break;
429  }
430  listItem = listItem->nextActiveLink;
431  }
432  }
433 
434  if (listItem == 0)
435  {
436  /* Didn't find the Link in the active list */
437  assert(0);
438  ERROR_PRINT(("ERROR: MHEG5linkDeactivate - couldn't find link in active list\n"));
439  }
440  }
441 
443  }
444 }
445 
446 /*
447  Actions
448  */
449 /*
450  Activate
451  Make a Link receptive to events that meet its LinkCondition.
452  Execute the following actions:
453  1. If the target Link object is active, disregard this action.
454  2. If the target Link is inactive, apply the Activation behaviour of the Link object.
455  */
457 {
458  assert(target);
459 
460  if (target->clazz != MHEG5LINK)
461  {
462  return MHEG5ERR_WRONGTARGET;
463  }
464 
465  if (!target->runningStatus)
466  {
467  MHEG5linkActivate((MHEG5Link *) target);
468  }
469 
470  return MHEG5ERR_NOERROR;
471 }
472 
473 /*
474  Deactivate
475  Make a Link not receptive to events.
476  Execute the following actions:
477  1. If the target Link object is inactive, disregard this action.
478  2. If the target Link is active, apply the Deactivation behaviour of the Link object.
479 
480  Provisions of use:
481  The Target object shall be an available Link object.
482  */
484 {
485  assert(target);
486 
487  if (target->clazz != MHEG5LINK)
488  {
489  return MHEG5ERR_WRONGTARGET;
490  }
491 
492  if (target->runningStatus)
493  {
494  MHEG5linkDeactivate((MHEG5Link *) target);
495  }
496 
497  return MHEG5ERR_NOERROR;
498 }
499 
MHEG5Bool availabilityStatus
Definition: mh5root.h:52
U8BIT indirect
Definition: mh5base.h:149
void MHEG5ingredientInit(MHEG5Ingredient *ingredient)
Initialise a ingredient object with default values.
void MHEG5notifyLinkActive(MHEG5Link *link)
Notify that a link is active.
Event to String conversion.
MHEG5Int i
Definition: mh5base.h:154
U16BIT type
Definition: mh5base.h:151
MHEG5Final clazz
Definition: mh5root.h:55
void MHEG5ingredientDestruct(MHEG5Ingredient *ingredient)
Implementation of the Destruction behaviour Execute the following sequence of actions: ...
Stream event subscription management.
union sMH5GroupRef::@5 ptr
union MHEG5Generic::@6 value
MHEG5EventType
Definition: mh5base.h:114
Implement the MHEG5 Variable Class 21 Variable Class Defines a variable within the context of a Group...
void MHEG5stringDestruct(MHEG5String *item)
Destruct a MHEG5String.
Definition: mh5base.c:686
uint8_t U8BIT
Definition: techtype.h:82
long MHEG5Int
Definition: mh5base.h:73
const char * MHEG5eventToString(MHEG5EventType event)
MHEG5ErrorCode
Definition: mh5base.h:222
unsigned char MHEG5Byte
Definition: mh5base.h:74
void MHEG5notifyLinkInactive(MHEG5Link *link)
Notify that a link has become inactive.
Event handling. Implementation of a combined queue for events and actions. This is the eventsystem wh...
MHEG5Byte * data
Definition: mh5base.h:85
#define MHEG5TRUE
Definition: mh5base.h:49
void MHEG5ingredientDeactivate(MHEG5Ingredient *ingredient)
Implementation of Deactivate behaviour Inherrited from Root class.
uint16_t U16BIT
Definition: techtype.h:84
Implement functions to retrieve MHEG5objects by GroupID and ID.
void MHEG5ingredientPrepare(MHEG5Ingredient *ingredient)
Implementation of the Preparation behaviour Inherrited from Root class.
Mheg5 logging and debug printing.
MHEG5Int len
Definition: mh5base.h:99
MHEG5Bool runningStatus
Definition: mh5root.h:51
MHEG5Byte * name
Definition: mh5base.h:102
redirection include
void MHEG5actionDestruct(MHEG5ActionList actions)
<Function description>="">
Definition: mh5action.c:118
MHEG5Int id
Definition: mh5root.h:48
#define ERROR_PRINT(x)
Definition: mh5debug.h:76
void MHEG5queueUnresolveTargets(MHEG5ActionList actions)
Clear targets for the action list.
Definition: mh5queue.c:1204
MHEG5Int len
Definition: mh5base.h:84
void MHEG5queueResolveTargets(MHEG5ActionList actions)
Finds targets for the action list.
Definition: mh5queue.c:1182
void MHEG5ingredientFree(MHEG5Ingredient *ingredient)
Free off all memory associated with the specified object, including any exchanged attributes and inte...
#define MHEG5FALSE
Definition: mh5base.h:48
void MHEG5sendSync(MHEG5Root *source, MHEG5EventType event, MHEG5Int data)
Store an event in the synchronous event queue.
Definition: mh5queue.c:1651
#define TRACE(t, x)
Definition: glue_debug.h:118