DVBCore  20.3.0
DVBCore Documentation
ap_epgsearch.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2011 Ocean Blue Software Ltd
4  *
5  * This file is part of a DTVKit Software Component
6  * You are permitted to copy, modify or distribute this file subject to the terms
7  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
8  *
9  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
10  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * If you or your organisation is not a member of DTVKit then you have access
14  * to this source code outside of the terms of the licence agreement
15  * and you are expected to delete this and any associated files immediately.
16  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
17  *******************************************************************************/
26 //---includes for this file-------------------------------------------------------------------------
27 // compiler library header files
28 
29 #include <stdio.h>
30 #include <wchar.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <math.h>
34 
35 // third party header files
36 
37 // Ocean Blue Software header files
38 #include "techtype.h" //generic data definitions
39 #include "dbgfuncs.h" //debug functions
40 
41 //#include "stbhwdsk.h"
42 #include "stbhwos.h"
43 #include "stbgc.h"
44 #include "stbdpc.h"
45 #include "stbsiflt.h"
46 #include "stbsitab.h"
47 #include "stbheap.h" // STB_AppFreeMemory
48 #include "stbuni.h" // STB_ConcatUnicodeStrings()
49 #include "stbllist.h"
50 
51 #include "app_nvm.h" // for APP_NvmRead
52 #include "ap_cfg.h"
53 #include "ap_dbacc.h"
54 #include "ap_epgsearch.h"
55 
56 #include "dba.h"
57 
58 //---constant definitions for this file-------------------------------------------------------------
59 //#define AGS_DEBUG
60 #ifdef AGS_DEBUG
61 #define AGS_DBG(x) STB_SPDebugWrite x
62 #else
63 #define AGS_DBG(x)
64 #endif
65 
66 //---local typedefs, structs, enumerations for this file--------------------------------------------
67 
68 /* This structure is used for timer database filters */
69 typedef struct
70 {
71  U8BIT *search_str;
72  E_AGS_SEARCH_FIELDS search_fields;
73  E_AGS_MATCH_TYPE match_type;
74  E_AGS_SEARCH_DAYS search_days;
75  U32BIT min_time;
76  U32BIT max_time;
77  E_AGS_MATCH_ACTION match_action;
78 
79  U16BIT num_entries;
80  void **event_list;
81  U16BIT max_services;
82  void *service;
83  U16BIT cur_service_idx;
84  U16BIT cur_event_idx;
85 } S_EPG_SEARCH;
86 
87 //---local (static) variable declarations for this file---------------------------------------------
88 // (internal variables declared static to make them local)
89 
90 //---local function prototypes for this file--------------------------------------------------------
91 // (internal functions declared static to make them local)
92 static BOOLEAN CheckMatch(U8BIT *search_string, U8BIT *compare_string, E_AGS_MATCH_TYPE type);
93 
94 
95 //---global function definitions-----------------------------------------------
96 
107 void* AGS_OpenSearch( U8BIT *search_str, E_AGS_SEARCH_FIELDS search_fields,
108  E_AGS_MATCH_TYPE match_type, E_AGS_SEARCH_DAYS search_days, S_AGS_TIME_RANGE *search_times,
109  E_AGS_MATCH_ACTION match_action)
110 {
111  void *ags_handle;
112  S_EPG_SEARCH *this_search;
113  U16BIT nchar;
114 
115  FUNCTION_START(AGS_OpenSearch);
116 
117  AGS_DBG(("AGS_OpenSearch"));
118  ags_handle = STB_AppGetMemory(sizeof(S_EPG_SEARCH));
119 
120  if (ags_handle != NULL)
121  {
122  this_search = (S_EPG_SEARCH *)ags_handle;
123  this_search->max_services = ADB_GetNumServices();
124  this_search->service = ADB_GetNextServiceInList(ADB_SERVICE_LIST_DIGITAL, NULL);
125  if (this_search->service != NULL)
126  {
127  ADB_GetEventSchedule(FALSE, this_search->service, &this_search->event_list, &this_search->num_entries);
128  }
129  else
130  {
131  this_search->num_entries = 0;
132  }
133  this_search->cur_service_idx = 0;
134  this_search->cur_event_idx = 0;
135 
136  // Copy search settings into this opened search's context
137  // Ensure we work with a Unicode version of the search string
138  this_search->search_str = STB_ConvertStringToUTF8(search_str, &nchar, TRUE, 0);
139  this_search->search_fields = search_fields;
140  this_search->match_type = match_type;
141  this_search->search_days = search_days;
142  if (search_times != NULL)
143  {
144  this_search->min_time = (search_times->min_hour * 60 * 60) + (search_times->min_minutes * 60) + search_times->min_seconds;
145  this_search->max_time = (search_times->max_hour * 60 * 60) + (search_times->max_minutes * 60) + search_times->max_seconds;
146  }
147  else
148  {
149  // If caller didn't want time range restriction, just use whole day as range
150  this_search->min_time = 0;
151  this_search->max_time = (24 * 60 * 60);
152  }
153  // Not used at the moment, will be for saved searches run daily etc.
154  this_search->match_action = match_action;
155  }
156 
157  FUNCTION_FINISH(AGS_OpenSearch);
158 
159  return ags_handle;
160 }
161 
169 BOOLEAN AGS_GetNextResult( void *ags_handle, U16BIT *event_id, void **serv_ptr )
170 {
171  S_EPG_SEARCH *this_search = ags_handle;
172  void *cur_event_ptr;
173  void *cur_service;
174  U8BIT *event_name = NULL;
175  U8BIT *event_desc = NULL;
176  U8BIT *event_ext_desc = NULL;
177  U32DHMS utc_event_time = 0;
178  U32DHMS loc_event_time = 0;
179  U8BIT event_weekday = 0;
180  U32BIT event_time;
181  BOOLEAN do_compare;
182  BOOLEAN match = FALSE;
183 
184  FUNCTION_START(AGS_GetNextResult);
185 
186  AGS_DBG(("AGS_GetNextResult"));
187 
188  while ((match == FALSE) &&
189  (this_search->cur_service_idx < this_search->max_services) &&
190  (this_search->cur_event_idx < this_search->num_entries))
191  {
192  cur_event_ptr = this_search->event_list[this_search->cur_event_idx];
193  cur_service = this_search->service;
194 
195  if (cur_event_ptr != NULL)
196  {
197  do_compare = TRUE; // Will get set to false if not right day or time range
198 
199  utc_event_time = ADB_GetEventStartDateTime(cur_event_ptr);
200  // User supplies local weekdays and time range, so convert event to local before comparisons
201  loc_event_time = STB_GCConvertDHMS(utc_event_time, CONV_LOCAL);
202 
203  event_time = (DHMS_HOUR32(loc_event_time) * 60 * 60) +
204  (DHMS_MINS32(loc_event_time) * 60) +
205  DHMS_SECS(loc_event_time);
206  event_weekday = (U8BIT)STB_GCGetDateWeekDay(DHMS_DATE(loc_event_time));
207  AGS_DBG(("Event day %d search days %02x", event_weekday, this_search->search_days));
208 
209  // search_days is a mask with bit 0 representing MONDAY and bit 6 SUNDAY
210  // so by raising 2 to the power of the day of the week of the event-1 (0-6)
211  // we can check if the event day matches the search mask
212  if (((U8BIT)pow(2, event_weekday - 1) & this_search->search_days) == 0)
213  {
214  do_compare = FALSE;
215  AGS_DBG(("Not comparing... weekday not in search"));
216  }
217 
218  if ((event_time < this_search->min_time) || (event_time > this_search->max_time))
219  {
220  do_compare = FALSE;
221  AGS_DBG(("Not comparing... time not in search range"));
222  }
223 
224  // If correct day and time range then proceed to string comparisons
225  if (do_compare == TRUE)
226  {
227  AGS_DBG(("Comparing against..."));
228  // Get the string(s) we'll be using for comparison from the events
229  if (this_search->search_fields & AGS_SEARCH_TITLE)
230  {
231  event_name = ADB_GetEventName(cur_event_ptr);
232  AGS_DBG(("Event Name [%s]", event_name));
233  match = CheckMatch(this_search->search_str, event_name, this_search->match_type);
234  }
235 
236  if ((match == FALSE) && (this_search->search_fields & AGS_SEARCH_DESC))
237  {
238  event_desc = ADB_GetEventDescription(cur_event_ptr);
239  AGS_DBG(("Event Desc [%s]", event_desc));
240  match = CheckMatch(this_search->search_str, event_desc, this_search->match_type);
241  }
242 
243  if ((match == FALSE) && (this_search->search_fields & AGS_SEARCH_EXT_DESC))
244  {
245  event_ext_desc = ADB_GetEventExtendedDescription(cur_event_ptr);
246  AGS_DBG(("Event Extended Desc [%s]", event_ext_desc));
247  match = CheckMatch(this_search->search_str, event_ext_desc, this_search->match_type);
248  }
249  }
250  }
251 
252  // Set the caller's return parameters if a match was found
253  if (match == TRUE)
254  {
255  *event_id = ADB_GetEventId(cur_event_ptr);
256  *serv_ptr = cur_service;
257  }
258 
259  // Move onto the next event in this service
260  this_search->cur_event_idx++;
261 
262  // If there are no more events, move onto the next service
263  if (this_search->cur_event_idx >= this_search->num_entries)
264  {
265  // Free all the events from the old service
266  ADB_ReleaseEventList(this_search->event_list, this_search->num_entries);
267  this_search->event_list = NULL;
268  this_search->num_entries = 0;
269 
270  // Move to the next service
271  this_search->service = ADB_GetNextServiceInList(ADB_SERVICE_LIST_DIGITAL, this_search->service);
272 
273  // Get the events for the new service
274  if (this_search->service != NULL)
275  {
276  AGS_DBG(("Populating event list"));
277  ADB_GetEventSchedule(FALSE, this_search->service, &this_search->event_list, &this_search->num_entries);
278  AGS_DBG(("Finished copying events"));
279  }
280  else
281  {
282  AGS_DBG(("No more services"));
283  this_search->num_entries = 0;
284  this_search->event_list = NULL;
285  }
286 
287  this_search->cur_service_idx++;
288  this_search->cur_event_idx = 0;
289  }
290  }
291 
292  FUNCTION_FINISH(AGS_GetNextResult);
293 
294  return match;
295 }
296 
301 void AGS_CloseSearch( void *ags_handle )
302 {
303  S_EPG_SEARCH *this_search = ags_handle;
304 
305  FUNCTION_START(AGS_CloseSearch);
306 
307  AGS_DBG(("AGS_CloseSearch"));
308 
309  // Free any events still cached
310  ADB_ReleaseEventList(this_search->event_list, this_search->num_entries);
311 
312  // Free the items allocated in this context
313  STB_ReleaseUnicodeString(this_search->search_str);
314 
315  // Finally, free the memory for this search context
316  STB_AppFreeMemory(ags_handle);
317 
318  FUNCTION_FINISH(AGS_CloseSearch);
319 }
320 
321 //---local function definitions-----------------------------------------------
322 static BOOLEAN CheckMatch(U8BIT *search_string, U8BIT *compare_string, E_AGS_MATCH_TYPE type)
323 {
324  BOOLEAN result = FALSE;
325  U8BIT *token;
326  U8BIT *tmp_string;
327  U8BIT *save_ptr = NULL;
328  U32BIT unicode_str_size;
329  BOOLEAN ignore_case = FALSE;
330 
331  // Don't attempt to work with null strings
332  if ((search_string == NULL) || (compare_string == NULL))
333  return FALSE;
334 
335  if ((type & AGS_MATCH_IGNORE_CASE) != 0)
336  {
337  ignore_case = TRUE;
338  type &= ~AGS_MATCH_IGNORE_CASE;
339  }
340 
341  switch (type)
342  {
343  case AGS_MATCH_ANY_WORD:
344  case AGS_MATCH_ALL_WORDS:
345  {
346  // Make a local copy of the search string so it can be tokenised
347  unicode_str_size = STB_GetNumBytesInString(search_string);
348  tmp_string = STB_AppGetMemory(unicode_str_size);
349  if (tmp_string != NULL)
350  {
351  memcpy(tmp_string, search_string, unicode_str_size);
352  }
353 
354  token = STB_UnicodeStringTokenise(tmp_string, &save_ptr);
355  while (token != NULL)
356  {
357  if (STB_UnicodeStrStr(compare_string, token, ignore_case) != NULL)
358  {
359  result = TRUE;
360  // May as well exit to save time... only need one match
361  if (type == AGS_MATCH_ANY_WORD)
362  break;
363  }
364  else
365  {
366  // Undo any previous match on a non-matching word and exit
367  if (type == AGS_MATCH_ALL_WORDS)
368  {
369  result = FALSE;
370  break;
371  }
372  }
373  token = STB_UnicodeStringTokenise(NULL, &save_ptr);
374  }
375 
376  if (tmp_string != NULL)
377  {
378  STB_AppFreeMemory(tmp_string);
379  }
380  break;
381  }
382 
383  // Check for EXACT match
384  // i.e. only if event name is "SPECIAL PROG" and search is "SPECIAL PROG"
385  case AGS_MATCH_EXACT_PHRASE:
386  {
387  if (STB_CompareUnicodeStrings(search_string, compare_string, TRUE, ignore_case) == 0)
388  {
389  result = TRUE;
390  }
391  break;
392  }
393 
394  case AGS_MATCH_NOT_EQUAL:
395  {
396  if (STB_CompareUnicodeStrings(search_string, compare_string, TRUE, ignore_case) != 0)
397  {
398  result = TRUE;
399  }
400  break;
401  }
402 
403  // Check for CONTAINS match
404  // i.e. if event name is "SOME SPECIAL PROG SHOWING" and search is "SPECIAL PROG"
405  case AGS_MATCH_CONTAINS_PHRASE:
406  {
407  if (STB_UnicodeStrStr(compare_string, search_string, ignore_case) != NULL)
408  {
409  result = TRUE;
410  }
411  break;
412  }
413 
414  default:
415  {
416  break;
417  }
418  }
419 
420  return result;
421 }
422 
U16BIT ADB_GetNumServices(void)
Returns the total number of services in the database.
Definition: ap_dbacc.c:3167
U8BIT * STB_UnicodeStrStr(U8BIT *str1, U8BIT *str2, BOOLEAN ignore_case)
Finds the first occurence of str2 in str1 and returns a pointer to the substring (as per strstr) ...
Definition: stbuni.c:788
U8BIT * STB_UnicodeStringTokenise(U8BIT *str, U8BIT **save_ptr)
Divides the (space separated) string up into individual words and returns them one per call...
Definition: stbuni.c:723
Application configuration.
Header file - macros and function prototypes for public use.
Header file for NVM data handling functions.
U32DHMS ADB_GetEventStartDateTime(void *event_ptr)
Returns a value representing the date and time of the start of the given event.
Definition: ap_dbacc.c:8441
void * STB_AppGetMemory(U32BIT bytes)
Attempts to allocate memory from the application heap.
Definition: stbheap.c:651
U8BIT * ADB_GetEventDescription(void *event_ptr)
Returns the short event description text of the event as a UTF-8 string. The returned string should b...
Definition: ap_dbacc.c:8773
U8BIT * STB_ConvertStringToUTF8(U8BIT *string, U16BIT *nchar, BOOLEAN strip_DVB_cntrl_char, U32BIT lang_code)
Converts the given DVB coded string into a UTF-8 unicode string. The returned string will be preceded...
Definition: stbuni.c:1508
U32DHMS STB_GCConvertDHMS(U32DHMS dhms, E_STB_GC_CONVTYPE conv)
Converts the given date/time to local or GMT.
Definition: stbgc.c:2206
S8BIT STB_CompareUnicodeStrings(U8BIT *string1_ptr, U8BIT *string2_ptr, BOOLEAN exact_match, BOOLEAN ignore_case)
Compares the contents of the two given unicode strings and returns the status (as per strcmp) ...
Definition: stbuni.c:910
void STB_ReleaseUnicodeString(U8BIT *string)
Releases the specified unicode string, freeing associated heap resources.
Definition: stbuni.c:1955
Debug functions header file.
Header file - Function prototypes for linked lists.
Header file - macros and function prototypes for public use.
Header file - macros and function prototypes for public use.
Database access defines, structures and public functions.
Header for STB unicode string handling routines.
U32BIT STB_GetNumBytesInString(U8BIT *string_ptr)
Determines the no of bytes of the given string.
Definition: stbuni.c:311
Header file - Function prototypes for operating system.
System Wide Global Technical Data Type Definitions.
void STB_AppFreeMemory(void *addr)
Releases previously allocated application heap memory.
Definition: stbheap.c:781
Header file - Function prototypes for heap memory.
U8BIT * ADB_GetEventExtendedDescription(void *event_ptr)
Returns the extended event description text of the event as a UTF-8 string. The returned string shoul...
Definition: ap_dbacc.c:8841
BOOLEAN AGS_GetNextResult(void *ags_handle, U16BIT *event_id, void **serv_ptr)
Gets the next matching result for an open search.
Definition: ap_epgsearch.c:169
void * ADB_GetNextServiceInList(U32BIT list_type, void *serv)
Returns the next service, in LCN order, for the given list type, starting from the given service...
Definition: ap_dbacc.c:3767
void ADB_GetEventSchedule(BOOLEAN include_old_events, void *serv_ptr, void ***elist_ptr, U16BIT *num_entries_ptr)
Allocates and returns an array containing copies of events for the given service from the service&#39;s E...
Definition: ap_dbacc.c:7634
U16BIT ADB_GetEventId(void *event_ptr)
Returns the event id for the given event.
Definition: ap_dbacc.c:8970
U8BIT * ADB_GetEventName(void *event_ptr)
Returns the name of the event as a UTF-8 string. The returned string should be freed using STB_Releas...
Definition: ap_dbacc.c:8740
void ADB_ReleaseEventList(void **elist, U16BIT num_entries)
Frees all teh events in the given list and all associated memory for those events.
Definition: ap_dbacc.c:7924
Application database access functions.
void AGS_CloseSearch(void *ags_handle)
Closes an open search and frees all associated resources.
Definition: ap_epgsearch.c:301
Header file - macros and function prototypes for public use.
void * AGS_OpenSearch(U8BIT *search_str, E_AGS_SEARCH_FIELDS search_fields, E_AGS_MATCH_TYPE match_type, E_AGS_SEARCH_DAYS search_days, S_AGS_TIME_RANGE *search_times, E_AGS_MATCH_ACTION match_action)
Opens an EPG Search.
Definition: ap_epgsearch.c:107
E_STB_GC_WEEKDAY STB_GCGetDateWeekDay(U16BIT code)
Returns the weekday number of the specified date code.
Definition: stbgc.c:1448
macros and function prototypes for public use