1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
|
/*
* channels.h: Channel handling
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: channels.h 5.2 2021/05/21 09:38:34 kls Exp $
*/
#ifndef __CHANNELS_H
#define __CHANNELS_H
#include "config.h"
#include "sources.h"
#include "thread.h"
#include "tools.h"
#define ISTRANSPONDER(f1, f2) (abs((f1) - (f2)) < 4) //XXX
#define CHANNELMOD_NONE 0x00
#define CHANNELMOD_ALL 0xFF
#define CHANNELMOD_NAME 0x01
#define CHANNELMOD_PIDS 0x02
#define CHANNELMOD_ID 0x04
#define CHANNELMOD_AUX 0x08
#define CHANNELMOD_CA 0x10
#define CHANNELMOD_TRANSP 0x20
#define CHANNELMOD_LANGS 0x40
#define CHANNELMOD_RETUNE (CHANNELMOD_PIDS | CHANNELMOD_CA | CHANNELMOD_TRANSP)
#define MAXAPIDS 32 // audio
#define MAXDPIDS 16 // dolby (AC3 + DTS)
#define MAXSPIDS 32 // subtitles
#define MAXCAIDS 12 // conditional access
#define MAXLANGCODE1 4 // a 3 letter language code, zero terminated
#define MAXLANGCODE2 8 // up to two 3 letter language codes, separated by '+' and zero terminated
#define CA_FTA 0x0000
#define CA_DVB_MIN 0x0001
#define CA_DVB_MAX 0x000F
#define CA_USER_MIN 0x0010
#define CA_USER_MAX 0x00FF
#define CA_ENCRYPTED_MIN 0x0100
#define CA_ENCRYPTED_MAX 0xFFFF
struct tChannelID {
private:
int source;
int nid; ///< actually the "original" network id
int tid;
int sid;
int rid;
public:
tChannelID(void) { source = nid = tid = sid = rid = 0; }
tChannelID(int Source, int Nid, int Tid, int Sid, int Rid = 0) { source = Source; nid = Nid; tid = Tid; sid = Sid; rid = Rid; }
bool operator== (const tChannelID &arg) const { return source == arg.source && nid == arg.nid && tid == arg.tid && sid == arg.sid && rid == arg.rid; }
bool Valid(void) const { return (nid || tid) && sid; } // rid is optional and source may be 0//XXX source may not be 0???
tChannelID &ClrRid(void) { rid = 0; return *this; }
tChannelID &ClrPolarization(void);
int Source(void) const { return source; }
int Nid(void) const { return nid; }
int Tid(void) const { return tid; }
int Sid(void) const { return sid; }
int Rid(void) const { return rid; }
static tChannelID FromString(const char *s);
cString ToString(void) const;
static const tChannelID InvalidID;
};
class cChannel;
class cLinkChannel : public cListObject {
private:
cChannel *channel;
public:
cLinkChannel(cChannel *Channel) { channel = Channel; }
cChannel *Channel(void) { return channel; }
};
class cLinkChannels : public cList<cLinkChannel> {
};
class cSchedule;
class cChannels;
class cChannel : public cListObject {
friend class cSchedules;
friend class cMenuEditChannel;
friend class cDvbSourceParam;
private:
static cString ToText(const cChannel *Channel);
char *name;
char *shortName;
char *provider;
char *portalName;
int __BeginData__;
int frequency; // MHz
mutable int transponder; // cached value
int source;
int srate;
int vpid;
int ppid;
int vtype;
int apids[MAXAPIDS + 1]; // list is zero-terminated
int atypes[MAXAPIDS + 1]; // list is zero-terminated
char alangs[MAXAPIDS][MAXLANGCODE2];
int dpids[MAXDPIDS + 1]; // list is zero-terminated
int dtypes[MAXDPIDS + 1]; // list is zero-terminated
char dlangs[MAXDPIDS][MAXLANGCODE2];
int spids[MAXSPIDS + 1]; // list is zero-terminated
char slangs[MAXSPIDS][MAXLANGCODE2];
uchar subtitlingTypes[MAXSPIDS];
uint16_t compositionPageIds[MAXSPIDS];
uint16_t ancillaryPageIds[MAXSPIDS];
int tpid;
int caids[MAXCAIDS + 1]; // list is zero-terminated
int nid;
int tid;
int sid;
int rid;
int lcn; // Logical channel number assigned by data stream (or -1 if not available)
int number; // Sequence number assigned on load
bool groupSep;
int __EndData__;
mutable cString nameSource;
mutable int nameSourceMode;
mutable cString shortNameSource;
cString parameters;
mutable int modification;
time_t seen; // When this channel was last seen in the SDT of its transponder
mutable const cSchedule *schedule;
cLinkChannels *linkChannels;
cChannel *refChannel;
cString TransponderDataToString(void) const;
public:
cChannel(void);
cChannel(const cChannel &Channel);
~cChannel();
cChannel& operator= (const cChannel &Channel);
cString ToText(void) const;
bool Parse(const char *s);
bool Save(FILE *f);
const char *Name(void) const;
const char *ShortName(bool OrName = false) const;
const char *Provider(void) const { return provider; }
const char *PortalName(void) const { return portalName; }
int Frequency(void) const { return frequency; } ///< Returns the actual frequency, as given in 'channels.conf'
int Transponder(void) const; ///< Returns the transponder frequency in MHz, plus the polarization in case of sat
static int Transponder(int Frequency, char Polarization); ///< builds the transponder from the given Frequency and Polarization
int Source(void) const { return source; }
int Srate(void) const { return srate; }
int Vpid(void) const { return vpid; }
int Ppid(void) const { return ppid; }
int Vtype(void) const { return vtype; }
const int *Apids(void) const { return apids; }
const int *Dpids(void) const { return dpids; }
const int *Spids(void) const { return spids; }
int Apid(int i) const { return (0 <= i && i < MAXAPIDS) ? apids[i] : 0; }
int Dpid(int i) const { return (0 <= i && i < MAXDPIDS) ? dpids[i] : 0; }
int Spid(int i) const { return (0 <= i && i < MAXSPIDS) ? spids[i] : 0; }
const char *Alang(int i) const { return (0 <= i && i < MAXAPIDS) ? alangs[i] : ""; }
const char *Dlang(int i) const { return (0 <= i && i < MAXDPIDS) ? dlangs[i] : ""; }
const char *Slang(int i) const { return (0 <= i && i < MAXSPIDS) ? slangs[i] : ""; }
int Atype(int i) const { return (0 <= i && i < MAXAPIDS) ? atypes[i] : 0; }
int Dtype(int i) const { return (0 <= i && i < MAXDPIDS) ? dtypes[i] : 0; }
uchar SubtitlingType(int i) const { return (0 <= i && i < MAXSPIDS) ? subtitlingTypes[i] : uchar(0); }
uint16_t CompositionPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? compositionPageIds[i] : uint16_t(0); }
uint16_t AncillaryPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? ancillaryPageIds[i] : uint16_t(0); }
int Tpid(void) const { return tpid; }
const int *Caids(void) const { return caids; }
int Ca(int Index = 0) const { return Index < MAXCAIDS ? caids[Index] : 0; }
int Nid(void) const { return nid; }
int Tid(void) const { return tid; }
int Sid(void) const { return sid; }
int Rid(void) const { return rid; }
int Lcn(void) const { return lcn; }
int Number(void) const { return number; }
void SetNumber(int Number) { number = Number; }
bool GroupSep(void) const { return groupSep; }
const char *Parameters(void) const { return parameters; }
const cSchedule *Schedule(void) const { return schedule; }
const cLinkChannels* LinkChannels(void) const { return linkChannels; }
const cChannel *RefChannel(void) const { return refChannel; }
bool IsAtsc(void) const { return cSource::IsAtsc(source); }
bool IsCable(void) const { return cSource::IsCable(source); }
bool IsSat(void) const { return cSource::IsSat(source); }
bool IsTerr(void) const { return cSource::IsTerr(source); }
bool IsSourceType(char Source) const { return cSource::IsType(source, Source); }
tChannelID GetChannelID(void) const { return tChannelID(source, nid, (nid || tid) ? tid : Transponder(), sid, rid); }
int Modification(int Mask = CHANNELMOD_ALL) const;
time_t Seen(void) const { return seen; }
void CopyTransponderData(const cChannel *Channel);
bool SetTransponderData(int Source, int Frequency, int Srate, const char *Parameters, bool Quiet = false);
bool SetSource(int Source);
bool SetId(cChannels *Channels, int Nid, int Tid, int Sid, int Rid = 0);
bool SetLcn(int Lcn);
bool SetName(const char *Name, const char *ShortName, const char *Provider);
bool SetPortalName(const char *PortalName);
bool SetPids(int Vpid, int Ppid, int Vtype, int *Apids, int *Atypes, char ALangs[][MAXLANGCODE2], int *Dpids, int *Dtypes, char DLangs[][MAXLANGCODE2], int *Spids, char SLangs[][MAXLANGCODE2], int Tpid);
bool SetCaIds(const int *CaIds); // list must be zero-terminated
bool SetCaDescriptors(int Level);
bool SetLinkChannels(cLinkChannels *LinkChannels);
void SetRefChannel(cChannel *RefChannel);
bool SetSubtitlingDescriptors(uchar *SubtitlingTypes, uint16_t *CompositionPageIds, uint16_t *AncillaryPageIds);
void SetSeen(void);
void DelLinkChannel(cChannel *LinkChannel);
};
class cChannels : public cConfig<cChannel> {
private:
static cChannels channels;
static int maxNumber;
static int maxChannelNameLength;
static int maxShortChannelNameLength;
int modifiedByUser;
cHash<cChannel> channelsHashSid;
void DeleteDuplicateChannels(void);
public:
cChannels(void);
static const cChannels *GetChannelsRead(cStateKey &StateKey, int TimeoutMs = 0);
///< Gets the list of channels for read access.
///< See cTimers::GetTimersRead() for details.
static cChannels *GetChannelsWrite(cStateKey &StateKey, int TimeoutMs = 0);
///< Gets the list of channels for write access.
///< See cTimers::GetTimersWrite() for details.
static bool Load(const char *FileName, bool AllowComments = false, bool MustExist = false);
void HashChannel(cChannel *Channel);
void UnhashChannel(cChannel *Channel);
int GetNextGroup(int Idx) const; ///< Get next channel group
int GetPrevGroup(int Idx) const; ///< Get previous channel group
int GetNextNormal(int Idx) const; ///< Get next normal channel (not group)
int GetPrevNormal(int Idx) const; ///< Get previous normal channel (not group)
void ReNumber(void); ///< Recalculate 'number' based on channel type
bool MoveNeedsDecrement(cChannel *From, cChannel *To); // Detect special case when moving a channel (closely related to Renumber())
void Del(cChannel *Channel); ///< Delete the given Channel from the list
const cChannel *GetByNumber(int Number, int SkipGap = 0) const;
cChannel *GetByNumber(int Number, int SkipGap = 0) { return const_cast<cChannel *>(static_cast<const cChannels *>(this)->GetByNumber(Number, SkipGap)); }
const cChannel *GetByServiceID(int Source, int Transponder, unsigned short ServiceID) const;
cChannel *GetByServiceID(int Source, int Transponder, unsigned short ServiceID) { return const_cast<cChannel *>(static_cast<const cChannels *>(this)->GetByServiceID(Source, Transponder, ServiceID)); }
const cChannel *GetByChannelID(tChannelID ChannelID, bool TryWithoutRid = false, bool TryWithoutPolarization = false) const;
cChannel *GetByChannelID(tChannelID ChannelID, bool TryWithoutRid = false, bool TryWithoutPolarization = false) { return const_cast<cChannel *>(static_cast<const cChannels *>(this)->GetByChannelID(ChannelID, TryWithoutRid, TryWithoutPolarization)); }
const cChannel *GetByTransponderID(tChannelID ChannelID) const;
cChannel *GetByTransponderID(tChannelID ChannelID) { return const_cast<cChannel *>(static_cast<const cChannels *>(this)->GetByTransponderID(ChannelID)); }
bool HasUniqueChannelID(const cChannel *NewChannel, const cChannel *OldChannel = NULL) const;
bool SwitchTo(int Number) const;
static int MaxNumber(void) { return maxNumber; }
static int MaxChannelNameLength(void);
static int MaxShortChannelNameLength(void);
void SetModifiedByUser(void);
bool ModifiedByUser(int &State) const;
///< Returns true if the channels have been modified by the user since the last call
///< to this function with the same State variable. State must be initialized with 0
///< and will be set to the current value of the list's internal state variable upon
///< return from this function.
cChannel *NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid = 0);
bool MarkObsoleteChannels(int Source, int Nid, int Tid);
};
// Provide lock controlled access to the list:
DEF_LIST_LOCK(Channels);
// These macros provide a convenient way of locking the global channels list
// and making sure the lock is released as soon as the current scope is left
// (note that these macros wait forever to obtain the lock!):
#define LOCK_CHANNELS_READ USE_LIST_LOCK_READ(Channels)
#define LOCK_CHANNELS_WRITE USE_LIST_LOCK_WRITE(Channels)
cString ChannelString(const cChannel *Channel, int Number);
#endif //__CHANNELS_H
|