Home

Dokumentation

Impressum

Dokumentation VDR
 

Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

channels.c

Go to the documentation of this file.
00001 /*
00002  * channels.c: Channel handling
00003  *
00004  * See the main source file 'vdr.c' for copyright information and
00005  * how to reach the author.
00006  *
00007  * $Id: channels.c 1.11 2002/11/29 14:10:46 kls Exp $
00008  */
00009 
00010 #include "channels.h"
00011 #include <linux/dvb/frontend.h>
00012 #include <ctype.h>
00013 
00014 // IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
00015 // format characters in order to allow any number of blanks after a numeric
00016 // value!
00017 
00018 // -- Channel Parameter Maps -------------------------------------------------
00019 
00020 const tChannelParameterMap InversionValues[] = {
00021   {   0, INVERSION_OFF },
00022   {   1, INVERSION_ON },
00023   { 999, INVERSION_AUTO },
00024   { -1 }
00025   };
00026 
00027 const tChannelParameterMap BandwidthValues[] = {
00028   {   6, BANDWIDTH_6_MHZ },
00029   {   7, BANDWIDTH_7_MHZ },
00030   {   8, BANDWIDTH_8_MHZ },
00031   { 999, BANDWIDTH_AUTO },
00032   { -1 }
00033   };
00034 
00035 const tChannelParameterMap CoderateValues[] = {
00036   {   0, FEC_NONE },
00037   {  12, FEC_1_2 },
00038   {  23, FEC_2_3 },
00039   {  34, FEC_3_4 },
00040   {  45, FEC_4_5 },
00041   {  56, FEC_5_6 },
00042   {  67, FEC_6_7 },
00043   {  78, FEC_7_8 },
00044   {  89, FEC_8_9 },
00045   { 999, FEC_AUTO },
00046   { -1 }
00047   };
00048 
00049 const tChannelParameterMap ModulationValues[] = {
00050   {   0, QPSK },
00051   {  16, QAM_16 },
00052   {  32, QAM_32 },
00053   {  64, QAM_64 },
00054   { 128, QAM_128 },
00055   { 256, QAM_256 },
00056   { 999, QAM_AUTO },
00057   { -1 }
00058   };
00059 
00060 const tChannelParameterMap TransmissionValues[] = {
00061   {   2, TRANSMISSION_MODE_2K },
00062   {   8, TRANSMISSION_MODE_8K },
00063   { 999, TRANSMISSION_MODE_AUTO },
00064   { -1 }
00065   };
00066 
00067 const tChannelParameterMap GuardValues[] = {
00068   {   4, GUARD_INTERVAL_1_4 },
00069   {   8, GUARD_INTERVAL_1_8 },
00070   {  16, GUARD_INTERVAL_1_16 },
00071   {  32, GUARD_INTERVAL_1_32 },
00072   { 999, GUARD_INTERVAL_AUTO },
00073   { -1 }
00074   };
00075 
00076 const tChannelParameterMap HierarchyValues[] = {
00077   {   0, HIERARCHY_NONE },
00078   {   1, HIERARCHY_1 },
00079   {   2, HIERARCHY_2 },
00080   {   4, HIERARCHY_4 },
00081   { 999, HIERARCHY_AUTO },
00082   { -1 }
00083   };
00084 
00085 int UserIndex(int Value, const tChannelParameterMap *Map)
00086 {
00087   const tChannelParameterMap *map = Map;
00088   while (map && map->userValue != -1) {
00089         if (map->userValue == Value)
00090            return map - Map;
00091         map++;
00092         }
00093   return -1;
00094 }
00095 
00096 int DriverIndex(int Value, const tChannelParameterMap *Map)
00097 {
00098   const tChannelParameterMap *map = Map;
00099   while (map && map->userValue != -1) {
00100         if (map->driverValue == Value)
00101            return map - Map;
00102         map++;
00103         }
00104   return -1;
00105 }
00106 
00107 int MapToUser(int Value, const tChannelParameterMap *Map)
00108 {
00109   int n = DriverIndex(Value, Map);
00110   if (n >= 0)
00111      return Map[n].userValue;
00112   return -1;
00113 }
00114 
00115 int MapToDriver(int Value, const tChannelParameterMap *Map)
00116 {
00117   int n = UserIndex(Value, Map);
00118   if (n >= 0)
00119      return Map[n].driverValue;
00120   return -1;
00121 }
00122 
00123 // -- tChannelID -------------------------------------------------------------
00124 
00125 const tChannelID tChannelID::InvalidID;
00126 
00127 bool tChannelID::operator== (const tChannelID &arg) const
00128 {
00129   return source == arg.source && nid == arg.nid && tid == arg.tid && sid == arg.sid && rid == arg.rid;
00130 }
00131 
00132 tChannelID tChannelID::FromString(const char *s)
00133 {
00134   char *sourcebuf = NULL;
00135   int nid;
00136   int tid;
00137   int sid;
00138   int rid = 0;
00139   int fields = sscanf(s, "%a[^-]-%d-%d-%d-%d", &sourcebuf, &nid, &tid, &sid, &rid);
00140   if (fields == 4 || fields == 5) {
00141      int source = cSource::FromString(sourcebuf);
00142      free(sourcebuf);
00143      if (source >= 0)
00144         return tChannelID(source, nid, tid, sid, rid);
00145      }
00146   return tChannelID::InvalidID;
00147 }
00148 
00149 const char *tChannelID::ToString(void)
00150 {
00151   static char buffer[256];
00152   snprintf(buffer, sizeof(buffer), rid ? "%s-%d-%d-%d-%d" : "%s-%d-%d-%d", cSource::ToString(source), nid, tid, sid, rid);
00153   return buffer;
00154 }
00155 
00156 // -- cChannel ---------------------------------------------------------------
00157 
00158 char *cChannel::buffer = NULL;
00159 
00160 cChannel::cChannel(void)
00161 {
00162   strcpy(name,   "Pro7");
00163   frequency    = 12480;
00164   source       = cSource::FromString("S19.2E");
00165   srate        = 27500;
00166   vpid         = 255;
00167   apid1        = 256;
00168   apid2        = 0;
00169   dpid1        = 257;
00170   dpid2        = 0;
00171   tpid         = 32;
00172   ca           = 0;
00173   nid          = 0;
00174   tid          = 0;
00175   sid          = 888;
00176   rid          = 0;
00177   number       = 0;
00178   groupSep     = false;
00179   polarization = 'v';
00180   inversion    = INVERSION_AUTO;
00181   bandwidth    = BANDWIDTH_AUTO;
00182   coderateH    = FEC_AUTO;
00183   coderateL    = FEC_AUTO;
00184   modulation   = QAM_AUTO;
00185   transmission = TRANSMISSION_MODE_AUTO;
00186   guard        = GUARD_INTERVAL_AUTO;
00187   hierarchy    = HIERARCHY_AUTO;
00188 }
00189 
00190 cChannel& cChannel::operator= (const cChannel &Channel)
00191 {
00192   memcpy(&__BeginData__, &Channel.__BeginData__, (char *)&Channel.__EndData__ - (char *)&Channel.__BeginData__);
00193   return *this;
00194 }
00195 
00196 static int MHz(int frequency)
00197 {
00198   while (frequency > 20000)
00199         frequency /= 1000;
00200   return frequency;
00201 }
00202 
00203 tChannelID cChannel::GetChannelID(void) const
00204 {
00205   return tChannelID(source, nid, nid ? tid : MHz(frequency), sid, rid);
00206 }
00207 
00208 static int PrintParameter(char *p, char Name, int Value)
00209 {
00210   return Value >= 0 && Value != 999 ? sprintf(p, "%c%d", Name, Value) : 0;
00211 }
00212 
00213 const char *cChannel::ParametersToString(void)
00214 {
00215   char type = *cSource::ToString(source);
00216   if (isdigit(type))
00217      type = 'S';
00218 #define ST(s) if (strchr(s, type))
00219   static char buffer[64];
00220   char *q = buffer;
00221   *q = 0;
00222   ST(" S ")  q += sprintf(q, "%c", polarization);
00223   ST("CST")  q += PrintParameter(q, 'I', MapToUser(inversion, InversionValues));
00224   ST("CST")  q += PrintParameter(q, 'C', MapToUser(coderateH, CoderateValues));
00225   ST("  T")  q += PrintParameter(q, 'D', MapToUser(coderateL, CoderateValues));
00226   ST("C T")  q += PrintParameter(q, 'M', MapToUser(modulation, ModulationValues));
00227   ST("  T")  q += PrintParameter(q, 'B', MapToUser(bandwidth, BandwidthValues));
00228   ST("  T")  q += PrintParameter(q, 'T', MapToUser(transmission, TransmissionValues));
00229   ST("  T")  q += PrintParameter(q, 'G', MapToUser(guard, GuardValues));
00230   ST("  T")  q += PrintParameter(q, 'Y', MapToUser(hierarchy, HierarchyValues));
00231   return buffer;
00232 }
00233 
00234 static const char *ParseParameter(const char *s, int &Value, const tChannelParameterMap *Map)
00235 {
00236   if (*++s) {
00237      char *p = NULL;
00238      errno = 0;
00239      int n = strtol(s, &p, 10);
00240      if (!errno && p != s) {
00241         Value = MapToDriver(n, Map);
00242         if (Value >= 0)
00243            return p;
00244         }
00245      }
00246   esyslog("ERROR: illegal value for parameter '%c'", *(s - 1));
00247   return NULL;
00248 }
00249 
00250 bool cChannel::StringToParameters(const char *s)
00251 {
00252   while (s && *s) {
00253         switch (toupper(*s)) {
00254           case 'B': s = ParseParameter(s, bandwidth, BandwidthValues); break;
00255           case 'C': s = ParseParameter(s, coderateH, CoderateValues); break;
00256           case 'D': s = ParseParameter(s, coderateL, CoderateValues); break;
00257           case 'G': s = ParseParameter(s, guard, GuardValues); break;
00258           case 'H': polarization = *s++; break;
00259           case 'I': s = ParseParameter(s, inversion, InversionValues); break;
00260           // 'L' reserved for possible circular polarization
00261           case 'M': s = ParseParameter(s, modulation, ModulationValues); break;
00262           // 'R' reserved for possible circular polarization
00263           case 'T': s = ParseParameter(s, transmission, TransmissionValues); break;
00264           case 'V': polarization = *s++; break;
00265           case 'Y': s = ParseParameter(s, hierarchy, HierarchyValues); break;
00266           default: esyslog("ERROR: unknown parameter key '%c'", *s);
00267                    return false;
00268           }
00269         }
00270   return true;
00271 }
00272 
00273 const char *cChannel::ToText(cChannel *Channel)
00274 {
00275   char buf[MaxChannelName * 2];
00276   char *s = Channel->name;
00277   if (strchr(s, ':')) {
00278      s = strcpy(buf, s);
00279      strreplace(s, ':', '|');
00280      }
00281   free(buffer);
00282   if (Channel->groupSep) {
00283      if (Channel->number)
00284         asprintf(&buffer, ":@%d %s\n", Channel->number, s);
00285      else
00286         asprintf(&buffer, ":%s\n", s);
00287      }
00288   else {
00289      char apidbuf[32];
00290      char *q = apidbuf;
00291      q += snprintf(q, sizeof(apidbuf), "%d", Channel->apid1);
00292      if (Channel->apid2)
00293         q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ",%d", Channel->apid2);
00294      if (Channel->dpid1 || Channel->dpid2)
00295         q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ";%d", Channel->dpid1);
00296      if (Channel->dpid2)
00297         q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ",%d", Channel->dpid2);
00298      *q = 0;
00299      asprintf(&buffer, "%s:%d:%s:%s:%d:%d:%s:%d:%d:%d:%d:%d:%d\n", s, Channel->frequency, Channel->ParametersToString(), cSource::ToString(Channel->source), Channel->srate, Channel->vpid, apidbuf, Channel->tpid, Channel->ca, Channel->sid, Channel->nid, Channel->tid, Channel->rid);
00300      }
00301   return buffer;
00302 }
00303 
00304 const char *cChannel::ToText(void)
00305 {
00306   return ToText(this);
00307 }
00308 
00309 bool cChannel::Parse(const char *s, bool AllowNonUniqueID)
00310 {
00311   if (*s == ':') {
00312      groupSep = true;
00313      if (*++s == '@' && *++s) {
00314         char *p = NULL;
00315         errno = 0;
00316         int n = strtol(s, &p, 10);
00317         if (!errno && p != s && n > 0) {
00318            number = n;
00319            s = p;
00320            }
00321         }
00322      strn0cpy(name, skipspace(s), MaxChannelName);
00323      }
00324   else {
00325      groupSep = false;
00326      char *namebuf = NULL;
00327      char *sourcebuf = NULL;
00328      char *parambuf = NULL;
00329      char *apidbuf = NULL;
00330      int fields = sscanf(s, "%a[^:]:%d :%a[^:]:%a[^:] :%d :%d :%a[^:]:%d :%d :%d :%d :%d :%d ", &namebuf, &frequency, &parambuf, &sourcebuf, &srate, &vpid, &apidbuf, &tpid, &ca, &sid, &nid, &tid, &rid);
00331      if (fields >= 9) {
00332         if (fields == 9) {
00333            // allow reading of old format
00334            sid = ca;
00335            ca = tpid;
00336            tpid = 0;
00337            }
00338         apid1 = apid2 = 0;
00339         dpid1 = dpid2 = 0;
00340         bool ok = false;
00341         if (parambuf && sourcebuf && apidbuf) {
00342            ok = StringToParameters(parambuf) && (source = cSource::FromString(sourcebuf)) >= 0;
00343            char *p = strchr(apidbuf, ';');
00344            if (p)
00345               *p++ = 0;
00346            sscanf(apidbuf, "%d ,%d ", &apid1, &apid2);
00347            if (p)
00348               sscanf(p, "%d ,%d ", &dpid1, &dpid2);
00349            }
00350         strn0cpy(name, namebuf, MaxChannelName);
00351         free(parambuf);
00352         free(sourcebuf);
00353         free(apidbuf);
00354         free(namebuf);
00355         if (!AllowNonUniqueID && Channels.GetByChannelID(GetChannelID())) {
00356            esyslog("ERROR: channel data not unique!");
00357            return false;
00358            }
00359         return ok;
00360         }
00361      else
00362         return false;
00363      }
00364   strreplace(name, '|', ':');
00365   return true;
00366 }
00367 
00368 bool cChannel::Save(FILE *f)
00369 {
00370   return fprintf(f, ToText()) > 0;
00371 }
00372 
00373 // -- cChannels --------------------------------------------------------------
00374 
00375 cChannels Channels;
00376 
00377 bool cChannels::Load(const char *FileName, bool AllowComments)
00378 {
00379   if (cConfig<cChannel>::Load(FileName, AllowComments)) {
00380      ReNumber();
00381      return true;
00382      }
00383   return false;
00384 }
00385 
00386 int cChannels::GetNextGroup(int Idx)
00387 {
00388   cChannel *channel = Get(++Idx);
00389   while (channel && !(channel->GroupSep() && *channel->Name()))
00390         channel = Get(++Idx);
00391   return channel ? Idx : -1;
00392 }
00393 
00394 int cChannels::GetPrevGroup(int Idx)
00395 {
00396   cChannel *channel = Get(--Idx);
00397   while (channel && !(channel->GroupSep() && *channel->Name()))
00398         channel = Get(--Idx);
00399   return channel ? Idx : -1;
00400 }
00401 
00402 int cChannels::GetNextNormal(int Idx)
00403 {
00404   cChannel *channel = Get(++Idx);
00405   while (channel && channel->GroupSep())
00406         channel = Get(++Idx);
00407   return channel ? Idx : -1;
00408 }
00409 
00410 void cChannels::ReNumber( void )
00411 {
00412   int Number = 1;
00413   for (cChannel *channel = First(); channel; channel = Next(channel)) {
00414       if (channel->GroupSep()) {
00415          if (channel->Number() > Number)
00416             Number = channel->Number();
00417          }
00418       else
00419          channel->SetNumber(Number++);
00420       }
00421   maxNumber = Number - 1;
00422 }
00423 
00424 cChannel *cChannels::GetByNumber(int Number, int SkipGap)
00425 {
00426   cChannel *previous = NULL;
00427   for (cChannel *channel = First(); channel; channel = Next(channel)) {
00428       if (!channel->GroupSep()) {
00429          if (channel->Number() == Number)
00430             return channel;
00431          else if (SkipGap && channel->Number() > Number)
00432             return SkipGap > 0 ? channel : previous;
00433          previous = channel;
00434          }
00435       }
00436   return NULL;
00437 }
00438 
00439 cChannel *cChannels::GetByServiceID(int Source, unsigned short ServiceID)
00440 {
00441   for (cChannel *channel = First(); channel; channel = Next(channel)) {
00442       if (!channel->GroupSep() && channel->Source() == Source && channel->Sid() == ServiceID)
00443          return channel;
00444       }
00445   return NULL;
00446 }
00447 
00448 cChannel *cChannels::GetByChannelID(tChannelID ChannelID, bool TryWithoutRid)
00449 {
00450   for (cChannel *channel = First(); channel; channel = Next(channel)) {
00451       if (!channel->GroupSep() && channel->GetChannelID() == ChannelID)
00452          return channel;
00453       }
00454   if (TryWithoutRid) {
00455      ChannelID.ClrRid();
00456      for (cChannel *channel = First(); channel; channel = Next(channel)) {
00457          if (!channel->GroupSep() && channel->GetChannelID().ClrRid() == ChannelID)
00458             return channel;
00459          }
00460      }
00461   return NULL;
00462 }
00463 
00464 bool cChannels::HasUniqueChannelID(cChannel *NewChannel, cChannel *OldChannel)
00465 {
00466   tChannelID NewChannelID = NewChannel->GetChannelID();
00467   for (cChannel *channel = First(); channel; channel = Next(channel)) {
00468       if (!channel->GroupSep() && channel != OldChannel && channel->GetChannelID() == NewChannelID)
00469          return false;
00470       }
00471   return true;
00472 }
00473 
00474 bool cChannels::SwitchTo(int Number)
00475 {
00476   cChannel *channel = GetByNumber(Number);
00477   return channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true);
00478 }

Generated on Wed Feb 5 23:30:07 2003 for VDR by doxygen1.3-rc2