DVBCore  20.3.0
DVBCore Documentation
stbpvr.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  *
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 // gives direct COM port access
27 /*#define STB_DEBUG*/
28 /*#define DEBUG_CIPLUS*/
29 
30 //---includes for this file----------------------------------------------------
31 // compiler library header files
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 /* third party header files */
38 
39 /* DVBCore header files */
40 
41 #include <techtype.h>
42 #include <dbgfuncs.h>
43 
44 #include "stbhwos.h"
45 #include "stbhwav.h"
46 #include "stbpvrpr.h"
47 #include "stbhwdsk.h"
48 #include "stbhwmem.h"
49 #include "stbhwcrypt.h"
50 
51 #include "stbpvr.h"
52 #include "stbheap.h"
53 #include "stbheap.h"
54 #include "stbgc.h"
55 #include "stbuni.h"
56 #include "stbdpc.h"
57 #include "stbpvrmsg.h"
58 #include "stberc.h"
59 #include "stbllist.h"
60 
61 #ifdef COMMON_INTERFACE
62 #include "stbhwdmx.h"
63 #include "stbsitab.h"
64 #include "stbcicc.h"
65 #endif
66 
67 /*---constant definitions for this file----------------------------------------*/
68 #ifdef STB_DEBUG
69  #define STB_PVR_PRINT(x) STB_SPDebugWrite x
70 #else
71  #define STB_PVR_PRINT(x)
72 #endif
73 
74 #ifdef DEBUG_CIPLUS
75  #define DBG_CIP(x, ...) {U32DHMS gmt = STB_GCNowDHMSGmt(); \
76  STB_SPDebugWrite("%02u:%02u:%02u: %s" x, DHMS_HOUR(gmt), DHMS_MINS(gmt), DHMS_SECS(gmt), __FUNCTION__, ##__VA_ARGS__); }
77 #else
78  #define DBG_CIP(x, ...)
79 #endif
80 
81 #if 0
82 #ifdef FUNCTION_START
83 #undef FUNCTION_START
84 #endif
85 #define FUNCTION_START(X) STB_SPDebugWrite(">>> %s\n", # X)
86 #ifdef FUNCTION_FINISH
87 #undef FUNCTION_FINISH
88 #endif
89 #define FUNCTION_FINISH(X) STB_SPDebugWrite("<<< %s\n", # X)
90 #endif
91 
92 #define HANDLE_BASE 0x00000001
93 
94 #define DB_FILENAME_LEN 32
95 #define BASENAME_LEN 16
96 
97 #define DB_FILE_EXTENSION ".odb"
98 #define DB_FILE_EXTENTION_LEN 4
99 
100 #define ODB_MAGIC_1 'O'
101 #define ODB_MAGIC_2 'd'
102 #define ODB_MAGIC_3 'B'
103 
104 #define ODB_VERSION_1 1
105 #define ODB_VERSION_2 2
106 #define ODB_CUR_VERSION ODB_VERSION_2
107 
108 #define BOOKMARK_FILENAME_SIZE 10
109 #define BOOKMARK_TOLERANCE 30 /* +/- number of seconds allowed when finding an existing bookmark */
110 
111 #define REC_AD_RECEIVER_MIX 0
112 #define REC_AD_BROADCAST_MIX 1
113 
114 #define REC_INFO_BUFFER_SIZE ((sizeof(S_REC_INFO) + (AES128_KEY_SIZE - 1)) & ~(AES128_KEY_SIZE - 1))
115 
116 /* Flags stored with a recording */
117 #define REC_LOCKED 0x0001
118 #define REC_ENCRYPTED 0x0002
119 #define REC_HAS_GUIDANCE 0x0004
120 #define REC_SERIES 0x0008
121 #define REC_RECOMMENDATION 0x0010
122 #define REC_HAS_VIDEO 0x0020
123 #define REC_PARENTAL_LOCK 0x0040
124 
125 /*---local typedef structs for this file---------------------------------------*/
126 
127 #ifdef COMMON_INTERFACE
128 typedef struct
129 {
130  BOOLEAN used;
131  U16BIT length;
132  U8BIT *data;
133 } S_REC_CIPLUS_LICENCE;
134 
135 typedef struct
136 {
137  U8BIT age_rating;
138  U8BIT private_data[CIP_PIN_PRIVATE_DATA_SIZE];
139 } S_REC_CIPLUS_PIN;
140 
141 typedef struct s_rec_ciplus_item
142 {
143  U32BIT timestamp;
144  U16BIT item_type;
145  union
146  {
147  U8BIT uri[CIP_URI_LEN];
148  S_REC_CIPLUS_LICENCE licence;
149  S_REC_CIPLUS_PIN pin;
150  } u;
151  struct s_rec_ciplus_item *prev;
152  struct s_rec_ciplus_item *next;
153 } S_REC_CIPLUS_ITEM;
154 #endif
155 
156 typedef struct
157 {
158  U32BIT handle;
159 #ifdef COMMON_INTERFACE
160  U8BIT slot_id;
161  void *play_sem;
162  S_REC_CIPLUS_ITEM *item_list;
163  S_REC_CIPLUS_ITEM *uri_item;
164  S_REC_CIPLUS_ITEM *licence_item;
165  S_REC_CIPLUS_ITEM *pin_item;
166 #endif
168 
169 #ifdef COMMON_INTERFACE
170 typedef struct
171 {
172  BOOLEAN valid;
173  U8BIT key[16];
174  U8BIT iv[16];
175 } S_KEY_INFO;
176 #endif
177 
178 typedef struct
179 {
180  U32BIT handle;
181  U32BIT start_time;
182  U32BIT duration;
183  BOOLEAN paused;
184  BOOLEAN encrypted;
185  U16BIT num_pids;
186  S_PVR_PID_INFO *rec_pids_array;
187  U16BIT serv_id;
188  U16BIT ts_id;
189  U16BIT orig_net_id;
190  U8BIT rec_index;
191  E_STB_PVR_START_MODE smode;
192  U32BIT timeshift_seconds;
193 #ifdef COMMON_INTERFACE
194  E_STB_DMX_DESC_TYPE desc_type;
195  S_KEY_INFO keys[2];
196 #endif
198 
199 typedef struct
200 {
201  U16BIT disk_id;
202  BOOLEAN valid;
203 } PVR_DB_DISK;
204 
205 typedef struct
206 {
207  U8BIT magic[3];
208  U8BIT version;
209 } S_REC_HEADER;
210 
211 typedef struct
212 {
213  U16BIT rec_date;
214  U8BIT rec_hour;
215  U8BIT rec_min;
216  U8BIT rec_sec;
217  U8BIT len_hour;
218  U8BIT len_min;
219  U8BIT len_sec;
220  U8BIT name[STB_PVR_NAME_LEN];
221  U8BIT prog_crid[STB_PVR_MAX_CRID_LEN];
222  U8BIT other_crid[STB_PVR_MAX_CRID_LEN];
223  U8BIT additional_info[STB_PVR_ADDITIONAL_INFO_LEN];
224  U16BIT serv_id;
225  U16BIT ts_id;
226  U16BIT orig_net_id;
227  U32BIT flags;
228  U32BIT parental_rating;
229  S32BIT start_padding;
230  S32BIT end_padding;
231  U8BIT status;
232 } S_REC_INFO;
233 
234 enum
235 {
236  EXT_INFO_SERVICE_NAME,
237  EXT_INFO_SHORT_DESC,
238  EXT_INFO_GUIDANCE,
239  EXT_INFO_EXTENDED_DESC,
240  EXT_INFO_CIPLUS_LICENCE,
241  EXT_INFO_CIPLUS_URI,
242  EXT_INFO_CIPLUS_CICAM_ID,
243  EXT_INFO_CIPLUS_PIN
244 };
245 
246 typedef struct s_recording
247 {
248  U32BIT handle;
249  U16BIT disk_id;
250  BOOLEAN recording;
251  BOOLEAN selected;
252  S_REC_INFO rec_info;
253  U8BIT basename[BASENAME_LEN];
254  struct s_recording *prev;
255  struct s_recording *next;
256 } S_RECORDING;
257 
258 typedef enum
259 {
260  BOOKMARK_USER,
261  BOOKMARK_PLAYBACK_POSITION
262 } E_BOOKMARK_TYPE;
263 
264 typedef struct
265 {
266  LINK_LIST_PTR_BLK ptrs;
267 
268  U32BIT time;
269  U8BIT *name;
270 } S_BOOKMARK;
271 
272 
273 //---local (static) variable declarations for this file------------------------
274 // (internal variables declared static to make them local)
275 
276 static BOOLEAN initialised_flag = FALSE;
277 static BOOLEAN formatting_flag = FALSE;
278 static BOOLEAN repairing_flag = FALSE;
279 
280 static U8BIT num_paths;
281 
282 static S_PVRPLAY_STATUS *play_status;
283 static S_PVRRECORD_STATUS *record_status;
284 
285 static void *disk_mutex;
286 static PVR_DB_DISK *disks_in_db;
287 static U16BIT num_disks_in_db;
288 
289 static U16BIT default_pvr_disk_id = INVALID_DISK_ID;
290 
291 static void *list_mutex;
292 static S_RECORDING *rec_list;
293 
294 static U8BIT *enc_dec_key;
295 static U8BIT *enc_dec_iv;
296 static U32BIT enc_dec_key_len;
297 static U8BIT *rec_info_buffer;
298 
299 //---local function prototypes for this file-----------------------------------
300 // (internal functions declared static to make them local)
301 
302 static void ReadRecordings(U16BIT disk_id);
303 static void RemoveRecordings(U16BIT disk_id);
304 
305 static U32BIT GetCurrentRecordTime(U32BIT handle);
306 
307 static BOOLEAN WriteODBFile(U16BIT disk_id, U8BIT *basename, BOOLEAN write_header,
308  S_REC_INFO *rec_info);
309 static BOOLEAN WriteExtendedInfo(U16BIT disk_id, U8BIT *basename, U16BIT ext_id,
310  U32BIT data_len, U8BIT *data);
311 static BOOLEAN ReadExtendedInfo(U16BIT disk_id, U8BIT *basename, U16BIT ext_id, U8BIT *data,
312  U32BIT data_len);
313 static U32BIT GetExtendedInfoSize(U16BIT disk_id, U8BIT *basename, U16BIT ext_id);
314 static void InsertRecordingInList(S_RECORDING *rec_ptr);
315 static void RemoveRecordingFromList(S_RECORDING *rec_ptr);
316 static U32BIT GetNextFreeHandle(void);
317 static S_RECORDING* GetRecording(U32BIT handle);
318 static void GetDBRecordBasename(U32BIT file_number, U8BIT *filename);
319 static void GetDBRecordFilename(U32BIT file_number, U8BIT *filename);
320 static BOOLEAN IncludesVideoPid(S_PVR_PID_INFO *pid_array, U16BIT num_pids);
321 
322 #ifdef COMMON_INTERFACE
323 static void FreeCIPlusItemList(U8BIT path);
324 static void FreeCIPlusItem(S_REC_CIPLUS_ITEM *item);
325 static void ReadCIPlusItems(U8BIT path, S_RECORDING *rec_ptr);
326 static void ApplyCIPlusItems(U8BIT path, S_RECORDING *rec_ptr, U32BIT position_in_seconds,
327  S16BIT speed);
328 static void FindNextCIPlusItem(U8BIT path, S16BIT speed);
329 static BOOLEAN WriteCIPlusInfo(U16BIT disk_id, U8BIT *basename, U16BIT ext_id, U32BIT timestamp,
330  U32BIT data_len, U8BIT *data);
331 static BOOLEAN UpdateCIPlusInfo(U16BIT disk_id, U8BIT *basename, U16BIT ext_id, U32BIT timestamp,
332  U32BIT data_len, U8BIT *data);
333 #endif
334 
335 static void GetBookmarkFolderName(U8BIT *basename, U8BIT *bookmark_folder_name);
336 static void GetBookmarkFileName(U32BIT time, E_BOOKMARK_TYPE type, U8BIT *name);
337 static E_BOOKMARK_TYPE GetBookmarkType(U8BIT *file_name);
338 static U32BIT GetBookmarkTime(U8BIT *file_name);
339 static BOOLEAN AddBookmark(U16BIT disk_id, U8BIT *basename, U32BIT time, U8BIT *name,
340  E_BOOKMARK_TYPE type);
341 static void RemoveBookmark(U16BIT disk_id, U8BIT *basename, U32BIT time, U8BIT *name,
342  E_BOOKMARK_TYPE type);
343 static void RemoveAllBookmarks(U16BIT disk_id, U8BIT *basename);
344 static U32BIT GetBookmarks(U16BIT disk_id, U8BIT *basename, LINK_LIST_HEADER *bookmarks,
345  E_BOOKMARK_TYPE type, BOOLEAN names);
346 static void EmptyBookmarks(LINK_LIST_HEADER *bookmarks, BOOLEAN release);
347 static S16BIT CompareBookmarks(LINK_LIST_PTR_BLK **bookmark1, LINK_LIST_PTR_BLK **bookmark2);
348 
349 
350 //---global function definitions-----------------------------------------------
351 
363 BOOLEAN STB_PVRInitialise(void)
364 {
365  U16BIT i;
366  U8BIT num_recorders, num_players;
367  U8BIT num_audio_decoders, num_video_decoders;
368 
369  FUNCTION_START(STB_PVRInitialise);
370 
371  num_paths = STB_DPGetNumPaths();
372  num_recorders = STB_HWGetNumRecorders();
373  num_audio_decoders = STB_HWGetAudioDecodePaths();
374  num_video_decoders = STB_HWGetVideoDecodePaths();
375 
376  STB_PVR_PRINT(("STB_PVRInitialise: tuners = %d, audio/video decoders = %d/%d", num_recorders,
377  num_audio_decoders, num_video_decoders));
378 
379  num_players = STB_PVRInitPlayback(num_audio_decoders, num_video_decoders);
380  num_recorders = STB_PVRInitRecording(num_recorders);
381 
382  STB_PVR_PRINT(("STB_PVRInitialise: num players = %d, num recorders = %d", num_players, num_recorders));
383 
384  if ((num_players > 0) && (num_recorders > 0))
385  {
386  play_status = (S_PVRPLAY_STATUS *)STB_GetMemory((U32BIT)(sizeof(S_PVRPLAY_STATUS) * num_paths));
387  if (play_status != NULL)
388  {
389  for (i = 0; i < num_paths; i++)
390  {
391  play_status[i].handle = 0;
392 #ifdef COMMON_INTERFACE
393  play_status[i].play_sem = STB_OSCreateSemaphore();
394  play_status[i].item_list = NULL;
395  play_status[i].uri_item = NULL;
396  play_status[i].licence_item = NULL;
397  play_status[i].pin_item = NULL;
398 #endif
399  }
400  }
401 
402  record_status = (S_PVRRECORD_STATUS *)STB_GetMemory((U32BIT)(sizeof(S_PVRRECORD_STATUS) * num_paths));
403  if (record_status != NULL)
404  {
405  for (i = 0; i < num_paths; i++)
406  {
407  record_status[i].handle = 0;
408  record_status[i].start_time = 0;
409  record_status[i].duration = 0;
410  record_status[i].paused = FALSE;
411  record_status[i].encrypted = FALSE;
412  record_status[i].rec_index = INVALID_RES_ID;
413  record_status[i].num_pids = 0;
414  record_status[i].rec_pids_array = NULL;
415 #ifdef COMMON_INTERFACE
416  record_status[i].keys[KEY_PARITY_EVEN].valid = FALSE;
417  record_status[i].keys[KEY_PARITY_ODD].valid = FALSE;
418 #endif
419  }
420  }
421 
422  list_mutex = STB_OSCreateMutex();
423 
425 
426  initialised_flag = TRUE;
427  }
428 
429  disk_mutex = STB_OSCreateMutex();
430 
431  disks_in_db = NULL;
432  num_disks_in_db = 0;
433  default_pvr_disk_id = INVALID_DISK_ID;
434 
435  /* Initialise buffers to be used for encrypting/decrypting data */
436  enc_dec_key = (U8BIT *)STB_MEMReadSecureConstant(SECURE_NVM_DEFAULT_ENCRYPTION_KEY, &enc_dec_key_len);
437  enc_dec_iv = (U8BIT *)STB_MEMReadSecureConstant(SECURE_NVM_DEFAULT_ENC_INIT_VECTOR, &enc_dec_key_len);
438 
439  rec_info_buffer = STB_GetMemory(REC_INFO_BUFFER_SIZE);
440 
441  FUNCTION_FINISH(STB_PVRInitialise);
442 
443  return(initialised_flag);
444 }
445 
457 void STB_PVRSetStandbyState(BOOLEAN state)
458 {
459  FUNCTION_START(STB_PVRSetStandbyState);
460 
461  if (initialised_flag == TRUE)
462  {
463  STB_DSKSetStandby(state);
464  }
465 
466  FUNCTION_FINISH(STB_PVRSetStandbyState);
467 }
468 
480 BOOLEAN STB_PVRIsInitialised(void)
481 {
482  BOOLEAN ret_val;
483 
484  FUNCTION_START(STB_PVRIsInitialised);
485 
486  ret_val = initialised_flag;
487 
488  FUNCTION_FINISH(STB_PVRIsInitialised);
489 
490  return(ret_val);
491 }
492 
498 void STB_PVRSetDefaultDisk(U16BIT disk_id)
499 {
500  FUNCTION_START(STB_PVRSetDefaultDisk);
501 
502  default_pvr_disk_id = disk_id;
503 
504  FUNCTION_FINISH(STB_PVRSetDefaultDisk);
505 }
506 
513 {
514  U16BIT num_disks;
515  U16BIT index;
516  U16BIT disk_id;
517 
518  FUNCTION_START(STB_PVRGetDefaultDisk);
519 
520  disk_id = default_pvr_disk_id;
521  if (disk_id == INVALID_DISK_ID)
522  {
523  num_disks = STB_DSKGetNumDisks();
524 
525  for (index = 0; (index < num_disks) && (disk_id == INVALID_DISK_ID); index++)
526  {
527  disk_id = STB_DSKGetDiskIdByIndex(index);
528  if ((disk_id != INVALID_DISK_ID) && !STB_DSKIsMounted(disk_id))
529  {
530  disk_id = INVALID_DISK_ID;
531  }
532  }
533  }
534 
535  FUNCTION_FINISH(STB_PVRGetDefaultDisk);
536 
537  return(disk_id);
538 }
539 
551 BOOLEAN STB_PVRCanDiskBeUsed(U16BIT disk_id)
552 {
553  BOOLEAN result = FALSE;
554 
555  FUNCTION_START(STB_PVRCanDiskBeUsed);
556 
557  if (STB_DSKIsMounted(disk_id))
558  {
559  result = TRUE;
560  }
561 
562  FUNCTION_FINISH(STB_PVRCanDiskBeUsed);
563 
564  return(result);
565 }
566 
580 BOOLEAN STB_PVRFormat(U16BIT disk_id, E_STB_PVR_FORMATMODE mode, U8BIT *prog)
581 {
582  BOOLEAN ret_val = FALSE;
583 
584  FUNCTION_START(STB_PVRFormat);
585 
586  STB_PVR_PRINT(("STB_PVRFormat (mode = %d)", mode));
587 
588  switch (mode)
589  {
590  case FORMAT_START:
591  if (formatting_flag == FALSE)
592  {
593  // start format if not in progress
594  STB_DSKFormat(disk_id);
595  formatting_flag = TRUE;
596  *prog = 0;
597  ret_val = TRUE;
598  RemoveRecordings(disk_id);
599  }
600  break;
601 
602  case FORMAT_PROGRESS:
603  if (formatting_flag == TRUE)
604  {
605  // return progress if formatting
606  *prog = STB_DSKGetFormatProgress(disk_id);
607  ret_val = TRUE;
608  }
609  break;
610 
611  case FORMAT_END:
612  if (formatting_flag == TRUE)
613  {
614  if (STB_DSKGetFormatProgress(disk_id) == 100)
615  {
618  formatting_flag = FALSE;
619  *prog = 100;
620  ret_val = TRUE;
621  }
622  }
623  break;
624 
625  default:
626  break;
627  }
628 
629  FUNCTION_FINISH(STB_PVRFormat);
630 
631  return(ret_val);
632 }
633 
647 BOOLEAN STB_PVRRepair(U16BIT disk_id, E_STB_PVR_REPAIRMODE mode, U8BIT *prog)
648 {
649  BOOLEAN ret_val = FALSE;
650 
651  FUNCTION_START(STB_PVRRepair);
652 
653  STB_PVR_PRINT(("STB_PVRRepair (mode = %d)", mode));
654 
655  if (initialised_flag == TRUE)
656  {
657  switch (mode)
658  {
659  case REPAIR_ENQUIRE:
660  if (repairing_flag == FALSE)
661  {
662  // return integrity if not scanning
663  *prog = 0;
664  ret_val = STB_DSKGetIntegrity(disk_id);
665  }
666  break;
667 
668  case REPAIR_START:
669  if (repairing_flag == FALSE)
670  {
671  // start scan if not scanning
672  STB_DSKRepair(disk_id);
673  repairing_flag = TRUE;
674  *prog = 0;
675  ret_val = TRUE;
676  }
677  break;
678 
679  case REPAIR_PROGRESS:
680  if (repairing_flag == TRUE)
681  {
682  // return progress if scanning
683  *prog = STB_DSKGetRepairProgress(disk_id);
684  ret_val = TRUE;
685  }
686  break;
687 
688  case REPAIR_END:
689  if (repairing_flag == TRUE)
690  {
691  if (STB_DSKGetRepairProgress(disk_id) == 100)
692  {
693  repairing_flag = FALSE;
694  *prog = 100;
695  ret_val = TRUE;
696  }
697  }
698  break;
699 
700  default:
701  break;
702  }
703  }
704 
705  FUNCTION_FINISH(STB_PVRRepair);
706 
707  return(ret_val);
708 }
709 
710 /*!**************************************************************************
711  * @brief Called when a disk is added or removed and updates the disk database
712  * and the recordings that are now available
713  * @param force_load - forces the recordings database to be updated
714  ****************************************************************************/
715 void STB_PVRUpdateRecordings(BOOLEAN force_load)
716 {
717  U16BIT num_disks;
718  U16BIT index, i;
719  U16BIT disk_id;
720  BOOLEAN disk_found;
721 
722  FUNCTION_START(STB_PVRUpdateRecordings);
723 
724  if (initialised_flag)
725  {
726  STB_OSMutexLock(disk_mutex);
727 
728  /* Mark all disks currently in the database as invalid */
729  for (index = 0; index < num_disks_in_db; index++)
730  {
731  disks_in_db[index].valid = FALSE;
732  }
733 
734  num_disks = STB_DSKGetNumDisks();
735 
736  /* Check all disks to see if there are any new ones */
737  for (index = 0; index < num_disks; index++)
738  {
739  disk_id = STB_DSKGetDiskIdByIndex(index);
740  if (STB_DSKIsMounted(disk_id))
741  {
742  /* Check whether the contents of this disk have already been loaded into the database */
743  disk_found = FALSE;
744 
745  for (i = 0; (i < num_disks_in_db) && !disk_found; i++)
746  {
747  if (disks_in_db[i].disk_id == disk_id)
748  {
749  disks_in_db[i].valid = TRUE;
750  disk_found = TRUE;
751  }
752  }
753 
754  if (!disk_found)
755  {
756  /* This is a new disk */
757  disks_in_db = STB_ResizeMemory(disks_in_db, (num_disks_in_db + 1) * sizeof(PVR_DB_DISK));
758  if (disks_in_db != NULL)
759  {
760  ReadRecordings(disk_id);
761 
762  disks_in_db[num_disks_in_db].disk_id = disk_id;
763  disks_in_db[num_disks_in_db].valid = TRUE;
764 
765  num_disks_in_db++;
766  }
767  }
768  else if (force_load)
769  {
770  ReadRecordings(disk_id);
771  }
772  }
773  }
774 
775  /* Check to see if any disks have been removed */
776  for (index = 0; index < num_disks_in_db; index++)
777  {
778  if (!disks_in_db[index].valid)
779  {
780  /* This disk is no longer present. Remove it's contents from the database */
781  RemoveRecordings(disks_in_db[index].disk_id);
782 
783  for (i = index + 1; i < num_disks_in_db; i++)
784  {
785  disks_in_db[i - 1].disk_id = disks_in_db[i].disk_id;
786  disks_in_db[i - 1].valid = disks_in_db[i].valid;
787  }
788 
789  num_disks_in_db--;
790 
791  if (num_disks_in_db == 0)
792  {
793  STB_FreeMemory(disks_in_db);
794  disks_in_db = NULL;
795  }
796  else
797  {
798  disks_in_db = STB_ResizeMemory(disks_in_db, num_disks_in_db * sizeof(PVR_DB_DISK));
799  }
800  }
801  }
802 
803  STB_OSMutexUnlock(disk_mutex);
804  }
805 
806  FUNCTION_FINISH(STB_PVRUpdateRecordings);
807 }
808 
809 /*!**************************************************************************
810  * @brief Determines whether the given handle is in the recording database
811  * @param handle - recording handle to be checked
812  * @return TRUE if the handle is found, FALSE otherwise
813  ****************************************************************************/
814 BOOLEAN STB_PVRIsValidHandle(U32BIT handle)
815 {
816  BOOLEAN valid;
817 
818  FUNCTION_START(STB_PVRIsValidHandle);
819 
820  valid = FALSE;
821 
822  if (initialised_flag)
823  {
824  STB_OSMutexLock(list_mutex);
825 
826  if (GetRecording(handle) != NULL)
827  {
828  valid = TRUE;
829  }
830 
831  STB_OSMutexUnlock(list_mutex);
832  }
833 
834  FUNCTION_FINISH(STB_PVRIsValidHandle);
835 
836  return(valid);
837 }
838 
839 /*!**************************************************************************
840  * @brief Create a new recording and return the handle
841  * @param disk_id - ID of disk to be used for the recording
842  * @param name - name of recording
843  * @param handle - returned recording handle
844  * @return TRUE if successful, FALSE otherwise
845  ****************************************************************************/
846 BOOLEAN STB_PVRCreateRecording(U16BIT disk_id, U8BIT *name, U32BIT *handle)
847 {
848  S_RECORDING *rec_ptr;
849  U8BIT db_filename[DB_FILENAME_LEN];
850  U8BIT basename[BASENAME_LEN];
851  U8BIT tmp_str[STB_PVR_NAME_LEN];
852  U32BIT file_number;
853  U32BIT num_bytes;
854  U16BIT date;
855  U8BIT hour, min, sec;
856  BOOLEAN retval;
857 
858  FUNCTION_START(STB_PVRCreateRecording);
859 
860  retval = FALSE;
861 
862  if (initialised_flag)
863  {
864  STB_OSMutexLock(list_mutex);
865 
866  /* Find the next available database handle for use by a recording */
867  *handle = GetNextFreeHandle();
868 
869  STB_PVR_PRINT(("STB_PVRCreateRecording(disk=0x%04x, name=\"%s\"): handle=0x%08lx", disk_id, name, *handle));
870 
871  /* Find a filename that can be used for recording on the given disk */
872  file_number = 0;
873  do
874  {
875  file_number++;
876 
877  GetDBRecordBasename(file_number, basename);
878  GetDBRecordFilename(file_number, db_filename);
879  }
880  while (STB_DSKFileExists(disk_id, db_filename) || !STB_PVRCanBeUsedForRecording(disk_id, basename));
881 
882  /* Create a new entry for the recording */
883  rec_ptr = (S_RECORDING *)STB_GetMemory(sizeof(S_RECORDING));
884  if (rec_ptr != NULL)
885  {
886  memset(rec_ptr, 0, sizeof(S_RECORDING));
887 
888  rec_ptr->handle = *handle;
889  rec_ptr->disk_id = disk_id;
890 
891  strncpy((char *)rec_ptr->basename, (char *)basename, BASENAME_LEN);
892 
893  STB_GCGetGMTDateTime(&date, &hour, &min, &sec);
894  STB_GCConvertDateTime(date, hour, min, sec,
895  &rec_ptr->rec_info.rec_date,
896  &rec_ptr->rec_info.rec_hour,
897  &rec_ptr->rec_info.rec_min,
898  &rec_ptr->rec_info.rec_sec,
899  CONV_LOCAL);
900 
901  if (name == NULL)
902  {
903  snprintf((char *)tmp_str, STB_PVR_NAME_LEN, "Recording %lu", (unsigned long)*handle);
904  strncpy((char *)rec_ptr->rec_info.name, (char *)tmp_str, STB_PVR_NAME_LEN);
905  }
906  else
907  {
908  num_bytes = STB_GetNumBytesInString(name);
909  if (num_bytes > sizeof(rec_ptr->rec_info.name))
910  {
911  /* If the name supplied is longer than the space to store it then it can't really
912  * be stored because we don't know how to terminate the string correctly
913  * (e.g. it might be compressed), so just have to store a default name to be safe */
914  snprintf((char *)tmp_str, STB_PVR_NAME_LEN, "Recording %lu", (unsigned long)*handle);
915  strncpy((char *)rec_ptr->rec_info.name, (char *)tmp_str, STB_PVR_NAME_LEN);
916  }
917  else
918  {
919  memcpy(rec_ptr->rec_info.name, name, num_bytes);
920  }
921  }
922 
923  if (WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, TRUE, &rec_ptr->rec_info))
924  {
925  InsertRecordingInList(rec_ptr);
926  retval = TRUE;
927  }
928  else
929  {
930  STB_FreeMemory(rec_ptr);
931  }
932  }
933 
934  STB_OSMutexUnlock(list_mutex);
935  }
936 
937  FUNCTION_FINISH(STB_PVRCreateRecording);
938 
939  return(retval);
940 }
941 
942 /*!**************************************************************************
943  * @brief Completely destroys a recording by deleting all files and removing
944  * it from the list of recordings
945  * @param handle - handle of recording to be destroyed
946  * @return TRUE if recording found and deleted, FALSE otherwise
947  ****************************************************************************/
948 BOOLEAN STB_PVRDestroyRecording(U32BIT handle)
949 {
950  S_RECORDING *rec_ptr;
951  U8BIT db_filename[DB_FILENAME_LEN];
952  BOOLEAN retval;
953 
954  FUNCTION_START(STB_PVRDestroyRecording);
955 
956  STB_PVR_PRINT(("STB_PVRDestroyRecording(0x%lx)", handle));
957 
958  retval = FALSE;
959 
960  if (initialised_flag)
961  {
962  STB_OSMutexLock(list_mutex);
963 
964  rec_ptr = GetRecording(handle);
965  if (rec_ptr != NULL)
966  {
967  if (strlen((char *)rec_ptr->basename) > 0)
968  {
969  strncpy((char *)db_filename, (char *)rec_ptr->basename, DB_FILENAME_LEN);
970  strncat((char *)db_filename, DB_FILE_EXTENSION, DB_FILENAME_LEN - strlen((char *)rec_ptr->basename));
971 
972  STB_DSKDeleteFile(rec_ptr->disk_id, db_filename);
973 
974  RemoveAllBookmarks(rec_ptr->disk_id, rec_ptr->basename);
975 
976  /* Delete all files associated with the recording */
977  STB_PVRDeleteRecording(rec_ptr->disk_id, rec_ptr->basename);
978  }
979 
980  RemoveRecordingFromList(rec_ptr);
981 
982  retval = TRUE;
983  }
984 
985  STB_OSMutexUnlock(list_mutex);
986  }
987 
988  FUNCTION_FINISH(STB_PVRDestroyRecording);
989 
990  return(retval);
991 }
992 
993 /*!**************************************************************************
994  * @brief Save all info on the given recording. The filename and disk should already
995  * have been setup, either when the recording is first created or when it's
996  * read from a disk.
997  * @param handle - recording handle
998  ****************************************************************************/
999 void STB_PVRSaveRecording(U32BIT handle)
1000 {
1001  S_RECORDING *rec_ptr;
1002 
1003  FUNCTION_START(STB_PVRSaveRecording);
1004 
1005  STB_PVR_PRINT(("STB_PVRSaveRecording(handle=0x%lx)", handle));
1006 
1007  if (initialised_flag)
1008  {
1009  STB_OSMutexLock(list_mutex);
1010 
1011  /* Find the recording */
1012  rec_ptr = GetRecording(handle);
1013  if (rec_ptr != NULL)
1014  {
1015  if (strlen((char *)rec_ptr->basename) > 0)
1016  {
1017  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, TRUE, &rec_ptr->rec_info);
1018  }
1019  }
1020 #ifdef STB_DEBUG
1021  else
1022  {
1023  STB_PVR_PRINT(("STB_PVRSaveRecording(0x%08lx): Failed to find recording", handle));
1024  }
1025 #endif
1026 
1027  STB_OSMutexUnlock(list_mutex);
1028  }
1029 
1030  FUNCTION_FINISH(STB_PVRSaveRecording);
1031 }
1032 
1033 /*!**************************************************************************
1034  * @brief Allocates and returns an array of all the recording handles
1035  * @param handle_array - pointer to array of handles, must be freed using
1036  * STB_PVRReleaseRecordingHandles
1037  * @return Number of handles returned in the array
1038  ****************************************************************************/
1039 U16BIT STB_PVRGetRecordingHandles(U32BIT **handle_array)
1040 {
1041  S_RECORDING *rec_ptr;
1042  U16BIT num_recordings;
1043  U16BIT index;
1044 
1045  FUNCTION_START(STB_PVRGetRecordingHandles);
1046 
1047  num_recordings = 0;
1048 
1049  if (initialised_flag)
1050  {
1051  STB_OSMutexLock(list_mutex);
1052 
1053  /* Count the number of recordings available */
1054  for (num_recordings = 0, rec_ptr = rec_list; rec_ptr != NULL;
1055  num_recordings++, rec_ptr = rec_ptr->next)
1056  ;
1057 
1058  if (num_recordings > 0)
1059  {
1060  /* Allocate an array to be returned */
1061  *handle_array = (U32BIT *)STB_GetMemory(num_recordings * sizeof(U32BIT));
1062  if (*handle_array != NULL)
1063  {
1064  for (index = 0, rec_ptr = rec_list; rec_ptr != NULL; index++, rec_ptr = rec_ptr->next)
1065  {
1066  (*handle_array)[index] = rec_ptr->handle;
1067  }
1068  }
1069  else
1070  {
1071  num_recordings = 0;
1072  }
1073  }
1074 
1075  STB_OSMutexUnlock(list_mutex);
1076  }
1077 
1078  FUNCTION_FINISH(STB_PVRGetRecordingHandles);
1079 
1080  return(num_recordings);
1081 }
1082 
1083 /*!**************************************************************************
1084  * @brief Frees the given array of handles allocated by the preceding function
1085  * @param handle_array - array to be freed
1086  ****************************************************************************/
1087 void STB_PVRReleaseRecordingHandles(U32BIT *handle_array)
1088 {
1089  FUNCTION_START(STB_PVRReleaseRecordingHandles);
1090 
1091  if (handle_array != NULL)
1092  {
1093  STB_FreeMemory(handle_array);
1094  }
1095 
1096  FUNCTION_FINISH(STB_PVRReleaseRecordingHandles);
1097 }
1098 
1099 /*!**************************************************************************
1100  * @brief Returns the handle of the recording with the given programme CRID
1101  * @param prog_crid - CRID to be searched for
1102  * @param handle - handle of recording found, returned
1103  * @return TRUE if a recording is found, FALSE otherwise
1104  ****************************************************************************/
1105 BOOLEAN STB_PVRFindRecordingFromCrid(U8BIT *prog_crid, U32BIT *handle)
1106 {
1107  S_RECORDING *rec_ptr;
1108  BOOLEAN found;
1109 
1110  FUNCTION_START(STB_PVRFindRecordingFromCrid);
1111 
1112  found = FALSE;
1113 
1114  if (initialised_flag)
1115  {
1116  STB_OSMutexLock(list_mutex);
1117 
1118  for (rec_ptr = rec_list; !found && (rec_ptr != NULL); rec_ptr = rec_ptr->next)
1119  {
1120  if (STB_CompareStringsIgnoreCase(rec_ptr->rec_info.prog_crid, prog_crid) == 0)
1121  {
1122  *handle = rec_ptr->handle;
1123  found = TRUE;
1124  }
1125  }
1126 
1127  STB_OSMutexUnlock(list_mutex);
1128  }
1129 
1130  FUNCTION_FINISH(STB_PVRFindRecordingFromCrid);
1131 
1132  return(found);
1133 }
1134 
1135 /*!**************************************************************************
1136  * @brief Returns the handle of a split event recording that follows on from
1137  * curr_handle
1138  * @param curr_handle - handle of the recording
1139  * @param next_handle - handle of recording found, returned
1140  * @return TRUE if a recording is found, FALSE otherwise
1141  ****************************************************************************/
1142 BOOLEAN STB_PVRFindNextSplitRecording(U32BIT curr_handle, U32BIT *next_handle)
1143 {
1144  S_RECORDING *curr_rec;
1145  S_RECORDING *rec_ptr;
1146  U16BIT end_date;
1147  U8BIT end_hour, end_min, end_secs;
1148  U16BIT earliest_date;
1149  U8BIT earliest_hour, earliest_min;
1150  BOOLEAN found;
1151 
1152  FUNCTION_START(STB_PVRFindNextSplitRecording);
1153 
1154  found = FALSE;
1155 
1156  if (initialised_flag)
1157  {
1158  STB_OSMutexLock(list_mutex);
1159 
1160  curr_rec = GetRecording(curr_handle);
1161  if ((curr_rec != NULL) && (STB_GetNumBytesInString(curr_rec->rec_info.prog_crid) > 1))
1162  {
1163  /* Calculate the end date/time so that the earliest recording following this can be found */
1164  STB_GCCalculateDateTime(curr_rec->rec_info.rec_date, curr_rec->rec_info.rec_hour,
1165  curr_rec->rec_info.rec_min, curr_rec->rec_info.rec_sec, curr_rec->rec_info.len_hour,
1166  curr_rec->rec_info.len_min, curr_rec->rec_info.len_sec, &end_date, &end_hour, &end_min,
1167  &end_secs, CALC_ADD);
1168 
1169  /* Search through all the recordings looking for one that follows this one */
1170  for (rec_ptr = rec_list; !found && (rec_ptr != NULL); rec_ptr = rec_ptr->next)
1171  {
1172  if (rec_ptr->handle != curr_handle)
1173  {
1174  if (STB_CompareStringsIgnoreCase(curr_rec->rec_info.prog_crid, rec_ptr->rec_info.prog_crid) == 0)
1175  {
1176  if (STB_GCCompareDateTime(end_date, end_hour, end_min, 0, rec_ptr->rec_info.rec_date,
1177  rec_ptr->rec_info.rec_hour, rec_ptr->rec_info.rec_min, 0, COMP_2GE1))
1178  {
1179  /* This part of the split occurs after the end of the currently playing part */
1180  if (found)
1181  {
1182  /* A later recording has already been found so check whether this part
1183  * is earlier than the one already found */
1184  if (STB_GCCompareDateTime(earliest_date, earliest_hour, earliest_min, 0,
1185  rec_ptr->rec_info.rec_date, rec_ptr->rec_info.rec_hour,
1186  rec_ptr->rec_info.rec_min, 0, COMP_2LT1))
1187  {
1188  /* This part is earlier than the previously found part */
1189  earliest_date = rec_ptr->rec_info.rec_date;
1190  earliest_hour = rec_ptr->rec_info.rec_hour;
1191  earliest_min = rec_ptr->rec_info.rec_min;
1192  *next_handle = rec_ptr->handle;
1193  }
1194  }
1195  else
1196  {
1197  /* This is the first recording found that occurs after the current part */
1198  earliest_date = rec_ptr->rec_info.rec_date;
1199  earliest_hour = rec_ptr->rec_info.rec_hour;
1200  earliest_min = rec_ptr->rec_info.rec_min;
1201  *next_handle = rec_ptr->handle;
1202 
1203  found = TRUE;
1204  }
1205  }
1206  }
1207  }
1208  }
1209  }
1210 
1211  STB_OSMutexUnlock(list_mutex);
1212  }
1213 
1214  FUNCTION_FINISH(STB_PVRFindNextSplitRecording);
1215 
1216  return(found);
1217 }
1218 
1219 #if 0
1220 
1231 BOOLEAN STB_PVRImportRecording(void)
1232 {
1233  BOOLEAN ret_val = FALSE;
1234  E_STB_DMX_DEMUX_SOURCE dmx_source;
1235  U8BIT dmx_param;
1236  U32BIT handle;
1237  BOOLEAN ts, video, audio;
1238 
1239  FUNCTION_START(STB_PVRImportRecording);
1240 
1241  STB_PVR_PRINT(("STB_PVRImportRecording"));
1242 
1243  if (initialised_flag == TRUE)
1244  {
1245  if (STB_PVRIsRecordStarted(0) == FALSE)
1246  {
1247  handle = STB_PVRGrabHandle("import");
1248  ts = STB_PVRTestDataImporter(0, handle, STREAM_TRANS);
1249  video = STB_PVRTestDataImporter(0, handle, STREAM_VIDEO);
1250  audio = STB_PVRTestDataImporter(0, handle, STREAM_AUDIO);
1251 
1252  if ((ts == TRUE) || (video == TRUE) || (audio == TRUE))
1253  {
1254  if (ts == TRUE)
1255  {
1256  STB_PVR_PRINT(("PVR - Start TS Import"));
1257  STB_DMXGetDemuxSource(0, &dmx_source, &dmx_param);
1258  STB_DMXSetDemuxSource(0, DMX_MEMORY, 0);
1259  STB_DMXChangeDecodePIDs(0, 0, 0x44, 0x45, 0, 0);
1262  STB_AVBlankVideo(0, FALSE);
1263  STB_PVRSetRecordStartMode(0, START_IMPORT_TS, 0);
1264  STB_PVRStartRecording(0, handle);
1265  }
1266  else
1267  {
1268  STB_PVR_PRINT(("PVR - Start PES Import"));
1269  STB_PVRSetRecordStartMode(0, START_IMPORT_PES, 0);
1270  STB_PVRStartRecording(0, handle);
1271  }
1272 
1273  do
1274  {
1275  STB_OSTaskDelay(100);
1276  STB_PVRRecordEnabled(0, &video, &audio);
1277  }
1278  while ((video == TRUE) || (audio == TRUE));
1279 
1280  if (ts == TRUE)
1281  {
1282  STB_AVBlankVideo(0, TRUE);
1285  STB_DMXSetDemuxSource(0, dmx_source, dmx_param);
1286  }
1287  STB_PVR_PRINT(("PVR - Finished Import"));
1289  STB_PVRSetRecordStartMode(0, START_RUNNING, 0);
1290  ret_val = TRUE;
1291  }
1292  else
1293  {
1294  STB_PVRReleaseHandle(handle);
1295  STB_PVR_PRINT(("PVR - No Import"));
1296  }
1297  }
1298  }
1299  FUNCTION_FINISH(STB_PVRImportRecording);
1300 
1301  return(ret_val);
1302 }
1303 
1304 #endif
1305 
1306 #if 0
1307 
1318 BOOLEAN STB_PVRExportRecording(U32BIT handle)
1319 {
1320  BOOLEAN ret_val = FALSE;
1321  USE_UNWANTED_PARAM(handle);
1322  BOOLEAN video, audio;
1323 
1324  FUNCTION_START(STB_PVRExportRecording);
1325 
1326  STB_PVR_PRINT(("STB_PVRExportRecording(%lx)", handle));
1327 
1328  if (initialised_flag == TRUE)
1329  {
1330  if (STB_PVRIsPlayStarted(0) == FALSE)
1331  {
1332  STB_PVR_PRINT(("PVR - Start Export"));
1333  STB_PVRSetPlayStartMode(0, START_EXPORT_PES);
1334  STB_PVRStartPlaying(0, handle);
1335 
1336  do
1337  {
1338  STB_OSTaskDelay(100);
1339  STB_PVRPlayEnabled(0, &video, &audio);
1340  }
1341  while ((video == TRUE) || (audio == TRUE));
1342 
1343  STB_PVR_PRINT(("PVR - Finished Export"));
1344  STB_PVRStopPlaying(0);
1345  STB_PVRSetPlayStartMode(0, START_RUNNING);
1346  ret_val = TRUE;
1347  }
1348  }
1349 
1350  FUNCTION_FINISH(STB_PVRExportRecording);
1351 
1352  return(ret_val);
1353 }
1354 
1355 #endif
1356 
1357 /*!**************************************************************************
1358  * @brief Returns the handle for the given recording index
1359  * @param rec_index - recording index
1360  * @return handle, or 0 if recording isn't found
1361  ****************************************************************************/
1362 U32BIT STB_PVRGetHandleForRecordingIndex(U8BIT rec_index)
1363 {
1364  U8BIT i;
1365  U32BIT handle;
1366 
1367  FUNCTION_START(STB_PVRGetHandleForRecordingIndex);
1368 
1369  handle = 0;
1370 
1371  for (i = 0; (i < num_paths) && (handle == 0); i++)
1372  {
1373  if (record_status[i].rec_index == rec_index)
1374  {
1375  handle = record_status[i].handle;
1376  }
1377  }
1378 
1379  FUNCTION_FINISH(STB_PVRGetHandleForRecordingIndex);
1380 
1381  return(handle);
1382 }
1383 
1384 /*!**************************************************************************
1385  * @brief Returns the path for the given recording index
1386  * @param rec_index - recording index
1387  * @return path, or INVALID_RES_ID if recording isn't found
1388  ****************************************************************************/
1389 U8BIT STB_PVRGetPathForRecordingIndex(U8BIT rec_index)
1390 {
1391  U8BIT i;
1392  U8BIT path;
1393 
1394  FUNCTION_START(STB_PVRGetPathForRecordingIndex);
1395 
1396  path = INVALID_RES_ID;
1397 
1398  for (i = 0; (i < num_paths) && (path == INVALID_RES_ID); i++)
1399  {
1400  if (record_status[i].rec_index == rec_index)
1401  {
1402  path = i;
1403  }
1404  }
1405 
1406  FUNCTION_FINISH(STB_PVRGetPathForRecordingIndex);
1407 
1408  return(path);
1409 }
1410 
1411 /*!**************************************************************************
1412  * @brief Sets the name for a recording
1413  * @param handle - recording handle
1414  * @param name - name to be set
1415  ****************************************************************************/
1416 void STB_PVRRecordingSetName(U32BIT handle, U8BIT *name)
1417 {
1418  S_RECORDING *rec_ptr;
1419  U32BIT num_bytes;
1420 
1421  FUNCTION_START(STB_PVRRecordingSetName);
1422 
1423  if (initialised_flag)
1424  {
1425  STB_OSMutexLock(list_mutex);
1426 
1427  /* Find the recording */
1428  rec_ptr = GetRecording(handle);
1429  if (rec_ptr != NULL)
1430  {
1431  if (strlen((char *)rec_ptr->basename) > 0)
1432  {
1433  num_bytes = STB_GetNumBytesInString(name);
1434 
1435  /* Only update the name if it's short enough */
1436  if (num_bytes <= sizeof(rec_ptr->rec_info.name))
1437  {
1438  memcpy(rec_ptr->rec_info.name, name, num_bytes);
1439  }
1440 
1441  /* Update the file */
1442  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, FALSE, &rec_ptr->rec_info);
1443  }
1444  }
1445 
1446  STB_OSMutexUnlock(list_mutex);
1447  }
1448 
1449  FUNCTION_FINISH(STB_PVRRecordingSetName);
1450 }
1451 
1452 /*!**************************************************************************
1453  * @brief Gets the name for a recording
1454  * @param handle - recording handle
1455  * @return Pointer to the name
1456  ****************************************************************************/
1457 U8BIT* STB_PVRRecordingGetName(U32BIT handle)
1458 {
1459  S_RECORDING *rec_ptr;
1460  U8BIT *name_ptr;
1461 
1462  FUNCTION_START(STB_PVRRecordingGetName);
1463 
1464  name_ptr = NULL;
1465 
1466  if (initialised_flag)
1467  {
1468  STB_OSMutexLock(list_mutex);
1469 
1470  /* Find the recording */
1471  rec_ptr = GetRecording(handle);
1472  if (rec_ptr != NULL)
1473  {
1474  name_ptr = &rec_ptr->rec_info.name[0];
1475  }
1476 
1477  STB_OSMutexUnlock(list_mutex);
1478  }
1479 
1480  FUNCTION_FINISH(STB_PVRRecordingGetName);
1481 
1482  return(name_ptr);
1483 }
1484 
1485 /*!**************************************************************************
1486  * @brief Gets the date and time for a recording
1487  * @param handle - recording handle
1488  * @param date - returned date value
1489  * @param hours - returned time in hours
1490  * @param mins - returned time in minutes
1491  * @param secs - returned time in seconds
1492  * @return TRUE if the recording is found
1493  ****************************************************************************/
1494 BOOLEAN STB_PVRRecordingGetDateTime(U32BIT handle, U16BIT *date, U8BIT *hours, U8BIT *mins, U8BIT *secs)
1495 {
1496  S_RECORDING *rec_ptr;
1497  BOOLEAN retval;
1498 
1499  FUNCTION_START(STB_PVRRecordingGetDateTime);
1500 
1501  retval = FALSE;
1502 
1503  if (initialised_flag)
1504  {
1505  STB_OSMutexLock(list_mutex);
1506 
1507  /* Find the recording */
1508  rec_ptr = GetRecording(handle);
1509  if (rec_ptr != NULL)
1510  {
1511  *date = rec_ptr->rec_info.rec_date;
1512  *hours = rec_ptr->rec_info.rec_hour;
1513  *mins = rec_ptr->rec_info.rec_min;
1514  *secs = rec_ptr->rec_info.rec_sec;
1515  retval = TRUE;
1516  }
1517 
1518  STB_OSMutexUnlock(list_mutex);
1519  }
1520 
1521  FUNCTION_FINISH(STB_PVRRecordingGetDateTime);
1522 
1523  return(retval);
1524 }
1525 
1526 /*!**************************************************************************
1527  * @brief Returns the length in time and size in KB of the recording with the given handle
1528  * @param handle - handle of recording being queried
1529  * @param length_hours - length of the recording in hours, returned
1530  * @param length_mins - length of the recording in minutes, returned
1531  * @param length_secs - length of the recording in seconds, returned
1532  * @param rec_size_kb - size of the recording in KB, returned
1533  * @return TRUE if the length and size are being returned, FALSE otherwise
1534  ****************************************************************************/
1535 BOOLEAN STB_PVRRecordingGetLength(U32BIT handle, U8BIT *length_hours, U8BIT *length_mins,
1536  U8BIT *length_secs, U32BIT *rec_size_kb)
1537 {
1538  S_RECORDING *rec_ptr;
1539  BOOLEAN retval;
1540  U32BIT rec_time;
1541 
1542  FUNCTION_START(STB_PVRRecordingGetLength);
1543 
1544  retval = FALSE;
1545 
1546  if (initialised_flag)
1547  {
1548  STB_OSMutexLock(list_mutex);
1549 
1550  rec_ptr = GetRecording(handle);
1551  if (rec_ptr != NULL)
1552  {
1553  if (rec_ptr->recording)
1554  {
1555  /* Recording is still taking place so the time needs to be calculated */
1556  rec_time = GetCurrentRecordTime(handle);
1557  *length_hours = rec_time / 3600;
1558  *length_mins = (rec_time % 3600) / 60;
1559  *length_secs = (rec_time % 3600) % 60;
1560  retval = TRUE;
1561  }
1562  else
1563  {
1564  *length_hours = rec_ptr->rec_info.len_hour;
1565  *length_mins = rec_ptr->rec_info.len_min;
1566  *length_secs = rec_ptr->rec_info.len_sec;
1567  retval = TRUE;
1568  }
1569 
1570  if (retval)
1571  {
1572  /* Get the size of the recording */
1573  if (!STB_PVRGetRecordingSize(rec_ptr->disk_id, rec_ptr->basename, rec_size_kb))
1574  {
1575  retval = FALSE;
1576  }
1577  }
1578  }
1579 
1580  STB_OSMutexUnlock(list_mutex);
1581  }
1582 
1583  FUNCTION_FINISH(STB_PVRRecordingGetLength);
1584 
1585  return(retval);
1586 }
1587 
1588 /*!**************************************************************************
1589  * @brief Gets the disk id for a recording
1590  * @param handle - recording handle
1591  * @return Disk id
1592  ****************************************************************************/
1593 U16BIT STB_PVRRecordingGetDiskId(U32BIT handle)
1594 {
1595  S_RECORDING *rec_ptr;
1596  U16BIT disk_id;
1597 
1598  FUNCTION_START(STB_PVRRecordingGetDiskId);
1599 
1600  disk_id = INVALID_DISK_ID;
1601 
1602  if (initialised_flag)
1603  {
1604  STB_OSMutexLock(list_mutex);
1605 
1606  /* Find the recording */
1607  rec_ptr = GetRecording(handle);
1608  if (rec_ptr != NULL)
1609  {
1610  disk_id = rec_ptr->disk_id;
1611  }
1612 
1613  STB_OSMutexUnlock(list_mutex);
1614  }
1615 
1616  FUNCTION_FINISH(STB_PVRRecordingGetDiskId);
1617 
1618  return(disk_id);
1619 }
1620 
1621 /*!**************************************************************************
1622  * @brief Sets the series/recommendation CRID for a recording and saves the database file
1623  * @param handle - recording handle
1624  * @param crid - crid string
1625  ****************************************************************************/
1626 void STB_PVRRecordingSetOtherCrid(U32BIT handle, U8BIT *crid)
1627 {
1628  S_RECORDING *rec_ptr;
1629  U32BIT name_len;
1630 
1631  FUNCTION_START(STB_PVRRecordingSetOtherCrid);
1632 
1633  if (initialised_flag)
1634  {
1635  STB_OSMutexLock(list_mutex);
1636 
1637  /* Find the recording */
1638  rec_ptr = GetRecording(handle);
1639  if (rec_ptr != NULL)
1640  {
1641  if (crid != NULL)
1642  {
1643  /* Can only save the crid if there's enough space for it */
1644  name_len = STB_GetNumBytesInString(crid);
1645  if (name_len <= sizeof(rec_ptr->rec_info.other_crid))
1646  {
1647  memcpy(rec_ptr->rec_info.other_crid, crid, name_len);
1648  }
1649  else
1650  {
1651  rec_ptr->rec_info.other_crid[0] = '\0';
1652  }
1653  }
1654  else
1655  {
1656  rec_ptr->rec_info.other_crid[0] = '\0';
1657  }
1658 
1659  if (strlen((char *)rec_ptr->basename) > 0)
1660  {
1661  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, FALSE, &rec_ptr->rec_info);
1662  }
1663  }
1664 
1665  STB_OSMutexUnlock(list_mutex);
1666  }
1667 
1668  FUNCTION_FINISH(STB_PVRRecordingSetOtherCrid);
1669 }
1670 
1671 /*!**************************************************************************
1672  * @brief Gets the series/recommendation CRID for a given recording
1673  * @param crid - array into which the crid will be copied
1674  * @param name_len - size of the crid array
1675  * @return TRUE if the recording is found and the crid copied
1676  ****************************************************************************/
1677 BOOLEAN STB_PVRRecordingGetOtherCrid(U32BIT handle, U8BIT *crid, U16BIT name_len)
1678 {
1679  S_RECORDING *rec_ptr;
1680  U32BIT len;
1681  BOOLEAN result;
1682 
1683  FUNCTION_START(STB_PVRRecordingGetOtherCrid);
1684 
1685  result = FALSE;
1686 
1687  if (initialised_flag)
1688  {
1689  STB_OSMutexLock(list_mutex);
1690 
1691  /* Find the recording */
1692  rec_ptr = GetRecording(handle);
1693  if (rec_ptr != NULL)
1694  {
1695  /* The string can only be returned if it will fully fit in the buffer provided */
1696  len = STB_GetNumBytesInString(rec_ptr->rec_info.other_crid);
1697  if ((len > 0) && (len < name_len))
1698  {
1699  memcpy(crid, rec_ptr->rec_info.other_crid, len);
1700  result = TRUE;
1701  }
1702  else
1703  {
1704  crid[0] = '\0';
1705  }
1706  }
1707 
1708  STB_OSMutexUnlock(list_mutex);
1709  }
1710 
1711  FUNCTION_FINISH(STB_PVRRecordingGetOtherCrid);
1712 
1713  return(result);
1714 }
1715 
1721 void STB_PVRRecordingSetAdditionalInfo(U32BIT handle, U8BIT *additional_info)
1722 {
1723  S_RECORDING *rec_ptr;
1724  U32BIT num_bytes;
1725 
1726  FUNCTION_START(STB_PVRRecordingSetAdditionalInfo);
1727 
1728  if (initialised_flag)
1729  {
1730  STB_OSMutexLock(list_mutex);
1731 
1732  /* Find the recording */
1733  rec_ptr = GetRecording(handle);
1734  if (rec_ptr != NULL)
1735  {
1736  if (strlen((char *)rec_ptr->basename) > 0)
1737  {
1738  num_bytes = STB_GetNumBytesInString(additional_info);
1739 
1740  if (num_bytes <= STB_PVR_ADDITIONAL_INFO_LEN)
1741  {
1742  memcpy(rec_ptr->rec_info.additional_info, additional_info, num_bytes);
1743  }
1744  else
1745  {
1746  memcpy(rec_ptr->rec_info.additional_info, additional_info, STB_PVR_ADDITIONAL_INFO_LEN);
1747  }
1748 
1749  /* Update the file */
1750  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, FALSE, &rec_ptr->rec_info);
1751  }
1752  }
1753 
1754  STB_OSMutexUnlock(list_mutex);
1755  }
1756 
1757  FUNCTION_FINISH(STB_PVRRecordingSetAdditionalInfo);
1758 }
1759 
1766 {
1767  S_RECORDING *rec_ptr;
1768  U8BIT *name_ptr;
1769 
1770  FUNCTION_START(STB_PVRRecordingGetAdditionalInfo);
1771 
1772  name_ptr = NULL;
1773 
1774  if (initialised_flag)
1775  {
1776  STB_OSMutexLock(list_mutex);
1777 
1778  /* Find the recording */
1779  rec_ptr = GetRecording(handle);
1780  if (rec_ptr != NULL)
1781  {
1782  name_ptr = &rec_ptr->rec_info.additional_info[0];
1783  }
1784 
1785  STB_OSMutexUnlock(list_mutex);
1786  }
1787 
1788  FUNCTION_FINISH(STB_PVRRecordingGetAdditionalInfo);
1789 
1790  return(name_ptr);
1791 }
1792 
1798 void STB_PVRRecordingSetParentalRatingAge(U32BIT handle, U32BIT parental_rating)
1799 {
1800  S_RECORDING *rec_ptr;
1801 
1802  FUNCTION_START(STB_PVRRecordingSetParentalRating);
1803 
1804  if (initialised_flag)
1805  {
1806  STB_OSMutexLock(list_mutex);
1807 
1808  /* Find the recording */
1809  rec_ptr = GetRecording(handle);
1810  if (rec_ptr != NULL)
1811  {
1812  rec_ptr->rec_info.parental_rating = parental_rating;
1813 
1814  /* Update the file */
1815  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, FALSE, &rec_ptr->rec_info);
1816  }
1817 
1818  STB_OSMutexUnlock(list_mutex);
1819  }
1820 
1821  FUNCTION_FINISH(STB_PVRRecordingSetParentalRating);
1822 }
1823 
1831 {
1832  S_RECORDING *rec_ptr;
1833  U32BIT parental_rating = 0;
1834 
1835  FUNCTION_START(STB_PVRRecordingGetParentalRating);
1836 
1837  if (initialised_flag)
1838  {
1839  STB_OSMutexLock(list_mutex);
1840 
1841  /* Find the recording */
1842  rec_ptr = GetRecording(handle);
1843  if (rec_ptr != NULL)
1844  {
1845  parental_rating = rec_ptr->rec_info.parental_rating;
1846  }
1847 
1848  STB_OSMutexUnlock(list_mutex);
1849  }
1850 
1851  FUNCTION_FINISH(STB_PVRRecordingGetParentalRating);
1852 
1853  return parental_rating;
1854 }
1855 
1861 void STB_PVRRecordingSetStartPadding(U32BIT handle, S32BIT start_padding)
1862 {
1863  S_RECORDING *rec_ptr;
1864 
1865  FUNCTION_START(STB_PVRRecordingSetStartPadding);
1866 
1867  if (initialised_flag)
1868  {
1869  STB_OSMutexLock(list_mutex);
1870 
1871  /* Find the recording */
1872  rec_ptr = GetRecording(handle);
1873  if (rec_ptr != NULL)
1874  {
1875  rec_ptr->rec_info.start_padding = start_padding;
1876 
1877  /* Update the file */
1878  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, FALSE, &rec_ptr->rec_info);
1879  }
1880 
1881  STB_OSMutexUnlock(list_mutex);
1882  }
1883 
1884  FUNCTION_FINISH(STB_PVRRecordingSetStartPadding);
1885 }
1886 
1893 S32BIT STB_PVRRecordingGetStartPadding(U32BIT handle)
1894 {
1895  S_RECORDING *rec_ptr;
1896  S32BIT start_padding = 0;
1897 
1898  FUNCTION_START(STB_PVRRecordingGetStartPadding);
1899 
1900  if (initialised_flag)
1901  {
1902  STB_OSMutexLock(list_mutex);
1903 
1904  /* Find the recording */
1905  rec_ptr = GetRecording(handle);
1906  if (rec_ptr != NULL)
1907  {
1908  start_padding = rec_ptr->rec_info.start_padding;
1909  }
1910 
1911  STB_OSMutexUnlock(list_mutex);
1912  }
1913 
1914  FUNCTION_FINISH(STB_PVRRecordingGetStartPadding);
1915 
1916  return start_padding;
1917 }
1918 
1924 void STB_PVRRecordingSetEndPadding(U32BIT handle, S32BIT end_padding)
1925 {
1926  S_RECORDING *rec_ptr;
1927 
1928  FUNCTION_START(STB_PVRRecordingSetEndPadding);
1929 
1930  if (initialised_flag)
1931  {
1932  STB_OSMutexLock(list_mutex);
1933 
1934  /* Find the recording */
1935  rec_ptr = GetRecording(handle);
1936  if (rec_ptr != NULL)
1937  {
1938  rec_ptr->rec_info.end_padding = end_padding;
1939 
1940  /* Update the file */
1941  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, FALSE, &rec_ptr->rec_info);
1942  }
1943 
1944  STB_OSMutexUnlock(list_mutex);
1945  }
1946 
1947  FUNCTION_FINISH(STB_PVRRecordingSetEndPadding);
1948 }
1949 
1956 S32BIT STB_PVRRecordingGetEndPadding(U32BIT handle)
1957 {
1958  S_RECORDING *rec_ptr;
1959  S32BIT end_padding = 0;
1960 
1961  FUNCTION_START(STB_PVRRecordingGetEndPadding);
1962 
1963  if (initialised_flag)
1964  {
1965  STB_OSMutexLock(list_mutex);
1966 
1967  /* Find the recording */
1968  rec_ptr = GetRecording(handle);
1969  if (rec_ptr != NULL)
1970  {
1971  end_padding = rec_ptr->rec_info.end_padding;
1972  }
1973 
1974  STB_OSMutexUnlock(list_mutex);
1975  }
1976 
1977  FUNCTION_FINISH(STB_PVRRecordingGetEndPadding);
1978 
1979  return end_padding;
1980 }
1981 
1982 /*!**************************************************************************
1983  * @brief Sets the service name for a recording and saves the database file
1984  * @param handle - recording handle
1985  * @param service_name - service name to be set
1986  ****************************************************************************/
1987 void STB_PVRRecordingSetServiceName(U32BIT handle, U8BIT *service_name)
1988 {
1989  S_RECORDING *rec_ptr;
1990  U32BIT name_len;
1991 
1992  FUNCTION_START(STB_PVRRecordingSetServiceName);
1993 
1994  if (initialised_flag)
1995  {
1996  STB_OSMutexLock(list_mutex);
1997 
1998  /* Find the recording */
1999  rec_ptr = GetRecording(handle);
2000  if ((rec_ptr != NULL) && (service_name != NULL))
2001  {
2002  if (strlen((char *)rec_ptr->basename) > 0)
2003  {
2004  name_len = STB_GetNumBytesInString(service_name);
2005  if (name_len > 0)
2006  {
2007  WriteExtendedInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_SERVICE_NAME,
2008  name_len, service_name);
2009  }
2010  }
2011  }
2012 
2013  STB_OSMutexUnlock(list_mutex);
2014  }
2015 
2016  FUNCTION_FINISH(STB_PVRRecordingSetServiceName);
2017 }
2018 
2019 /*!**************************************************************************
2020  * @brief Gets the service name for a given recording
2021  * @param service_name - array into which the name will be copied
2022  * @param name_len - size of the name array
2023  * @return TRUE if the recording is found and it's database file is successfully opened
2024  ****************************************************************************/
2025 BOOLEAN STB_PVRRecordingGetServiceName(U32BIT handle, U8BIT *service_name, U16BIT name_len)
2026 {
2027  S_RECORDING *rec_ptr;
2028  BOOLEAN result;
2029 
2030  FUNCTION_START(STB_PVRRecordingGetServiceName);
2031 
2032  result = FALSE;
2033 
2034  if (initialised_flag)
2035  {
2036  STB_OSMutexLock(list_mutex);
2037 
2038  /* Find the recording */
2039  rec_ptr = GetRecording(handle);
2040  if (rec_ptr != NULL)
2041  {
2042  result = ReadExtendedInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_SERVICE_NAME,
2043  service_name, name_len);
2044  }
2045 
2046  STB_OSMutexUnlock(list_mutex);
2047  }
2048 
2049  FUNCTION_FINISH(STB_PVRRecordingGetServiceName);
2050 
2051  return(result);
2052 }
2053 
2054 /*!**************************************************************************
2055  * @brief Sets the short description for a recorded programme
2056  * @param handle - recording handle
2057  * @param description - text string
2058  ****************************************************************************/
2059 void STB_PVRRecordingSetDescription(U32BIT handle, U8BIT *description)
2060 {
2061  S_RECORDING *rec_ptr;
2062  U16BIT desc_len;
2063 
2064  FUNCTION_START(STB_PVRRecordingSetDescription);
2065 
2066  if (initialised_flag)
2067  {
2068  STB_OSMutexLock(list_mutex);
2069 
2070  /* Find the recording */
2071  rec_ptr = GetRecording(handle);
2072  if ((rec_ptr != NULL) && (description != NULL))
2073  {
2074  if (strlen((char *)rec_ptr->basename) > 0)
2075  {
2076  desc_len = STB_GetNumBytesInString(description);
2077  if (desc_len > 0)
2078  {
2079  WriteExtendedInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_SHORT_DESC,
2080  desc_len, description);
2081  }
2082  }
2083  }
2084 
2085  STB_OSMutexUnlock(list_mutex);
2086  }
2087 
2088  FUNCTION_FINISH(STB_PVRRecordingSetDescription);
2089 }
2090 
2091 /*!**************************************************************************
2092  * @brief Gets the short description for a given recording
2093  * @param handle - recording handle
2094  * @param description - array into which the description is copied
2095  * @param desc_len - size of the description array
2096  ****************************************************************************/
2097 BOOLEAN STB_PVRRecordingGetDescription(U32BIT handle, U8BIT *description, U16BIT desc_len)
2098 {
2099  S_RECORDING *rec_ptr;
2100  BOOLEAN result;
2101 
2102  FUNCTION_START(STB_PVRRecordingGetDescription);
2103 
2104  result = FALSE;
2105 
2106  if (initialised_flag)
2107  {
2108  STB_OSMutexLock(list_mutex);
2109 
2110  /* Find the recording */
2111  rec_ptr = GetRecording(handle);
2112  if (rec_ptr != NULL)
2113  {
2114  result = ReadExtendedInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_SHORT_DESC,
2115  description, desc_len);
2116  }
2117 
2118  STB_OSMutexUnlock(list_mutex);
2119  }
2120 
2121  FUNCTION_FINISH(STB_PVRRecordingGetDescription);
2122 
2123  return(result);
2124 }
2125 
2126 /*!**************************************************************************
2127  * @brief Gets the length of the short description for a given recording
2128  * @param handle - recording handle
2129  * @return length of the short description text, or 0 if none available
2130  ****************************************************************************/
2132 {
2133  S_RECORDING *rec_ptr;
2134  U32BIT length;
2135 
2136  FUNCTION_START(STB_PVRRecordingGetDescriptionLen);
2137 
2138  length = 0;
2139 
2140  if (initialised_flag)
2141  {
2142  STB_OSMutexLock(list_mutex);
2143 
2144  /* Find the recording */
2145  rec_ptr = GetRecording(handle);
2146  if (rec_ptr != NULL)
2147  {
2148  length = GetExtendedInfoSize(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_SHORT_DESC);
2149  }
2150 
2151  STB_OSMutexUnlock(list_mutex);
2152  }
2153 
2154  FUNCTION_FINISH(STB_PVRRecordingGetDescriptionLen);
2155 
2156  return((U16BIT)length);
2157 }
2158 
2159 /*!**************************************************************************
2160  * @brief Sets the extended description for a recorded programme
2161  * @param handle - recording handle
2162  * @param description - text string
2163  ****************************************************************************/
2164 void STB_PVRRecordingSetExtendedDescription(U32BIT handle, U8BIT *description)
2165 {
2166  S_RECORDING *rec_ptr;
2167  U16BIT desc_len;
2168 
2170 
2171  if (initialised_flag)
2172  {
2173  STB_OSMutexLock(list_mutex);
2174 
2175  /* Find the recording */
2176  rec_ptr = GetRecording(handle);
2177  if ((rec_ptr != NULL) && (description != NULL))
2178  {
2179  if (strlen((char *)rec_ptr->basename) > 0)
2180  {
2181  desc_len = STB_GetNumBytesInString(description);
2182  if (desc_len > 0)
2183  {
2184  WriteExtendedInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_EXTENDED_DESC,
2185  desc_len, description);
2186  }
2187  }
2188  }
2189 
2190  STB_OSMutexUnlock(list_mutex);
2191  }
2192 
2193  FUNCTION_FINISH(STB_PVRRecordingSetExtendedDescription);
2194 }
2195 
2196 /*!**************************************************************************
2197  * @brief Gets the extended description for a given recording
2198  * @param handle - recording handle
2199  * @param description - array into which the description is copied
2200  * @param desc_len - size of the description array
2201  ****************************************************************************/
2202 BOOLEAN STB_PVRRecordingGetExtendedDescription(U32BIT handle, U8BIT *description, U16BIT desc_len)
2203 {
2204  S_RECORDING *rec_ptr;
2205  BOOLEAN result;
2206 
2208 
2209  result = FALSE;
2210 
2211  if (initialised_flag)
2212  {
2213  STB_OSMutexLock(list_mutex);
2214 
2215  /* Find the recording */
2216  rec_ptr = GetRecording(handle);
2217  if (rec_ptr != NULL)
2218  {
2219  result = ReadExtendedInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_EXTENDED_DESC,
2220  description, desc_len);
2221  }
2222 
2223  STB_OSMutexUnlock(list_mutex);
2224  }
2225 
2226  FUNCTION_FINISH(STB_PVRRecordingGetExtendedDescription);
2227 
2228  return(result);
2229 }
2230 
2231 /*!**************************************************************************
2232  * @brief Gets the length of the extended description for a given recording
2233  * @param handle - recording handle
2234  * @return length of the extended description text, or 0 if none available
2235  ****************************************************************************/
2237 {
2238  S_RECORDING *rec_ptr;
2239  U32BIT length;
2240 
2242 
2243  length = 0;
2244 
2245  if (initialised_flag)
2246  {
2247  STB_OSMutexLock(list_mutex);
2248 
2249  /* Find the recording */
2250  rec_ptr = GetRecording(handle);
2251  if (rec_ptr != NULL)
2252  {
2253  length = GetExtendedInfoSize(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_EXTENDED_DESC);
2254  }
2255 
2256  STB_OSMutexUnlock(list_mutex);
2257  }
2258 
2260 
2261  return((U16BIT)length);
2262 }
2263 
2264 /*!**************************************************************************
2265  * @brief Sets the programme CRID for a recording and saves the database file
2266  * @param handle - recording handle
2267  * @param crid - programme crid string
2268  ****************************************************************************/
2269 void STB_PVRRecordingSetCrid(U32BIT handle, U8BIT *crid)
2270 {
2271  S_RECORDING *rec_ptr;
2272  U32BIT name_len;
2273 
2274  FUNCTION_START(STB_PVRRecordingSetCrid);
2275 
2276  if (initialised_flag)
2277  {
2278  STB_OSMutexLock(list_mutex);
2279 
2280  /* Find the recording */
2281  rec_ptr = GetRecording(handle);
2282  if (rec_ptr != NULL)
2283  {
2284  if (crid != NULL)
2285  {
2286  /* Can only save the crid if there's enough space for it */
2287  name_len = STB_GetNumBytesInString(crid);
2288  if (name_len <= sizeof(rec_ptr->rec_info.prog_crid))
2289  {
2290  memcpy(rec_ptr->rec_info.prog_crid, crid, name_len);
2291  }
2292  else
2293  {
2294  rec_ptr->rec_info.prog_crid[0] = '\0';
2295  }
2296  }
2297  else
2298  {
2299  rec_ptr->rec_info.prog_crid[0] = '\0';
2300  }
2301 
2302  if (strlen((char *)rec_ptr->basename) > 0)
2303  {
2304  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, FALSE, &rec_ptr->rec_info);
2305  }
2306  }
2307 
2308  STB_OSMutexUnlock(list_mutex);
2309  }
2310 
2311  FUNCTION_FINISH(STB_PVRRecordingSetCrid);
2312 }
2313 
2314 /*!**************************************************************************
2315  * @brief Gets the programme CRID for a given recording
2316  * @param crid - array into which the crid will be copied
2317  * @param name_len - size of the crid array
2318  * @return TRUE if the recording is found and the crid copied
2319  ****************************************************************************/
2320 BOOLEAN STB_PVRRecordingGetCrid(U32BIT handle, U8BIT *crid, U16BIT name_len)
2321 {
2322  S_RECORDING *rec_ptr;
2323  U32BIT len;
2324  BOOLEAN result;
2325 
2326  FUNCTION_START(STB_PVRRecordingGetCrid);
2327 
2328  result = FALSE;
2329 
2330  if (initialised_flag)
2331  {
2332  STB_OSMutexLock(list_mutex);
2333 
2334  /* Find the recording */
2335  rec_ptr = GetRecording(handle);
2336  if (rec_ptr != NULL)
2337  {
2338  /* The string can only be returned if it will fully fit in the buffer provided */
2339  len = STB_GetNumBytesInString(rec_ptr->rec_info.prog_crid);
2340  if ((len > 0) && (len < name_len))
2341  {
2342  memcpy(crid, rec_ptr->rec_info.prog_crid, len);
2343  result = TRUE;
2344  }
2345  else
2346  {
2347  crid[0] = '\0';
2348  }
2349  }
2350 
2351  STB_OSMutexUnlock(list_mutex);
2352  }
2353 
2354  FUNCTION_FINISH(STB_PVRRecordingGetCrid);
2355 
2356  return(result);
2357 }
2358 
2359 /*!**************************************************************************
2360  * @brief Returns whether the recording with the given handle is currently being recorded
2361  * @param handle - recording being queried
2362  * @return TRUE if recording, FALSE otherwise
2363  ****************************************************************************/
2364 BOOLEAN STB_PVRIsBeingRecorded(U32BIT handle)
2365 {
2366  S_RECORDING *rec_ptr;
2367  BOOLEAN is_recording;
2368 
2369  FUNCTION_START(STB_PVRIsBeingRecorded);
2370 
2371  is_recording = FALSE;
2372 
2373  if (initialised_flag)
2374  {
2375  STB_OSMutexLock(list_mutex);
2376 
2377  rec_ptr = GetRecording(handle);
2378  if (rec_ptr != NULL)
2379  {
2380  is_recording = rec_ptr->recording;
2381  }
2382 
2383  STB_OSMutexUnlock(list_mutex);
2384  }
2385 
2386  FUNCTION_FINISH(STB_PVRIsBeingRecorded);
2387 
2388  return(is_recording);
2389 }
2390 
2391 /*!**************************************************************************
2392  * @brief Sets a recording to a series recording.
2393  * @param handle - recording handle
2394  * @param crid - crid string
2395  ****************************************************************************/
2396 void STB_PVRRecordingSetSeries(U32BIT handle)
2397 {
2398  S_RECORDING *rec_ptr;
2399 
2400  FUNCTION_START(STB_PVRRecordingSetSeries);
2401 
2402  if (initialised_flag)
2403  {
2404  STB_OSMutexLock(list_mutex);
2405 
2406  rec_ptr = GetRecording(handle);
2407  if (rec_ptr != NULL)
2408  {
2409  rec_ptr->rec_info.flags |= REC_SERIES;
2410 
2411  if (strlen((char *)rec_ptr->basename) > 0)
2412  {
2413  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, FALSE, &rec_ptr->rec_info);
2414  }
2415  }
2416 
2417  STB_OSMutexUnlock(list_mutex);
2418  }
2419 
2420  FUNCTION_FINISH(STB_PVRRecordingSetSeries);
2421 }
2422 
2423 /*!**************************************************************************
2424  * @brief Sets a recording to a recommendation recording.
2425  * @param handle - recording handle
2426  * @param crid - crid string
2427  ****************************************************************************/
2429 {
2430  S_RECORDING *rec_ptr;
2431 
2432  FUNCTION_START(STB_PVRRecordingSetRecommendation);
2433 
2434  if (initialised_flag)
2435  {
2436  STB_OSMutexLock(list_mutex);
2437 
2438  rec_ptr = GetRecording(handle);
2439  if (rec_ptr != NULL)
2440  {
2441  rec_ptr->rec_info.flags |= REC_RECOMMENDATION;
2442 
2443  if (strlen((char *)rec_ptr->basename) > 0)
2444  {
2445  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, FALSE, &rec_ptr->rec_info);
2446  }
2447  }
2448 
2449  STB_OSMutexUnlock(list_mutex);
2450  }
2451 
2452  FUNCTION_FINISH(STB_PVRRecordingSetRecommendation);
2453 }
2454 
2455 /*!**************************************************************************
2456  * @brief Returns whether the given recording is a series
2457  * @param handle - recording handle
2458  * @return TRUE if recording is part of a series, FALSE otherwise
2459  ****************************************************************************/
2460 BOOLEAN STB_PVRRecordingGetSeries(U32BIT handle)
2461 {
2462  S_RECORDING *rec_ptr;
2463  BOOLEAN series;
2464 
2465  FUNCTION_START(STB_PVRRecordingGetSeries);
2466 
2467  series = FALSE;
2468 
2469  if (initialised_flag)
2470  {
2471  STB_OSMutexLock(list_mutex);
2472 
2473  rec_ptr = GetRecording(handle);
2474  if (rec_ptr != NULL)
2475  {
2476  if ((rec_ptr->rec_info.flags & REC_SERIES) != 0)
2477  {
2478  series = TRUE;
2479  }
2480  }
2481 
2482  STB_OSMutexUnlock(list_mutex);
2483  }
2484 
2485  FUNCTION_FINISH(STB_PVRRecordingGetSeries);
2486 
2487  return(series);
2488 }
2489 
2490 /*!**************************************************************************
2491  * @brief Returns whether the given recording is a recommendation
2492  * @param handle - recording handle
2493  * @return TRUE if recording is a recommendation, FALSE otherwise
2494  ****************************************************************************/
2496 {
2497  S_RECORDING *rec_ptr;
2498  BOOLEAN recommendation;
2499 
2500  FUNCTION_START(STB_PVRRecordingGetRecommendation);
2501 
2502  recommendation = FALSE;
2503 
2504  if (initialised_flag)
2505  {
2506  STB_OSMutexLock(list_mutex);
2507 
2508  rec_ptr = GetRecording(handle);
2509  if (rec_ptr != NULL)
2510  {
2511  if ((rec_ptr->rec_info.flags & REC_RECOMMENDATION) != 0)
2512  {
2513  recommendation = TRUE;
2514  }
2515  }
2516 
2517  STB_OSMutexUnlock(list_mutex);
2518  }
2519 
2520  FUNCTION_FINISH(STB_PVRRecordingGetRecommendation);
2521 
2522  return(recommendation);
2523 }
2524 
2525 /*!**************************************************************************
2526  * @brief Sets the locked state of a recording
2527  * @param handle - recording handle
2528  * @param state - TRUE for locked, FALSE for unlocked
2529  * @return TRUE if recording is valid, FALSE otherwise
2530  ****************************************************************************/
2531 BOOLEAN STB_PVRRecordingSetLocked(U32BIT handle, BOOLEAN state)
2532 {
2533  S_RECORDING *rec_ptr;
2534  BOOLEAN retval;
2535 
2536  FUNCTION_START(STB_PVRRecordingSetLocked);
2537 
2538  retval = FALSE;
2539 
2540  if (initialised_flag)
2541  {
2542  STB_OSMutexLock(list_mutex);
2543 
2544  rec_ptr = GetRecording(handle);
2545  if (rec_ptr != NULL)
2546  {
2547  if (state)
2548  {
2549  rec_ptr->rec_info.flags |= REC_LOCKED;
2550  }
2551  else
2552  {
2553  rec_ptr->rec_info.flags &= ~REC_LOCKED;
2554  }
2555 
2556  if (strlen((char *)rec_ptr->basename) > 0)
2557  {
2558  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, FALSE, &rec_ptr->rec_info);
2559  }
2560 
2561  retval = TRUE;
2562  }
2563 
2564  STB_OSMutexUnlock(list_mutex);
2565  }
2566 
2567  FUNCTION_FINISH(STB_PVRRecordingSetLocked);
2568 
2569  return(retval);
2570 }
2571 
2572 /*!**************************************************************************
2573  * @brief Returns whether the given recording is locked
2574  * @param handle - recording handle
2575  * @return TRUE if recording is locked, FALSE otherwise
2576  ****************************************************************************/
2577 BOOLEAN STB_PVRRecordingGetLocked(U32BIT handle)
2578 {
2579  S_RECORDING *rec_ptr;
2580  BOOLEAN locked;
2581 
2582  FUNCTION_START(STB_PVRRecordingGetLocked);
2583 
2584  locked = FALSE;
2585 
2586  if (initialised_flag)
2587  {
2588  STB_OSMutexLock(list_mutex);
2589 
2590  rec_ptr = GetRecording(handle);
2591  if (rec_ptr != NULL)
2592  {
2593  if ((rec_ptr->rec_info.flags & REC_LOCKED) != 0)
2594  {
2595  locked = TRUE;
2596  }
2597  }
2598 
2599  STB_OSMutexUnlock(list_mutex);
2600  }
2601 
2602  FUNCTION_FINISH(STB_PVRRecordingGetLocked);
2603 
2604  return(locked);
2605 }
2606 
2607 /*!**************************************************************************
2608  * @brief Sets the selected state of a recording
2609  * @param handle - recording handle
2610  * @param state - TRUE for selected, FALSE for unselected
2611  * @return TRUE if recording is valid, FALSE otherwise
2612  ****************************************************************************/
2613 BOOLEAN STB_PVRRecordingSetSelected(U32BIT handle, BOOLEAN state)
2614 {
2615  S_RECORDING *rec_ptr;
2616  BOOLEAN retval;
2617 
2618  FUNCTION_START(STB_PVRRecordingSetSelected);
2619 
2620  retval = FALSE;
2621 
2622  if (initialised_flag)
2623  {
2624  STB_OSMutexLock(list_mutex);
2625 
2626  rec_ptr = GetRecording(handle);
2627  if (rec_ptr != NULL)
2628  {
2629  rec_ptr->selected = state;
2630  retval = TRUE;
2631  }
2632 
2633  STB_OSMutexUnlock(list_mutex);
2634  }
2635 
2636  FUNCTION_FINISH(STB_PVRRecordingSetSelected);
2637 
2638  return(retval);
2639 }
2640 
2641 /*!**************************************************************************
2642  * @brief Returns whether the given recording is selected
2643  * @param handle - recording handle
2644  * @return TRUE if recording is selected, FALSE otherwise
2645  ****************************************************************************/
2646 BOOLEAN STB_PVRRecordingGetSelected(U32BIT handle)
2647 {
2648  S_RECORDING *rec_ptr;
2649  BOOLEAN selected;
2650 
2651  FUNCTION_START(STB_PVRRecordingGetSelected);
2652 
2653  selected = FALSE;
2654 
2655  if (initialised_flag)
2656  {
2657  STB_OSMutexLock(list_mutex);
2658 
2659  rec_ptr = GetRecording(handle);
2660  if (rec_ptr != NULL)
2661  {
2662  selected = rec_ptr->selected;
2663  }
2664 
2665  STB_OSMutexUnlock(list_mutex);
2666  }
2667 
2668  FUNCTION_FINISH(STB_PVRRecordingGetSelected);
2669 
2670  return(selected);
2671 }
2672 
2673 /*!**************************************************************************
2674  * @brief Returns whether the given recording is encrypted
2675  * @param handle - recording handle
2676  * @return TRUE if recording is encrypted, FALSE otherwise
2677  ****************************************************************************/
2678 BOOLEAN STB_PVRRecordingIsEncrypted(U32BIT handle)
2679 {
2680  S_RECORDING *rec_ptr;
2681  BOOLEAN encrypted;
2682 
2683  FUNCTION_START(STB_PVRRecordingIsEncrypted);
2684 
2685  encrypted = FALSE;
2686 
2687  if (initialised_flag)
2688  {
2689  STB_OSMutexLock(list_mutex);
2690 
2691  rec_ptr = GetRecording(handle);
2692  if (rec_ptr != NULL)
2693  {
2694  if ((rec_ptr->rec_info.flags & REC_ENCRYPTED) != 0)
2695  {
2696  encrypted = TRUE;
2697  }
2698  }
2699 
2700  STB_OSMutexUnlock(list_mutex);
2701  }
2702 
2703  FUNCTION_FINISH(STB_PVRRecordingIsEncrypted);
2704 
2705  return(encrypted);
2706 }
2707 
2708 /*!**************************************************************************
2709  * @brief Sets the parental lock state of a recording
2710  * @param handle - recording handle
2711  * @param state - TRUE for locked, FALSE for unlocked
2712  * @return TRUE if recording is valid, FALSE otherwise
2713  ****************************************************************************/
2714 BOOLEAN STB_PVRRecordingSetParentalLock(U32BIT handle, BOOLEAN state)
2715 {
2716  S_RECORDING *rec_ptr;
2717  BOOLEAN retval;
2718 
2719  FUNCTION_START(STB_PVRRecordingSetParentalLock);
2720 
2721  retval = FALSE;
2722 
2723  if (initialised_flag)
2724  {
2725  STB_OSMutexLock(list_mutex);
2726 
2727  rec_ptr = GetRecording(handle);
2728  if (rec_ptr != NULL)
2729  {
2730  if (state)
2731  {
2732  rec_ptr->rec_info.flags |= REC_PARENTAL_LOCK;
2733  }
2734  else
2735  {
2736  rec_ptr->rec_info.flags &= ~REC_PARENTAL_LOCK;
2737  }
2738 
2739  if (strlen((char *)rec_ptr->basename) > 0)
2740  {
2741  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, FALSE, &rec_ptr->rec_info);
2742  }
2743 
2744  retval = TRUE;
2745  }
2746 
2747  STB_OSMutexUnlock(list_mutex);
2748  }
2749 
2750  FUNCTION_FINISH(STB_PVRRecordingSetParentalLock);
2751 
2752  return(retval);
2753 }
2754 
2755 /*!**************************************************************************
2756  * @brief Returns the parental lock state of the given recording
2757  * @param handle - recording handle
2758  * @return TRUE if recording is locked, FALSE otherwise
2759  ****************************************************************************/
2760 BOOLEAN STB_PVRRecordingGetParentalLock(U32BIT handle)
2761 {
2762  S_RECORDING *rec_ptr;
2763  BOOLEAN locked;
2764 
2765  FUNCTION_START(STB_PVRRecordingGetParentalLock);
2766 
2767  locked = FALSE;
2768 
2769  if (initialised_flag)
2770  {
2771  STB_OSMutexLock(list_mutex);
2772 
2773  rec_ptr = GetRecording(handle);
2774  if (rec_ptr != NULL)
2775  {
2776  if ((rec_ptr->rec_info.flags & REC_PARENTAL_LOCK) != 0)
2777  {
2778  locked = TRUE;
2779  }
2780  }
2781 
2782  STB_OSMutexUnlock(list_mutex);
2783  }
2784 
2785  FUNCTION_FINISH(STB_PVRRecordingGetParentalLock);
2786 
2787  return(locked);
2788 }
2789 
2790 /*!**************************************************************************
2791  * @brief Sets the guidance text of a recording
2792  * @param handle - recording handle
2793  * @param text - guidance text
2794  * @return TRUE if recording is valid, FALSE otherwise
2795  ****************************************************************************/
2796 BOOLEAN STB_PVRRecordingSetGuidance(U32BIT handle, U8BIT *text)
2797 {
2798  S_RECORDING *rec_ptr;
2799  U16BIT text_len;
2800  BOOLEAN retval;
2801 
2802  FUNCTION_START(STB_PVRRecordingSetGuidance);
2803 
2804  retval = FALSE;
2805 
2806  if (initialised_flag)
2807  {
2808  STB_OSMutexLock(list_mutex);
2809 
2810  rec_ptr = GetRecording(handle);
2811  if ((rec_ptr != NULL) && (text != NULL))
2812  {
2813  if (strlen((char *)rec_ptr->basename) > 0)
2814  {
2815  text_len = STB_GetNumBytesInString(text);
2816  if (text_len > 0)
2817  {
2818  if (WriteExtendedInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_GUIDANCE,
2819  text_len, text))
2820  {
2821  rec_ptr->rec_info.flags |= REC_HAS_GUIDANCE;
2822  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, FALSE, &rec_ptr->rec_info);
2823  }
2824  }
2825  }
2826  }
2827 
2828  STB_OSMutexUnlock(list_mutex);
2829  }
2830 
2831  FUNCTION_FINISH(STB_PVRRecordingSetGuidance);
2832 
2833  return(retval);
2834 }
2835 
2836 /*!**************************************************************************
2837  * @brief Returns whether the given recording has guidance
2838  * @param handle - recording handle
2839  * @return TRUE if recording has guidance, FALSE otherwise
2840  ****************************************************************************/
2841 BOOLEAN STB_PVRRecordingHasGuidance(U32BIT handle)
2842 {
2843  S_RECORDING *rec_ptr;
2844  BOOLEAN has_guidance;
2845 
2846  FUNCTION_START(STB_PVRRecordingHasGuidance);
2847 
2848  has_guidance = FALSE;
2849 
2850  if (initialised_flag)
2851  {
2852  STB_OSMutexLock(list_mutex);
2853 
2854  rec_ptr = GetRecording(handle);
2855  if (rec_ptr != NULL)
2856  {
2857  if ((rec_ptr->rec_info.flags & REC_HAS_GUIDANCE) != 0)
2858  {
2859  has_guidance = TRUE;
2860  }
2861  }
2862 
2863  STB_OSMutexUnlock(list_mutex);
2864  }
2865 
2866  FUNCTION_FINISH(STB_PVRRecordingHasGuidance);
2867 
2868  return(has_guidance);
2869 }
2870 
2871 /*!**************************************************************************
2872  * @brief Returns the whether a recording has guidance and the guidance text if available
2873  * @param handle - recording handle
2874  * @param text - array into which the guidance text is copied, can be NULL if text isn't required
2875  * @param text_len - size of the array passed in, ignored if text is NULL
2876  * @return TRUE if recording has guidance, FALSE otherwise
2877  ****************************************************************************/
2878 BOOLEAN STB_PVRRecordingGetGuidance(U32BIT handle, U8BIT *text, U16BIT text_len)
2879 {
2880  S_RECORDING *rec_ptr;
2881  BOOLEAN result;
2882 
2883  FUNCTION_START(STB_PVRRecordingGetGuidance);
2884 
2885  result = FALSE;
2886 
2887  if (initialised_flag)
2888  {
2889  STB_OSMutexLock(list_mutex);
2890 
2891  rec_ptr = GetRecording(handle);
2892  if (rec_ptr != NULL)
2893  {
2894  /* Don't bother reading the text if guidance isn't available */
2895  if ((rec_ptr->rec_info.flags & REC_HAS_GUIDANCE) != 0)
2896  {
2897  result = ReadExtendedInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_GUIDANCE,
2898  text, text_len);
2899  }
2900  }
2901 
2902  STB_OSMutexUnlock(list_mutex);
2903  }
2904 
2905  FUNCTION_FINISH(STB_PVRRecordingGetGuidance);
2906 
2907  return(result);
2908 }
2909 
2910 /*!**************************************************************************
2911  * @brief Gets the length of the guidance text for a given recording
2912  * @param handle - recording handle
2913  * @return length of the guidance text, or 0 if none available
2914  ****************************************************************************/
2915 U16BIT STB_PVRRecordingGetGuidanceLen(U32BIT handle)
2916 {
2917  S_RECORDING *rec_ptr;
2918  U32BIT length;
2919 
2920  FUNCTION_START(STB_PVRRecordingGetGuidanceLen);
2921 
2922  length = 0;
2923 
2924  if (initialised_flag)
2925  {
2926  STB_OSMutexLock(list_mutex);
2927 
2928  /* Find the recording */
2929  rec_ptr = GetRecording(handle);
2930  if (rec_ptr != NULL)
2931  {
2932  /* Don't bother reading the text if guidance isn't available */
2933  if ((rec_ptr->rec_info.flags & REC_HAS_GUIDANCE) != 0)
2934  {
2935  length = GetExtendedInfoSize(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_GUIDANCE);
2936  }
2937  }
2938 
2939  STB_OSMutexUnlock(list_mutex);
2940  }
2941 
2942  FUNCTION_FINISH(STB_PVRRecordingGetGuidanceLen);
2943 
2944  return((U16BIT)length);
2945 }
2946 
2953 BOOLEAN STB_PVRRecordingSetStatus(U32BIT handle, E_PVR_RECORDING_STATUS status)
2954 {
2955  BOOLEAN retval;
2956  S_RECORDING *rec_ptr;
2957 
2958  FUNCTION_START(STB_PVRRecordingSetStatus);
2959 
2960  retval = FALSE;
2961 
2962  if (initialised_flag)
2963  {
2964  STB_OSMutexLock(list_mutex);
2965 
2966  rec_ptr = GetRecording(handle);
2967  if (rec_ptr != NULL)
2968  {
2969  rec_ptr->rec_info.status = (U8BIT)status;
2970 
2971  retval = WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, FALSE, &rec_ptr->rec_info);
2972  }
2973 
2974  STB_OSMutexUnlock(list_mutex);
2975  }
2976 
2977  FUNCTION_FINISH(STB_PVRRecordingSetStatus);
2978 
2979  return(retval);
2980 }
2981 
2988 BOOLEAN STB_PVRRecordingGetStatus(U32BIT handle, E_PVR_RECORDING_STATUS *status)
2989 {
2990  BOOLEAN retval;
2991  S_RECORDING *rec_ptr;
2992 
2993  FUNCTION_START(STB_PVRRecordingGetStatus);
2994 
2995  retval = FALSE;
2996 
2997  if (initialised_flag && (status != NULL))
2998  {
2999  STB_OSMutexLock(list_mutex);
3000 
3001  /* Find the recording */
3002  rec_ptr = GetRecording(handle);
3003  if (rec_ptr != NULL)
3004  {
3005  *status = (E_PVR_RECORDING_STATUS)rec_ptr->rec_info.status;
3006  retval = TRUE;
3007  }
3008 
3009  STB_OSMutexUnlock(list_mutex);
3010  }
3011 
3012  FUNCTION_FINISH(STB_PVRRecordingGetStatus);
3013 
3014  return(retval);
3015 }
3016 
3017 #ifdef COMMON_INTERFACE
3018 /*!**************************************************************************
3019  * @brief Saves the given CI+ CICAM id with a recording
3020  * @param handle - recording handle
3021  * @param cicam_id - an array of bytes defining the cicam id
3022  * @param id_len - number of bytes in the array
3023  * @return TRUE if value is saved, FALSE otherwise
3024  ****************************************************************************/
3025 BOOLEAN STB_PVRRecordingSetCicamId(U32BIT handle, U8BIT *cicam_id, U8BIT id_len)
3026 {
3027  S_RECORDING *rec_ptr;
3028  BOOLEAN retval;
3029 
3030  FUNCTION_START(STB_PVRRecordingSetCicamId);
3031 
3032  retval = FALSE;
3033 
3034  if (initialised_flag)
3035  {
3036  STB_OSMutexLock(list_mutex);
3037 
3038  /* Find the recording */
3039  rec_ptr = GetRecording(handle);
3040  if (rec_ptr != NULL)
3041  {
3042  if (strlen((char *)rec_ptr->basename) > 0)
3043  {
3044  retval = WriteExtendedInfo(rec_ptr->disk_id, rec_ptr->basename,
3045  EXT_INFO_CIPLUS_CICAM_ID, id_len, cicam_id);
3046  }
3047  }
3048 
3049  STB_OSMutexUnlock(list_mutex);
3050  }
3051 
3052  FUNCTION_FINISH(STB_PVRRecordingSetCicamId);
3053 
3054  return(retval);
3055 }
3056 
3057 /*!**************************************************************************
3058  * @brief Reads the CI+ CICAM id for the given recording
3059  * @param handle - recording handle
3060  * @param cicam_id - an array of bytes to read into
3061  * @param id_len - number of bytes in the array
3062  * @return TRUE if value is read, FALSE otherwise
3063  ****************************************************************************/
3064 BOOLEAN STB_PVRRecordingGetCicamId(U32BIT handle, U8BIT *cicam_id, U8BIT id_len)
3065 {
3066  BOOLEAN retval;
3067  S_RECORDING *rec_ptr;
3068 
3069  FUNCTION_START(STB_PVRRecordingGetCicamId);
3070 
3071  retval = FALSE;
3072 
3073  if (initialised_flag)
3074  {
3075  STB_OSMutexLock(list_mutex);
3076 
3077  /* Find the recording */
3078  rec_ptr = GetRecording(handle);
3079  if (rec_ptr != NULL)
3080  {
3081  retval = ReadExtendedInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_CIPLUS_CICAM_ID,
3082  cicam_id, id_len);
3083  }
3084 
3085  STB_OSMutexUnlock(list_mutex);
3086  }
3087 
3088  FUNCTION_FINISH(STB_PVRRecordingGetCicamId);
3089 
3090  return(retval);
3091 }
3092 
3093 /*!**************************************************************************
3094  * @brief Stores the given CI+ URI with a recording, along with a timestamp
3095  * @param handle - recording handle
3096  * @param uri - usage rules
3097  * @return TRUE if URI is stored, FALSE otherwise
3098  ****************************************************************************/
3099 BOOLEAN STB_PVRRecordingAddURI(U32BIT handle, U8BIT *uri)
3100 {
3101  S_RECORDING *rec_ptr;
3102  BOOLEAN retval;
3103  U32BIT timestamp;
3104  U8BIT play_path;
3105  S_REC_CIPLUS_ITEM *item;
3106  S_REC_CIPLUS_ITEM *list_item;
3107  U8BIT audio_decoder;
3108  U8BIT video_decoder;
3109  S16BIT speed;
3110 
3111  FUNCTION_START(STB_PVRRecordingAddURI);
3112 
3113  retval = FALSE;
3114 
3115  if (initialised_flag)
3116  {
3117  STB_OSMutexLock(list_mutex);
3118 
3119  /* Find the recording */
3120  rec_ptr = GetRecording(handle);
3121  if (rec_ptr != NULL)
3122  {
3123  if (strlen((char *)rec_ptr->basename) > 0)
3124  {
3125  timestamp = GetCurrentRecordTime(handle);
3126  retval = WriteCIPlusInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_CIPLUS_URI,
3127  timestamp, CIP_URI_LEN, uri);
3128 
3129  DBG_CIP("(0x%08lx): Added URI @ %lu secs", handle, timestamp)
3130 
3131  /* If this recording is also being played, such as timeshift or chase playback, then
3132  * the playback status needs to be updated with this new URI so that it can be applied
3133  * at the appropriate time */
3134  for (play_path = 0; play_path < num_paths; play_path++)
3135  {
3136  if (play_status[play_path].handle == handle)
3137  {
3138  STB_OSSemaphoreWait(play_status[play_path].play_sem);
3139 
3140  /* Recording is being played, so add an item for this URI to the end of its list */
3141  if ((item = (S_REC_CIPLUS_ITEM *)STB_GetMemory(sizeof(S_REC_CIPLUS_ITEM))) != NULL)
3142  {
3143  memset(item, 0, sizeof(S_REC_CIPLUS_ITEM));
3144 
3145  item->item_type = EXT_INFO_CIPLUS_URI;
3146  item->timestamp = timestamp;
3147  memcpy(item->u.uri, uri, CIP_URI_LEN);
3148 
3149  if (play_status[play_path].item_list == NULL)
3150  {
3151  /* First item in the list */
3152  play_status[play_path].item_list = item;
3153  }
3154  else
3155  {
3156  /* Find the end of the list */
3157  for (list_item = play_status[play_path].item_list; list_item->next != NULL;
3158  list_item = list_item->next)
3159  ;
3160 
3161  list_item->next = item;
3162  item->prev = list_item;
3163  }
3164 
3165  /* Playback will always be behind this item that has just been recorded,
3166  * so re-evaluate the next item to be applied during playback */
3167  audio_decoder = STB_DPGetPathAudioDecoder(play_path);
3168  video_decoder = STB_DPGetPathVideoDecoder(play_path);
3169  speed = STB_PVRGetPlaySpeed(audio_decoder, video_decoder);
3170 
3171  FindNextCIPlusItem(play_path, speed);
3172  }
3173 
3174  STB_OSSemaphoreSignal(play_status[play_path].play_sem);
3175  break;
3176  }
3177  }
3178  }
3179  }
3180 
3181  STB_OSMutexUnlock(list_mutex);
3182  }
3183 
3184  FUNCTION_FINISH(STB_PVRRecordingAddURI);
3185 
3186  return(retval);
3187 }
3188 
3189 /*!**************************************************************************
3190  * @brief Update during playback the CI+ URI that's stored with a recording
3191  * @param handle - recording handle
3192  * @param uri - usage rules
3193  * @return TRUE if URI is stored, FALSE otherwise
3194  ****************************************************************************/
3195 BOOLEAN STB_PVRRecordingUpdateURI(U32BIT handle, U8BIT *uri)
3196 {
3197  S_RECORDING *rec_ptr;
3198  U8BIT path;
3199  BOOLEAN retval;
3200 
3201  FUNCTION_START(STB_PVRRecordingUpdateURI);
3202 
3203  retval = FALSE;
3204 
3205  if (initialised_flag)
3206  {
3207  STB_OSMutexLock(list_mutex);
3208 
3209  /* Find the recording */
3210  rec_ptr = GetRecording(handle);
3211  if (rec_ptr != NULL)
3212  {
3213  if (strlen((char *)rec_ptr->basename) > 0)
3214  {
3215  /* Find the playback path */
3216  for (path = 0; (path < num_paths) && (play_status[path].handle != handle); path++)
3217  ;
3218 
3219  if (path < num_paths)
3220  {
3221  /* The URI item being updated should be the last one that was passed to the CAM */
3222  if (play_status[path].uri_item != NULL)
3223  {
3224  /* Update this URI and save it back to the recording */
3225  memcpy(play_status[path].uri_item->u.uri, uri, CIP_URI_LEN);
3226 
3227  retval = UpdateCIPlusInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_CIPLUS_URI,
3228  play_status[path].uri_item->timestamp, CIP_URI_LEN, uri);
3229 
3230  DBG_CIP("(0x%08lx): Updated URI @ %lu secs", handle,
3231  play_status[path].uri_item->timestamp)
3232  }
3233  else
3234  {
3235  /* No URI item saved with the recording, so can't be updated */
3236  retval = TRUE;
3237  }
3238  }
3239  }
3240  }
3241 
3242  STB_OSMutexUnlock(list_mutex);
3243  }
3244 
3245  FUNCTION_FINISH(STB_PVRRecordingUpdateURI);
3246 
3247  return(retval);
3248 }
3249 
3250 /*!**************************************************************************
3251  * @brief Stores the given CI+ licence with the recording along with a timestamp
3252  * @param handle - recording handle
3253  * @param licence - licence data
3254  * @param licence_len - number of bytes
3255  * @return TRUE if licence is stored, FALSE otherwise
3256  ****************************************************************************/
3257 BOOLEAN STB_PVRRecordingAddLicence(U32BIT handle, U8BIT *licence, U16BIT licence_len)
3258 {
3259  S_RECORDING *rec_ptr;
3260  BOOLEAN retval;
3261  U8BIT play_path;
3262  U32BIT timestamp;
3263  S_REC_CIPLUS_ITEM *item;
3264  S_REC_CIPLUS_ITEM *list_item;
3265  U8BIT audio_decoder;
3266  U8BIT video_decoder;
3267  S16BIT speed;
3268 
3269  FUNCTION_START(STB_PVRRecordingAddLicence);
3270 
3271  retval = FALSE;
3272 
3273  if (initialised_flag)
3274  {
3275  STB_OSMutexLock(list_mutex);
3276 
3277  rec_ptr = GetRecording(handle);
3278  if ((rec_ptr != NULL) && (licence != NULL) && (licence_len > 0))
3279  {
3280  if (strlen((char *)rec_ptr->basename) > 0)
3281  {
3282  timestamp = GetCurrentRecordTime(handle);
3283 
3284  retval = WriteCIPlusInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_CIPLUS_LICENCE,
3285  timestamp, licence_len, licence);
3286 
3287  DBG_CIP("(0x%08lx): Added licence, len %u, @ %lu secs", handle,
3288  licence_len, timestamp)
3289 
3290  /* If this recording is also being played, such as timeshift or chase playback, then
3291  * the playback status needs to be updated with this new licence so that it can be applied
3292  * at the appropriate time */
3293  for (play_path = 0; play_path < num_paths; play_path++)
3294  {
3295  if (play_status[play_path].handle == handle)
3296  {
3297  STB_OSSemaphoreWait(play_status[play_path].play_sem);
3298 
3299  /* Recording is being played, so add an item for this licence to the end of its list */
3300  if ((item = (S_REC_CIPLUS_ITEM *)STB_GetMemory(sizeof(S_REC_CIPLUS_ITEM))) != NULL)
3301  {
3302  memset(item, 0, sizeof(S_REC_CIPLUS_ITEM));
3303 
3304  item->item_type = EXT_INFO_CIPLUS_LICENCE;
3305  item->timestamp = timestamp;
3306  item->u.licence.used = FALSE;
3307 
3308  if ((item->u.licence.data = STB_GetMemory(licence_len)) != NULL)
3309  {
3310  memcpy(item->u.licence.data, licence, licence_len);
3311  item->u.licence.length = licence_len;
3312  }
3313 
3314  if (play_status[play_path].item_list == NULL)
3315  {
3316  /* First item in the list */
3317  play_status[play_path].item_list = item;
3318  }
3319  else
3320  {
3321  /* Find the end of the list */
3322  for (list_item = play_status[play_path].item_list; list_item->next != NULL;
3323  list_item = list_item->next)
3324  ;
3325 
3326  list_item->next = item;
3327  item->prev = list_item;
3328  }
3329 
3330  /* Playback will always be behind this item that has just been recorded,
3331  * so re-evaluate the next item to be applied during playback */
3332  audio_decoder = STB_DPGetPathAudioDecoder(play_path);
3333  video_decoder = STB_DPGetPathVideoDecoder(play_path);
3334  speed = STB_PVRGetPlaySpeed(audio_decoder, video_decoder);
3335 
3336  FindNextCIPlusItem(play_path, speed);
3337  }
3338 
3339  STB_OSSemaphoreSignal(play_status[play_path].play_sem);
3340  break;
3341  }
3342  }
3343  }
3344  }
3345 
3346  STB_OSMutexUnlock(list_mutex);
3347  }
3348 
3349  FUNCTION_FINISH(STB_PVRRecordingAddLicence);
3350 
3351  return(retval);
3352 }
3353 
3354 /*!**************************************************************************
3355  * @brief Update during playback the CI+ licence that's stored with a recording
3356  * @param handle - recording handle
3357  * @param licence - licence data
3358  * @param licence_len - number of bytes
3359  * @return TRUE if licence is stored, FALSE otherwise
3360  ****************************************************************************/
3361 BOOLEAN STB_PVRRecordingUpdateLicence(U32BIT handle, U8BIT *licence, U16BIT licence_len)
3362 {
3363  S_RECORDING *rec_ptr;
3364  U8BIT path;
3365  BOOLEAN retval;
3366 
3367  FUNCTION_START(STB_PVRRecordingUpdateLicence);
3368 
3369  retval = FALSE;
3370 
3371  if (initialised_flag)
3372  {
3373  STB_OSMutexLock(list_mutex);
3374 
3375  /* Find the recording */
3376  rec_ptr = GetRecording(handle);
3377  if (rec_ptr != NULL)
3378  {
3379  if (strlen((char *)rec_ptr->basename) > 0)
3380  {
3381  /* Find the playback path */
3382  for (path = 0; (path < num_paths) && (play_status[path].handle != handle); path++)
3383  ;
3384 
3385  if (path < num_paths)
3386  {
3387  /* The licence item being updated should be the last one that was passed to the CAM */
3388  if (play_status[path].licence_item != NULL)
3389  {
3390  /* Update this licence and save it back to the recording.
3391  * Licences don't change in size during playback */
3392  memcpy(play_status[path].licence_item->u.licence.data, licence, licence_len);
3393 
3394  retval = UpdateCIPlusInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_CIPLUS_LICENCE,
3395  play_status[path].licence_item->timestamp, licence_len, licence);
3396 
3397  DBG_CIP("(0x%08lx): Updated licence @ %lu secs", handle,
3398  play_status[path].licence_item->timestamp)
3399  }
3400  }
3401  }
3402  }
3403 
3404  STB_OSMutexUnlock(list_mutex);
3405  }
3406 
3407  FUNCTION_FINISH(STB_PVRRecordingUpdateLicence);
3408 
3409  return(retval);
3410 }
3411 
3412 /*!**************************************************************************
3413  * @brief Stores a CI+ pin event with the recording along with a timestamp
3414  * @param handle - recording handle
3415  * @param age_rating - age rating introduced by the pin, 0 = no rating
3416  * @param private_data - pin private data - this is a fixed size, defined by CI+
3417  * @param date_code - UTC MJD date code when pin is to be applied
3418  * @param hour - UTC hour when pin is to be applied
3419  * @param min - UTC minute when pin is to be applied
3420  * @param secs - UTC seconds when pin is to be applied
3421  * @return TRUE if pin is stored, FALSE otherwise
3422  ****************************************************************************/
3423 BOOLEAN STB_PVRRecordingAddPin(U32BIT handle, U8BIT age_rating, U8BIT *private_data,
3424  U16BIT date_code, U8BIT hour, U8BIT min, U8BIT secs)
3425 {
3426  S_RECORDING *rec_ptr;
3427  BOOLEAN retval;
3428  S_REC_CIPLUS_PIN pin_item;
3429  U32BIT timestamp;
3430  U16BIT gmt_date;
3431  U8BIT gmt_hour, gmt_min, gmt_secs;
3432  S32BIT time_diff;
3433  U8BIT play_path;
3434  S_REC_CIPLUS_ITEM *item;
3435  S_REC_CIPLUS_ITEM *list_item;
3436  U8BIT audio_decoder;
3437  U8BIT video_decoder;
3438  S16BIT speed;
3439 
3440  FUNCTION_START(STB_PVRRecordingAddPin);
3441 
3442  retval = FALSE;
3443 
3444  if (initialised_flag)
3445  {
3446  STB_OSMutexLock(list_mutex);
3447 
3448  rec_ptr = GetRecording(handle);
3449  if (rec_ptr != NULL)
3450  {
3451  if (strlen((char *)rec_ptr->basename) > 0)
3452  {
3453  pin_item.age_rating = age_rating;
3454  memcpy(pin_item.private_data, private_data, CIP_PIN_PRIVATE_DATA_SIZE);
3455 
3456  /* Convert the time included with the pin event to a timestamp relative to the
3457  * time the recording started */
3458  timestamp = GetCurrentRecordTime(handle);
3459  if (date_code != 0)
3460  {
3461  STB_GCGetGMTDateTime(&gmt_date, &gmt_hour, &gmt_min, &gmt_secs);
3462 
3463  if ((time_diff = STB_GCDateTimeDiff(date_code, hour, min, secs,
3464  gmt_date, gmt_hour, gmt_min, gmt_secs)) < 0)
3465  {
3466  if ((U32BIT)-time_diff > timestamp)
3467  {
3468  /* Pin is defined to be applied before the recording started,
3469  * so change the time so it will start at the beginning */
3470  time_diff = -(S32BIT)timestamp;
3471  }
3472  }
3473 
3474  timestamp = (S32BIT)timestamp + time_diff;
3475  }
3476 
3477  retval = WriteCIPlusInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_CIPLUS_PIN,
3478  timestamp, sizeof(pin_item), (U8BIT *)&pin_item);
3479 
3480  DBG_CIP("(0x%08lx): Added pin rating %u, @ %lu secs", handle,
3481  age_rating, timestamp)
3482 
3483  /* If this recording is also being played, such as timeshift or chase playback, then
3484  * the playback status needs to be updated with this new pin so that it can be applied
3485  * at the appropriate time */
3486  for (play_path = 0; play_path < num_paths; play_path++)
3487  {
3488  if (play_status[play_path].handle == handle)
3489  {
3490  STB_OSSemaphoreWait(play_status[play_path].play_sem);
3491 
3492  /* Recording is being played, so add an item for this pin to the end of its list */
3493  if ((item = (S_REC_CIPLUS_ITEM *)STB_GetMemory(sizeof(S_REC_CIPLUS_ITEM))) != NULL)
3494  {
3495  memset(item, 0, sizeof(S_REC_CIPLUS_ITEM));
3496 
3497  item->item_type = EXT_INFO_CIPLUS_PIN;
3498  item->timestamp = timestamp;
3499  item->u.pin.age_rating = age_rating;
3500  memcpy(item->u.pin.private_data, private_data, CIP_PIN_PRIVATE_DATA_SIZE);
3501 
3502  if (play_status[play_path].item_list == NULL)
3503  {
3504  /* First item in the list */
3505  play_status[play_path].item_list = item;
3506  }
3507  else
3508  {
3509  /* Find the end of the list */
3510  for (list_item = play_status[play_path].item_list; list_item->next != NULL;
3511  list_item = list_item->next)
3512  ;
3513 
3514  list_item->next = item;
3515  item->prev = list_item;
3516  }
3517 
3518  /* Playback will always be behind this item that has just been recorded,
3519  * so re-evaluate the next item to be applied during playback */
3520  audio_decoder = STB_DPGetPathAudioDecoder(play_path);
3521  video_decoder = STB_DPGetPathVideoDecoder(play_path);
3522  speed = STB_PVRGetPlaySpeed(audio_decoder, video_decoder);
3523 
3524  FindNextCIPlusItem(play_path, speed);
3525  }
3526 
3527  STB_OSSemaphoreSignal(play_status[play_path].play_sem);
3528  break;
3529  }
3530  }
3531  }
3532  }
3533 
3534  STB_OSMutexUnlock(list_mutex);
3535  }
3536 
3537  FUNCTION_FINISH(STB_PVRRecordingAddPin);
3538 
3539  return(retval);
3540 }
3541 
3542 #endif /* COMMON_INTERFACE */
3543 
3544 /*!**************************************************************************
3545  * @brief Calculates the total disk space used in minutes
3546  * @param disk_id - disk to be used
3547  * @return Total size of all recordings in minutes
3548  ****************************************************************************/
3549 U32BIT STB_PVRGetTimeOfAllRecordings(U16BIT disk_id)
3550 {
3551  S_RECORDING *rec_ptr;
3552  U32BIT retval;
3553 
3554  FUNCTION_START(STB_PVRGetTimeOfAllRecordings);
3555 
3556  retval = 0;
3557 
3558  if (initialised_flag)
3559  {
3560  STB_OSMutexLock(list_mutex);
3561 
3562  for (rec_ptr = rec_list; rec_ptr != NULL; rec_ptr = rec_ptr->next)
3563  {
3564  /* Only get info for recordings on the specified disk */
3565  if (rec_ptr->disk_id == disk_id)
3566  {
3567  if (rec_ptr->recording)
3568  {
3569  /* The final length of the recording won't be known yet, so use the time taken so far */
3570  retval += ((GetCurrentRecordTime(rec_ptr->handle) + 29) / 60);
3571  }
3572  else
3573  {
3574  retval += (rec_ptr->rec_info.len_hour * 60) + rec_ptr->rec_info.len_min;
3575  }
3576  }
3577  }
3578 
3579  STB_OSMutexUnlock(list_mutex);
3580  }
3581 
3582  FUNCTION_FINISH(STB_PVRGetTimeOfAllRecordings);
3583 
3584  return(retval);
3585 }
3586 
3587 /*!**************************************************************************
3588  * @brief Calculates the total disk space used in KB for all recordings
3589  * @param disk_id - disk to be used
3590  * @return Total size of all recordings in KB
3591  ****************************************************************************/
3592 U32BIT STB_PVRGetSizeOfAllRecordings(U16BIT disk_id)
3593 {
3594  S_RECORDING *rec_ptr;
3595  U32BIT rec_size;
3596  U32BIT total_size;
3597 
3598  FUNCTION_START(STB_PVRGetSizeOfAllRecordings);
3599 
3600  total_size = 0;
3601 
3602  if (initialised_flag)
3603  {
3604  STB_OSMutexLock(list_mutex);
3605 
3606  for (rec_ptr = rec_list; rec_ptr != NULL; rec_ptr = rec_ptr->next)
3607  {
3608  /* Only get info for recordings on the specified disk */
3609  if (rec_ptr->disk_id == disk_id)
3610  {
3611  if (STB_PVRGetRecordingSize(disk_id, rec_ptr->basename, &rec_size))
3612  {
3613  total_size += rec_size;
3614  }
3615  }
3616  }
3617 
3618  STB_OSMutexUnlock(list_mutex);
3619  }
3620 
3621  FUNCTION_FINISH(STB_PVRGetSizeOfAllRecordings);
3622 
3623  return(total_size);
3624 }
3625 
3638 BOOLEAN STB_PVRStartPlaying(U8BIT path, U32BIT handle, BOOLEAN resume)
3639 {
3640  S_RECORDING *rec_ptr;
3641  U8BIT audio_decoder, video_decoder;
3642  BOOLEAN retval;
3643  CREATE_LINK_LIST_HEADER(bookmarks);
3644  U32BIT position_in_seconds;
3645  BOOLEAN start_playback;
3646 #ifdef COMMON_INTERFACE
3647  U8BIT cicam_id[8];
3648 #endif
3649  S_BOOKMARK *b;
3650 
3651  FUNCTION_START(STB_PVRStartPlaying);
3652 
3653  retval = FALSE;
3654 
3655  STB_PVR_PRINT(("PVR - StartPlaying(%d): handle=0x%lx", path, handle));
3656 
3657  if (initialised_flag)
3658  {
3659  STB_OSMutexLock(list_mutex);
3660 
3661  rec_ptr = GetRecording(handle);
3662  if (rec_ptr != NULL)
3663  {
3664  audio_decoder = STB_DPGetPathAudioDecoder(path);
3665  video_decoder = STB_DPGetPathVideoDecoder(path);
3666 
3667  if (strlen((char *)rec_ptr->basename) > 0)
3668  {
3669  start_playback = TRUE;
3670 
3671 #ifdef COMMON_INTERFACE
3672  if (ReadExtendedInfo(rec_ptr->disk_id, rec_ptr->basename, EXT_INFO_CIPLUS_CICAM_ID,
3673  cicam_id, sizeof(cicam_id)))
3674  {
3675  /* This recording is protected by CI+, check that the CAM is present */
3676  if ((play_status[path].slot_id = STB_CiCcFindSlotForCicamId(cicam_id)) != INVALID_RES_ID)
3677  {
3678  /* Read all URI, licence and PIN items so they can be applied
3679  * at the appropriate times during playback */
3680  STB_OSSemaphoreWait(play_status[path].play_sem);
3681  ReadCIPlusItems(path, rec_ptr);
3682  STB_OSSemaphoreSignal(play_status[path].play_sem);
3683  }
3684  else
3685  {
3686  /* CAM isn't available so can't start playback */
3687  start_playback = FALSE;
3688  }
3689  }
3690 #endif
3691 
3692  if (start_playback)
3693  {
3694  play_status[path].handle = handle;
3695  position_in_seconds = 0;
3696 
3697  if (resume)
3698  {
3699  /* Read the playback position boookmark */
3700  if (GetBookmarks(rec_ptr->disk_id, rec_ptr->basename, &bookmarks,
3701  BOOKMARK_PLAYBACK_POSITION, FALSE) > 0)
3702  {
3703  b = (S_BOOKMARK *)STB_LLGetFirstBlock(&bookmarks);
3704  if (b != NULL)
3705  {
3706  position_in_seconds = b->time;
3707  }
3708  EmptyBookmarks(&bookmarks, TRUE);
3709  }
3710  STB_PVR_PRINT(("PVR - StartPlaying(%d): resuming from %d seconds", path, position_in_seconds));
3711  }
3712 
3713  if ((rec_ptr->rec_info.flags & REC_ENCRYPTED) != 0)
3714  {
3715  /* Get the encryption key to be used */
3716  if ((enc_dec_key != NULL) && (enc_dec_iv != NULL))
3717  {
3718  STB_PVRSetPlaybackDecryptionKey(audio_decoder, video_decoder, TRUE, enc_dec_key,
3719  enc_dec_iv, enc_dec_key_len);
3720  }
3721 #ifdef STB_DEBUG
3722  else
3723  {
3724  STB_PVR_PRINT(("STB_PVRStartPlaying(%u 0x%08lx): Playback failed, encryption key not available",
3725  path, handle));
3726  }
3727 #endif
3728  }
3729  else
3730  {
3731  STB_PVRSetPlaybackDecryptionKey(audio_decoder, video_decoder, FALSE, NULL, NULL, 0);
3732  }
3733 
3734 #ifdef COMMON_INTERFACE
3735  if ((play_status[path].slot_id != INVALID_RES_ID) && (play_status[path].item_list != NULL))
3736  {
3737  STB_OSSemaphoreWait(play_status[path].play_sem);
3738 
3739  /* Find the URI/licence/pin that should be applied at the start of playback */
3740  ApplyCIPlusItems(path, rec_ptr, position_in_seconds, 100);
3741 
3742  /* Find the next URI/licence/pin to be applied */
3743  FindNextCIPlusItem(path, 100);
3744 
3745  STB_OSSemaphoreSignal(play_status[path].play_sem);
3746  }
3747 #endif
3748 
3749  if ((rec_ptr->rec_info.flags & REC_HAS_VIDEO) != 0)
3750  {
3751  STB_PVRPlayHasVideo(audio_decoder, video_decoder, TRUE);
3752  }
3753  else
3754  {
3755  STB_PVRPlayHasVideo(audio_decoder, video_decoder, FALSE);
3756  }
3757 
3758  if (STB_PVRPlayStart(rec_ptr->disk_id, audio_decoder, video_decoder,
3759  STB_DPGetPathDemux(path), rec_ptr->basename))
3760  {
3761  if (resume)
3762  {
3763  STB_PVRPlaySetPosition(audio_decoder, video_decoder, position_in_seconds);
3764  }
3765 
3766  retval = TRUE;
3767  }
3768  }
3769  }
3770  }
3771 
3772  STB_OSMutexUnlock(list_mutex);
3773  }
3774 
3775  FUNCTION_FINISH(STB_PVRStartPlaying);
3776 
3777  return(retval);
3778 }
3779 
3792 BOOLEAN STB_PVRIsPlaying(U8BIT path, U32BIT *handle)
3793 {
3794  BOOLEAN ret_val;
3795 
3796  FUNCTION_START(STB_PVRIsPlaying);
3797 
3798  *handle = play_status[path].handle;
3800 
3801  FUNCTION_FINISH(STB_PVRIsPlaying);
3802 
3803  return(ret_val);
3804 }
3805 
3813 void STB_PVRSavePlayPosition(U8BIT path)
3814 {
3815  U8BIT audio_decoder;
3816  U8BIT video_decoder;
3817  S_RECORDING *rec_ptr;
3818  CREATE_LINK_LIST_HEADER(bookmarks);
3819  U8BIT hours, mins, secs;
3820  U32BIT position_in_seconds;
3821  S_BOOKMARK *b;
3822 
3823  FUNCTION_START(STB_PVRSavePlayPosition);
3824 
3825  if ((path < num_paths) && (play_status[path].handle != 0))
3826  {
3827  STB_OSMutexLock(list_mutex);
3828 
3829  rec_ptr = GetRecording(play_status[path].handle);
3830  if ((rec_ptr != NULL) && (strlen((char *)rec_ptr->basename) > 0))
3831  {
3832  /* Read the old playback position boookmark */
3833  if (GetBookmarks(rec_ptr->disk_id, rec_ptr->basename, &bookmarks,
3834  BOOKMARK_PLAYBACK_POSITION, FALSE) > 0)
3835  {
3836  b = (S_BOOKMARK *)STB_LLGetFirstBlock(&bookmarks);
3837  if (b != NULL)
3838  {
3839  position_in_seconds = b->time;
3840 
3841  /* Remove it */
3842  STB_PVR_PRINT(("PVR - STB_PVRSavePlayPosition(%d): removing bookmark at %d seconds",
3843  path, position_in_seconds));
3844 
3845  RemoveBookmark(rec_ptr->disk_id, rec_ptr->basename, position_in_seconds, NULL,
3846  BOOKMARK_PLAYBACK_POSITION);
3847  }
3848  EmptyBookmarks(&bookmarks, TRUE);
3849  }
3850 
3851  audio_decoder = STB_DPGetPathAudioDecoder(path);
3852  video_decoder = STB_DPGetPathVideoDecoder(path);
3853 
3854  /* Get the elapsed playback time and save it so playback can be resumed from current
3855  position */
3856  if (STB_PVRGetElapsedTime(audio_decoder, video_decoder, &hours, &mins, &secs))
3857  {
3858  position_in_seconds = (hours * 3600) + (mins * 60) + secs;
3859  }
3860  else
3861  {
3862  STB_PVR_PRINT(("PVR - STB_PVRSavePlayPosition(%d): failed retrieving elapsed time", path));
3863  position_in_seconds = 0;
3864  }
3865 
3866  STB_PVR_PRINT(("PVR - STB_PVRSavePlayPosition(%d): adding bookmark at %d seconds", path,
3867  position_in_seconds));
3868 
3869  AddBookmark(rec_ptr->disk_id, rec_ptr->basename, position_in_seconds, NULL,
3870  BOOKMARK_PLAYBACK_POSITION);
3871  }
3872 
3873  STB_OSMutexUnlock(list_mutex);
3874  }
3875 
3876  FUNCTION_FINISH(STB_PVRSavePlayPosition);
3877 }
3878 
3884 U32BIT STB_PVRGetPlayPosition(U32BIT handle)
3885 {
3886  S_RECORDING *rec_ptr;
3887  CREATE_LINK_LIST_HEADER(bookmarks);
3888  U32BIT position;
3889  S_BOOKMARK *b;
3890 
3891  FUNCTION_START(STB_PVRGetPlayPosition);
3892 
3893  position = 0;
3894 
3895  STB_OSMutexLock(list_mutex);
3896 
3897  rec_ptr = GetRecording(handle);
3898  if ((rec_ptr != NULL) && (strlen((char *)rec_ptr->basename) > 0))
3899  {
3900  /* Read the playback position boookmark */
3901  if (GetBookmarks(rec_ptr->disk_id, rec_ptr->basename, &bookmarks,
3902  BOOKMARK_PLAYBACK_POSITION, FALSE) > 0)
3903  {
3904  b = (S_BOOKMARK *)STB_LLGetFirstBlock(&bookmarks);
3905  if (b != NULL)
3906  {
3907  position = b->time;
3908  }
3909  EmptyBookmarks(&bookmarks, TRUE);
3910  }
3911  }
3912 
3913  STB_OSMutexUnlock(list_mutex);
3914 
3915  FUNCTION_FINISH(STB_PVRGetPlayPosition);
3916 
3917  return(position);
3918 }
3919 
3931 void STB_PVRStopPlaying(U8BIT path)
3932 {
3933  U8BIT audio_decoder;
3934  U8BIT video_decoder;
3935  S_RECORDING *rec_ptr;
3936 
3937  FUNCTION_START(STB_PVRStopPlaying);
3938 
3939  STB_PVR_PRINT(("PVR - StopPlaying (%d)", path));
3940 
3941  if ((path < num_paths) && (play_status[path].handle != 0))
3942  {
3943  audio_decoder = STB_DPGetPathAudioDecoder(path);
3944  video_decoder = STB_DPGetPathVideoDecoder(path);
3945 
3946  STB_OSMutexLock(list_mutex);
3947 
3948  rec_ptr = GetRecording(play_status[path].handle);
3949  if ((rec_ptr != NULL) && (strlen((char *)rec_ptr->basename) > 0))
3950  {
3951 #ifdef COMMON_INTERFACE
3952  /* Free all CI+ items */
3953  FreeCIPlusItemList(path);
3954 #endif
3955  }
3956 
3957  STB_OSMutexUnlock(list_mutex);
3958 
3959  STB_PVRPlayStop(audio_decoder, video_decoder);
3960 
3961  play_status[path].handle = 0;
3962  }
3963 
3964  FUNCTION_FINISH(STB_PVRStopPlaying);
3965 }
3966 
3967 /*!**************************************************************************
3968  * @brief Read the DVB triplet (service id, transport id, orig net id) for a recording
3969  * @param handle - handle of recording
3970  * @param serv_id - pointer to return service id
3971  * @param ts_id - pointer to return transport id
3972  * @param orig_net_id - pointer to return original network id
3973  * @return TRUE if values are returned
3974  ****************************************************************************/
3975 BOOLEAN STB_PVRRecordingGetTriplet(U32BIT handle, U16BIT *serv_id, U16BIT *ts_id, U16BIT *orig_net_id)
3976 {
3977  BOOLEAN ret_val;
3978  S_RECORDING *rec_ptr;
3979 
3980  FUNCTION_START(STB_PVRGetTriplet);
3981 
3982  ret_val = FALSE;
3983 
3984  rec_ptr = GetRecording(handle);
3985  if (rec_ptr != NULL)
3986  {
3987  *serv_id = rec_ptr->rec_info.serv_id;
3988  *ts_id = rec_ptr->rec_info.ts_id;
3989  *orig_net_id = rec_ptr->rec_info.orig_net_id;
3990  ret_val = TRUE;
3991  }
3992  FUNCTION_FINISH(STB_PVRGetTriplet);
3993 
3994  return(ret_val);
3995 }
3996 
4008 void STB_PVRStartPlayRunning(U8BIT path)
4009 {
4010  FUNCTION_START(STB_PVRStartPlayRunning);
4011 
4012  STB_PVR_PRINT(("STB_PVRStartPlayRunning(%d)", path));
4013 
4015 
4016  FUNCTION_FINISH(STB_PVRStartPlayRunning);
4017 }
4018 
4030 void STB_PVRStartPlayPaused(U8BIT path)
4031 {
4032  FUNCTION_START(STB_PVRStartPlayPaused);
4033 
4034  STB_PVR_PRINT(("STB_PVRStartPlayPaused(%d)", path));
4035 
4037 
4038  FUNCTION_FINISH(STB_PVRStartPlayPaused);
4039 }
4040 
4052 void STB_PVRStartPlaySync(U8BIT path)
4053 {
4054  FUNCTION_START(STB_PVRStartPlaySync);
4055 
4056  STB_PVR_PRINT(("STB_PVRStartPlaySync(%d)", path));
4057 
4059 
4060  FUNCTION_FINISH(STB_PVRStartPlaySync);
4061 }
4062 
4074 BOOLEAN STB_PVRIsPlayVideo(U32BIT handle)
4075 {
4076  S_RECORDING *rec_ptr;
4077  BOOLEAN video;
4078 
4079  FUNCTION_START(STB_PVRIsPlayVideo);
4080 
4081  video = FALSE;
4082 
4083  if (initialised_flag)
4084  {
4085  STB_OSMutexLock(list_mutex);
4086 
4087  rec_ptr = GetRecording(handle);
4088  if (rec_ptr != NULL)
4089  {
4090  if ((rec_ptr->rec_info.flags & REC_HAS_VIDEO) != 0)
4091  {
4092  video = TRUE;
4093  }
4094  }
4095 
4096  STB_OSMutexUnlock(list_mutex);
4097  }
4098 
4099  FUNCTION_FINISH(STB_PVRIsPlayVideo);
4100 
4101  return(video);
4102 }
4103 
4115 BOOLEAN STB_PVRIsPlayAudio(U8BIT path)
4116 {
4117  BOOLEAN video, audio;
4118 
4119  FUNCTION_START(STB_PVRIsPlayAudio);
4120 
4121  audio = FALSE;
4122 
4124  {
4126  }
4127 
4128  FUNCTION_FINISH(STB_PVRIsPlayAudio);
4129 
4130  return(audio);
4131 }
4132 
4133 /*!**************************************************************************
4134  * @brief Saves (takes a copy of) the array of pids to be recorded
4135  * @param path - decode path that will be used for the recording
4136  * @param num_pids - number of pids in the array
4137  * @param pid_array - array of structures describing PIDs
4138  * @return TRUE if the PIDs are saved successfully, FALSE otherwise
4139  ****************************************************************************/
4140 BOOLEAN STB_PVRSetRecordingPids(U8BIT path, U16BIT num_pids, S_PVR_PID_INFO *pid_array)
4141 {
4142  BOOLEAN retval;
4143 
4144  FUNCTION_START(STB_PVRSetRecordingPids);
4145 
4146  retval = FALSE;
4147 
4148  if (path < num_paths)
4149  {
4150  if (record_status[path].rec_pids_array != NULL)
4151  {
4152  STB_FreeMemory(record_status[path].rec_pids_array);
4153  record_status[path].rec_pids_array = NULL;
4154  record_status[path].num_pids = 0;
4155  }
4156 
4157  if ((num_pids > 0) && (pid_array != NULL))
4158  {
4159  record_status[path].rec_pids_array = (S_PVR_PID_INFO *)STB_GetMemory(num_pids * sizeof(S_PVR_PID_INFO));
4160  if (record_status[path].rec_pids_array != NULL)
4161  {
4162  memcpy(record_status[path].rec_pids_array, pid_array, num_pids * sizeof(S_PVR_PID_INFO));
4163  record_status[path].num_pids = num_pids;
4164  retval = TRUE;
4165  }
4166  }
4167  }
4168 
4169  FUNCTION_FINISH(STB_PVRSetRecordingPids);
4170 
4171  return(retval);
4172 }
4173 
4174 /*!**************************************************************************
4175  * @brief Saves (takes a copy of) the array of pids to be recorded and
4176  pass them to the platform
4177  * @param path - decode path that used for the recording
4178  * @param num_pids - number of pids in the array
4179  * @param pid_array - array of structures describing PIDs
4180  * @return TRUE if the PIDs are updated successfully, FALSE otherwise
4181  ****************************************************************************/
4182 BOOLEAN STB_PVRUpdateRecordingPids(U8BIT path, U16BIT num_pids, S_PVR_PID_INFO *pid_array)
4183 {
4184  BOOLEAN retval;
4185  S_RECORDING *rec_ptr;
4186 
4187  FUNCTION_START(STB_PVRUpdateRecordingPids);
4188 
4189  retval = FALSE;
4190 
4191  if (initialised_flag)
4192  {
4193  STB_OSMutexLock(list_mutex);
4194 
4195  rec_ptr = GetRecording(record_status[path].handle);
4196  if (rec_ptr != NULL)
4197  {
4198  retval = STB_PVRSetRecordingPids(path, num_pids, pid_array);
4199  if (retval)
4200  {
4201  retval = STB_PVRRecordChangePids(record_status[path].rec_index, record_status[path].num_pids,
4202  record_status[path].rec_pids_array);
4203  }
4204  }
4205 
4206  STB_OSMutexUnlock(list_mutex);
4207  }
4208 
4209  FUNCTION_FINISH(STB_PVRUpdateRecordingPids);
4210 
4211  return(retval);
4212 }
4213 
4214 /*!**************************************************************************
4215  * @brief Saves the DVB triplet of the service to be recorded
4216  * @param path - decode path that will be used for the recording
4217  * @param serv_id - service id
4218  * @param ts_id - transport stream
4219  * @param orig_net_id - original network id
4220  * @return TRUE if the triplet is saved successfully, FALSE otherwise
4221  ****************************************************************************/
4222 BOOLEAN STB_PVRSetRecoringTriplet(U8BIT path, U16BIT serv_id, U16BIT ts_id, U16BIT orig_net_id)
4223 {
4224  BOOLEAN retval;
4225 
4226  FUNCTION_START(STB_PVRSetRecoringTriplet);
4227 
4228  retval = FALSE;
4229 
4230  if (path < num_paths)
4231  {
4232  record_status[path].serv_id = serv_id;
4233  record_status[path].ts_id = ts_id;
4234  record_status[path].orig_net_id = orig_net_id;
4235  retval = TRUE;
4236  }
4237 
4238  FUNCTION_FINISH(STB_PVRSetRecoringTriplet);
4239 
4240  return(retval);
4241 }
4242 
4243 /*!**************************************************************************
4244  * @brief Creates or deletes a bookmark at the current position during playback.
4245  * If there's a bookmark within a defined number of seconds of the current
4246  * position then the bookmark is deleted, otherwise one is created.
4247  * @param path - playback decode path
4248  * @return TRUE if a bookmark is created or deleted, FALSE otherwise
4249  ****************************************************************************/
4250 BOOLEAN STB_PVRToggleBookmark(U8BIT path)
4251 {
4252  S_RECORDING *rec_ptr;
4253  CREATE_LINK_LIST_HEADER(bookmarks);
4254  U8BIT audio_decoder;
4255  U8BIT video_decoder;
4256  U8BIT hours, mins, secs;
4257  U32BIT position_in_seconds;
4258  S_BOOKMARK *b;
4259  BOOLEAN retval;
4260 
4261  FUNCTION_START(STB_PVRToggleBookmark);
4262 
4263  retval = FALSE;
4264 
4265  if ((path < num_paths) && (play_status[path].handle != 0))
4266  {
4267  audio_decoder = STB_DPGetPathAudioDecoder(path);
4268  video_decoder = STB_DPGetPathVideoDecoder(path);
4269 
4270  STB_OSMutexLock(list_mutex);
4271 
4272  rec_ptr = GetRecording(play_status[path].handle);
4273  if ((rec_ptr != NULL) && (strlen((char *)rec_ptr->basename) > 0))
4274  {
4275  /* Read the boookmarks */
4276  GetBookmarks(rec_ptr->disk_id, rec_ptr->basename, &bookmarks,
4277  BOOKMARK_USER, FALSE);
4278 
4279  /* The elapsed playback time is where the bookmark needs to be set */
4280  if (STB_PVRGetElapsedTime(audio_decoder, video_decoder, &hours, &mins, &secs))
4281  {
4282  position_in_seconds = (hours * 3600) + (mins * 60) + secs;
4283 
4284  /* Check whether this position coincides with an existing bookmark.
4285  * The first bookmark is always used to save the position for resume playback */
4286  b = (S_BOOKMARK *)STB_LLGetFirstBlock(&bookmarks);
4287  while (b != NULL)
4288  {
4289  if ((position_in_seconds <= BOOKMARK_TOLERANCE) &&
4290  (b->time <= BOOKMARK_TOLERANCE))
4291  {
4292  break;
4293  }
4294  else if ((position_in_seconds >= b->time - BOOKMARK_TOLERANCE) &&
4295  (position_in_seconds <= b->time + BOOKMARK_TOLERANCE))
4296  {
4297  break;
4298  }
4299 
4301  }
4302 
4303  if (b != NULL)
4304  {
4305  /* Existing bookmark has been found so delete it */
4306  RemoveBookmark(rec_ptr->disk_id, rec_ptr->basename, b->time, NULL,
4307  BOOKMARK_USER);
4308  }
4309  else
4310  {
4311  /* This is a new bookmark */
4312  AddBookmark(rec_ptr->disk_id, rec_ptr->basename, position_in_seconds, NULL,
4313  BOOKMARK_USER);
4314  }
4315  }
4316 
4317  EmptyBookmarks(&bookmarks, TRUE);
4318  }
4319 
4320  STB_OSMutexUnlock(list_mutex);
4321  }
4322 
4323  FUNCTION_FINISH(STB_PVRToggleBookmark);
4324 
4325  return(retval);
4326 }
4327 
4328 /*!**************************************************************************
4329  * @brief Jumps playback to the position of the bookmark after the current play position
4330  * @param path - playback decode path
4331  * @return TRUE if a bookmark exists and play position is changed, FALSE otherwise
4332  ****************************************************************************/
4333 BOOLEAN STB_PVRGotoNextBookmark(U8BIT path)
4334 {
4335  S_RECORDING *rec_ptr;
4336  CREATE_LINK_LIST_HEADER(bookmarks);
4337  U32BIT num_bookmarks;
4338  U8BIT audio_decoder;
4339  U8BIT video_decoder;
4340  U8BIT hours, mins, secs;
4341  U32BIT position_in_seconds;
4342  S_BOOKMARK *b;
4343  BOOLEAN retval;
4344 
4345  FUNCTION_START(STB_PVRGotoNextBookmark);
4346 
4347  retval = FALSE;
4348 
4349  if ((path < num_paths) && (play_status[path].handle != 0))
4350  {
4351  audio_decoder = STB_DPGetPathAudioDecoder(path);
4352  video_decoder = STB_DPGetPathVideoDecoder(path);
4353 
4354  STB_OSMutexLock(list_mutex);
4355 
4356  rec_ptr = GetRecording(play_status[path].handle);
4357  if ((rec_ptr != NULL) && (strlen((char *)rec_ptr->basename) > 0))
4358  {
4359  /* Read the boookmarks */
4360  num_bookmarks = GetBookmarks(rec_ptr->disk_id, rec_ptr->basename, &bookmarks,
4361  BOOKMARK_USER, FALSE);
4362 
4363  if (num_bookmarks > 0)
4364  {
4365  STB_LLSort(&bookmarks, CompareBookmarks);
4366 
4367  /* Need to find the bookmark that occurs after the current playback position */
4368  if (STB_PVRGetElapsedTime(audio_decoder, video_decoder, &hours, &mins, &secs))
4369  {
4370  position_in_seconds = (hours * 3600) + (mins * 60) + secs;
4371 
4372  b = (S_BOOKMARK *)STB_LLGetFirstBlock(&bookmarks);
4373  while (b != NULL)
4374  {
4375  if (b->time > position_in_seconds)
4376  {
4377  break;
4378  }
4380  }
4381 
4382  if (b != NULL)
4383  {
4384  retval = STB_PVRPlaySetPosition(audio_decoder, video_decoder, b->time);
4385  }
4386  }
4387  }
4388 
4389  EmptyBookmarks(&bookmarks, TRUE);
4390  }
4391 
4392  STB_OSMutexUnlock(list_mutex);
4393  }
4394 
4395  FUNCTION_FINISH(STB_PVRGotoNextBookmark);
4396 
4397  return(retval);
4398 }
4399 
4407 U16BIT STB_PVRGetBookmarks(U8BIT path, void ***bookmarks)
4408 {
4409  U16BIT num_bookmarks;
4410 
4411  FUNCTION_START(STB_PVRGetBookmarks);
4412 
4413  num_bookmarks = 0;
4414 
4415  if (path < num_paths)
4416  {
4417  num_bookmarks = STB_PVRGetBookmarksForRecording(play_status[path].handle, bookmarks);
4418  }
4419 
4420  FUNCTION_FINISH(STB_PVRGetBookmarks);
4421 
4422  return(num_bookmarks);
4423 }
4424 
4432 U16BIT STB_PVRGetBookmarksForRecording(U32BIT handle, void ***bookmarks)
4433 {
4434  CREATE_LINK_LIST_HEADER(bookmark_list);
4435  U32BIT num_bookmarks;
4436  S_RECORDING *rec_ptr;
4437  S_BOOKMARK *b;
4438  U32BIT i;
4439 
4440  FUNCTION_START(STB_PVRGetBookmarksForRecording);
4441 
4442  num_bookmarks = 0;
4443 
4444  if (bookmarks != NULL)
4445  {
4446  *bookmarks = NULL;
4447  }
4448 
4449  if (initialised_flag && (handle != 0))
4450  {
4451  STB_OSMutexLock(list_mutex);
4452 
4453  rec_ptr = GetRecording(handle);
4454  if ((rec_ptr != NULL) && (strlen((char *)rec_ptr->basename) > 0))
4455  {
4456  /* Read the boookmarks */
4457  num_bookmarks = GetBookmarks(rec_ptr->disk_id, rec_ptr->basename, &bookmark_list,
4458  BOOKMARK_USER, TRUE);
4459  if ((num_bookmarks > 0) && (bookmarks != NULL))
4460  {
4461  *bookmarks = STB_GetMemory(num_bookmarks * sizeof(void *));
4462  if (*bookmarks != NULL)
4463  {
4464  i = 0;
4465  b = (S_BOOKMARK *)STB_LLGetFirstBlock(&bookmark_list);
4466  while (b != NULL)
4467  {
4468  (*bookmarks)[i] = b;
4470  i++;
4471  }
4472  }
4473  else
4474  {
4475  num_bookmarks = 0;
4476  }
4477  }
4478 
4479  EmptyBookmarks(&bookmark_list, FALSE);
4480  }
4481 
4482  STB_OSMutexUnlock(list_mutex);
4483  }
4484 
4485  FUNCTION_FINISH(STB_PVRGetBookmarksForRecording);
4486 
4487  return(num_bookmarks);
4488 }
4489 
4495 void STB_PVRReleaseBookmarks(void **bookmarks, U16BIT num)
4496 {
4497  U16BIT i;
4498  S_BOOKMARK *b
4499 
4500  FUNCTION_START(STB_PVRReleaseBookmarks);
4501 
4502  if (bookmarks != NULL)
4503  {
4504  for (i = 0; i < num; i++)
4505  {
4506  b = bookmarks[i];
4507  if (b->name != NULL)
4508  {
4509  STB_FreeMemory(b->name);
4510  }
4511  STB_FreeMemory(b);
4512  }
4513 
4514  STB_FreeMemory(bookmarks);
4515  }
4516 
4517  FUNCTION_FINISH(STB_PVRReleaseBookmarks);
4518 }
4519 
4525 U32BIT STB_PVRGetBookmarkTime(void *bookmark_handle)
4526 {
4527  U32BIT time;
4528 
4529  FUNCTION_START(STB_PVRGetBookmarkTime);
4530 
4531  time = ((S_BOOKMARK *)bookmark_handle)->time;
4532 
4533  FUNCTION_FINISH(STB_PVRGetBookmarkTime);
4534 
4535  return time;
4536 }
4537 
4543 U8BIT *STB_PVRGetBookmarkName(void *bookmark_handle)
4544 {
4545  U8BIT *name, *n;
4546  U32BIT len;
4547 
4548  FUNCTION_START(STB_PVRGetBookmarkName);
4549 
4550  n = ((S_BOOKMARK *)bookmark_handle)->name;
4551  if (n != NULL)
4552  {
4553  len = strlen((char *)n);
4554  if (len >= STB_PVR_NAME_LEN)
4555  {
4556  len = STB_PVR_NAME_LEN - 1;
4557  }
4558 
4559  name = STB_GetMemory(len + 1);
4560  if (name != NULL)
4561  {
4562  memcpy(name, n, len);
4563  name[len] = '\0';
4564  }
4565  }
4566  else
4567  {
4568  name = NULL;
4569  }
4570 
4571  FUNCTION_FINISH(STB_PVRGetBookmarkName);
4572 
4573  return name;
4574 }
4575 
4576 /*!**************************************************************************
4577  * @brief Handles the notification received from the platform code when playback
4578  * reaches a set position. For CI+, this works out the next URI/licence/pin
4579  * that needs to be applied, applies them and sets the next notification time
4580  * @param path - decode path
4581  ****************************************************************************/
4583 {
4584 #ifdef COMMON_INTERFACE
4585  S_RECORDING *rec_ptr;
4586  U8BIT audio_decoder;
4587  U8BIT video_decoder;
4588  U8BIT hours, mins, secs;
4589  U32BIT position_in_seconds;
4590  S16BIT speed;
4591 #endif
4592 
4593  FUNCTION_START(STB_PVRPlaybackNotifyTime);
4594 
4595 #ifdef COMMON_INTERFACE
4596  if ((path < num_paths) && (play_status[path].handle != 0))
4597  {
4598  if ((play_status[path].slot_id != INVALID_RES_ID) && (play_status[path].item_list != NULL))
4599  {
4600  STB_OSMutexLock(list_mutex);
4601 
4602  if ((rec_ptr = GetRecording(play_status[path].handle)) != NULL)
4603  {
4604  audio_decoder = STB_DPGetPathAudioDecoder(path);
4605  video_decoder = STB_DPGetPathVideoDecoder(path);
4606 
4607  if (STB_PVRGetElapsedTime(audio_decoder, video_decoder, &hours, &mins, &secs))
4608  {
4609  position_in_seconds = (hours * 3600) + (mins * 60) + secs;
4610  speed = STB_PVRGetPlaySpeed(audio_decoder, video_decoder);
4611 
4612  /* Get the current playback position and apply the next URI/licence/pin for this position */
4613  ApplyCIPlusItems(path, rec_ptr, position_in_seconds, speed);
4614 
4615  /* Find the next URI/licence/pin to be applied */
4616  FindNextCIPlusItem(path, speed);
4617  }
4618  }
4619 
4620  STB_OSMutexUnlock(list_mutex);
4621  }
4622  }
4623 #else
4624  USE_UNWANTED_PARAM(path);
4625 #endif
4626 
4627  FUNCTION_FINISH(STB_PVRPlaybackNotifyTime);
4628 }
4629 
4642 BOOLEAN STB_PVRStartRecording(U8BIT path, U32BIT handle)
4643 {
4644  S_RECORDING *rec_ptr;
4645  BOOLEAN start_recording;
4646  BOOLEAN retval;
4647 
4648  FUNCTION_START(STB_PVRStartRecording);
4649 
4650  retval = FALSE;
4651 
4652  ASSERT(path < num_paths);
4653 
4654  if (initialised_flag)
4655  {
4656  STB_OSMutexLock(list_mutex);
4657 
4658  rec_ptr = GetRecording(handle);
4659  if ((rec_ptr != NULL) && (strlen((char *)rec_ptr->basename) > 0))
4660  {
4661  /* Copy the triplet into the info */
4662  rec_ptr->rec_info.serv_id = record_status[path].serv_id;
4663  rec_ptr->rec_info.ts_id = record_status[path].ts_id;
4664  rec_ptr->rec_info.orig_net_id = record_status[path].orig_net_id;
4665 
4666  if (record_status[path].encrypted && (enc_dec_key != NULL) && (enc_dec_iv != NULL))
4667  {
4668  rec_ptr->rec_info.flags |= REC_ENCRYPTED;
4669  }
4670  else
4671  {
4672  rec_ptr->rec_info.flags &= ~REC_ENCRYPTED;
4673  }
4674 
4675  /* Remember whether the recording has video */
4676  if (IncludesVideoPid(record_status[path].rec_pids_array, record_status[path].num_pids))
4677  {
4678  rec_ptr->rec_info.flags |= REC_HAS_VIDEO;
4679  }
4680  else
4681  {
4682  rec_ptr->rec_info.flags &= ~REC_HAS_VIDEO;
4683  }
4684 
4685  rec_ptr->rec_info.status = RECORDING_STATUS_STARTED;
4686 
4687  /* Write the updated info to disk */
4688  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, FALSE, &rec_ptr->rec_info);
4689 
4690  record_status[path].rec_index = STB_PVRAcquireRecorderIndex(STB_DPGetPathTuner(path), STB_DPGetPathDemux(path));
4691 
4692  start_recording = FALSE;
4693 
4694  if (record_status[path].encrypted)
4695  {
4696  /* Get the encryption key to be used */
4697  if ((enc_dec_key != NULL) && (enc_dec_iv != NULL))
4698  {
4699  STB_PVRSetRecordEncryptionKey(record_status[path].rec_index, TRUE, enc_dec_key, enc_dec_iv, enc_dec_key_len);
4700  start_recording = TRUE;
4701  }
4702  else
4703  {
4704  STB_PVRReleaseRecorderIndex(record_status[path].rec_index);
4705  record_status[path].rec_index = INVALID_RES_ID;
4706  STB_PVR_PRINT(("STB_PVRStartRecording(%u 0x%08lx): Recording failed, encryption key not available",
4707  path, handle));
4708  }
4709  }
4710  else
4711  {
4712  STB_PVRSetRecordEncryptionKey(record_status[path].rec_index, FALSE, NULL, NULL, 0);
4713  start_recording = TRUE;
4714  }
4715 
4716  if (start_recording)
4717  {
4718  STB_PVRSetRecordStartMode(record_status[path].rec_index, record_status[path].smode,
4719  record_status[path].timeshift_seconds);
4720 
4721  record_status[path].handle = handle;
4722 
4723 #ifdef COMMON_INTERFACE
4724  /* Apply descrambler key if it's been provided */
4725  if (record_status[path].keys[KEY_PARITY_EVEN].valid)
4726  {
4727  STB_PVRApplyDescramblerKey(record_status[path].rec_index, record_status[path].desc_type,
4728  KEY_PARITY_EVEN, record_status[path].keys[KEY_PARITY_EVEN].key,
4729  record_status[path].keys[KEY_PARITY_EVEN].iv);
4730  }
4731  if (record_status[path].keys[KEY_PARITY_ODD].valid)
4732  {
4733  STB_PVRApplyDescramblerKey(record_status[path].rec_index, record_status[path].desc_type,
4734  KEY_PARITY_ODD, record_status[path].keys[KEY_PARITY_ODD].key,
4735  record_status[path].keys[KEY_PARITY_ODD].iv);
4736  }
4737 #endif
4738 
4739  if (STB_PVRRecordStart(rec_ptr->disk_id, record_status[path].rec_index, rec_ptr->basename,
4740  record_status[path].num_pids, record_status[path].rec_pids_array))
4741  {
4742  record_status[path].start_time = STB_OSGetClockMilliseconds();
4743  record_status[path].paused = FALSE;
4744  record_status[path].duration = 0;
4745 
4746  rec_ptr->recording = TRUE;
4747  retval = TRUE;
4748  }
4749  else
4750  {
4751  record_status[path].handle = 0;
4752  STB_PVRReleaseRecorderIndex(record_status[path].rec_index);
4753  record_status[path].rec_index = INVALID_RES_ID;
4754  STB_PVR_PRINT(("STB_PVRStartRecording(%u, 0x%08lx): Failed to start recording", path, handle));
4755  }
4756  }
4757  else
4758  {
4759  STB_PVRReleaseRecorderIndex(record_status[path].rec_index);
4760  record_status[path].rec_index = INVALID_RES_ID;
4761  }
4762  }
4763 #ifdef STB_DEBUG
4764  else
4765  {
4766  if (rec_ptr == NULL)
4767  {
4768  STB_PVR_PRINT(("STB_PVRStartRecording(%u, 0x%08lx): Couldn't find recording to be started", path, handle));
4769  }
4770  else
4771  {
4772  STB_PVR_PRINT(("STB_PVRStartRecording(%u, 0x%08lx): Basename not set for recording", path, handle));
4773  }
4774  }
4775 #endif
4776 
4777  STB_OSMutexUnlock(list_mutex);
4778  }
4779 
4780  FUNCTION_FINISH(STB_PVRStartRecording);
4781 
4782  return(retval);
4783 }
4784 
4785 /*!**************************************************************************
4786  * @brief Pauses recording after it's been started
4787  * @param path - decode path of the recording
4788  * @return TRUE if recording is paused or is already paused, FALSE otherwise
4789  ****************************************************************************/
4790 BOOLEAN STB_PVRPauseRecording(U8BIT path)
4791 {
4792  BOOLEAN retval;
4793 
4794  FUNCTION_START(STB_PVRPauseRecording);
4795 
4796  if (!record_status[path].paused)
4797  {
4798  retval = STB_PVRRecordPause(record_status[path].rec_index);
4799  if (retval)
4800  {
4801  /* Update the recording duration upto this point */
4802  record_status[path].duration += STB_OSGetClockDiff(record_status[path].start_time);
4803  record_status[path].paused = TRUE;
4804  }
4805  }
4806  else
4807  {
4808  retval = TRUE;
4809  }
4810 
4811  FUNCTION_FINISH(STB_PVRPauseRecording);
4812 
4813  return(retval);
4814 }
4815 
4816 /*!**************************************************************************
4817  * @brief Resumes a recording after it's been paused
4818  * @param path - decode path of the recording
4819  * @return TRUE if the recording is resumed or isn't currently paused, FALSE otherwise
4820  ****************************************************************************/
4821 BOOLEAN STB_PVRResumeRecording(U8BIT path)
4822 {
4823  BOOLEAN retval;
4824 
4825  FUNCTION_START(STB_PVRResumeRecording);
4826 
4827  if (record_status[path].paused)
4828  {
4829  retval = STB_PVRRecordResume(record_status[path].rec_index);
4830  if (retval)
4831  {
4832  /* Save the time the recording has been started again */
4833  record_status[path].start_time = STB_OSGetClockMilliseconds();
4834  record_status[path].paused = FALSE;
4835  }
4836  }
4837  else
4838  {
4839  retval = TRUE;
4840  }
4841 
4842  FUNCTION_FINISH(STB_PVRResumeRecording);
4843 
4844  return(retval);
4845 }
4846 
4858 void STB_PVRStopRecording(U8BIT path)
4859 {
4860  S_RECORDING *rec_ptr;
4861  U32BIT recording_time;
4862  U8BIT hours, mins, secs;
4863 
4864  FUNCTION_START(STB_PVRStopRecording);
4865 
4866  ASSERT(path < num_paths);
4867 
4868  STB_PVRRecordStop(record_status[path].rec_index);
4869 
4870  if (initialised_flag)
4871  {
4872  STB_OSMutexLock(list_mutex);
4873 
4874  rec_ptr = GetRecording(record_status[path].handle);
4875  if ((rec_ptr != NULL) && (strlen((char *)rec_ptr->basename) > 0))
4876  {
4877  /* Work out the duration of the recording and save to the DB */
4878  if (record_status[path].paused)
4879  {
4880  recording_time = record_status[path].duration;
4881  }
4882  else
4883  {
4884  recording_time = record_status[path].duration + STB_OSGetClockDiff(record_status[path].start_time);
4885  }
4886 
4887  recording_time = (recording_time + 499) / 1000;
4888 
4889  hours = recording_time / 3600;
4890  mins = (recording_time / 60) - (hours * 60);
4891  secs = recording_time % 60;
4892 
4893  rec_ptr->rec_info.len_hour = hours;
4894  rec_ptr->rec_info.len_min = mins;
4895  rec_ptr->rec_info.len_sec = secs;
4896  rec_ptr->rec_info.status = RECORDING_STATUS_COMPLETED;
4897 
4898  rec_ptr->recording = FALSE;
4899  WriteODBFile(rec_ptr->disk_id, rec_ptr->basename, TRUE, &rec_ptr->rec_info);
4900  }
4901 
4902  if (record_status[path].rec_pids_array != NULL)
4903  {
4904  STB_FreeMemory(record_status[path].rec_pids_array);
4905  record_status[path].rec_pids_array = NULL;
4906  record_status[path].num_pids = 0;
4907  }
4908 
4909  record_status[path].handle = 0; /* Recording handle not valid any more */
4910 
4911 #ifdef COMMON_INTERFACE
4912  /* Make sure the keys aren't used for the next recording */
4913  record_status[path].keys[KEY_PARITY_EVEN].valid = FALSE;
4914  record_status[path].keys[KEY_PARITY_ODD].valid = FALSE;
4915 #endif
4916 
4917  STB_PVRReleaseRecorderIndex(record_status[path].rec_index);
4918  record_status[path].rec_index = INVALID_RES_ID;
4919 
4920  STB_OSMutexUnlock(list_mutex);
4921  }
4922 
4923  FUNCTION_FINISH(STB_PVRStopRecording);
4924 }
4925 
4938 BOOLEAN STB_PVRIsRecording(U8BIT path, U32BIT *handle)
4939 {
4940  BOOLEAN ret_val;
4941  S_RECORDING *rec_ptr;
4942 
4943  FUNCTION_START(STB_PVRIsRecording);
4944 
4945  ASSERT(path < num_paths);
4946 
4947  ret_val = FALSE;
4948 
4949  if (initialised_flag)
4950  {
4951  if (STB_DPIsRecordingPath(path) == TRUE)
4952  {
4953  *handle = record_status[path].handle;
4954  rec_ptr = GetRecording(*handle);
4955  if (rec_ptr != NULL)
4956  {
4957  ret_val = TRUE;
4958  }
4959  }
4960  }
4961 
4962  FUNCTION_FINISH(STB_PVRIsRecording);
4963 
4964  return(ret_val);
4965 }
4966 
4979 {
4980  FUNCTION_START(STB_PVRStartRecordRunning);
4981 
4982  ASSERT(path < num_paths);
4983 
4984  STB_PVR_PRINT(("STB_PVRStartRecordRunning(%d)", path));
4985 
4986  record_status[path].smode = START_RUNNING;
4987  record_status[path].timeshift_seconds = 0;
4988 
4989  FUNCTION_FINISH(STB_PVRStartRecordRunning);
4990 }
4991 
5004 void STB_PVRStartRecordPaused(U8BIT path, U32BIT timeshift_seconds)
5005 {
5006  FUNCTION_START(STB_PVRStartRecordPaused);
5007 
5008  ASSERT(path < num_paths);
5009 
5010  STB_PVR_PRINT(("STB_PVRStartRecordPaused(%d)", path));
5011 
5012  record_status[path].smode = START_PAUSED;
5013  record_status[path].timeshift_seconds = timeshift_seconds;
5014 
5015  FUNCTION_FINISH(STB_PVRStartRecordPaused);
5016 }
5017 
5029 BOOLEAN STB_PVRIsRecordVideo(U8BIT path)
5030 {
5031  BOOLEAN audio, video;
5032 
5033  FUNCTION_START(STB_PVRIsRecordVideo);
5034 
5035  ASSERT(path < num_paths);
5036 
5037  video = FALSE;
5038 
5039  if (STB_PVRIsRecordStarted(record_status[path].rec_index))
5040  {
5041  STB_PVRRecordEnabled(record_status[path].rec_index, &video, &audio);
5042  }
5043 
5044  FUNCTION_FINISH(STB_PVRIsRecordVideo);
5045 
5046  return(video);
5047 }
5048 
5060 BOOLEAN STB_PVRIsRecordAudio(U8BIT path)
5061 {
5062  BOOLEAN video, audio;
5063 
5064  FUNCTION_START(STB_PVRIsRecordAudio);
5065 
5066  ASSERT(path < num_paths);
5067 
5068  audio = FALSE;
5069 
5070  if (STB_PVRIsRecordStarted(record_status[path].rec_index))
5071  {
5072  STB_PVRRecordEnabled(record_status[path].rec_index, &video, &audio);
5073  }
5074 
5075  FUNCTION_FINISH(STB_PVRIsRecordAudio);
5076 
5077  return(audio);
5078 }
5079 
5080 /*!**************************************************************************
5081  * @brief Sets whether a recording should be encrypted.
5082  * Must be set before the recording is started
5083  * @param path - decode path that will be used for the recording
5084  * @param state - TRUE if it's to be encrypted
5085  ****************************************************************************/
5086 void STB_PVREncryptRecording(U8BIT path, BOOLEAN state)
5087 {
5088  FUNCTION_START(STB_PVREncryptRecording);
5089 
5090  record_status[path].encrypted = state;
5091 
5092  FUNCTION_FINISH(STB_PVREncryptRecording);
5093 }
5094 
5095 #ifdef COMMON_INTERFACE
5096 /*!**************************************************************************
5097  * @brief Sets the descrambler key data to be applied with a recording
5098  * @param path - decode path that will be/is being used for the recording
5099  * @param desc_type - type of descrambling to be applied, normally DES or AES
5100  * @param parity - key parity
5101  * @param key - key data
5102  * @param iv - initialisation vector for AES
5103  * @return TRUE if the key data is saved successfully, FALSE otherwise
5104  ****************************************************************************/
5105 BOOLEAN STB_PVRSetDescramblerKey(U8BIT path, E_STB_DMX_DESC_TYPE desc_type,
5106  E_STB_DMX_DESC_KEY_PARITY parity, U8BIT *key, U8BIT *iv)
5107 {
5108  BOOLEAN retval;
5109 
5110  FUNCTION_START(STB_PVRSetDescramblerKey);
5111 
5112  retval = FALSE;
5113 
5114  if (path < num_paths)
5115  {
5116  if (record_status[path].rec_index != INVALID_RES_ID)
5117  {
5118  /* Recording has been started so apply the updated descrambler key immediately */
5119  retval = STB_PVRApplyDescramblerKey(record_status[path].rec_index, desc_type,
5120  parity, key, iv);
5121  }
5122  else
5123  {
5124  /* Save the descrambler info for use when the recording is started */
5125  retval = TRUE;
5126 
5127  switch (desc_type)
5128  {
5129  case DESC_TYPE_DES:
5130  record_status[path].desc_type = desc_type;
5131  memcpy(record_status[path].keys[parity].key, key, 8);
5132  record_status[path].keys[parity].valid = TRUE;
5133  break;
5134 
5135  case DESC_TYPE_AES:
5136  record_status[path].desc_type = desc_type;
5137  memcpy(record_status[path].keys[parity].key, key, 16);
5138  memcpy(record_status[path].keys[parity].iv, iv, 16);
5139  record_status[path].keys[parity].valid = TRUE;
5140  break;
5141 
5142  default:
5143  record_status[path].keys[parity].valid = FALSE;
5144  retval = FALSE;
5145  break;
5146  }
5147  }
5148  }
5149 
5150  FUNCTION_FINISH(STB_PVRSetDescramblerKey);
5151 
5152  return(retval);
5153 }
5154 
5155 #endif /* COMMON_INTERFACE */
5156 
5157 #if 0
5158 
5169 void STB_PVRExportFrame(U8BIT path)
5170 {
5171  FUNCTION_START(STB_PVRExportFrame);
5172 
5173  ASSERT(path < num_paths);
5174 
5175  STB_PVR_PRINT(("STB_PVRExportFrame(%d)", path));
5176 
5178  {
5180  }
5181 
5182  FUNCTION_FINISH(STB_PVRExportFrame);
5183 }
5184 
5185 #endif
5186 
5198 void STB_PVRPlayNormal(U8BIT path)
5199 {
5200  U8BIT audio_decoder, video_decoder;
5201  S16BIT play_speed;
5202 
5203  FUNCTION_START(STB_PVRPlayNormal);
5204 
5205  ASSERT(path < num_paths);
5206 
5207  STB_PVR_PRINT(("STB_PVRPlayNormal(%u)", path));
5208 
5209  audio_decoder = STB_DPGetPathAudioDecoder(path);
5210  video_decoder = STB_DPGetPathVideoDecoder(path);
5211 
5212  if (STB_PVRIsPlayStarted(audio_decoder, video_decoder))
5213  {
5214  play_speed = STB_PVRGetPlaySpeed(audio_decoder, video_decoder);
5215  if (play_speed != 100)
5216  {
5217  /* Request normal playback */
5218  STB_PVRSetPlaySpeed(audio_decoder, video_decoder, 100);
5219 
5220 #ifdef COMMON_INTERFACE
5221  if (play_speed < 0)
5222  {
5223  /* Change of direction, so re-evaluate the next URI/licence/pin that needs to be applied */
5224  FindNextCIPlusItem(path, play_speed);
5225  }
5226 #endif
5227  }
5228  }
5229 
5230  FUNCTION_FINISH(STB_PVRPlayNormal);
5231 }
5232 
5244 BOOLEAN STB_PVRIsPlayNormal(U8BIT path)
5245 {
5246  U8BIT audio_decoder, video_decoder;
5247  BOOLEAN ret_val = FALSE;
5248 
5249  FUNCTION_START(STB_PVRIsPlayNormal);
5250 
5251  ASSERT(path < num_paths);
5252 
5253  audio_decoder = STB_DPGetPathAudioDecoder(path);
5254  video_decoder = STB_DPGetPathVideoDecoder(path);
5255 
5256  if (STB_PVRIsPlayStarted(audio_decoder, video_decoder))
5257  {
5258  if (STB_PVRGetPlaySpeed(audio_decoder, video_decoder) == 100)
5259  {
5260  ret_val = TRUE;
5261  }
5262  }
5263 
5264  FUNCTION_FINISH(STB_PVRIsPlayNormal);
5265 
5266  return(ret_val);
5267 }
5268 
5280 void STB_PVRPlayPause(U8BIT path)
5281 {
5282  U8BIT audio_decoder, video_decoder;
5283 
5284  FUNCTION_START(STB_PVRPlayPause);
5285 
5286  ASSERT(path < num_paths);
5287 
5288  STB_PVR_PRINT(("STB_PVRPlayPause(%d)", path));
5289 
5290  audio_decoder = STB_DPGetPathAudioDecoder(path);
5291  video_decoder = STB_DPGetPathVideoDecoder(path);
5292 
5293  if (STB_PVRIsPlayStarted(audio_decoder, video_decoder) == TRUE)
5294  {
5295  STB_PVRSetPlaySpeed(audio_decoder, video_decoder, 0);
5296  }
5297 
5298  FUNCTION_FINISH(STB_PVRPlayPause);
5299 }
5300 
5312 BOOLEAN STB_PVRIsPlayPause(U8BIT path)
5313 {
5314  U8BIT audio_decoder, video_decoder;
5315  BOOLEAN ret_val = FALSE;
5316 
5317  FUNCTION_START(STB_PVRIsPlayPause);
5318 
5319  ASSERT(path < num_paths);
5320 
5321  audio_decoder = STB_DPGetPathAudioDecoder(path);
5322  video_decoder = STB_DPGetPathVideoDecoder(path);
5323 
5324  if (STB_PVRIsPlayStarted(audio_decoder, video_decoder) == TRUE)
5325  {
5326  if (STB_PVRGetPlaySpeed(audio_decoder, video_decoder) == 0)
5327  {
5328  ret_val = TRUE;
5329  }
5330  }
5331 
5332  FUNCTION_FINISH(STB_PVRIsPlayPause);
5333 
5334  return(ret_val);
5335 }
5336 
5348 void STB_PVRPlayForward(U8BIT path)
5349 {
5350  U8BIT audio_decoder, video_decoder;
5351  S16BIT play_speed;
5352 
5353  FUNCTION_START(STB_PVRPlayForward);
5354 
5355  ASSERT(path < num_paths);
5356 
5357  STB_PVR_PRINT(("STB_PVRPlayForward(%d)", path));
5358 
5359  audio_decoder = STB_DPGetPathAudioDecoder(path);
5360  video_decoder = STB_DPGetPathVideoDecoder(path);
5361 
5362  if (STB_PVRIsPlayStarted(audio_decoder, video_decoder))
5363  {
5364  /* Request forwards PVR trick mode */
5365  play_speed = STB_PVRGetPlaySpeed(audio_decoder, video_decoder);
5366  if (play_speed <= 0)
5367  {
5368  play_speed = -play_speed;
5369 
5370  STB_PVR_PRINT(("STB_PVRPlayForward(%d): requesting FF play speed %d", path, play_speed));
5371 
5372  STB_PVRSetPlaySpeed(audio_decoder, video_decoder, play_speed);
5373 
5374 #ifdef COMMON_INTERFACE
5375  /* Change of direction, so re-evaluate the next URI/licence/pin that needs to be applied */
5376  FindNextCIPlusItem(path, play_speed);
5377 #endif
5378  }
5379  }
5380 
5381  FUNCTION_FINISH(STB_PVRPlayForward);
5382 }
5383 
5395 BOOLEAN STB_PVRIsPlayForward(U8BIT path)
5396 {
5397  U8BIT audio_decoder, video_decoder;
5398  BOOLEAN ret_val = FALSE;
5399 
5400  FUNCTION_START(STB_PVRIsPlayForward);
5401 
5402  ASSERT(path < num_paths);
5403 
5404  audio_decoder = STB_DPGetPathAudioDecoder(path);
5405  video_decoder = STB_DPGetPathVideoDecoder(path);
5406 
5407  if (STB_PVRIsPlayStarted(audio_decoder, video_decoder))
5408  {
5409  if (STB_PVRGetPlaySpeed(audio_decoder, video_decoder) > 0)
5410  {
5411  ret_val = TRUE;
5412  }
5413  }
5414 
5415  FUNCTION_FINISH(STB_PVRIsPlayForward);
5416 
5417  return(ret_val);
5418 }
5419 
5431 void STB_PVRPlayReverse(U8BIT path)
5432 {
5433  U8BIT audio_decoder, video_decoder;
5434  S16BIT play_speed;
5435 
5436  FUNCTION_START(STB_PVRPlayReverse);
5437 
5438  ASSERT(path < num_paths);
5439 
5440  STB_PVR_PRINT(("STB_PVRPlayReverse(%d)", path));
5441 
5442  audio_decoder = STB_DPGetPathAudioDecoder(path);
5443  video_decoder = STB_DPGetPathVideoDecoder(path);
5444 
5445  if (STB_PVRIsPlayStarted(audio_decoder, video_decoder))
5446  {
5447  /* Request backwards PVR trick mode */
5448  play_speed = STB_PVRGetPlaySpeed(audio_decoder, video_decoder);
5449  if (play_speed > 0)
5450  {
5451  play_speed = -play_speed;
5452 
5453  STB_PVR_PRINT(("STB_PVRPlayReverse(%d): requesting FR play speed %d", path, play_speed));
5454 
5455  STB_PVRSetPlaySpeed(audio_decoder, video_decoder, play_speed);
5456 
5457 #ifdef COMMON_INTERFACE
5458  /* Change of direction, so re-evaluate the next URI/licence/pin that needs to be applied */
5459  FindNextCIPlusItem(path, play_speed);
5460 #endif
5461  }
5462  }
5463 
5464  FUNCTION_FINISH(STB_PVRPlayReverse);
5465 }
5466 
5478 BOOLEAN STB_PVRIsPlayReverse(U8BIT path)
5479 {
5480  U8BIT audio_decoder, video_decoder;
5481  BOOLEAN ret_val = FALSE;
5482 
5483  FUNCTION_START(STB_PVRIsPlayReverse);
5484 
5485  ASSERT(path < num_paths);
5486 
5487  audio_decoder = STB_DPGetPathAudioDecoder(path);
5488  video_decoder = STB_DPGetPathVideoDecoder(path);
5489 
5490  if (STB_PVRIsPlayStarted(audio_decoder, video_decoder))
5491  {
5492  if (STB_PVRGetPlaySpeed(audio_decoder, video_decoder) < 0)
5493  {
5494  ret_val = TRUE;
5495  }
5496  }
5497 
5498  FUNCTION_FINISH(STB_PVRIsPlayReverse);
5499 
5500  return(ret_val);
5501 }
5502 
5514 void STB_PVRPlayFrameInc(U8BIT path)
5515 {
5516  FUNCTION_START(STB_PVRPlayFrameInc);
5517 
5518  ASSERT(path < num_paths);
5519 
5520  STB_PVR_PRINT(("STB_PVRPlayFrameInc(%d)", path));
5521 
5523  {
5524  // request frame PVR trick mode
5526  }
5527 
5528  FUNCTION_FINISH(STB_PVRPlayFrameInc);
5529 }
5530 
5542 void STB_PVRPlayFrameDec(U8BIT path)
5543 {
5544  FUNCTION_START(STB_PVRPlayFrameDec);
5545 
5546  ASSERT(path < num_paths);
5547 
5548  STB_PVR_PRINT(("STB_PVRPlayFrameDec(%d)", path));
5549 
5551  {
5552  // request frame PVR trick mode
5553  STB_PVRPlayTrickMode(STB_DPGetPathAudioDecoder(path), STB_DPGetPathVideoDecoder(path), PLAY_TRICK_FRAME, -1);
5554  }
5555 
5556  FUNCTION_FINISH(STB_PVRPlayFrameDec);
5557 }
5558 
5570 void STB_PVRPlayMedium(U8BIT path)
5571 {
5572  FUNCTION_START(STB_PVRPlayMedium);
5573 
5574  ASSERT(path < num_paths);
5575 
5576  STB_PVRPlayNormal(path);
5577 
5578  FUNCTION_FINISH(STB_PVRPlayMedium);
5579 }
5580 
5592 BOOLEAN STB_PVRIsPlayMedium(U8BIT path)
5593 {
5594  BOOLEAN ret_val;
5595 
5596  FUNCTION_START(STB_PVRIsPlayMedium);
5597 
5598  ASSERT(path < num_paths);
5599 
5600  ret_val = STB_PVRIsPlayNormal(path);
5601 
5602  FUNCTION_FINISH(STB_PVRIsPlayMedium);
5603 
5604  return(ret_val);
5605 }
5606 
5607 /*!**************************************************************************
5608  * @brief Decrease play speed - has no effect when decoding from demux.
5609  * @param path - ID of the decode path to use
5610  * @param include_slow_speeds - selects whether slow motion speeds, >-100% and <100%, are included
5611  ****************************************************************************/
5612 void STB_PVRPlaySlower(U8BIT path, BOOLEAN include_slow_speeds)
5613 {
5614  S16BIT speed;
5615  U8BIT audio_decoder, video_decoder;
5616 
5617  FUNCTION_START(STB_PVRPlaySlower);
5618 
5619  ASSERT(path < num_paths);
5620 
5621  STB_PVR_PRINT(("STB_PVRPlaySlower(%d)", path));
5622 
5623  audio_decoder = STB_DPGetPathAudioDecoder(path);
5624  video_decoder = STB_DPGetPathVideoDecoder(path);
5625 
5626  if (STB_PVRIsPlayStarted(audio_decoder, video_decoder))
5627  {
5628  speed = STB_PVRGetPlaySpeed(audio_decoder, video_decoder);
5629  speed = STB_AVGetNextPlaySpeed(video_decoder, speed, -1, include_slow_speeds);
5630  STB_PVRSetPlaySpeed(audio_decoder, video_decoder, speed);
5631  }
5632 
5633  FUNCTION_FINISH(STB_PVRPlaySlower);
5634 }
5635 
5647 BOOLEAN STB_PVRIsPlaySlowest(U8BIT path)
5648 {
5649  BOOLEAN ret_val = FALSE;
5650  U8BIT audio_decoder, video_decoder;
5651 
5652  FUNCTION_START(STB_PVRIsPlaySlowest);
5653 
5654  ASSERT(path < num_paths);
5655 
5656  audio_decoder = STB_DPGetPathAudioDecoder(path);
5657  video_decoder = STB_DPGetPathVideoDecoder(path);
5658 
5659  if (STB_PVRIsPlayStarted(audio_decoder, video_decoder))
5660  {
5661  if (STB_PVRGetPlaySpeed(audio_decoder, video_decoder) == STB_PVRGetMinPlaySpeed(path))
5662  {
5663  ret_val = TRUE;
5664  }
5665  }
5666 
5667  FUNCTION_FINISH(STB_PVRIsPlaySlowest);
5668 
5669  return(ret_val);
5670 }
5671 
5672 /*!**************************************************************************
5673  * @brief Increase play speed - has no effect when decoding from demux.
5674  * @param path - ID of the decode path to use
5675  * @param include_slow_speeds - selects whether slow motion speeds, >-100% and <100%, are included
5676  ****************************************************************************/
5677 void STB_PVRPlayFaster(U8BIT path, BOOLEAN include_slow_speeds)
5678 {
5679  S16BIT speed;
5680  U8BIT audio_decoder, video_decoder;
5681 
5682  FUNCTION_START(STB_PVRPlayFaster);
5683 
5684  ASSERT(path < num_paths);
5685 
5686  STB_PVR_PRINT(("STB_PVRPlayFaster(%d)", path));
5687 
5688  audio_decoder = STB_DPGetPathAudioDecoder(path);
5689  video_decoder = STB_DPGetPathVideoDecoder(path);
5690 
5691  if (STB_PVRIsPlayStarted(audio_decoder, video_decoder))
5692  {
5693  /* Set play speed to the next fastest speed */
5694  speed = STB_PVRGetPlaySpeed(audio_decoder, video_decoder);
5695  speed = STB_AVGetNextPlaySpeed(video_decoder, speed, 1, include_slow_speeds);
5696  STB_PVRSetPlaySpeed(audio_decoder, video_decoder, speed);
5697  }
5698 
5699  FUNCTION_FINISH(STB_PVRPlayFaster);
5700 }
5701 
5713 BOOLEAN STB_PVRIsPlayFastest(U8BIT path)
5714 {
5715  BOOLEAN ret_val = FALSE;
5716  U8BIT audio_decoder, video_decoder;
5717 
5718  FUNCTION_START(STB_PVRIsPlayFastest);
5719 
5720  ASSERT(path < num_paths);
5721 
5722  audio_decoder = STB_DPGetPathAudioDecoder(path);
5723  video_decoder = STB_DPGetPathVideoDecoder(path);
5724 
5725  if (STB_PVRIsPlayStarted(audio_decoder, video_decoder))
5726  {
5727  if (STB_PVRGetPlaySpeed(audio_decoder, video_decoder) == STB_PVRGetMaxPlaySpeed(path))
5728  {
5729  ret_val = TRUE;
5730  }
5731  }
5732 
5733  FUNCTION_FINISH(STB_PVRIsPlayFastest);
5734 
5735  return(ret_val);
5736 }
5737 
5749 S16BIT STB_PVRGetMinPlaySpeed(U8BIT path)
5750 {
5751  S16BIT ret_val;
5752 
5753  FUNCTION_START(STB_PVRGetMinPlaySpeed);
5754 
5755  ASSERT(path < num_paths);
5756 
5758 
5759  FUNCTION_FINISH(STB_PVRGetMinPlaySpeed);
5760 
5761  return(ret_val);
5762 }
5763 
5775 S16BIT STB_PVRGetMaxPlaySpeed(U8BIT path)
5776 {
5777  S16BIT ret_val;
5778 
5779  FUNCTION_START(STB_PVRGetMaxPlaySpeed);
5780 
5781  ASSERT(path < num_paths);
5782 
5784 
5785  FUNCTION_FINISH(STB_PVRGetMaxPlaySpeed);
5786 
5787  return(ret_val);
5788 }
5789 
5802 void STB_PVRDiskUsed(U16BIT disk_id, U8BIT *hours, U8BIT *mins)
5803 {
5804  U32BIT temp_val;
5805 
5806  FUNCTION_START(STB_PVRDiskUsed);
5807 
5808  temp_val = STB_PVRGetTimeOfAllRecordings(disk_id);
5809  *hours = (U8BIT)(temp_val / 60);
5810  *mins = (U8BIT)(temp_val % 60);
5811 
5812  FUNCTION_FINISH(STB_PVRDiskUsed);
5813 }
5814 
5828 void STB_PVRDiskFree(U16BIT disk_id, U8BIT *hours, U8BIT *mins)
5829 {
5830  U32BIT recording_time;
5831  U32BIT disk_used;
5832  U32BIT disk_free;
5833  U32BIT space_in_mins;
5834  U32BIT kb_per_min;
5835 
5836  FUNCTION_START(STB_PVRDiskFree);
5837 
5838  disk_used = STB_PVRGetSizeOfAllRecordings(disk_id);
5839  recording_time = STB_PVRGetTimeOfAllRecordings(disk_id);
5840 
5841  if ((disk_used == 0) || (recording_time == 0))
5842  {
5843  /* Estimate for the KB per minute */
5844  kb_per_min = 85 * 1024;
5845  }
5846  else
5847  {
5848  /* Calculate the KB/min for all current recordings */
5849  kb_per_min = disk_used / recording_time;
5850  }
5851 
5852  disk_free = STB_DSKGetSize(disk_id) - STB_DSKGetUsed(disk_id);
5853  space_in_mins = disk_free / kb_per_min;
5854 
5855  *hours = (U8BIT)(space_in_mins / 60);
5856  *mins = (U8BIT)(space_in_mins % 60);
5857 
5858  FUNCTION_FINISH(STB_PVRDiskFree);
5859 }
5860 
5872 U32BIT STB_PVRDiskSize(U16BIT disk_id)
5873 {
5874  U32BIT ret_val;
5875 
5876  FUNCTION_START(STB_PVRDiskSize);
5877 
5878  ret_val = STB_DSKGetSize(disk_id) / 1024;
5879 
5880  FUNCTION_FINISH(STB_PVRDiskSize);
5881 
5882  return(ret_val);
5883 }
5884 
5894 BOOLEAN STB_PVRCreateBookmark(U32BIT handle, U32BIT time, U8BIT *name)
5895 {
5896  BOOLEAN retval;
5897  S_RECORDING *rec_ptr;
5898 
5899  FUNCTION_START(STB_PVRCreateBookmark);
5900 
5901  STB_PVR_PRINT(("STB_PVRCreateBookmark(handle = 0x%x, time = %d, name = %p", handle, time, name));
5902  rec_ptr = GetRecording(handle);
5903  if ((rec_ptr != NULL) && (strlen((char *)rec_ptr->basename) > 0))
5904  {
5905  retval = AddBookmark(rec_ptr->disk_id, rec_ptr->basename, time, name, BOOKMARK_USER);
5906  }
5907  else
5908  {
5909  STB_PVR_PRINT(("STB_PVRCreateBookmark: failed finding the recording"));
5910  retval = FALSE;
5911  }
5912 
5913  FUNCTION_FINISH(STB_PVRCreateBookmark);
5914 
5915  return retval;
5916 }
5917 
5927 BOOLEAN STB_PVRDeleteBookmark(U32BIT handle, U32BIT time, U8BIT *name)
5928 {
5929  BOOLEAN retval;
5930  S_RECORDING *rec_ptr;
5931 
5932  FUNCTION_START(STB_PVRDeleteBookmark);
5933 
5934  STB_PVR_PRINT(("STB_PVRDeleteBookmark(handle = 0x%x, time = %d, name = %p", handle, time, name));
5935  rec_ptr = GetRecording(handle);
5936  if ((rec_ptr != NULL) && (strlen((char *)rec_ptr->basename) > 0))
5937  {
5938  RemoveBookmark(rec_ptr->disk_id, rec_ptr->basename, time, name, BOOKMARK_USER);
5939  retval = TRUE;
5940  }
5941  else
5942  {
5943  STB_PVR_PRINT(("STB_PVRDeleteBookmark: failed finding the recording"));
5944  retval = FALSE;
5945  }
5946 
5947  FUNCTION_FINISH(STB_PVRDeleteBookmark);
5948 
5949  return retval;
5950 }
5951 
5952 
5953 //---local function definitions------------------------------------------------
5954 
5955 /*!**************************************************************************
5956  * @brief Read all recording info from a given disk and create an entry in the recording list
5957  * for each one. Recordings are only recognised in the disk's base/root directory.
5958  * @param disk_id - disk to be read
5959  ****************************************************************************/
5960 static void ReadRecordings(U16BIT disk_id)
5961 {
5962  void *dir;
5963  U8BIT filename[DB_FILENAME_LEN];
5964  E_STB_DIR_ENTRY_TYPE entry_type;
5965  void *dbfile;
5966  S_RECORDING *rec_ptr;
5967  S_REC_HEADER header;
5968  S_REC_INFO rec_info;
5969  BOOLEAN result;
5970 
5971  FUNCTION_START(ReadRecordings);
5972 
5973  STB_PVR_PRINT(("ReadRecordings(0x%04x)", disk_id));
5974 
5975  /* Get a list of all the filenames in the base directory */
5976  dir = STB_DSKOpenDirectory(disk_id, (U8BIT *)"/");
5977  if (dir != NULL)
5978  {
5979  while (STB_DSKReadDirectory(dir, filename, sizeof(filename), &entry_type))
5980  {
5981  if (entry_type == DIR_ENTRY_FILE)
5982  {
5983  /* Look for recording database files */
5984  if ((strlen((char *)filename) > strlen(DB_FILE_EXTENSION)) &&
5985  (strlen((char *)filename) <= (STB_PVR_BASENAME_LEN + strlen(DB_FILE_EXTENSION))) &&
5986  (strcmp((char *)&filename[strlen((char *)filename) - strlen(DB_FILE_EXTENSION)], DB_FILE_EXTENSION) == 0))
5987  {
5988  /* Check the file is valid */
5989  dbfile = STB_DSKOpenFile(disk_id, filename, FILE_MODE_READ);
5990  if (dbfile != NULL)
5991  {
5992  rec_ptr = NULL;
5993 
5994  if (STB_DSKReadFile(dbfile, (U8BIT *)&header, (U32BIT)sizeof(S_REC_HEADER)) ==
5995  (U32BIT)sizeof(S_REC_HEADER))
5996  {
5997  /* Check header */
5998  if ((header.magic[0] == ODB_MAGIC_1) && (header.magic[1] == ODB_MAGIC_2) &&
5999  (header.magic[2] == ODB_MAGIC_3))
6000  {
6001  result = FALSE;
6002 
6003  /* Now read the basic recording info that is held in memory */
6004  if ((header.version == ODB_VERSION_1) || (header.version == ODB_VERSION_2))
6005  {
6006  /* Data will be encrypted, so read and decrypt it */
6007  if (STB_DSKReadFile(dbfile, rec_info_buffer, REC_INFO_BUFFER_SIZE) == REC_INFO_BUFFER_SIZE)
6008  {
6009  if ((enc_dec_key != NULL) && (enc_dec_iv != NULL))
6010  {
6011  STB_CRYPTAesCbcDecrypt(rec_info_buffer, rec_info_buffer, REC_INFO_BUFFER_SIZE,
6012  enc_dec_key, enc_dec_iv);
6013  }
6014 
6015  /* Copy the decrypted data */
6016  memcpy(&rec_info, rec_info_buffer, sizeof(S_REC_INFO));
6017 
6018  if (header.version == ODB_VERSION_1)
6019  {
6020  /* Version 1 files don't have status to indicate whether the
6021  * recording completed successfully or not, so check the recording
6022  * duration and set the status accordingly */
6023  if ((rec_info.len_hour == 0) && (rec_info.len_min == 0) &&
6024  (rec_info.len_sec == 0))
6025  {
6026  rec_info.status = RECORDING_STATUS_FAILED;
6027  }
6028  else
6029  {
6030  rec_info.status = RECORDING_STATUS_COMPLETED;
6031  }
6032  }
6033  else if (header.version == ODB_VERSION_2)
6034  {
6035  if (rec_info.status == RECORDING_STATUS_STARTED)
6036  {
6037  /* Recording didn't complete */
6038  rec_info.status = RECORDING_STATUS_FAILED;
6039  }
6040  }
6041 
6042  result = TRUE;
6043  }
6044  }
6045 
6046  if (result)
6047  {
6048  /* Get the basename for the recording by terminating the filename
6049  * before the extension string */
6050  filename[strlen((char *)filename) - strlen(DB_FILE_EXTENSION)] = '\0';
6051 
6052  /* Check the platform to make sure this is a valid recording */
6053  if (STB_PVRIsValidRecording(disk_id, filename))
6054  {
6055  /* Create a list entry for this recording */
6056  rec_ptr = STB_GetMemory(sizeof(S_RECORDING));
6057  if (rec_ptr != NULL)
6058  {
6059  memset(rec_ptr, 0, sizeof(S_RECORDING));
6060 
6061  /* Copy the recording info into the list entry */
6062  memcpy(&rec_ptr->rec_info, &rec_info, sizeof(S_REC_INFO));
6063 
6064  /* Store the disk ID with the recording */
6065  rec_ptr->disk_id = disk_id;
6066 
6067  /* Store the base filename for this recording */
6068  strncpy((char *)rec_ptr->basename, (char *)filename, BASENAME_LEN);
6069 
6070  /* Add into the recording list according to the recording date/time */
6071  STB_OSMutexLock(list_mutex);
6072 
6073  /* Assign a unique handle to the recording */
6074  rec_ptr->handle = GetNextFreeHandle();
6075 
6076  /* Find where this recording should be inserted into the recording list
6077  * based on the date & time of the recording */
6078  InsertRecordingInList(rec_ptr);
6079 
6080  STB_OSMutexUnlock(list_mutex);
6081  }
6082  }
6083  }
6084  }
6085  }
6086 
6087  STB_DSKCloseFile(dbfile);
6088  }
6089  }
6090  }
6091  }
6092 
6093  STB_DSKCloseDirectory(dir);
6094  }
6095 
6096  FUNCTION_FINISH(ReadRecordings);
6097 }
6098 
6099 /*!**************************************************************************
6100  * @brief Remove all recordings from the database that are on a given disk id.
6101  * This would be due to the disk being removed.
6102  * @param disk_id - ID of disk
6103  ****************************************************************************/
6104 static void RemoveRecordings(U16BIT disk_id)
6105 {
6106  S_RECORDING *rec_ptr;
6107  S_RECORDING *next_rec;
6108 
6109  FUNCTION_START(RemoveRecordings);
6110 
6111  STB_OSMutexLock(list_mutex);
6112 
6113  /* Iterate through the database looking for any entries with the given disk ID */
6114  rec_ptr = rec_list;
6115  while (rec_ptr != NULL)
6116  {
6117  next_rec = rec_ptr->next;
6118 
6119  if (rec_ptr->disk_id == disk_id)
6120  {
6121  RemoveRecordingFromList(rec_ptr);
6122  }
6123 
6124  rec_ptr = next_rec;
6125  }
6126 
6127  STB_OSMutexUnlock(list_mutex);
6128 
6129  FUNCTION_FINISH(RemoveRecordings);
6130 }
6131 
6132 /*!**************************************************************************
6133  * @brief Returns the current recording duration, in seconds, of the given recording handle
6134  * @param handle - recording handle
6135  * @return Recording time in seconds, 0 if not found.
6136  ****************************************************************************/
6137 static U32BIT GetCurrentRecordTime(U32BIT handle)
6138 {
6139  U16BIT path;
6140  U32BIT record_time;
6141 
6142  FUNCTION_START(GetCurrentRecordTime);
6143 
6144  record_time = 0;
6145 
6146  /* Find the recording status for the given recording handle */
6147  for (path = 0; path < num_paths; path++)
6148  {
6149  if (record_status[path].handle == handle)
6150  {
6151  if (record_status[path].paused)
6152  {
6153  record_time = record_status[path].duration;
6154  }
6155  else
6156  {
6157  record_time = record_status[path].duration + STB_OSGetClockDiff(record_status[path].start_time);
6158  }
6159 
6160  record_time /= 1000;
6161  break;
6162  }
6163  }
6164 
6165  FUNCTION_FINISH(GetCurrentRecordTime);
6166 
6167  return(record_time);
6168 }
6169 
6170 /*!**************************************************************************
6171  * @brief Returns the next available handle value that isn't already used in the DB
6172  * @return handle value
6173  ****************************************************************************/
6174 static U32BIT GetNextFreeHandle(void)
6175 {
6176  U32BIT handle = HANDLE_BASE;
6177 
6178  FUNCTION_START(GetNextFreeHandle);
6179 
6180  while (GetRecording(handle) != NULL)
6181  {
6182  handle++;
6183  }
6184 
6185  FUNCTION_FINISH(GetNextFreeHandle);
6186 
6187  return(handle);
6188 }
6189 
6190 /*!**************************************************************************
6191  * @brief Finds recording entry for given handle
6192  * @param handle - recording handle
6193  * @return pointer to recording
6194  ****************************************************************************/
6195 static S_RECORDING* GetRecording(U32BIT handle)
6196 {
6197  S_RECORDING *rec_ptr;
6198 
6199  FUNCTION_START(GetRecording);
6200 
6201  rec_ptr = NULL;
6202 
6203  if (initialised_flag)
6204  {
6205  STB_OSMutexLock(list_mutex);
6206 
6207  for (rec_ptr = rec_list; (rec_ptr != NULL) && (rec_ptr->handle != handle); )
6208  {
6209  rec_ptr = rec_ptr->next;
6210  }
6211 
6212  STB_OSMutexUnlock(list_mutex);
6213  }
6214 
6215  FUNCTION_FINISH(GetRecording);
6216 
6217  return(rec_ptr);
6218 }
6219 
6220 /*!**************************************************************************
6221  * @brief Constructs the base filename for a recording
6222  * @param file_number - number to be used to create the filename
6223  * @param filename - array in which the filename is returned
6224  ****************************************************************************/
6225 static void GetDBRecordBasename(U32BIT file_number, U8BIT *filename)
6226 {
6227  FUNCTION_START(GetDBRecordBasename);
6228 
6229  snprintf((char *)filename, BASENAME_LEN, "%08lx", (long)file_number);
6230 
6231  FUNCTION_FINISH(GetDBRecordBasename);
6232 }
6233 
6234 /*!**************************************************************************
6235  * @brief Constructs the filename used to store the database info for a recording
6236  * @param file_number - number to be used to create the filename
6237  * @param filename - array in which the filename is returned
6238  ****************************************************************************/
6239 static void GetDBRecordFilename(U32BIT file_number, U8BIT *filename)
6240 {
6241  FUNCTION_START(GetDBRecordFilename);
6242 
6243  GetDBRecordBasename(file_number, filename);
6244  strncat((char *)filename, DB_FILE_EXTENSION, DB_FILE_EXTENTION_LEN);
6245 
6246  FUNCTION_FINISH(GetDBRecordFilename);
6247 }
6248 
6249 /*!**************************************************************************
6250  * @brief Writes the various parts of the ODB file
6251  * @param disk_id - ID of disk file is to be written to
6252  * @param basename - name of file ODB name is to be based on
6253  * @param write_header - TRUE if ODB header is to be written
6254  * @param rec_info - standard recording info, can be NULL if not to be written
6255  * @return TRUE if file is written successfully, FALSE otherwise
6256  ****************************************************************************/
6257 static BOOLEAN WriteODBFile(U16BIT disk_id, U8BIT *basename, BOOLEAN write_header, S_REC_INFO *rec_info)
6258 {
6259  U8BIT db_filename[DB_FILENAME_LEN];
6260  void *dbfile;
6261  S_REC_HEADER header;
6262  BOOLEAN retval;
6263 
6264  FUNCTION_START(WriteODBFile);
6265 
6266  retval = TRUE;
6267 
6268  strncpy((char *)db_filename, (char *)basename, DB_FILENAME_LEN);
6269  strncat((char *)db_filename, DB_FILE_EXTENSION, DB_FILENAME_LEN - (strlen((char *)basename)));
6270 
6271  if (STB_DSKFileExists(disk_id, db_filename))
6272  {
6273  dbfile = STB_DSKOpenFile(disk_id, db_filename, FILE_MODE_WRITE);
6274  }
6275  else
6276  {
6277  dbfile = STB_DSKOpenFile(disk_id, db_filename, FILE_MODE_OVERWRITE);
6278  }
6279 
6280  if (dbfile != NULL)
6281  {
6282  if (write_header)
6283  {
6284  /* Ensure the header is set */
6285  header.magic[0] = ODB_MAGIC_1;
6286  header.magic[1] = ODB_MAGIC_2;
6287  header.magic[2] = ODB_MAGIC_3;
6288  header.version = ODB_CUR_VERSION;
6289 
6290  if (STB_DSKWriteFile(dbfile, (U8BIT *)&header, (U32BIT)sizeof(S_REC_HEADER)) != sizeof(S_REC_HEADER))
6291  {
6292  retval = FALSE;
6293  }
6294  }
6295  else
6296  {
6297  /* Skip the header */
6298  retval = STB_DSKSeekFile(dbfile, FILE_POSITION_START, sizeof(S_REC_HEADER));
6299  }
6300 
6301  if (retval)
6302  {
6303  /* Encrypt the info before storing it */
6304  memcpy(rec_info_buffer, (U8BIT *)rec_info, sizeof(S_REC_INFO));
6305  memset(rec_info_buffer + sizeof(S_REC_INFO), 0, REC_INFO_BUFFER_SIZE - sizeof(S_REC_INFO));
6306 
6307  if ((enc_dec_key != NULL) && (enc_dec_iv != NULL))
6308  {
6309  STB_CRYPTAesCbcEncrypt(rec_info_buffer, rec_info_buffer, REC_INFO_BUFFER_SIZE, enc_dec_key, enc_dec_iv);
6310  }
6311 
6312  if (STB_DSKWriteFile(dbfile, rec_info_buffer, REC_INFO_BUFFER_SIZE) != REC_INFO_BUFFER_SIZE)
6313  {
6314  retval = FALSE;
6315  }
6316  }
6317 
6318  STB_DSKCloseFile(dbfile);
6319  }
6320 #ifdef STB_DEBUG
6321  else
6322  {
6323  STB_PVR_PRINT(("WriteODBFile: Failed to open file \"%s\" on disk 0x%04x", db_filename, disk_id));
6324  }
6325 #endif
6326 
6327  FUNCTION_FINISH(WriteODBFile);
6328 
6329  return(retval);
6330 }
6331 
6332 /*!**************************************************************************
6333  * @brief Writes the extended info data to the end of the ODB file
6334  * @param disk_id - ID of disk containing the file
6335  * @param basename - base name of the ODB file
6336  * @param ext_id - ID of the extended info
6337  * @param data_len - number of bytes of data to be written
6338  * @param data - extended info data
6339  * @return TRUE if the data is written successfully, FALSE otherwise
6340  ****************************************************************************/
6341 static BOOLEAN WriteExtendedInfo(U16BIT disk_id, U8BIT *basename, U16BIT ext_id,
6342  U32BIT data_len, U8BIT *data)
6343 {
6344  U8BIT db_filename[DB_FILENAME_LEN];
6345  void *dbfile;
6346  S32BIT offset;
6347  U16BIT id;
6348  U32BIT size;
6349  BOOLEAN id_found;
6350  BOOLEAN retval;
6351 
6352  FUNCTION_START(WriteExtendedInfo);
6353 
6354  retval = FALSE;
6355 
6356  strncpy((char *)db_filename, (char *)basename, DB_FILENAME_LEN);
6357  strncat((char *)db_filename, DB_FILE_EXTENSION, DB_FILENAME_LEN - (strlen((char *)basename)));
6358 
6359  dbfile = STB_DSKOpenFile(disk_id, db_filename, FILE_MODE_WRITE);
6360  if (dbfile != NULL)
6361  {
6362  /* Move to the start of the extended info */
6363  offset = sizeof(S_REC_HEADER) + REC_INFO_BUFFER_SIZE;
6364 
6365  if (STB_DSKSeekFile(dbfile, FILE_POSITION_START, offset))
6366  {
6367  id_found = FALSE;
6368 
6369  /* Check to see if the extended info has already been written */
6370  while (STB_DSKReadFile(dbfile, (U8BIT *)&id, sizeof(id)) == sizeof(id))
6371  {
6372  if (STB_DSKReadFile(dbfile, (U8BIT *)&size, sizeof(size)) == sizeof(size))
6373  {
6374  if (id == ext_id)
6375  {
6376  /* The extended info already exists */
6377  id_found = TRUE;
6378 
6379  if (size == data_len)
6380  {
6381  /* The data size hasn't changed so can be updated */
6382  if (STB_DSKWriteFile(dbfile, data, data_len) == data_len)
6383  {
6384  retval = TRUE;
6385  }
6386  }
6387  }
6388  else
6389  {
6390  /* Seek to the start of the next info id */
6391  STB_DSKSeekFile(dbfile, FILE_POSITION_CURRENT, size);
6392  }
6393  }
6394  }
6395 
6396  if (!id_found)
6397  {
6398  /* This extended info doesn't exist or shouldn't be updated,
6399  * so write it to the end of the file */
6400 
6401  /* Write the ext id first */
6402  if (STB_DSKWriteFile(dbfile, (U8BIT *)&ext_id, sizeof(ext_id)) == sizeof(ext_id))
6403  {
6404  /* Now write the size of the extended item */
6405  if (STB_DSKWriteFile(dbfile, (U8BIT *)&data_len, sizeof(data_len)) == sizeof(data_len))
6406  {
6407  /* Now write the actual data */
6408  if (STB_DSKWriteFile(dbfile, data, data_len) == data_len)
6409  {
6410  retval = TRUE;
6411  }
6412  }
6413  }
6414  }
6415  }
6416 
6417  STB_DSKCloseFile(dbfile);
6418  }
6419 
6420  FUNCTION_FINISH(WriteExtendedInfo);
6421 
6422  return(retval);
6423 }
6424 
6425 /*!**************************************************************************
6426  * @brief Reads extended info from the ODB file
6427  * @param disk_id - ID of disk containing the file to be read
6428  * @param basename - base name of the ODB file
6429  * @param ext_id - ID of the extended info to be read
6430  * @param data - buffer into which data is to be read
6431  * @param data_len - size of the provided buffer
6432  * @return TRUE if the info is read, FALSE otherwise
6433  ****************************************************************************/
6434 static BOOLEAN ReadExtendedInfo(U16BIT disk_id, U8BIT *basename, U16BIT ext_id, U8BIT *data,
6435  U32BIT data_len)
6436 {
6437  U8BIT db_filename[DB_FILENAME_LEN];
6438  void *dbfile;
6439  S32BIT offset;
6440  U16BIT id;
6441  U32BIT size;
6442  BOOLEAN retval;
6443 
6444  FUNCTION_START(ReadExtendedInfo);
6445 
6446  retval = FALSE;
6447 
6448  strncpy((char *)db_filename, (char *)basename, DB_FILENAME_LEN);
6449  strncat((char *)db_filename, DB_FILE_EXTENSION, DB_FILENAME_LEN - strlen((char *)basename));
6450 
6451  dbfile = STB_DSKOpenFile(disk_id, db_filename, FILE_MODE_READ);
6452  if (dbfile != NULL)
6453  {
6454  /* Move to the start of the extended info */
6455  offset = sizeof(S_REC_HEADER) + REC_INFO_BUFFER_SIZE;
6456 
6457  if (STB_DSKSeekFile(dbfile, FILE_POSITION_START, offset))
6458  {
6459  /* Read each extended info item until the required one is found or there's no more */
6460  while (STB_DSKReadFile(dbfile, (U8BIT *)&id, sizeof(id)) == sizeof(id))
6461  {
6462  if (STB_DSKReadFile(dbfile, (U8BIT *)&size, sizeof(size)) == sizeof(size))
6463  {
6464  if (id == ext_id)
6465  {
6466  if (data_len >= size)
6467  {
6468  /* Found the item we're looking for and there's enough space to read the data */
6469  if (STB_DSKReadFile(dbfile, data, size) == size)
6470  {
6471  retval = TRUE;
6472  }
6473  }
6474  break;
6475  }
6476  else
6477  {
6478  /* Seek to the start of the next info id */
6479  STB_DSKSeekFile(dbfile, FILE_POSITION_CURRENT, size);
6480  }
6481  }
6482  }
6483  }
6484 
6485  STB_DSKCloseFile(dbfile);
6486  }
6487 
6488  FUNCTION_FINISH(ReadExtendedInfo);
6489 
6490  return(retval);
6491 }
6492 
6493 /*!**************************************************************************
6494  * @brief Finds the extended info in the ODB file and returns the data size
6495  * @param disk_id - ID of disk containing the file to be read
6496  * @param basename - base name of the ODB file
6497  * @param ext_id - ID of the extended info to be read
6498  * @return Size of the data for the extended info, or 0 if not found
6499  ****************************************************************************/
6500 static U32BIT GetExtendedInfoSize(U16BIT disk_id, U8BIT *basename, U16BIT ext_id)
6501 {
6502  U8BIT db_filename[DB_FILENAME_LEN];
6503  void *dbfile;
6504  S32BIT offset;
6505  U16BIT id;
6506  U32BIT size;
6507  U32BIT retval;
6508 
6509  FUNCTION_START(GetExtendedInfoSize);
6510 
6511  retval = 0;
6512 
6513  strncpy((char *)db_filename, (char *)basename, DB_FILENAME_LEN);
6514  strncat((char *)db_filename, DB_FILE_EXTENSION, DB_FILENAME_LEN - strlen((char *)basename));
6515 
6516  dbfile = STB_DSKOpenFile(disk_id, db_filename, FILE_MODE_READ);
6517  if (dbfile != NULL)
6518  {
6519  /* Move to the start of the extended info */
6520  offset = sizeof(S_REC_HEADER) + REC_INFO_BUFFER_SIZE;
6521 
6522  if (STB_DSKSeekFile(dbfile, FILE_POSITION_START, offset))
6523  {
6524  /* Read each extended info item until the required one is found or there's no more */
6525  while (STB_DSKReadFile(dbfile, (U8BIT *)&id, sizeof(id)) == sizeof(id))
6526  {
6527  if (STB_DSKReadFile(dbfile, (U8BIT *)&size, sizeof(size)) == sizeof(size))
6528  {
6529  if (id == ext_id)
6530  {
6531  retval = size;
6532  break;
6533  }
6534  else
6535  {
6536  /* Seek to the start of the next info id */
6537  STB_DSKSeekFile(dbfile, FILE_POSITION_CURRENT, size);
6538  }
6539  }
6540  }
6541  }
6542 
6543  STB_DSKCloseFile(dbfile);
6544  }
6545 
6546  FUNCTION_FINISH(GetExtendedInfoSize);
6547 
6548  return(retval);
6549 }
6550 
6551 /*!**************************************************************************
6552  * @brief Inserts a recording into the recording list based on its date & time
6553  * @param rec_ptr - recording to be inserted
6554  ****************************************************************************/
6555 static void InsertRecordingInList(S_RECORDING *rec_ptr)
6556 {
6557  S_RECORDING *prev;
6558  S_RECORDING *list_ptr;
6559  BOOLEAN found;
6560 
6561  FUNCTION_START(InsertRecordingInList);
6562 
6563  prev = NULL;
6564  found = FALSE;
6565 
6566  for (list_ptr = rec_list; (list_ptr != NULL) && !found; )
6567  {
6568  if (STB_GCCompareDateTime(list_ptr->rec_info.rec_date, list_ptr->rec_info.rec_hour,
6569  list_ptr->rec_info.rec_min, list_ptr->rec_info.rec_sec,
6570  rec_ptr->rec_info.rec_date, rec_ptr->rec_info.rec_hour,
6571  rec_ptr->rec_info.rec_min, rec_ptr->rec_info.rec_sec, COMP_1GT2))
6572  {
6573  prev = list_ptr;
6574  list_ptr = list_ptr->next;
6575  }
6576  else
6577  {
6578  found = TRUE;
6579  }
6580  }
6581 
6582  if (prev == NULL)
6583  {
6584  if (rec_list != NULL)
6585  {
6586  rec_list->prev = rec_ptr;
6587  }
6588 
6589  rec_ptr->prev = NULL;
6590  rec_ptr->next = rec_list;
6591  rec_list = rec_ptr;
6592  }
6593  else
6594  {
6595  rec_ptr->prev = prev;
6596  rec_ptr->next = list_ptr;
6597  prev->next = rec_ptr;
6598 
6599  if (list_ptr != NULL)
6600  {
6601  list_ptr->prev = rec_ptr;
6602  }
6603  }
6604 
6605  FUNCTION_FINISH(InsertRecordingInList);
6606 }
6607 
6608 /*!**************************************************************************
6609  * @brief Unlinks a recording fro the list and frees all its memory
6610  * @param rec_ptr - recording to be removed
6611  ****************************************************************************/
6612 static void RemoveRecordingFromList(S_RECORDING *rec_ptr)
6613 {
6614  FUNCTION_START(RemoveRecordingFromList);
6615 
6616  if (rec_list == rec_ptr)
6617  {
6618  rec_list = rec_ptr->next;
6619  }
6620 
6621  if (rec_ptr->prev != NULL)
6622  {
6623  rec_ptr->prev->next = rec_ptr->next;
6624  }
6625 
6626  if (rec_ptr->next != NULL)
6627  {
6628  rec_ptr->next->prev = rec_ptr->prev;
6629  }
6630 
6631  STB_FreeMemory(rec_ptr);
6632 
6633  FUNCTION_FINISH(RemoveRecordingFromList);
6634 }
6635 
6636 /*!**************************************************************************
6637  * @brief Searches the given pid array for any video type pids
6638  * @param pid_array - PID array to be searched
6639  * @param num_pids - number of PIDs in the given array
6640  * @return TRUE if a video PID is found, FALSE otherwise
6641  ****************************************************************************/
6642 static BOOLEAN IncludesVideoPid(S_PVR_PID_INFO *pid_array, U16BIT num_pids)
6643 {
6644  BOOLEAN found;
6645  U16BIT i;
6646 
6647  FUNCTION_START(IncludesVideoPid);
6648 
6649  found = FALSE;
6650 
6651  for (i = 0; (i < num_pids) && !found; i++)
6652  {
6653  if (pid_array[i].type == PVR_PID_TYPE_VIDEO)
6654  {
6655  found = TRUE;
6656  }
6657  }
6658 
6659  FUNCTION_FINISH(IncludesVideoPid);
6660 
6661  return(found);
6662 }
6663 
6664 #ifdef COMMON_INTERFACE
6665 /*!**************************************************************************
6666  * @brief Frees the list of CI+ items for a recording
6667  * @param rec_ptr - recording
6668  ****************************************************************************/
6669 static void FreeCIPlusItemList(U8BIT path)
6670 {
6671  S_REC_CIPLUS_ITEM *item;
6672  S_REC_CIPLUS_ITEM *next_item;
6673 
6674  FUNCTION_START(FreeCIPlusItemList);
6675 
6676  for (item = play_status[path].item_list; item != NULL; item = next_item)
6677  {
6678  next_item = item->next;
6679 
6680  FreeCIPlusItem(item);
6681  }
6682 
6683  play_status[path].item_list = NULL;
6684  play_status[path].uri_item = NULL;
6685  play_status[path].licence_item = NULL;
6686  play_status[path].pin_item = NULL;
6687 
6688  FUNCTION_FINISH(FreeCIPlusItemList);
6689 }
6690 
6691 /*!**************************************************************************
6692  * @brief Frees the list of CI+ items for a recording
6693  * @param item - item to be freed
6694  ****************************************************************************/
6695 static void FreeCIPlusItem(S_REC_CIPLUS_ITEM *item)
6696 {
6697  FUNCTION_START(FreeCIPlusItem);
6698 
6699  if (item->item_type == EXT_INFO_CIPLUS_LICENCE)
6700  {
6701  if (item->u.licence.data != NULL)
6702  {
6703  STB_FreeMemory(item->u.licence.data);
6704  }
6705  }
6706 
6707  STB_FreeMemory(item);
6708 
6709  FUNCTION_FINISH(FreeCIPlusItem);
6710 }
6711 
6712 /*!**************************************************************************
6713  * @brief Reads the CI+ related extedned info from an odb file and creates
6714  * a list in memory for a given recording
6715  * @param path - decode path
6716  * @param rec_ptr - recording
6717  ****************************************************************************/
6718 static void ReadCIPlusItems(U8BIT path, S_RECORDING *rec_ptr)
6719 {
6720  U8BIT db_filename[DB_FILENAME_LEN];
6721  void *dbfile;
6722  S32BIT offset;
6723  U16BIT id;
6724  U32BIT size;
6725  S_REC_CIPLUS_ITEM *item;
6726  S_REC_CIPLUS_ITEM *prev_item;
6727 
6728  FUNCTION_START(ReadCIPlusItems);
6729 
6730  /* Free any existing items */
6731  FreeCIPlusItemList(path);
6732 
6733  strcpy((char *)db_filename, (char *)rec_ptr->basename);
6734  strcat((char *)db_filename, DB_FILE_EXTENSION);
6735 
6736  dbfile = STB_DSKOpenFile(rec_ptr->disk_id, db_filename, FILE_MODE_READ);
6737  if (dbfile != NULL)
6738  {
6739  /* Move to the start of the extended info */
6740  offset = sizeof(S_REC_HEADER) + REC_INFO_BUFFER_SIZE;
6741 
6742  if (STB_DSKSeekFile(dbfile, FILE_POSITION_START, offset))
6743  {
6744  prev_item = NULL;
6745 
6746  /* Check each extended info item to find the ones related to CI+ */
6747  while (STB_DSKReadFile(dbfile, (U8BIT *)&id, sizeof(id)) == sizeof(id))
6748  {
6749  item = NULL;
6750 
6751  if (STB_DSKReadFile(dbfile, (U8BIT *)&size, sizeof(size)) == sizeof(size))
6752  {
6753  if (id == EXT_INFO_CIPLUS_URI)
6754  {
6755  /* Create a new item for the URI */
6756  if ((item = (S_REC_CIPLUS_ITEM *)STB_GetMemory(sizeof(S_REC_CIPLUS_ITEM))) != NULL)
6757  {
6758  memset(item, 0, sizeof(S_REC_CIPLUS_ITEM));
6759 
6760  item->item_type = id;
6761 
6762  STB_DSKReadFile(dbfile, (U8BIT *)&item->timestamp, sizeof(U32BIT));
6763  STB_DSKReadFile(dbfile, item->u.uri, CIP_URI_LEN);
6764  }
6765  }
6766  else if (id == EXT_INFO_CIPLUS_LICENCE)
6767  {
6768  /* Create a new item for the licence */
6769  if ((item = (S_REC_CIPLUS_ITEM *)STB_GetMemory(sizeof(S_REC_CIPLUS_ITEM))) != NULL)
6770  {
6771  memset(item, 0, sizeof(S_REC_CIPLUS_ITEM));
6772 
6773  item->item_type = id;
6774  item->u.licence.used = FALSE;
6775 
6776  STB_DSKReadFile(dbfile, (U8BIT *)&item->timestamp, sizeof(U32BIT));
6777 
6778  /* Length of the licence is all the data excluing the timestamp */
6779  item->u.licence.length = size - sizeof(U32BIT);
6780 
6781  if ((item->u.licence.data = STB_GetMemory(item->u.licence.length)) != NULL)
6782  {
6783  STB_DSKReadFile(dbfile, item->u.licence.data, item->u.licence.length);
6784  }
6785  }
6786  }
6787  else if (id == EXT_INFO_CIPLUS_PIN)
6788  {
6789  /* Create a new item for the pin event */
6790  if ((item = (S_REC_CIPLUS_ITEM *)STB_GetMemory(sizeof(S_REC_CIPLUS_ITEM))) != NULL)
6791  {
6792  memset(item, 0, sizeof(S_REC_CIPLUS_ITEM));
6793 
6794  item->item_type = id;
6795 
6796  STB_DSKReadFile(dbfile, (U8BIT *)&item->timestamp, sizeof(U32BIT));
6797  STB_DSKReadFile(dbfile, (U8BIT *)&item->u.pin, sizeof(item->u.pin));
6798  }
6799  }
6800  else
6801  {
6802  /* Seek to the start of the next info id */
6803  STB_DSKSeekFile(dbfile, FILE_POSITION_CURRENT, size);
6804  }
6805 
6806  if (item != NULL)
6807  {
6808  /* Add the item to the recording's item list */
6809  item->prev = prev_item;
6810 
6811  if (prev_item == NULL)
6812  {
6813  play_status[path].item_list = item;
6814  }
6815  else
6816  {
6817  prev_item->next = item;
6818  }
6819 
6820  prev_item = item;
6821  }
6822  }
6823  }
6824  }
6825 
6826  STB_DSKCloseFile(dbfile);
6827  }
6828 
6829  FUNCTION_FINISH(ReadCIPlusItems);
6830 }
6831 
6832 /*!**************************************************************************
6833  * @brief Checks the CI+ items for a recording and applies any that should be used
6834  * at the given position. It's assumed that items are held in timestamp order,
6835  * such that current timestamp <= next timestamp.
6836  * @param path - decode path
6837  * @param rec_ptr - recording
6838  * @param position_in_seconds - position in the recording
6839  * @param speed - playback speed, only used to determine direction of playback
6840  ****************************************************************************/
6841 static void ApplyCIPlusItems(U8BIT path, S_RECORDING *rec_ptr, U32BIT position_in_seconds,
6842  S16BIT speed)
6843 {
6844  S_REC_CIPLUS_ITEM *item;
6845  S_REC_CIPLUS_ITEM *found_item;
6846  U32BIT retention_limit;
6847  U8BIT uri[CIP_URI_LEN];
6848 
6849  FUNCTION_START(ApplyCIPlusItems);
6850 
6851  /* Find the URI that should be applied for the given position in the recording */
6852  found_item = NULL;
6853 
6854  if (((item = play_status[path].uri_item) == NULL) || (speed >= 0))
6855  {
6856  if (item == NULL)
6857  {
6858  /* No current URI, so work forwards through the item list to find the URI that
6859  * precedes the position and so should be applied. This will be true irrespective
6860  * of the direction of playback at the start */
6861  item = play_status[path].item_list;
6862  }
6863 
6864  for (; item != NULL; item = item->next)
6865  {
6866  if (item->timestamp <= position_in_seconds)
6867  {
6868  if (item->item_type == EXT_INFO_CIPLUS_URI)
6869  {
6870  if ((found_item == NULL) || (item->timestamp > found_item->timestamp))
6871  {
6872  found_item = item;
6873  }
6874  }
6875  }
6876  else
6877  {
6878  /* All items from now on will occur later in the recording so can be ignored */
6879  break;
6880  }
6881  }
6882  }
6883  else
6884  {
6885  /* Backwards */
6886  for (item = item->prev; item != NULL; item = item->prev)
6887  {
6888  if (item->item_type == EXT_INFO_CIPLUS_URI)
6889  {
6890  /* Found the previous URI */
6891  found_item = item;
6892  break;
6893  }
6894  }
6895  }
6896 
6897  /* Check if there's a URI item and if it's changed */
6898  if (found_item == NULL)
6899  {
6900  DBG_CIP(": No URI found, so applying default URI for playback")
6901 
6902  /* No URI, so need to apply the default URI */
6904 
6905  /* Set retention limit for playback */
6906  retention_limit = STB_CiCcGetRetentionLimit(uri);
6907 
6909  retention_limit, rec_ptr->rec_info.rec_date, rec_ptr->rec_info.rec_hour,
6910  rec_ptr->rec_info.rec_min);
6911 
6912  /* Apply the URI */
6914  }
6915  else if ((found_item != NULL) && (found_item != play_status[path].uri_item))
6916  {
6917  DBG_CIP(": Applying URI at %lu seconds for playback", found_item->timestamp)
6918 
6919  /* Save the URI item so it can be updated during playback */
6920  play_status[path].uri_item = found_item;
6921 
6922  /* Set retention limit for playback */
6923  retention_limit = STB_CiCcGetRetentionLimit(found_item->u.uri);
6925  retention_limit, rec_ptr->rec_info.rec_date, rec_ptr->rec_info.rec_hour,
6926  rec_ptr->rec_info.rec_min);
6927 
6928  /* Apply the URI */
6929  STB_CiCcApplyUsageRulesInfoForPlayback(found_item->u.uri);
6930  }
6931 
6932  /* Is there a licence that should be sent to the CAM for this position in the recording? */
6933  found_item = NULL;
6934 
6935  if (((item = play_status[path].licence_item) == NULL) || (speed >= 0))
6936  {
6937  if (item == NULL)
6938  {
6939  /* No current licence, so work forwards through the item list to find the licence that
6940  * precedes the position and so should be applied. This will be true irrespective
6941  * of the direction of playback at the start */
6942  item = play_status[path].item_list;
6943  }
6944 
6945  for (; item != NULL; item = item->next)
6946  {
6947  if (item->timestamp <= position_in_seconds)
6948  {
6949  if (item->item_type == EXT_INFO_CIPLUS_LICENCE)
6950  {
6951  if (!item->u.licence.used)
6952  {
6953  if ((found_item == NULL) || (item->timestamp > found_item->timestamp))
6954  {
6955  found_item = item;
6956  }
6957  }
6958  }
6959  else if ((found_item != NULL) && (item->item_type == EXT_INFO_CIPLUS_URI))
6960  {
6961  /* A licence is valid upto the next URI or licence - see 5.12 of CI+ 1.3.1 spec */
6962  if (item->timestamp > found_item->timestamp)
6963  {
6964  /* This URI cancels the licence */
6965  found_item = NULL;
6966  }
6967  }
6968  }
6969  else
6970  {
6971  /* All items from now on will occur later in the recording so can be ignored */
6972  break;
6973  }
6974  }
6975  }
6976  else
6977  {
6978  /* Backwards */
6979  for (item = item->prev; item != NULL; item = item->prev)
6980  {
6981  if ((item->item_type == EXT_INFO_CIPLUS_LICENCE) && !item->u.licence.used)
6982  {
6983  /* Found the previous licence */
6984  found_item = item;
6985  break;
6986  }
6987  }
6988  }
6989 
6990  /* Check if there's a licence item and if it's changed */
6991  if ((found_item != NULL) && (found_item != play_status[path].licence_item))
6992  {
6993  DBG_CIP(": Sending licence at %lu seconds to CAM in slot %u",
6994  found_item->timestamp, play_status[path].slot_id)
6995 
6996  /* Save the licence item so it can be updated during playback */
6997  play_status[path].licence_item = found_item;
6998 
6999  /* Send the licence to the CAM so it can be updated */
7000  if (STB_CiCcSendPlaybackLicence(play_status[path].slot_id, rec_ptr->rec_info.serv_id,
7001  found_item->u.licence.data, found_item->u.licence.length))
7002  {
7003  /* Licences should only be sent to the CAM once during playback, so mark as used */
7004  found_item->u.licence.used = TRUE;
7005  }
7006  else
7007  {
7008  play_status[path].licence_item = NULL;
7009  DBG_CIP(": Failed to send CI+ licence for recording 0x%08lx to slot %u", rec_ptr->handle, play_status[path].slot_id)
7010  }
7011  }
7012 
7013  /* Find the pin that should be applied for the given position in the recording */
7014  found_item = NULL;
7015 
7016  if (((item = play_status[path].pin_item) == NULL) || (speed >= 0))
7017  {
7018  if (item == NULL)
7019  {
7020  /* No current pin, so work forwards through the item list to find the pin that
7021  * precedes the position and so should be applied. This will be true irrespective
7022  * of the direction of playback at the start */
7023  item = play_status[path].item_list;
7024  }
7025 
7026  for (; item != NULL; item = item->next)
7027  {
7028  if (item->timestamp <= position_in_seconds)
7029  {
7030  if (item->item_type == EXT_INFO_CIPLUS_PIN)
7031  {
7032  if ((found_item == NULL) || (item->timestamp > found_item->timestamp))
7033  {
7034  found_item = item;
7035  }
7036  }
7037  }
7038  else
7039  {
7040  /* All items from now on will occur later in the recording so can be ignored */
7041  break;
7042  }
7043  }
7044  }
7045  else
7046  {
7047  /* Backwards */
7048  for (item = item->prev; item != NULL; item = item->prev)
7049  {
7050  if (item->item_type == EXT_INFO_CIPLUS_PIN)
7051  {
7052  /* Found the previous URI */
7053  found_item = item;
7054  break;
7055  }
7056  }
7057  }
7058 
7059  /* Check if there's a pin item and if it's changed */
7060  if ((found_item != NULL) && (found_item != play_status[path].pin_item))
7061  {
7062  DBG_CIP(": Applying PIN at %lu seconds for playback", found_item->timestamp)
7063 
7064  /* Save the pin item so it can be updated during playback */
7065  play_status[path].pin_item = found_item;
7066 
7067  /* Send an event to blank the video and pass the pin event to the CAM.
7068  * The video will be unblanked when a reply is received for the pin */
7069  STB_ERSendEvent(FALSE, FALSE, EV_CLASS_CI, EV_TYPE_CI_PLAYBACK_BLANK_VIDEO, NULL, 0);
7070  STB_CiCcSendPinPlayback(play_status[path].slot_id, found_item->u.pin.age_rating,
7071  found_item->u.pin.private_data);
7072  }
7073 
7074  FUNCTION_FINISH(ApplyCIPlusItems);
7075 }
7076 
7077 /*!**************************************************************************
7078  * @brief Finds the CI+ item after the given position in seconds that needs to be applied
7079  * during the playback. This time is passed to the platform so that it can provide a
7080  * notification when this position is reached and the item can be applied.
7081  * @param path - decode path
7082  * @param speed - playback speed, only used to determine direction of playback
7083  ****************************************************************************/
7084 static void FindNextCIPlusItem(U8BIT path, S16BIT speed)
7085 {
7086  S_REC_CIPLUS_ITEM *item;
7087  S_REC_CIPLUS_ITEM *next_item;
7088  U8BIT audio_decoder, video_decoder;
7089 
7090  FUNCTION_START(FindNextCIPlusItem);
7091 
7092  next_item = NULL;
7093 
7094  /* Find the next URI, licence and pin items to be applied */
7095  for (item = play_status[path].item_list; item != NULL; item = item->next)
7096  {
7097  if (item->item_type == EXT_INFO_CIPLUS_URI)
7098  {
7099  /* Check whether this is the next URI item */
7100  if (speed >= 0)
7101  {
7102  /* Play forwards */
7103  if (((play_status[path].uri_item == NULL) || (item->timestamp > play_status[path].uri_item->timestamp)) &&
7104  ((next_item == NULL) || (item->timestamp < next_item->timestamp)))
7105  {
7106  next_item = item;
7107  }
7108  }
7109  else
7110  {
7111  /* Play backwards */
7112  if (((play_status[path].uri_item == NULL) || (item->timestamp < play_status[path].uri_item->timestamp)) &&
7113  ((next_item == NULL) || (item->timestamp > next_item->timestamp)))
7114  {
7115  next_item = item;
7116  }
7117  }
7118  }
7119 
7120  if ((item->item_type == EXT_INFO_CIPLUS_LICENCE) && !item->u.licence.used)
7121  {
7122  /* Check whether this is the next licence item */
7123  if (speed >= 0)
7124  {
7125  /* Play forwards */
7126  if (((play_status[path].licence_item == NULL) || (item->timestamp > play_status[path].licence_item->timestamp)) &&
7127  ((next_item == NULL) || (item->timestamp < next_item->timestamp)))
7128  {
7129  next_item = item;
7130  }
7131  }
7132  else
7133  {
7134  /* Play backwards */
7135  if (((play_status[path].licence_item == NULL) || (item->timestamp < play_status[path].licence_item->timestamp)) &&
7136  ((next_item == NULL) || (item->timestamp > next_item->timestamp)))
7137  {
7138  next_item = item;
7139  }
7140  }
7141  }
7142 
7143  if (item->item_type == EXT_INFO_CIPLUS_PIN)
7144  {
7145  /* Check whether this is the next pin item */
7146  if (speed >= 0)
7147  {
7148  /* Play forwards */
7149  if (((play_status[path].pin_item == NULL) || (item->timestamp > play_status[path].pin_item->timestamp)) &&
7150  ((next_item == NULL) || (item->timestamp < next_item->timestamp)))
7151  {
7152  next_item = item;
7153  }
7154  }
7155  else
7156  {
7157  /* Play backwards */
7158  if (((play_status[path].pin_item == NULL) || (item->timestamp < play_status[path].pin_item->timestamp)) &&
7159  ((next_item == NULL) || (item->timestamp > next_item->timestamp)))
7160  {
7161  next_item = item;
7162  }
7163  }
7164  }
7165  }
7166 
7167  if (next_item != NULL)
7168  {
7169  DBG_CIP(": Next item is a change of %s @ %lu seconds",
7170  ((next_item->item_type == EXT_INFO_CIPLUS_URI) ? "URI" :
7171  (next_item->item_type == EXT_INFO_CIPLUS_LICENCE) ? "LICENCE" : "PIN"), next_item->timestamp)
7172 
7173  /* Set the time the next item needs to be applied */
7174  audio_decoder = STB_DPGetPathAudioDecoder(path);
7175  video_decoder = STB_DPGetPathVideoDecoder(path);
7176  STB_PVRSetPlaybackNotifyTime(audio_decoder, video_decoder, next_item->timestamp);
7177  }
7178 
7179  FUNCTION_FINISH(FindNextCIPlusItem);
7180 }
7181 
7182 /*!**************************************************************************
7183  * @brief Writes the CI+ info as an extended info item to the end of the ODB file
7184  * @param disk_id - ID of disk containing the file
7185  * @param basename - base name of the ODB file
7186  * @param ext_id - ID of the extended info
7187  * @param timestamp - timestamp to be written as part of the data
7188  * @param data_len - number of bytes of data to be written
7189  * @param data - extended info data
7190  * @return TRUE if the data is written successfully, FALSE otherwise
7191  ****************************************************************************/
7192 static BOOLEAN WriteCIPlusInfo(U16BIT disk_id, U8BIT *basename, U16BIT ext_id, U32BIT timestamp,
7193  U32BIT data_len, U8BIT *data)
7194 {
7195  U8BIT db_filename[DB_FILENAME_LEN];
7196  void *dbfile;
7197  S32BIT offset;
7198  U16BIT id;
7199  U32BIT size;
7200  BOOLEAN retval;
7201 
7202  FUNCTION_START(WriteCIPlusInfo);
7203 
7204  retval = FALSE;
7205 
7206  strcpy((char *)db_filename, (char *)basename);
7207  strcat((char *)db_filename, DB_FILE_EXTENSION);
7208 
7209  dbfile = STB_DSKOpenFile(disk_id, db_filename, FILE_MODE_WRITE);
7210  if (dbfile != NULL)
7211  {
7212  /* Move to the start of the extended info */
7213  offset = sizeof(S_REC_HEADER) + REC_INFO_BUFFER_SIZE;
7214 
7215  if (STB_DSKSeekFile(dbfile, FILE_POSITION_START, offset))
7216  {
7217  /* Move to the end of the last written item */
7218  while (STB_DSKReadFile(dbfile, (U8BIT *)&id, sizeof(id)) == sizeof(id))
7219  {
7220  if (STB_DSKReadFile(dbfile, (U8BIT *)&size, sizeof(size)) == sizeof(size))
7221  {
7222  /* Seek to the start of the next info id */
7223  STB_DSKSeekFile(dbfile, FILE_POSITION_CURRENT, size);
7224  }
7225  }
7226 
7227  /* Write the ext id first */
7228  if (STB_DSKWriteFile(dbfile, (U8BIT *)&ext_id, sizeof(ext_id)) == sizeof(ext_id))
7229  {
7230  /* Now write the size of the extended item */
7231  size = data_len + sizeof(timestamp);
7232 
7233  if (STB_DSKWriteFile(dbfile, (U8BIT *)&size, sizeof(size)) == sizeof(size))
7234  {
7235  /* Write the timestamp for the item */
7236  if (STB_DSKWriteFile(dbfile, (U8BIT *)&timestamp, sizeof(timestamp)) == sizeof(timestamp))
7237  {
7238  /* Now write the actual data */
7239  if (STB_DSKWriteFile(dbfile, data, data_len) == data_len)
7240  {
7241  retval = TRUE;
7242  }
7243  }
7244  }
7245  }
7246  }
7247 
7248  STB_DSKCloseFile(dbfile);
7249  }
7250 
7251  FUNCTION_FINISH(WriteCIPlusInfo);
7252 
7253  return(retval);
7254 }
7255 
7256 /*!**************************************************************************
7257  * @brief Updates and existing CI+ extended info item in place in the ODB file
7258  * @param disk_id - ID of disk containing the file
7259  * @param basename - base name of the ODB file
7260  * @param ext_id - ID of the extended info
7261  * @param timestamp - timestamp of the item to be updated
7262  * @param data_len - number of bytes of data to be written
7263  * @param data - extended info data
7264  * @return TRUE if the data is written successfully, FALSE otherwise
7265  ****************************************************************************/
7266 static BOOLEAN UpdateCIPlusInfo(U16BIT disk_id, U8BIT *basename, U16BIT ext_id, U32BIT timestamp,
7267  U32BIT data_len, U8BIT *data)
7268 {
7269  U8BIT db_filename[DB_FILENAME_LEN];
7270  void *dbfile;
7271  S32BIT offset;
7272  U16BIT id;
7273  U32BIT size;
7274  U32BIT file_time;
7275  BOOLEAN retval;
7276 
7277  FUNCTION_START(UpdateCIPlusInfo);
7278 
7279  retval = FALSE;
7280 
7281  strcpy((char *)db_filename, (char *)basename);
7282  strcat((char *)db_filename, DB_FILE_EXTENSION);
7283 
7284  dbfile = STB_DSKOpenFile(disk_id, db_filename, FILE_MODE_WRITE);
7285  if (dbfile != NULL)
7286  {
7287  /* Move to the start of the extended info */
7288  offset = sizeof(S_REC_HEADER) + REC_INFO_BUFFER_SIZE;
7289 
7290  if (STB_DSKSeekFile(dbfile, FILE_POSITION_START, offset))
7291  {
7292  /* Find the extended info item to be updated */
7293  while (STB_DSKReadFile(dbfile, (U8BIT *)&id, sizeof(id)) == sizeof(id))
7294  {
7295  if (STB_DSKReadFile(dbfile, (U8BIT *)&size, sizeof(size)) == sizeof(size))
7296  {
7297  if (id == ext_id)
7298  {
7299  if (STB_DSKReadFile(dbfile, (U8BIT *)&file_time, sizeof(file_time)) == sizeof(file_time))
7300  {
7301  if (file_time == timestamp)
7302  {
7303  /* Found the item to be updated */
7304  if (size == (data_len + sizeof(timestamp)))
7305  {
7306  /* The data size hasn't changed so can be updated */
7307  if (STB_DSKWriteFile(dbfile, data, data_len) == data_len)
7308  {
7309  retval = TRUE;
7310  break;
7311  }
7312  }
7313  }
7314  else
7315  {
7316  /* Seek to the start of the next info id - timestamp has already been read */
7317  STB_DSKSeekFile(dbfile, FILE_POSITION_CURRENT, size - sizeof(timestamp));
7318  }
7319  }
7320  }
7321  else
7322  {
7323  /* Seek to the start of the next info id */
7324  STB_DSKSeekFile(dbfile, FILE_POSITION_CURRENT, size);
7325  }
7326  }
7327  }
7328  }
7329 
7330  STB_DSKCloseFile(dbfile);
7331  }
7332 
7333  FUNCTION_FINISH(UpdateCIPlusInfo);
7334 
7335  return(retval);
7336 }
7337 
7338 #endif /* COMMON_INTERFACE */
7339 
7347 static void GetBookmarkFolderName(U8BIT *basename, U8BIT *bookmark_folder_name)
7348 {
7349  FUNCTION_START(GetBookmarkFolderName);
7350 
7351  sprintf((char *)bookmark_folder_name, "bm%s", (char *)basename);
7352 
7353  FUNCTION_FINISH(GetBookmarkFolderName);
7354 }
7355 
7366 static void GetBookmarkFileName(U32BIT time, E_BOOKMARK_TYPE type, U8BIT *name)
7367 {
7368  char tail;
7369 
7370  FUNCTION_START(GetBookmarkFileName);
7371 
7372  switch (type)
7373  {
7374  case BOOKMARK_PLAYBACK_POSITION:
7375  {
7376  tail = 'p';
7377  break;
7378  }
7379 
7380  case BOOKMARK_USER:
7381  default:
7382  {
7383  tail = 'u';
7384  break;
7385  }
7386  }
7387 
7388  sprintf((char *)name, "%08x%c", (unsigned int)time, tail);
7389 
7390  FUNCTION_FINISH(GetBookmarkFileName);
7391 }
7392 
7398 static E_BOOKMARK_TYPE GetBookmarkType(U8BIT *file_name)
7399 {
7400  E_BOOKMARK_TYPE type;
7401 
7402  FUNCTION_START(GetBookmarkType);
7403 
7404  switch (file_name[BOOKMARK_FILENAME_SIZE - 2])
7405  {
7406  case 'p':
7407  {
7408  type = BOOKMARK_PLAYBACK_POSITION;
7409  break;
7410  }
7411 
7412  case 'u':
7413  default:
7414  {
7415  type = BOOKMARK_USER;
7416  break;
7417  }
7418  }
7419 
7420  FUNCTION_FINISH(GetBookmarkType);
7421 
7422  return type;
7423 }
7424 
7430 static U32BIT GetBookmarkTime(U8BIT *file_name)
7431 {
7432  U32BIT time;
7433 
7434  FUNCTION_START(GetBookmarkTime);
7435 
7436  sscanf((char *)file_name, "%08x%*c", (unsigned int *)&time);
7437 
7438  FUNCTION_FINISH(GetBookmarkTime);
7439 
7440  return time;
7441 }
7442 
7456 static BOOLEAN AddBookmark(U16BIT disk_id, U8BIT *basename, U32BIT time, U8BIT *name, E_BOOKMARK_TYPE type)
7457 {
7458  BOOLEAN success = TRUE, check_folder = TRUE;
7459  void *dir;
7460  U8BIT folder_name[STB_PVR_BASENAME_LEN + 2];
7461  U8BIT file_name[BOOKMARK_FILENAME_SIZE];
7462  U8BIT file_str[STB_PVR_BASENAME_LEN + 2 + BOOKMARK_FILENAME_SIZE];
7463  U8BIT default_name[9];
7464  void *file;
7465  U32BIT size;
7466 
7467  FUNCTION_START(AddBookmark);
7468 
7469  GetBookmarkFolderName(basename, folder_name);
7470  GetBookmarkFileName(time, type, file_name);
7471  sprintf((char *)file_str, "%s/%.*s", (char *)folder_name, BOOKMARK_FILENAME_SIZE - 1,
7472  (char *)file_name);
7473 
7474  if (STB_DSKFileExists(disk_id, file_str))
7475  {
7476  check_folder = FALSE; /* If file exists, folder exists, no need to check */
7477  if (type == BOOKMARK_USER)
7478  {
7479  /* User bookmarks will not be overwritten */
7480  STB_PVR_PRINT(("AddBookmark: bookmark %s already exists", file_str));
7481  success = FALSE;
7482  }
7483  }
7484 
7485  if (check_folder)
7486  {
7487  /* Create the bookmark folder if it does not exist */
7488  dir = STB_DSKOpenDirectory(disk_id, folder_name);
7489  if (dir == NULL)
7490  {
7491  STB_PVR_PRINT(("AddBookmark: creating folder %s", folder_name));
7492  if (!STB_DSKCreateDirectory(disk_id, folder_name))
7493  {
7494  STB_PVR_PRINT(("AddBookmark: failed creating folder %s", folder_name));
7495  success = FALSE;
7496  }
7497  }
7498  else
7499  {
7500  STB_DSKCloseDirectory(dir);
7501  }
7502  }
7503 
7504  if (success)
7505  {
7506  STB_PVR_PRINT(("AddBookmark: creating bookmark %s", file_str));
7507  file = STB_DSKOpenFile(disk_id, file_str, FILE_MODE_OVERWRITE);
7508  if (file != NULL)
7509  {
7510  if (name == NULL)
7511  {
7512  U8BIT h, m, s;
7513 
7514  m = time / 60;
7515  s = time % 60;
7516  h = m / 60;
7517  m = m % 60;
7518 
7519  sprintf((char *)default_name, "%02d:%02d:%02d", h, m, s);
7520  name = default_name;
7521  size = 8;
7522  }
7523  else
7524  {
7525  size = strlen((char *)name);
7526  if (size > STB_PVR_NAME_LEN - 1)
7527  {
7528  STB_PVR_PRINT(("AddBookmark: name is too long, limiting it to %d characters", STB_PVR_NAME_LEN));
7529  size = STB_PVR_NAME_LEN - 1;
7530  }
7531  }
7532 
7533  if (STB_DSKWriteFile(file, name, size) != size)
7534  {
7535  success = FALSE;
7536  }
7537 
7538  STB_DSKCloseFile(file);
7539 
7540  if (!success)
7541  {
7542  STB_PVR_PRINT(("AddBookmark: failed writing bookmark %s", file_str));
7543  STB_DSKDeleteFile(disk_id, file_str);
7544  }
7545  }
7546 #ifdef STB_DEBUG
7547  else
7548  {
7549  STB_PVR_PRINT(("AddBookmark: could not create file %s", file_str));
7550  }
7551 #endif
7552  }
7553 
7554  FUNCTION_FINISH(AddBookmark);
7555 
7556  return success;
7557 }
7558 
7569 static void RemoveBookmark(U16BIT disk_id, U8BIT *basename, U32BIT time, U8BIT *name, E_BOOKMARK_TYPE type)
7570 {
7571  U8BIT folder_name[STB_PVR_BASENAME_LEN + 2];
7572  U8BIT file_name[BOOKMARK_FILENAME_SIZE];
7573  U8BIT file_str[STB_PVR_BASENAME_LEN + 2 + BOOKMARK_FILENAME_SIZE];
7574 
7575  FUNCTION_START(RemoveBookmark);
7576  USE_UNWANTED_PARAM(name);
7577 
7578  GetBookmarkFolderName(basename, folder_name);
7579  GetBookmarkFileName(time, type, file_name);
7580  sprintf((char *)file_str, "%s/%.*s", (char *)folder_name, BOOKMARK_FILENAME_SIZE - 1,
7581  (char *)file_name);
7582 
7583  STB_PVR_PRINT(("Deleting bookmark %s", file_str));
7584  STB_DSKDeleteFile(disk_id, file_str);
7585 
7586  FUNCTION_FINISH(RemoveBookmark);
7587 }
7588 
7595 static void RemoveAllBookmarks(U16BIT disk_id, U8BIT *basename)
7596 {
7597  CREATE_LINK_LIST_HEADER(bookmarks);
7598  S_BOOKMARK *b_ptr;
7599  U8BIT folder_name[STB_PVR_BASENAME_LEN + 2];
7600 
7601  FUNCTION_START(RemoveAllBookmarks);
7602 
7603  if (GetBookmarks(disk_id, basename, &bookmarks, BOOKMARK_USER, FALSE) != 0)
7604  {
7605  b_ptr = (S_BOOKMARK *)STB_LLGetFirstBlock(&bookmarks);
7606  while (b_ptr != NULL)
7607  {
7608  RemoveBookmark(disk_id, basename, b_ptr->time, NULL, BOOKMARK_USER);
7609  b_ptr = (S_BOOKMARK*)STB_LLGetNextBlock((LINK_LIST_PTR_BLK *)b_ptr);
7610  }
7611 
7612  EmptyBookmarks(&bookmarks, TRUE);
7613  }
7614 
7615  if (GetBookmarks(disk_id, basename, &bookmarks, BOOKMARK_PLAYBACK_POSITION, FALSE) != 0)
7616  {
7617  b_ptr = (S_BOOKMARK *)STB_LLGetFirstBlock(&bookmarks);
7618  while (b_ptr != NULL)
7619  {
7620  RemoveBookmark(disk_id, basename, b_ptr->time, NULL, BOOKMARK_PLAYBACK_POSITION);
7621  b_ptr = (S_BOOKMARK*)STB_LLGetNextBlock((LINK_LIST_PTR_BLK *)b_ptr);
7622  }
7623 
7624  EmptyBookmarks(&bookmarks, TRUE);
7625  }
7626 
7627  GetBookmarkFolderName(basename, folder_name);
7628  STB_DSKDeleteDirectory(disk_id, folder_name);
7629 
7630  FUNCTION_FINISH(RemoveAllBookmarks);
7631 }
7632 
7645 static U32BIT GetBookmarks(U16BIT disk_id, U8BIT *basename, LINK_LIST_HEADER *bookmarks,
7646  E_BOOKMARK_TYPE type, BOOLEAN names)
7647 {
7648  U32BIT num;
7649  void *dir;
7650  U8BIT folder_name[STB_PVR_BASENAME_LEN + 2];
7651  U8BIT file_name[BOOKMARK_FILENAME_SIZE];
7652  U8BIT file_str[STB_PVR_BASENAME_LEN + 2 + BOOKMARK_FILENAME_SIZE];
7653  void *file;
7654  U32BIT read_bytes, offset;
7655  S_BOOKMARK *b;
7656  E_STB_DIR_ENTRY_TYPE entry_type;
7657 
7658  FUNCTION_START(GetBookmarks);
7659 
7660  num = 0;
7661  GetBookmarkFolderName(basename, folder_name);
7662  dir = STB_DSKOpenDirectory(disk_id, folder_name);
7663  if (dir != NULL)
7664  {
7665  read_bytes = 0;
7666  while (STB_DSKReadDirectory(dir, file_name, BOOKMARK_FILENAME_SIZE, &entry_type))
7667  {
7668  if ((entry_type == DIR_ENTRY_FILE) && (GetBookmarkType(file_name) == type))
7669  {
7670  b = STB_GetMemory(sizeof(S_BOOKMARK));
7671  if (b != NULL)
7672  {
7673  num++;
7674  b->time = GetBookmarkTime(file_name);
7675  b->name = NULL;
7676  if (names)
7677  {
7678  sprintf((char *)file_str, "%s/%.*s", (char *)folder_name,
7679  BOOKMARK_FILENAME_SIZE - 1, (char *)file_name);
7680  file = STB_DSKOpenFile(disk_id, file_str, FILE_MODE_READ);
7681  if (file != NULL)
7682  {
7683  STB_DSKSeekFile(file, FILE_POSITION_END, 0);
7684  if (STB_DSKTellFile(file, &offset))
7685  {
7686  if (offset < STB_PVR_NAME_LEN)
7687  {
7688  read_bytes = offset;
7689  }
7690  else
7691  {
7692  read_bytes = STB_PVR_NAME_LEN - 1;
7693  }
7694 
7695  STB_DSKSeekFile(file, FILE_POSITION_START, 0);
7696 
7697  b->name = STB_GetMemory(read_bytes + 1);
7698  STB_DSKReadFile(file, b->name, read_bytes);
7699  b->name[read_bytes] = '\0';
7700  }
7701 
7702  STB_DSKCloseFile(file);
7703  }
7704  }
7705 
7706  STB_LLAddBlockToEnd(bookmarks, (LINK_LIST_PTR_BLK *)b);
7707  }
7708  }
7709  }
7710 
7711  STB_DSKCloseDirectory(dir);
7712  }
7713 #ifdef STB_DEBUG
7714  else
7715  {
7716  STB_PVR_PRINT(("GetBookmarks: could not open folder %s", folder_name));
7717  }
7718 #endif
7719 
7720  FUNCTION_FINISH(GetBookmarks);
7721 
7722  return num;
7723 }
7724 
7730 static void EmptyBookmarks(LINK_LIST_HEADER *bookmarks, BOOLEAN release)
7731 {
7732  S_BOOKMARK *b, *next;
7733 
7734  FUNCTION_START(EmptyBookmarks);
7735 
7736  b = (S_BOOKMARK *)STB_LLGetFirstBlock(bookmarks);
7737  while (b != NULL)
7738  {
7741 
7742  if (release)
7743  {
7744  if (b->name != NULL)
7745  {
7746  STB_FreeMemory(b->name);
7747  }
7748  STB_FreeMemory(b);
7749  }
7750  b = next;
7751  }
7752 
7753  FUNCTION_FINISH(EmptyBookmarks);
7754 }
7755 
7763 static S16BIT CompareBookmarks(LINK_LIST_PTR_BLK **bookmark1, LINK_LIST_PTR_BLK **bookmark2)
7764 {
7765  S_BOOKMARK *b1, *b2;
7766  S16BIT retval;
7767 
7768  FUNCTION_START(CompareBookmarks);
7769 
7770  b1 = (S_BOOKMARK *)*bookmark1;
7771  b2 = (S_BOOKMARK *)*bookmark2;
7772 
7773  if ((b1 != NULL) && (b2 != NULL))
7774  {
7775  if (b1->time < b2->time)
7776  {
7777  retval = -1;
7778  }
7779  else if (b1->time > b2->time)
7780  {
7781  retval = 1;
7782  }
7783  else
7784  {
7785  retval = 0;
7786  }
7787  }
7788  else if (b1 != NULL)
7789  {
7790  retval = 1;
7791  }
7792  else if (b2 != NULL)
7793  {
7794  retval = -1;
7795  }
7796  else
7797  {
7798  retval = 0;
7799  }
7800 
7801  FUNCTION_FINISH(CompareBookmarks);
7802 
7803  return retval;
7804 }
7805 
7806 //*****************************************************************************
7807 // End of file
7808 //*****************************************************************************
BOOLEAN STB_PVRCreateBookmark(U32BIT handle, U32BIT time, U8BIT *name)
Creates a bookmark associated with the a recording.
Definition: stbpvr.c:5894
U32BIT STB_PVRGetPlayPosition(U32BIT handle)
Returns the bookmarked play position for the given recording.
Definition: stbpvr.c:3884
BOOLEAN STB_DSKGetIntegrity(U16BIT disk_id)
Returns a summary of the disk integrity.
BOOLEAN STB_PVRIsValidRecording(U16BIT disk_id, U8BIT *basename)
Checks whether any of the files already exist that would be created by a recording with the given bas...
BOOLEAN STB_PVRFindRecordingFromCrid(U8BIT *prog_crid, U32BIT *handle)
Returns the handle of the recording with the given programme CRID.
Definition: stbpvr.c:1105
BOOLEAN STB_PVRDeleteRecording(U16BIT disk_id, U8BIT *basename)
Deletes any files associated with the given base filename that were created as a result of the record...
void STB_LLAddBlockToEnd(LINK_LIST_HEADER *hdr, LINK_LIST_PTR_BLK *new_blk)
Adds the block identified by the new_blk pointer to the end of the linked list identified by the list...
Definition: stbllist.c:325
U8BIT STB_PVRInitRecording(U8BIT num_tuners)
Initialisation for recording.
U32BIT STB_DSKGetUsed(U16BIT disk_id)
Returns the amount of space used on the disk.
void STB_PVRSetPlaybackNotifyTime(U8BIT audio_decoder, U8BIT video_decoder, U32BIT notify_time)
Sets the time the next notification event should be sent during playback. This is required for CI+...
void * STB_GetMemory(U32BIT bytes)
Attempts to allocate memory from the heap.
Definition: stbheap.c:221
void STB_PVRRecordingSetName(U32BIT handle, U8BIT *name)
Sets the name for a recording.
Definition: stbpvr.c:1416
S16BIT STB_PVRGetMaxPlaySpeed(U8BIT path)
Reads the PVR max play speed.
Definition: stbpvr.c:5775
BOOLEAN STB_PVRRecordingGetServiceName(U32BIT handle, U8BIT *service_name, U16BIT name_len)
Gets the service name for a given recording.
Definition: stbpvr.c:2025
void STB_PVRPlayFaster(U8BIT path, BOOLEAN include_slow_speeds)
Increase play speed - has no effect when decoding from demux.
Definition: stbpvr.c:5677
U32BIT STB_PVRRecordingGetParentalRating(U32BIT handle)
Returns the parental rating age for the specified recording as set by STB_PVRRecordingSetParentalRati...
Definition: stbpvr.c:1830
void STB_PVRPlaySetRetentionLimit(U8BIT audio_decoder, U8BIT video_decoder, U32BIT retention_limit, U16BIT rec_date, U8BIT rec_hour, U8BIT rec_min)
Set the retention limit for the playback. This function is used for CI+.
U16BIT STB_PVRRecordingGetDiskId(U32BIT handle)
Gets the disk id for a recording.
Definition: stbpvr.c:1593
S16BIT STB_AVGetMaxPlaySpeed(U8BIT video_decoder)
Returns maximum video play speed as a percentage.
U8BIT STB_DSKGetFormatProgress(U16BIT disk_id)
Gets the progress of the format operation.
void STB_PVRSetPlaybackDecryptionKey(U8BIT audio_decoder, U8BIT video_decoder, BOOLEAN state, U8BIT *key, U8BIT *iv, U32BIT key_len)
Enables and sets the key that will be used to decrypt an encrypted recording during playback...
void STB_PVRSetRecordEncryptionKey(U8BIT rec_index, BOOLEAN state, U8BIT *key, U8BIT *iv, U32BIT key_len)
Enables or disables encryption and sets the encryption key to be used.
void STB_PVRReleaseRecorderIndex(U8BIT rec_index)
Releases a recording index when no longer needed.
void * STB_DSKOpenFile(U16BIT disk_id, U8BIT *name, E_STB_DSK_FILE_MODE mode)
Opens an existing file or creates a new one.
U16BIT STB_PVRRecordingGetGuidanceLen(U32BIT handle)
Gets the length of the guidance text for a given recording.
Definition: stbpvr.c:2915
BOOLEAN STB_PVRGetRecordingSize(U16BIT disk_id, U8BIT *basename, U32BIT *rec_size_kb)
Returns the size in kilobytes of the recording defined by the given base filename.
BOOLEAN STB_PVRResumeRecording(U8BIT path)
Resumes a recording after it&#39;s been paused.
Definition: stbpvr.c:4821
void STB_PVRSaveFrame(U8BIT audio_decoder, U8BIT video_decoder)
Save current frame of playback.
BOOLEAN STB_PVRRecordingSetStatus(U32BIT handle, E_PVR_RECORDING_STATUS status)
Set the status to be saved with the recording.
Definition: stbpvr.c:2953
BOOLEAN STB_PVRRecordingHasGuidance(U32BIT handle)
Returns whether the given recording has guidance.
Definition: stbpvr.c:2841
void STB_PVRRecordingSetStartPadding(U32BIT handle, S32BIT start_padding)
Sets the start padding value for the specified recording.
Definition: stbpvr.c:1861
BOOLEAN STB_DSKSeekFile(void *file, E_STB_DSK_FILE_POSITION position, S32BIT offset)
Sets the read/write position of an open file.
S16BIT STB_AVGetMinPlaySpeed(U8BIT video_decoder)
Returns minimum video play speed as a percentage.
void * STB_DSKOpenDirectory(U16BIT disk_id, U8BIT *dir_name)
Opens a directory in order to read the entries.
U32BIT STB_OSGetClockDiff(U32BIT timestamp)
Get Difference between Given Time and Current Time.
Header file - macros and function prototypes for public use.
void * STB_OSCreateSemaphore(void)
Create a Semaphore.
BOOLEAN STB_PVRRecordingSetParentalLock(U32BIT handle, BOOLEAN state)
Sets the parental lock state of a recording.
Definition: stbpvr.c:2714
BOOLEAN STB_PVRRecordingGetOtherCrid(U32BIT handle, U8BIT *crid, U16BIT name_len)
Gets the series/recommendation CRID for a given recording.
Definition: stbpvr.c:1677
BOOLEAN STB_PVRRepair(U16BIT disk_id, E_STB_PVR_REPAIRMODE mode, U8BIT *prog)
Repairs disk for PVR. Call this for each mode.
Definition: stbpvr.c:647
S16BIT STB_PVRGetPlaySpeed(U8BIT audio_decoder, U8BIT video_decoder)
Returns the current playback speed.
void STB_PVRPlayNormal(U8BIT path)
Restarts playback (no trick mode) - has no effect when decoding from demux.
Definition: stbpvr.c:5198
BOOLEAN STB_PVRDeleteBookmark(U32BIT handle, U32BIT time, U8BIT *name)
Deletes a bookmark associated with the a recording.
Definition: stbpvr.c:5927
BOOLEAN STB_PVRRecordingGetStatus(U32BIT handle, E_PVR_RECORDING_STATUS *status)
Returns the status saved with the given recording.
Definition: stbpvr.c:2988
BOOLEAN STB_PVRIsPlayNormal(U8BIT path)
Returns TRUE if play is not in trick mode.
Definition: stbpvr.c:5244
BOOLEAN STB_PVRIsPlayMedium(U8BIT path)
Returns TRUE if play speed is medium (1x).
Definition: stbpvr.c:5592
BOOLEAN STB_CiCcSendPinPlayback(U8BIT slot_id, U8BIT age_rating, U8BIT *private_data)
Sends a pin event to the CAM during playback.
Definition: stbcicc.c:1037
void STB_PVRSetRecordStartMode(U8BIT rec_index, E_STB_PVR_START_MODE mode, U32BIT param)
Sets the startup mode for a recording. This function should be called before the recording is started...
BOOLEAN STB_PVRIsRecordAudio(U8BIT path)
Returns TRUE if record contains audio data.
Definition: stbpvr.c:5060
void STB_AVStopAudioDecoding(U8BIT decoder)
Stops audio decoding on the given audio path.
void STB_DMXChangeDecodePIDs(U8BIT path, U16BIT pcr_pid, U16BIT video_pid, U16BIT audio_pid, U16BIT text_pid, U16BIT data_pid, U16BIT ad_pid)
Changes the packet IDs for the PCR Video, Audio, Text and Data.
void STB_CiCcGetDefaultUsageRulesInfo(U8BIT raw_uri[CIP_URI_LEN])
Sets the default URI values into the given array. The URI requires HDCP.
Definition: stbcicc.c:477
void STB_DMXGetDemuxSource(U8BIT path, E_STB_DMX_DEMUX_SOURCE *source, U8BIT *param)
Gets the current source of a given demux.
S32BIT STB_PVRRecordingGetStartPadding(U32BIT handle)
Gets the start padding value for the specified recording as set by STB_PVRRecordingSetStartPadding.
Definition: stbpvr.c:1893
void STB_GCCalculateDateTime(U16BIT code, U8BIT hour, U8BIT min, U8BIT secs, U8BIT ohour, U8BIT omin, U8BIT osecs, U16BIT *rcode, U8BIT *rhour, U8BIT *rmin, U8BIT *rsecs, E_STB_GC_CALCTYPE calc)
Adds or subtracts offset from a date/time.
Definition: stbgc.c:1540
BOOLEAN STB_PVRRecordingGetTriplet(U32BIT handle, U16BIT *serv_id, U16BIT *ts_id, U16BIT *orig_net_id)
Read the DVB triplet (service id, transport id, orig net id) for a recording.
Definition: stbpvr.c:3975
U16BIT STB_DSKGetDiskIdByIndex(U16BIT index)
Returns the id of the disk at the given index.
U8BIT STB_DPGetPathVideoDecoder(U8BIT path)
Returns the video decoder ID acquired by the given decode path.
Definition: stbdpc.c:1757
BOOLEAN STB_DSKTellFile(void *file, U32BIT *offset)
Gets the current position in an open file.
void STB_DSKCloseFile(void *file)
Flushes and closes an open file.
BOOLEAN STB_PVRIsPlayForward(U8BIT path)
Returns TRUE if play is forwards trick mode.
Definition: stbpvr.c:5395
U8BIT STB_PVRGetPathForRecordingIndex(U8BIT rec_index)
Returns the path for the given recording index.
Definition: stbpvr.c:1389
PVR messages database access functions header file.
BOOLEAN STB_PVRPlayStart(U16BIT disk_id, U8BIT audio_decoder, U8BIT video_decoder, U8BIT demux, U8BIT *basename)
Starts playback.
void STB_CiCcApplyUsageRulesInfoForPlayback(U8BIT *uri)
Apply the given Usage Rules Information for playback.
Definition: stbcicc.c:578
Header file - Function prototypes for A/V control.
BOOLEAN STB_PVRIsPlayPause(U8BIT path)
Returns TRUE if play is paused trick mode.
Definition: stbpvr.c:5312
void STB_DMXSetDemuxSource(U8BIT path, E_STB_DMX_DEMUX_SOURCE source, U8BIT param)
Configures the source of the demux.
void STB_OSSemaphoreSignal(void *semaphore)
Signal a Semaphore to Release it by decrementing its counter.
S32BIT STB_PVRRecordingGetEndPadding(U32BIT handle)
Gets the end padding value for the specified recording as set by STB_PVRRecordingSetEndPadding.
Definition: stbpvr.c:1956
BOOLEAN STB_PVRIsInitialised(void)
Returns Initialised status.
Definition: stbpvr.c:480
void STB_GCConvertDateTime(U16BIT code, U8BIT hour, U8BIT min, U8BIT secs, U16BIT *rcode, U8BIT *rhour, U8BIT *rmin, U8BIT *rsecs, E_STB_GC_CONVTYPE conv)
Converts specified date / time to another.
Definition: stbgc.c:1591
BOOLEAN STB_PVRIsValidHandle(U32BIT handle)
Determines whether the given handle is in the recording database.
Definition: stbpvr.c:814
void STB_PVRRecordingSetParentalRatingAge(U32BIT handle, U32BIT parental_rating)
Sets the parental rating age for the specified recording.
Definition: stbpvr.c:1798
BOOLEAN STB_PVRRecordingGetLocked(U32BIT handle)
Returns whether the given recording is locked.
Definition: stbpvr.c:2577
void STB_PVRSavePlayPosition(U8BIT path)
Saves the bookmark holding the playback position. This bookmark is used to resume a playback when STB...
Definition: stbpvr.c:3813
void STB_PVRRecordingSetAdditionalInfo(U32BIT handle, U8BIT *additional_info)
Sets the additional info string for a recording.
Definition: stbpvr.c:1721
void * STB_ResizeMemory(void *ptr, U32BIT new_num_bytes)
Re-allocates a given memory area to the new size, ensuring data contained within the original memory ...
Definition: stbheap.c:550
BOOLEAN STB_PVRRecordingSetGuidance(U32BIT handle, U8BIT *text)
Sets the guidance text of a recording.
Definition: stbpvr.c:2796
BOOLEAN STB_PVRIsRecording(U8BIT path, U32BIT *handle)
Reads the PVR record status.
Definition: stbpvr.c:4938
BOOLEAN STB_PVRRecordingSetLocked(U32BIT handle, BOOLEAN state)
Sets the locked state of a recording.
Definition: stbpvr.c:2531
void STB_OSMutexUnlock(void *mutex)
Unlock a mutex (a.k.a. &#39;leave&#39;, &#39;signal&#39; or &#39;release&#39;)
void STB_PVRRecordStop(U8BIT rec_index)
Stops a recording.
BOOLEAN STB_PVRSetRecoringTriplet(U8BIT path, U16BIT serv_id, U16BIT ts_id, U16BIT orig_net_id)
Saves the DVB triplet of the service to be recorded.
Definition: stbpvr.c:4222
BOOLEAN STB_PVRInitialise(void)
Initialises PVR path control.
Definition: stbpvr.c:363
void STB_PVRRecordingSetCrid(U32BIT handle, U8BIT *crid)
Sets the programme CRID for a recording and saves the database file.
Definition: stbpvr.c:2269
void STB_PVRStopPlaying(U8BIT path)
Stop the PVR play back.
Definition: stbpvr.c:3931
void STB_OSSemaphoreWait(void *semaphore)
Wait on Semaphore Indefinity or Until Released.
Header file - macros and function prototypes for public use.
U32BIT STB_PVRDiskSize(U16BIT disk_id)
Returns disk size in MBytes.
Definition: stbpvr.c:5872
BOOLEAN STB_DSKDeleteDirectory(U16BIT disk_id, U8BIT *dir_name)
Deletes a directory and all it contents, so use with care!
BOOLEAN STB_PVRFindNextSplitRecording(U32BIT curr_handle, U32BIT *next_handle)
Returns the handle of a split event recording that follows on from curr_handle.
Definition: stbpvr.c:1142
U16BIT STB_DSKGetNumDisks(void)
Returns the number of disks currently detected.
void STB_ERSendEvent(BOOLEAN latched, BOOLEAN repeat, U16BIT path_class, U16BIT type, void *data, U32BIT data_size)
Sends an event to event reporting control module.
Definition: stberc.c:571
CI Content Control.
BOOLEAN STB_PVRIsPlayAudio(U8BIT path)
Returns TRUE if play contains audio data.
Definition: stbpvr.c:4115
BOOLEAN STB_PVRCanBeUsedForRecording(U16BIT disk_id, U8BIT *basename)
Checks whether any of the files already exist that would be created by a recording with the given bas...
void STB_PVRPlayTrickMode(U8BIT audio_decoder, U8BIT video_decoder, E_STB_PVR_PLAY_MODE mode, S16BIT speed)
Sets trick mode during playback.
U8BIT * STB_PVRRecordingGetAdditionalInfo(U32BIT handle)
Gets the additional info string pointer for a recording.
Definition: stbpvr.c:1765
S16BIT STB_AVGetNextPlaySpeed(U8BIT video_decoder, S16BIT speed, S16BIT inc, BOOLEAN include_slow_speeds)
Returns the next valid speed that is +/- inc above or below the given speed. Slow motion speeds (>-10...
U8BIT STB_DPGetNumPaths(void)
Returns the maximum number of decode paths.
Definition: stbdpc.c:532
BOOLEAN STB_PVRUpdateRecordingPids(U8BIT path, U16BIT num_pids, S_PVR_PID_INFO *pid_array)
Saves (takes a copy of) the array of pids to be recorded and pass them to the platform.
Definition: stbpvr.c:4182
BOOLEAN STB_PVRRecordStart(U16BIT disk_id, U8BIT rec_index, U8BIT *basename, U16BIT num_pids, S_PVR_PID_INFO *pid_array)
Starts recording.
BOOLEAN STB_PVRRecordingGetRecommendation(U32BIT handle)
Returns whether the given recording is a recommendation.
Definition: stbpvr.c:2495
void STB_PVRPlayFrameDec(U8BIT path)
Decrements play by one frame - has no effect when decoding from demux.
Definition: stbpvr.c:5542
BOOLEAN STB_PVRCreateRecording(U16BIT disk_id, U8BIT *name, U32BIT *handle)
Create a new recording and return the handle.
Definition: stbpvr.c:846
BOOLEAN STB_PVRIsPlaying(U8BIT path, U32BIT *handle)
Reads the PVR play status.
Definition: stbpvr.c:3792
void STB_PVREncryptRecording(U8BIT path, BOOLEAN state)
Sets whether a recording should be encrypted. Must be set before the recording is started...
Definition: stbpvr.c:5086
void STB_PVRStartRecordRunning(U8BIT path)
Set to start recording in running mode.
Definition: stbpvr.c:4978
void STB_DSKCloseDirectory(void *dir)
Closes the directory for reading.
void STB_PVRPlayForward(U8BIT path)
Set play forwards - has no effect when decoding from demux.
Definition: stbpvr.c:5348
U32BIT STB_DSKWriteFile(void *file, U8BIT *data, U32BIT size)
Writes data to an open file.
BOOLEAN STB_PVRRecordResume(U8BIT rec_index)
Resumes a paused recording.
void STB_FreeMemory(void *addr)
Releases previously allocated heap memory.
Definition: stbheap.c:336
BOOLEAN STB_PVRIsPlayVideo(U32BIT handle)
Returns TRUE if play contains video data.
Definition: stbpvr.c:4074
U8BIT STB_HWGetVideoDecodePaths(void)
Returns the number of video decoding paths on the platform.
BOOLEAN STB_PVRPauseRecording(U8BIT path)
Pauses recording after it&#39;s been started.
Definition: stbpvr.c:4790
BOOLEAN STB_PVRIsPlayReverse(U8BIT path)
Returns TRUE if play is backwards trick mode.
Definition: stbpvr.c:5478
U8BIT STB_PVRAcquireRecorderIndex(U8BIT tuner, U8BIT demux)
Acquires an index to be used to reference a recording.
void STB_PVRPlaybackNotifyTime(U8BIT path)
Handles the notification received from the platform code when playback reaches a set position...
Definition: stbpvr.c:4582
BOOLEAN STB_PVRFormat(U16BIT disk_id, E_STB_PVR_FORMATMODE mode, U8BIT *prog)
Formats disk for PVR. Call this for each mode.
Definition: stbpvr.c:580
BOOLEAN STB_PVRIsRecordVideo(U8BIT path)
Returns TRUE if record contains video data.
Definition: stbpvr.c:5029
Debug functions header file.
void STB_PVRDiskUsed(U16BIT disk_id, U8BIT *hours, U8BIT *mins)
Returns disk space used in hours and minutes.
Definition: stbpvr.c:5802
void STB_LLRemoveBlock(LINK_LIST_PTR_BLK *blk)
Removes the block identified by the blk pointer from its linked list.
Definition: stbllist.c:488
Header file - Function prototypes for linked lists.
BOOLEAN STB_PVRRecordingGetSelected(U32BIT handle)
Returns whether the given recording is selected.
Definition: stbpvr.c:2646
Header file - macros and function prototypes for public use.
void STB_OSMutexLock(void *mutex)
Lock a mutex (a.k.a. &#39;enter&#39;, &#39;wait&#39; or &#39;get&#39;).
U16BIT STB_PVRGetDefaultDisk(void)
Returns the set default disk, or finds the first mounted (usable) disk if a default hasn&#39;t been set...
Definition: stbpvr.c:512
Header file - macros and function prototypes for public use.
void STB_AVStartVideoDecoding(U8BIT path)
Starts video decoding on the given video path.
void STB_AVStopVideoDecoding(U8BIT decoder)
Stops video decoding on the given video path. The video is not expected to be blanked.
LINK_LIST_PTR_BLK * STB_LLGetNextBlock(LINK_LIST_PTR_BLK *blk)
Returns a pointer to the next block in the linked list, or NULL if at the end of the list...
Definition: stbllist.c:566
void STB_PVRStartPlaySync(U8BIT path)
Set to start playback synced to AV decoder.
Definition: stbpvr.c:4052
BOOLEAN STB_PVRDestroyRecording(U32BIT handle)
Completely destroys a recording by deleting all files and removing it from the list of recordings...
Definition: stbpvr.c:948
BOOLEAN STB_CiCcSendPlaybackLicence(U8BIT slot_id, U16BIT program_number, U8BIT *licence, U16BIT licence_len)
Sends a CICAM licence to a module during playback, which will result in a modified licence being noti...
Definition: stbcicc.c:1324
void STB_GCGetGMTDateTime(U16BIT *code, U8BIT *hour, U8BIT *min, U8BIT *secs)
Reads the current GMT date code and time.
Definition: stbgc.c:1372
BOOLEAN STB_PVRIsBeingRecorded(U32BIT handle)
Returns whether the recording with the given handle is currently being recorded.
Definition: stbpvr.c:2364
void STB_PVRPlaySlower(U8BIT path, BOOLEAN include_slow_speeds)
Decrease play speed - has no effect when decoding from demux.
Definition: stbpvr.c:5612
BOOLEAN STB_PVRRecordPause(U8BIT rec_index)
Pauses a recording currently taking place.
BOOLEAN STB_DSKReadDirectory(void *dir, U8BIT *filename, U16BIT filename_len, E_STB_DIR_ENTRY_TYPE *entry_type)
Reads the next entry from the directory, returning the name of the entry and the type of the entry...
void STB_PVRSaveRecording(U32BIT handle)
Save all info on the given recording. The filename and disk should already have been setup...
Definition: stbpvr.c:999
void STB_PVRSetStandbyState(BOOLEAN state)
Sets the standby state of the PVR path control.
Definition: stbpvr.c:457
U8BIT STB_DPGetPathTuner(U8BIT path)
Returns the tuner ID acquired by the given decode path.
Definition: stbdpc.c:1605
BOOLEAN STB_PVRRecordingSetSelected(U32BIT handle, BOOLEAN state)
Sets the selected state of a recording.
Definition: stbpvr.c:2613
U32BIT STB_PVRGetTimeOfAllRecordings(U16BIT disk_id)
Calculates the total disk space used in minutes.
Definition: stbpvr.c:3549
Header file - Function prototypes for Event Reporting.
Header for STB unicode string handling routines.
BOOLEAN STB_DSKFileExists(U16BIT disk_id, U8BIT *filename)
Checks whether a file/directory will the given name exists.
BOOLEAN STB_PVRIsRecordStarted(U8BIT rec_index)
Returns whether recording has been started.
void STB_PVRPlayHasVideo(U8BIT audio_decoder, U8BIT video_decoder, BOOLEAN has_video)
Informs the platform whether there&#39;s video in the file to be played. Should be called before playback...
U8BIT STB_DPGetPathAudioDecoder(U8BIT path)
Returns the audio decoder ID acquired by the given decode path.
Definition: stbdpc.c:1734
void STB_PVRRecordingSetExtendedDescription(U32BIT handle, U8BIT *description)
Sets the extended description for a recorded programme.
Definition: stbpvr.c:2164
U8BIT STB_HWGetAudioDecodePaths(void)
Returns the number of audio decoding paths on the platform.
U32BIT STB_PVRGetSizeOfAllRecordings(U16BIT disk_id)
Calculates the total disk space used in KB for all recordings.
Definition: stbpvr.c:3592
void STB_PVRReleaseRecordingHandles(U32BIT *handle_array)
Frees the given array of handles allocated by the preceding function.
Definition: stbpvr.c:1087
BOOLEAN STB_PVRRecordingGetDescription(U32BIT handle, U8BIT *description, U16BIT desc_len)
Gets the short description for a given recording.
Definition: stbpvr.c:2097
BOOLEAN STB_PVRCanDiskBeUsed(U16BIT disk_id)
Checks whether the given disk can be used for PVR functions.
Definition: stbpvr.c:551
LINK_LIST_PTR_BLK * STB_LLGetFirstBlock(LINK_LIST_HEADER *hdr)
Returns a pointer to the first block in the linked list, identified by hdr.
Definition: stbllist.c:633
U32BIT STB_DSKGetSize(U16BIT disk_id)
Returns the size (capacity) of the disk.
void STB_PVRRecordingSetOtherCrid(U32BIT handle, U8BIT *crid)
Sets the series/recommendation CRID for a recording and saves the database file.
Definition: stbpvr.c:1626
U8BIT * STB_PVRGetBookmarkName(void *bookmark_handle)
Allocates and returns the name associated with a bookmark.
Definition: stbpvr.c:4543
U32BIT STB_GetNumBytesInString(U8BIT *string_ptr)
Determines the no of bytes of the given string.
Definition: stbuni.c:311
BOOLEAN STB_PVRPlaySetPosition(U8BIT audio_decoder, U8BIT video_decoder, U32BIT position_in_seconds)
Sets the playback position after playback has started (i.e. jump to bookmark)
U8BIT STB_PVRInitPlayback(U8BIT num_audio_decoders, U8BIT num_video_decoders)
Initialisation for playback.
BOOLEAN STB_PVRRecordChangePids(U8BIT rec_index, U16BIT num_pids, S_PVR_PID_INFO *pids_array)
Changes the PIDs while recording.
Header file - Function prototypes for NVM and Heap.
U32BIT STB_PVRGetHandleForRecordingIndex(U8BIT rec_index)
Returns the handle for the given recording index.
Definition: stbpvr.c:1362
const void * STB_MEMReadSecureConstant(U8BIT key, U32BIT *len)
Read constant defined by the given key from secure NVM. The data must not be released (it is managed ...
Header file - Function prototypes for operating system.
System Wide Global Technical Data Type Definitions.
void STB_PVRRecordingSetSeries(U32BIT handle)
Sets a recording to a series recording.
Definition: stbpvr.c:2396
void STB_PVRSetDefaultDisk(U16BIT disk_id)
Sets the disk ID to be used as the default disk for PVR recordings. If this is set to INVALID_DISK_ID...
Definition: stbpvr.c:498
BOOLEAN STB_PVRApplyDescramblerKey(U8BIT rec_index, E_STB_DMX_DESC_TYPE desc_type, E_STB_DMX_DESC_KEY_PARITY parity, U8BIT *key, U8BIT *iv)
Called to apply the given descrambler key to the PID data being recorded. This function may be called...
BOOLEAN STB_PVRRecordingIsEncrypted(U32BIT handle)
Returns whether the given recording is encrypted.
Definition: stbpvr.c:2678
U32BIT STB_DSKReadFile(void *file, U8BIT *data, U32BIT size)
Reads data from an open file.
Header file - macros and function prototypes for public use.
BOOLEAN STB_PVRRecordingGetGuidance(U32BIT handle, U8BIT *text, U16BIT text_len)
Returns the whether a recording has guidance and the guidance text if available.
Definition: stbpvr.c:2878
void STB_PVRRecordEnabled(U8BIT rec_index, BOOLEAN *video, BOOLEAN *audio)
Returns status of audio/video recording.
void STB_PVRPlayMedium(U8BIT path)
Sets play speed to medium (1x) - has no effect when decoding from demux.
Definition: stbpvr.c:5570
BOOLEAN STB_PVRStartRecording(U8BIT path, U32BIT handle)
Start the PVR record tasks.
Definition: stbpvr.c:4642
U16BIT STB_PVRRecordingGetDescriptionLen(U32BIT handle)
Gets the length of the short description for a given recording.
Definition: stbpvr.c:2131
void STB_PVRRecordingSetRecommendation(U32BIT handle)
Sets a recording to a recommendation recording.
Definition: stbpvr.c:2428
BOOLEAN STB_PVRInitialiseMessages(void)
Initialises file that provides messages for recording er.
Definition: stbpvrmsg.c:85
BOOLEAN STB_DPIsRecordingPath(U8BIT path)
Is the given decode path being used for recording.
Definition: stbdpc.c:1320
void STB_PVRDiskFree(U16BIT disk_id, U8BIT *hours, U8BIT *mins)
Returns disk space free in hours and minutes.
Definition: stbpvr.c:5828
void STB_AVStartAudioDecoding(U8BIT decoder)
Starts audio decoding on the given audio path.
BOOLEAN STB_PVRIsPlayStarted(U8BIT audio_decoder, U8BIT video_decoder)
Returns status of playback with the given decoders.
BOOLEAN STB_DSKDeleteFile(U16BIT disk_id, U8BIT *filename)
Deletes the file from the given disk.
void STB_PVRPlayFrameInc(U8BIT path)
Increments play by one frame - has no effect when decoding from demux.
Definition: stbpvr.c:5514
S8BIT STB_CompareStringsIgnoreCase(U8BIT *string1_ptr, U8BIT *string2_ptr)
Compares the contents of the two given ASCII strings and returns the status (as per strcmp) but ignor...
Definition: stbuni.c:2183
U32BIT STB_PVRGetBookmarkTime(void *bookmark_handle)
Returns the time associated with a bookmark.
Definition: stbpvr.c:4525
void STB_PVRUpdateRecordings(BOOLEAN force_load)
Called when a disk is added or removed and updates the disk database and the recordings that are now ...
Definition: stbpvr.c:715
BOOLEAN STB_PVRRecordingGetParentalLock(U32BIT handle)
Returns the parental lock state of the given recording.
Definition: stbpvr.c:2760
U32BIT STB_CiCcGetRetentionLimit(U8BIT uri[CIP_URI_LEN])
Return the retention limit given a packed URI.
Definition: stbcicc.c:495
U8BIT STB_DSKGetRepairProgress(U16BIT disk_id)
Gets the progress of the repair operation.
Header file - Function prototypes for heap memory.
U16BIT STB_PVRGetRecordingHandles(U32BIT **handle_array)
Allocates and returns an array of all the recording handles.
Definition: stbpvr.c:1039
void * STB_OSCreateMutex(void)
Create a mutex.
U8BIT STB_CiCcFindSlotForCicamId(U8BIT cicam_id[CIP_CICAM_ID_LEN])
Checks CAMs in all slots to find the one with the given CAM id.
Definition: stbcicc.c:399
void STB_PVRRecordingSetServiceName(U32BIT handle, U8BIT *service_name)
Sets the service name for a recording and saves the database file.
Definition: stbpvr.c:1987
BOOLEAN STB_PVRRecordingGetLength(U32BIT handle, U8BIT *length_hours, U8BIT *length_mins, U8BIT *length_secs, U32BIT *rec_size_kb)
Returns the length in time and size in KB of the recording with the given handle. ...
Definition: stbpvr.c:1535
BOOLEAN STB_DSKCreateDirectory(U16BIT disk_id, U8BIT *dir_path)
Creates a directory with the given name.
void STB_PVRStopRecording(U8BIT path)
Stop the PVR recording.
Definition: stbpvr.c:4858
U8BIT * STB_PVRRecordingGetName(U32BIT handle)
Gets the name for a recording.
Definition: stbpvr.c:1457
void STB_PVRRecordingSetDescription(U32BIT handle, U8BIT *description)
Sets the short description for a recorded programme.
Definition: stbpvr.c:2059
void STB_DSKSetStandby(BOOLEAN state)
Put all disks into or out of standby mode.
U8BIT STB_HWGetNumRecorders(void)
Returns the number of recordings that can take place at the same time.
Function prototypes for disk functions.
void STB_PVRSetPlayStartMode(U8BIT audio_decoder, U8BIT video_decoder, E_STB_PVR_START_MODE mode)
Set startup mode for playback.
BOOLEAN STB_PVRRecordingGetDateTime(U32BIT handle, U16BIT *date, U8BIT *hours, U8BIT *mins, U8BIT *secs)
Gets the date and time for a recording.
Definition: stbpvr.c:1494
void STB_PVRStartRecordPaused(U8BIT path, U32BIT timeshift_seconds)
Set to start recording in paused mode for timeshift recording.
Definition: stbpvr.c:5004
void STB_PVRPlayReverse(U8BIT path)
Set play backwards - has no effect when decoding from demux.
Definition: stbpvr.c:5431
U16BIT STB_PVRGetBookmarksForRecording(U32BIT handle, void ***bookmarks)
Allocates and returns an array containing the handles of the bookmarks for the recording specified by...
Definition: stbpvr.c:4432
void STB_OSTaskDelay(U16BIT timeout)
Delay Task for Specifed Time Period.
BOOLEAN STB_PVRIsPlayFastest(U8BIT path)
Returns TRUE if play speed is fastest possible.
Definition: stbpvr.c:5713
Header file - Function prototypes for Demux control.
BOOLEAN STB_GCCompareDateTime(U16BIT code1, U8BIT hour1, U8BIT min1, U8BIT secs1, U16BIT code2, U8BIT hour2, U8BIT min2, U8BIT secs2, E_STB_GC_COMPTYPE comp)
Compares one date/time to another.
Definition: stbgc.c:1647
void STB_PVRRecordingSetEndPadding(U32BIT handle, S32BIT end_padding)
Sets the end padding value for the specified recording.
Definition: stbpvr.c:1924
void STB_DSKRepair(U16BIT disk_id)
Initiates a data repair of the hard disk. This may cause the disk to become unreadable.
U32BIT STB_OSGetClockMilliseconds(void)
Get Current Computer Clock Time.
void STB_PVRPlayStop(U8BIT audio_decoder, U8BIT video_decoder)
Stops playback.
void STB_PVRPlayEnabled(U8BIT audio_decoder, U8BIT video_decoder, BOOLEAN *video, BOOLEAN *audio)
Returns whether audio and video playback has been started.
BOOLEAN STB_PVRSetRecordingPids(U8BIT path, U16BIT num_pids, S_PVR_PID_INFO *pid_array)
Saves (takes a copy of) the array of pids to be recorded.
Definition: stbpvr.c:4140
void STB_AVBlankVideo(U8BIT path, BOOLEAN blank)
Blanks or unblanks the video display.
U16BIT STB_PVRRecordingGetExtendedDescriptionLen(U32BIT handle)
Gets the length of the extended description for a given recording.
Definition: stbpvr.c:2236
void STB_PVRStartPlayRunning(U8BIT path)
Set to start playback in running mode.
Definition: stbpvr.c:4008
void STB_PVRReleaseBookmarks(void **bookmarks, U16BIT num)
Frees a previously allocated array of bookmark handles.
Definition: stbpvr.c:4495
U8BIT STB_DPGetPathDemux(U8BIT path)
Returns the demux path ID acquired by the given decode path.
Definition: stbdpc.c:1711
void STB_PVRStartPlayPaused(U8BIT path)
Set to start playback in paused mode.
Definition: stbpvr.c:4030
BOOLEAN STB_PVRSetPlaySpeed(U8BIT audio_decoder, U8BIT video_decoder, S16BIT speed)
Set the play speed for the specified decoder.
BOOLEAN STB_PVRRecordingGetCrid(U32BIT handle, U8BIT *crid, U16BIT name_len)
Gets the programme CRID for a given recording.
Definition: stbpvr.c:2320
BOOLEAN STB_PVRGotoNextBookmark(U8BIT path)
Jumps playback to the position of the bookmark after the current play position.
Definition: stbpvr.c:4333
BOOLEAN STB_PVRGetElapsedTime(U8BIT audio_decoder, U8BIT video_decoder, U8BIT *elapsed_hours, U8BIT *elapsed_mins, U8BIT *elapsed_secs)
Returns the elapsed playback time in hours, mins & secs.
BOOLEAN STB_PVRRecordingGetExtendedDescription(U32BIT handle, U8BIT *description, U16BIT desc_len)
Gets the extended description for a given recording.
Definition: stbpvr.c:2202
BOOLEAN STB_LLSort(LINK_LIST_HEADER *ll_hdr, S16BIT(*cmp_func)(LINK_LIST_PTR_BLK **, LINK_LIST_PTR_BLK **))
Sorts the blocks of a link list object in ascending or descending order NOTE: The order in which the ...
Definition: stbllist.c:161
BOOLEAN STB_PVRStartPlaying(U8BIT path, U32BIT handle, BOOLEAN resume)
Start the PVR playing.
Definition: stbpvr.c:3638
S32BIT STB_GCDateTimeDiff(U16BIT code1, U8BIT hour1, U8BIT min1, U8BIT secs1, U16BIT code2, U8BIT hour2, U8BIT min2, U8BIT secs2)
Returns the difference in seconds between the two dates/times, as time1 - time2, so the result will b...
Definition: stbgc.c:1714
BOOLEAN STB_DSKIsMounted(U16BIT disk_id)
Checks if the given disk is mounted.
BOOLEAN STB_PVRRecordingGetSeries(U32BIT handle)
Returns whether the given recording is a series.
Definition: stbpvr.c:2460
void STB_PVRPlayPause(U8BIT path)
Pauses play - has no effect when decoding from demux.
Definition: stbpvr.c:5280
U16BIT STB_PVRGetBookmarks(U8BIT path, void ***bookmarks)
Allocates and returns an array containing the handles of the bookmarks for the recording currently be...
Definition: stbpvr.c:4407
BOOLEAN STB_PVRToggleBookmark(U8BIT path)
Creates or deletes a bookmark at the current position during playback. If there&#39;s a bookmark within a...
Definition: stbpvr.c:4250
S16BIT STB_PVRGetMinPlaySpeed(U8BIT path)
Reads the PVR min play speed.
Definition: stbpvr.c:5749
void STB_DSKFormat(U16BIT disk_id)
Initiates formatting and partitioning of the hard disk. This will erase all data on the disk! ...
BOOLEAN STB_PVRIsPlaySlowest(U8BIT path)
Returns TRUE if play speed is slowest possible.
Definition: stbpvr.c:5647