@@ -194,7 +194,7 @@ private:
public:
cSkinCursesDisplayChannel(bool WithInfo);
virtual ~cSkinCursesDisplayChannel();
- virtual void SetChannel(const cChannel *Channel, int Number);
+ virtual void SetChannel(cChannelConfig channelConfig, int Number);
virtual void SetEvents(const cEvent *Present, const cEvent *Following);
virtual void SetMessage(eMessageType Type, const char *Text);
virtual void Flush(void);
@@ -214,10 +214,10 @@ cSkinCursesDisplayChannel::~cSkinCursesDisplayChannel()
delete osd;
}
-void cSkinCursesDisplayChannel::SetChannel(const cChannel *Channel, int Number)
+void cSkinCursesDisplayChannel::SetChannel(cChannelConfig channelConfig, int Number)
{
osd->DrawRectangle(0, 0, ScOsdWidth - 1, 0, clrBackground);
- osd->DrawText(0, 0, ChannelString(Channel, Number), clrWhite, clrBackground, &Font);
+ osd->DrawText(0, 0, ChannelString(channelConfig, Number), clrWhite, clrBackground, &Font);
}
void cSkinCursesDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
@@ -13,6 +13,7 @@
#include "epg.h"
#include "libsi/si.h"
#include "timers.h"
+#include "sources.h"
// IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
// format characters in order to allow any number of blanks after a numeric
@@ -697,6 +698,12 @@ bool cChannel::Save(FILE *f)
return fprintf(f, "%s", *ToText()) > 0;
}
+bool cChannel::IsAtsc(void) const { return cSource::IsAtsc(source); }
+bool cChannel::IsCable(void) const { return cSource::IsCable(source); }
+bool cChannel::IsSat(void) const { return cSource::IsSat(source); }
+bool cChannel::IsTerr(void) const { return cSource::IsTerr(source); }
+bool cChannel::IsSourceType(char Source) const { return cSource::IsType(source, Source); }
+
// --- cChannelSorter --------------------------------------------------------
class cChannelSorter : public cListObject {
@@ -924,14 +931,20 @@ cChannel *cChannels::NewChannel(const cChannel *Transponder, const char *Name, c
return NULL;
}
-cString ChannelString(const cChannel *Channel, int Number)
+cString ChannelString(cChannelConfig cc, int Number)
{
char buffer[256];
- if (Channel) {
- if (Channel->GroupSep())
- snprintf(buffer, sizeof(buffer), "%s", Channel->Name());
- else
- snprintf(buffer, sizeof(buffer), "%d%s %s", Channel->Number(), Number ? "-" : "", Channel->Name());
+ const cChannel *selected = Channels.Get(cc.selected()-1);
+ const cChannel *receiving = Channels.Get(cc.receiving()-1);
+ if (selected) {
+ if (selected->GroupSep())
+ snprintf(buffer, sizeof(buffer), "%s", selected->Name());
+ else {
+ if (selected == receiving || receiving == NULL)
+ snprintf(buffer, sizeof(buffer), "%d%s %s", selected->Number(), Number ? "-" : "", selected->Name());
+ else
+ snprintf(buffer, sizeof(buffer), "%d(%d)%s %s", selected->Number(), receiving->Number(), Number ? "-" : "", selected->Name());
+ }
}
else if (Number)
snprintf(buffer, sizeof(buffer), "%d-", Number);
@@ -10,10 +10,9 @@
#ifndef __CHANNELS_H
#define __CHANNELS_H
-#include "config.h"
-#include "sources.h"
#include "thread.h"
#include "tools.h"
+#include "config.h"
#define ISTRANSPONDER(f1, f2) (abs((f1) - (f2)) < 4) //XXX
@@ -176,11 +175,11 @@ public:
const char *Parameters(void) const { return parameters; }
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); }
+ bool IsAtsc(void) const;
+ bool IsCable(void) const;
+ bool IsSat(void) const;
+ bool IsTerr(void) const;
+ bool IsSourceType(char Source) const;
tChannelID GetChannelID(void) const { return tChannelID(source, nid, (nid || tid) ? tid : Transponder(), sid, rid); }
bool HasTimer(void) const;
int Modification(int Mask = CHANNELMOD_ALL);
@@ -234,6 +233,18 @@ public:
extern cChannels Channels;
-cString ChannelString(const cChannel *Channel, int Number);
+class cChannelConfig {
+private:
+ const int selectedChannel;
+ const int receivingChannel;
+public:
+ cChannelConfig(
+ int selectedChannel, int receivingChannel) :
+ selectedChannel(selectedChannel), receivingChannel(receivingChannel) { }
+ int selected() {return selectedChannel;}
+ int receiving() {return receivingChannel;}
+};
+
+cString ChannelString(cChannelConfig cc, int Number);
#endif //__CHANNELS_H
@@ -15,6 +15,7 @@
#include "interface.h"
#include "plugin.h"
#include "recording.h"
+#include "sources.h"
// IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
// format characters in order to allow any number of blanks after a numeric
@@ -304,6 +305,228 @@ bool cSetupLine::Save(FILE *f)
return fprintf(f, "%s%s%s = %s\n", plugin ? plugin : "", plugin ? "." : "", name, value) > 0;
}
+// -- Class cAlternative ------------------------------------------------------------
+
+cAlternative::cAlternative(const cChannel *master) : master(master), alternativeChannels() {
+}
+
+void cAlternative::AddAlternativeChannel(const cChannel *Alternative) {
+ if (Alternative == master) return; // master cannot be an alternative
+ cAlternativeContainer *next = alternativeChannels.First();
+ while(next) {
+ if (next->channel == Alternative) return; // Already in list
+ if (Alternative->Number() < next->channel->Number()) {
+ alternativeChannels.Ins(new cAlternativeContainer(Alternative), next);
+ return;
+ }
+ next = alternativeChannels.Next(next);
+ }
+ alternativeChannels.Add(new cAlternativeContainer(Alternative));
+}
+
+void cAlternative::RemoveAlternativeChannel(const cChannel *Alternative) {
+ cAlternativeContainer *next = alternativeChannels.First();
+ while(next) {
+ if (next->channel == Alternative) {
+ alternativeChannels.Del(next, true);
+ return;
+ }
+ next = alternativeChannels.Next(next);
+ }
+}
+
+cList<cAlternativeContainer>& cAlternative::GetAlternativeChannels() {
+
+ return alternativeChannels;
+}
+
+bool cAlternative::operator<(const cAlternative& Other) {
+ if (master->Number() < Other.master->Number())
+ return -1;
+ if (master->Number() > Other.master->Number())
+ return 1;
+ return 0;
+}
+
+const cChannel *cAlternative::GetMaster() {
+ return master;
+}
+
+cAlternative::cAlternative(cAlternative *AlternativeToCopy) {
+ master = AlternativeToCopy->master;
+ alternativeChannels.Clear();
+ cAlternativeContainer *next = AlternativeToCopy->alternativeChannels.First();
+ while(next) {
+ alternativeChannels.Add(new cAlternativeContainer(next->channel));
+ next = AlternativeToCopy->alternativeChannels.Next(next);
+ }
+}
+
+cAlternative& cAlternative::operator= (const cAlternative &Other) {
+ master = Other.master;
+ alternativeChannels.Clear();
+ cAlternativeContainer *next = Other.alternativeChannels.First();
+ while(next) {
+ alternativeChannels.Add(new cAlternativeContainer(next->channel));
+ next = Other.alternativeChannels.Next(next);
+ }
+ return *this;
+}
+
+bool cAlternative::operator==(const cAlternative &Other) {
+ if (master != Other.master) return false;
+ cAlternativeContainer *thisNext = alternativeChannels.First();
+ cAlternativeContainer *otherNext = Other.alternativeChannels.First();
+ while(thisNext != NULL && otherNext != NULL) {
+ if (thisNext == NULL || otherNext == NULL) return false;
+ if (thisNext->channel != otherNext->channel) return false;
+ thisNext = alternativeChannels.Next(thisNext);
+ otherNext = Other.alternativeChannels.Next(otherNext);
+ }
+ return true;
+}
+
+
+cAlternative::~cAlternative() {
+}
+
+void cAlternative::Del(const cChannel *Channel) {
+ for(cAlternativeContainer * next = alternativeChannels.First() ; next ; next = alternativeChannels.Next(next)) {
+ if (next->channel == Channel) {
+ alternativeChannels.Del(next);
+ return;
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////
+// Class: cAllAlternatives
+
+cAlternative *cAllAlternatives::FindAlternative(const cChannel *Master) {
+ Init();
+ for(cAlternative *next = alternatives.First() ; next ; next = alternatives.Next(next)) {
+ if (next->GetMaster() == Master) {
+ return next;
+ }
+ }
+ return NULL;
+}
+
+void cAllAlternatives::CreateAlternative(const cChannel *Master) {
+ Init();
+ if (FindAlternative(Master) == NULL) {
+ cAlternative *ptr = new cAlternative(Master);
+ for(cAlternative *next = alternatives.First() ; next ; next = alternatives.Next(next)) {
+ if (Master->Number() < next->GetMaster()->Number()) {
+ alternatives.Ins(ptr, next);
+ ptr = NULL;
+ break;
+ }
+ }
+ if (ptr) alternatives.Add(ptr);
+ }
+}
+
+void cAllAlternatives::RemoveAlternative(cAlternative* AlternativeToRemove) {
+ Init();
+ for(cAlternative *next = alternatives.First() ; next ; next = alternatives.Next(next)) {
+ if (next == AlternativeToRemove) {
+ alternatives.Del(next, true /*delete*/);
+ return;
+ }
+ }
+}
+
+int cAllAlternatives::CountAlternatives() {
+ Init();
+ return alternatives.Count();
+}
+
+
+cAllAlternatives::~cAllAlternatives() {
+ alternatives.Clear();
+ masterToAlternative.Clear();
+}
+
+cAlternative *cAllAlternatives::GetAlternative(int Index) {
+ Init();
+ cAlternative *next = alternatives.First();
+ while(Index > 0 || next == NULL) {
+ next = alternatives.Next(next);
+ Index--;
+ }
+ return next;
+}
+
+void cAllAlternatives::AddAlternative(const cChannel *Master, const cChannel *AlternativeToAdd) {
+ Init();
+ cAlternative *alt = FindAlternative(Master);
+ if (alt == NULL) {
+ CreateAlternative(Master);
+ alt = FindAlternative(Master);
+ }
+ alt->AddAlternativeChannel(AlternativeToAdd);
+}
+
+void cAllAlternatives::LoadAlternative(int MasterNr, int AlternativeNr) {
+ masterToAlternative.Ins(new cIntPair(MasterNr, AlternativeNr));
+}
+
+void cAllAlternatives::Init() {
+ if (!init) {
+ init = true;
+ for(cIntPair *next = masterToAlternative.First() ; next ; next = masterToAlternative.Next(next)) {
+ const cChannel *master = Channels.Get(next->int1-1);
+ const cChannel *alternative = Channels.Get(next->int2-1);
+ if (master == NULL) continue;
+ if (alternative == NULL) continue;
+ AddAlternative(master, alternative);
+ }
+ }
+}
+
+cAllAlternatives& cAllAlternatives::operator= (const cAllAlternatives &Other) {
+ init = Other.init;
+ masterToAlternative.Clear();
+ for(cIntPair *next = Other.masterToAlternative.First() ; next ; next = Other.masterToAlternative.Next(next)) {
+ masterToAlternative.Add(new cIntPair(*next));
+ }
+ alternatives.Clear();
+ for(cAlternative *next = Other.alternatives.First() ; next ; next = Other.alternatives.Next(next)) {
+ alternatives.Add(new cAlternative(next));
+ }
+ return *this;
+}
+
+bool cAllAlternatives::operator==(cAllAlternatives &Other) {
+ Init();
+ Other.Init();
+ cAlternative *thisNext = alternatives.First();
+ cAlternative *otherNext = Other.alternatives.First();
+ while(thisNext != NULL && otherNext != NULL) {
+ if (thisNext == NULL || otherNext == NULL) return false;
+ if (*thisNext != *otherNext) return false;
+ thisNext = alternatives.Next(thisNext);
+ otherNext = Other.alternatives.Next(otherNext);
+ }
+ return true;
+}
+
+
+void cAllAlternatives::Del(const cChannel *Channel) {
+ for(cAlternative *next = alternatives.First() ; next ; next = alternatives.Next(next)) {
+ if (next->GetMaster() == Channel) {
+ alternatives.Del(next);
+ break;
+ }
+ }
+ for(cAlternative *next = alternatives.First() ; next ; next = alternatives.Next(next)) {
+ next->Del(Channel);
+ }
+}
+
+
// --- cSetup ----------------------------------------------------------------
cSetup Setup;
@@ -404,6 +627,7 @@ cSetup::cSetup(void)
cSetup& cSetup::operator= (const cSetup &s)
{
memcpy(&__BeginData__, &s.__BeginData__, (char *)&s.__EndData__ - (char *)&s.__BeginData__);
+ Alternatives = s.Alternatives;
return *this;
}
@@ -423,7 +647,7 @@ void cSetup::Store(const char *Name, const char *Value, const char *Plugin, bool
if (Name && *Name) {
cSetupLine *l = Get(Name, Plugin);
if (l && !AllowMultiple)
- Del(l);
+ this->cList<cSetupLine>::Del(l);
if (Value)
Add(new cSetupLine(Name, Value, Plugin));
}
@@ -590,11 +814,23 @@ bool cSetup::Parse(const char *Name, const char *Value)
else if (!strcasecmp(Name, "InitialVolume")) InitialVolume = atoi(Value);
else if (!strcasecmp(Name, "ChannelsWrap")) ChannelsWrap = atoi(Value);
else if (!strcasecmp(Name, "EmergencyExit")) EmergencyExit = atoi(Value);
+ else if (strstr(Name, "master:")) return LoadAlternative(Name, Value);
else
return false;
return true;
}
+bool cSetup::LoadAlternative(const char *Name, const char *Value) {
+ Name += strlen("master:");
+ char helper[128];
+ strcpy(helper, Name);
+ helper[strlen(helper)-4] = 0;
+ int masterNr = atoi(helper);
+ int alternativeNr = atoi(Value);
+ Alternatives.LoadAlternative(masterNr, alternativeNr);
+ return true;
+}
+
bool cSetup::Save(void)
{
Store("OSDLanguage", OSDLanguage);
@@ -686,7 +922,7 @@ bool cSetup::Save(void)
Store("InitialVolume", InitialVolume);
Store("ChannelsWrap", ChannelsWrap);
Store("EmergencyExit", EmergencyExit);
-
+ SaveAlternatives();
Sort();
if (cConfig<cSetupLine>::Save()) {
@@ -695,3 +931,48 @@ bool cSetup::Save(void)
}
return false;
}
+
+void cSetup::SaveAlternatives() {
+ // Remove old alternatives or otherwise they will stay forever
+ for(cSetupLine *line = First() ; line ; line = Next(line)) {
+ if (strstr(line->Name(), "master:") == line->Name()) {
+ if (line->Prev() != NULL) {
+ cSetupLine *temp = line;
+ line = Prev(line);
+ this->cList<cSetupLine>::Del(temp);
+ } else {
+ this->cList<cSetupLine>::Del(line);
+ line = First();
+ }
+ }
+ }
+ int counter = 1000;
+ for(int i = 0 ; i < Alternatives.CountAlternatives() ; i++) {
+ cAlternative *alt = Alternatives.GetAlternative(i);
+ cList<cAlternativeContainer> &alternatives = alt->GetAlternativeChannels();
+
+ const cChannel *master = alt->GetMaster();
+
+ for(cAlternativeContainer *next = alternatives.First(); next ; next = alternatives.Next(next)) {
+ cString key = cString::sprintf("master:%d%d", master->Number(), counter);
+ Store(*key, next->channel->Number());
+ counter++;
+ }
+ }
+}
+
+cAllAlternatives& cSetup::getAllAlternatives() {
+ return Alternatives;
+}
+
+cList<cAlternativeContainer>& cSetup::findAlternativeChannels(const cChannel* channel) {
+ cAlternative *alt = Alternatives.FindAlternative(channel);
+ if (alt) {
+ return alt->GetAlternativeChannels();
+ }
+ return nullAlternatives;
+}
+
+void cSetup::Del(const cChannel* Channel) {
+ Alternatives.Del(Channel);
+}
@@ -7,49 +7,18 @@
* $Id: config.h 2.28 2010/09/12 11:31:21 kls Exp $
*/
-#ifndef __CONFIG_H
-#define __CONFIG_H
+#ifndef __CCONFIG_H
+#define __CCONFIG_H
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <time.h>
#include <unistd.h>
#include "i18n.h"
#include "font.h"
#include "tools.h"
-// VDR's own version number:
-
-#define VDRVERSION "1.7.16"
-#define VDRVERSNUM 10716 // Version * 10000 + Major * 100 + Minor
-
-// The plugin API's version number:
-
-#define APIVERSION "1.7.16"
-#define APIVERSNUM 10716 // Version * 10000 + Major * 100 + Minor
-
-// When loading plugins, VDR searches them by their APIVERSION, which
-// may be smaller than VDRVERSION in case there have been no changes to
-// VDR header files since the last APIVERSION. This allows compiled
-// plugins to work with newer versions of the core VDR as long as no
-// VDR header files have changed.
-
-#define MAXPRIORITY 99
-#define MAXLIFETIME 99
-
-#define MINOSDWIDTH 480
-#define MAXOSDWIDTH 1920
-#define MINOSDHEIGHT 324
-#define MAXOSDHEIGHT 1200
-
-#define MaxFileName 256
-#define MaxSkinName 16
-#define MaxThemeName 16
-
-typedef uint32_t in_addr_t; //XXX from /usr/include/netinet/in.h (apparently this is not defined on systems with glibc < 2.2)
-
class cSVDRPhost : public cListObject {
private:
struct in_addr addr;
@@ -144,6 +113,44 @@ public:
}
};
+
+#endif //__CCONFIG_H
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include "channels.h"
+
+// VDR's own version number:
+
+#define VDRVERSION "1.7.16"
+#define VDRVERSNUM 10716 // Version * 10000 + Major * 100 + Minor
+
+// The plugin API's version number:
+
+#define APIVERSION "1.7.16"
+#define APIVERSNUM 10716 // Version * 10000 + Major * 100 + Minor
+
+// When loading plugins, VDR searches them by their APIVERSION, which
+// may be smaller than VDRVERSION in case there have been no changes to
+// VDR header files since the last APIVERSION. This allows compiled
+// plugins to work with newer versions of the core VDR as long as no
+// VDR header files have changed.
+
+#define MAXPRIORITY 99
+#define MAXLIFETIME 99
+
+#define MINOSDWIDTH 480
+#define MAXOSDWIDTH 1920
+#define MINOSDHEIGHT 324
+#define MAXOSDHEIGHT 1200
+
+#define MaxFileName 256
+#define MaxSkinName 16
+#define MaxThemeName 16
+
+typedef uint32_t in_addr_t; //XXX from /usr/include/netinet/in.h (apparently this is not defined on systems with glibc < 2.2)
+
class cNestedItem : public cListObject {
private:
char *text;
@@ -200,6 +207,70 @@ public:
bool Save(FILE *f);
};
+class cChannel;
+
+// -- Class cAlternativeContainer
+
+class cAlternativeContainer : public cListObject {
+public:
+ const cChannel *channel;
+ cAlternativeContainer(const cChannel *channel) : channel(channel) { };
+ cAlternativeContainer(const cAlternativeContainer& ref) {*this=ref;};
+ cAlternativeContainer& operator=(const cAlternativeContainer& ref) {channel = ref.channel;return *this;};
+};
+
+class cAlternative : public cListObject {
+private:
+ const cChannel *master;
+ cList<cAlternativeContainer> alternativeChannels;
+public:
+ cAlternative(const cChannel *master);
+ cAlternative(cAlternative &other) { *this = other;};
+ cAlternative(cAlternative *other);
+ void AddAlternativeChannel(const cChannel *Alternative);
+ void RemoveAlternativeChannel(const cChannel *alternative);
+ cList<cAlternativeContainer>& GetAlternativeChannels();
+ // < Returns a reference the alternative channel cList
+ const cChannel* GetMaster();
+ bool operator<(const cAlternative& other);
+ cAlternative& operator= (const cAlternative &s);
+ bool operator==(const cAlternative &Other);
+ bool operator!=(const cAlternative &Other) { return !(*this == Other);}
+ virtual ~cAlternative();
+ void Del(const cChannel *Channel);
+};
+
+class cIntPair : public cListObject {
+public:
+ int int1, int2;
+ cIntPair(int int1, int int2) : int1(int1), int2(int2) { }
+};
+
+class cAllAlternatives {
+ friend class cSetup;
+private:
+ cList<cAlternative> alternatives;
+ cList<cIntPair> masterToAlternative;
+ // Cache because when parsing the configuration the channels are not parsed yet.
+ void Init();
+ bool init;
+ cAlternative *FindAlternative(const cChannel *Master);
+public:
+ cAlternative *GetAlternative(int Index); // zero-based index
+ void CreateAlternative(const cChannel *Mmaster);
+ void RemoveAlternative(cAlternative *Alternative);
+ virtual ~cAllAlternatives();
+ int CountAlternatives();
+ void AddAlternative(const cChannel *Master, const cChannel *AlternativeToAdd);
+ cAllAlternatives() : init(false) { };
+ cAllAlternatives(cAllAlternatives &Other) { *this = Other;};
+ void LoadAlternative(int MasterNr, int AlternativeNr);
+ cAllAlternatives& operator= (const cAllAlternatives &Other);
+ bool operator==(cAllAlternatives &Other);
+ bool operator!=(cAllAlternatives &Other) { return !(*this == Other);}
+ void Del(const cChannel *Channel);
+};
+
class cSetup : public cConfig<cSetupLine> {
friend class cPlugin; // needs to be able to call Store()
private:
@@ -210,7 +281,9 @@ private:
void Store(const char *Name, const char *Value, const char *Plugin = NULL, bool AllowMultiple = false);
void Store(const char *Name, int Value, const char *Plugin = NULL);
void Store(const char *Name, double &Value, const char *Plugin = NULL);
+ cList<cAlternativeContainer> nullAlternatives;
public:
+ cAllAlternatives Alternatives;
// Also adjust cMenuSetup (menu.c) when adding parameters here!
int __BeginData__;
char OSDLanguage[I18N_MAX_LOCALE_LEN];
@@ -296,6 +369,11 @@ public:
cSetup& operator= (const cSetup &s);
bool Load(const char *FileName);
bool Save(void);
+ bool LoadAlternative(const char *Name, const char *Value);
+ void SaveAlternatives();
+ cAllAlternatives& getAllAlternatives();
+ cList<cAlternativeContainer>& findAlternativeChannels(const cChannel* channel);
+ void Del(const cChannel *Channel);
};
extern cSetup Setup;
@@ -67,7 +67,8 @@ bool cDeviceHook::DeviceProvidesTransponder(const cDevice *Device, const cChanne
int cDevice::numDevices = 0;
int cDevice::useDevice = 0;
int cDevice::nextCardIndex = 0;
-int cDevice::currentChannel = 1;
+int cDevice::currentSelectedChannel = 1;
+int cDevice::currentReceivingChannel = 1;
cDevice *cDevice::device[MAXDEVICES] = { NULL };
cDevice *cDevice::primaryDevice = NULL;
cDevice *cDevice::avoidDevice = NULL;
@@ -228,7 +229,52 @@ static int GetClippedNumProvidedSystems(int AvailableBits, cDevice *Device)
return NumProvidedSystems;
}
-cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView)
+cDevice *cDevice::QueryDevice(const cChannel *Channel, int Priority, bool LiveView, const cChannel *&foundChannelRef, bool allowAlternatives)
+{
+ cList<cAlternativeContainer> &alternatives = Setup.findAlternativeChannels(Channel);
+ if (!LiveView) {
+ /*
+ * Searching for alternative without detaching is not relevant for LiveView.
+ * Why?: There can be other receivers with priority = -1 (like osdteletext) and
+ * there are no other receivers with priority <= 0 for live view. Timers,
+ * streamdev and so on have receivers with priority > 0. So detaching is allowed.
+ */
+ // first try original channel without detaching
+ cDevice *device = GetDevice(Channel, Priority, LiveView, false);
+ if (device) {
+ foundChannelRef = Channel;
+ return device;
+ }
+ // now try alternatives without detaching
+ if (allowAlternatives) {
+ for(cAlternativeContainer *next = alternatives.First(); next ; next = alternatives.Next(next)) {
+ device = GetDevice(next->channel, Priority, LiveView, false);
+ if (device) {
+ foundChannelRef = next->channel;
+ return device;
+ }
+ }
+ }
+ }
+ // once again the same steps, this time detaching is allowed
+ cDevice *device = GetDevice(Channel, Priority, LiveView, true);
+ if (device) {
+ foundChannelRef = Channel;
+ return device;
+ }
+ if (allowAlternatives) {
+ for(cAlternativeContainer *next = alternatives.First(); next ; next = alternatives.Next(next)) {
+ device = GetDevice(next->channel, Priority, LiveView, true);
+ if (device) {
+ foundChannelRef = next->channel;
+ return device;
+ }
+ }
+ }
+ return NULL;
+}
+
+cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView, bool DetachingAllowed)
{
cDevice *AvoidDevice = avoidDevice;
avoidDevice = NULL;
@@ -291,12 +337,18 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView
imp <<= 1; imp |= device[i]->HasDecoder(); // avoid full featured cards
imp <<= 1; imp |= NumUsableSlots ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), j + 1) : 0; // prefer CAMs that are known to decrypt this channel
if (imp < Impact) {
+ // If this is the primary device and not live view, this is like detaching.
+ // The primary device can be used if there is a player (=>Not watching live tv)
+ bool likeNdr = device[i]->IsPrimaryDevice() && !LiveView && device[i]->player == NULL;
// This device has less impact than any previous one, so we take it.
- Impact = imp;
- d = device[i];
- NeedsDetachReceivers = ndr;
- if (NumUsableSlots)
- s = CamSlots.Get(j);
+ if (DetachingAllowed && (ndr || likeNdr) || !ndr) {
+ // Only use the device if detaching is allowed or detaching is not needed
+ Impact = imp;
+ d = device[i];
+ NeedsDetachReceivers = ndr;
+ if (NumUsableSlots)
+ s = CamSlots.Get(j);
+ }
}
}
}
@@ -660,12 +712,13 @@ bool cDevice::SwitchChannel(int Direction)
Direction = sgn(Direction);
if (Direction) {
cControl::Shutdown(); // prevents old channel from being shown too long if GetDevice() takes longer
- int n = CurrentChannel() + Direction;
+ int n = CurrentChannelConfig().selected() + Direction;
int first = n;
cChannel *channel;
+ const cChannel *ptrAlternative;
while ((channel = Channels.GetByNumber(n, Direction)) != NULL) {
// try only channels which are currently available
- if (GetDevice(channel, 0, true))
+ if (QueryDevice(channel, 0, true, ptrAlternative))
break;
n = channel->Number() + Direction;
}
@@ -692,7 +745,15 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
DELETENULL(dvbSubtitleConverter);
}
- cDevice *Device = (LiveView && IsPrimaryDevice()) ? GetDevice(Channel, 0, LiveView) : this;
+ cDevice *Device = NULL;
+ const cChannel *SourceChannel = NULL;
+ if (LiveView && IsPrimaryDevice()) {
+ Device = QueryDevice(Channel, 0, LiveView, SourceChannel);
+ }
+ else {
+ Device = this;
+ SourceChannel = Channel;
+ }
bool NeedsTransferMode = Device != this;
@@ -704,8 +765,8 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
if (NeedsTransferMode) {
if (Device && CanReplay()) {
cStatus::MsgChannelSwitch(this, 0); // only report status if we are actually going to switch the channel
- if (Device->SetChannel(Channel, false) == scrOk) // calling SetChannel() directly, not SwitchChannel()!
- cControl::Launch(new cTransferControl(Device, Channel));
+ if (Device->SetChannel(SourceChannel, false) == scrOk) // calling SetChannel() directly, not SwitchChannel()!
+ cControl::Launch(new cTransferControl(Device, SourceChannel));
else
Result = scrNoTransfer;
}
@@ -714,6 +775,7 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
}
else {
Channels.Lock(false);
+
cStatus::MsgChannelSwitch(this, 0); // only report status if we are actually going to switch the channel
// Stop section handling:
if (sectionHandler) {
@@ -723,11 +785,11 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
// Tell the camSlot about the channel switch and add all PIDs of this
// channel to it, for possible later decryption:
if (camSlot)
- camSlot->AddChannel(Channel);
- if (SetChannelDevice(Channel, LiveView)) {
+ camSlot->AddChannel(SourceChannel);
+ if (SetChannelDevice(SourceChannel, LiveView)) {
// Start section handling:
if (sectionHandler) {
- sectionHandler->SetChannel(Channel);
+ sectionHandler->SetChannel(SourceChannel);
sectionHandler->SetStatus(true);
}
// Start decrypting any PIDs that might have been set in SetChannelDevice():
@@ -741,17 +803,18 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
if (Result == scrOk) {
if (LiveView && IsPrimaryDevice()) {
- currentChannel = Channel->Number();
+ currentSelectedChannel = Channel->Number();
+ currentReceivingChannel = SourceChannel->Number();
// Set the available audio tracks:
ClrAvailableTracks();
for (int i = 0; i < MAXAPIDS; i++)
- SetAvailableTrack(ttAudio, i, Channel->Apid(i), Channel->Alang(i));
+ SetAvailableTrack(ttAudio, i, SourceChannel->Apid(i), SourceChannel->Alang(i));
if (Setup.UseDolbyDigital) {
for (int i = 0; i < MAXDPIDS; i++)
- SetAvailableTrack(ttDolby, i, Channel->Dpid(i), Channel->Dlang(i));
+ SetAvailableTrack(ttDolby, i, SourceChannel->Dpid(i), SourceChannel->Dlang(i));
}
for (int i = 0; i < MAXSPIDS; i++)
- SetAvailableTrack(ttSubtitle, i, Channel->Spid(i), Channel->Slang(i));
+ SetAvailableTrack(ttSubtitle, i, SourceChannel->Spid(i), SourceChannel->Slang(i));
if (!NeedsTransferMode)
EnsureAudioTrack(true);
EnsureSubtitleTrack();
@@ -765,7 +828,7 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
void cDevice::ForceTransferMode(void)
{
if (!cTransferControl::ReceiverDevice()) {
- cChannel *Channel = Channels.GetByNumber(CurrentChannel());
+ cChannel *Channel = Channels.GetByNumber(CurrentChannelConfig().receiving());
if (Channel)
SetChannelDevice(Channel, false); // this implicitly starts Transfer Mode
}
@@ -138,7 +138,12 @@ public:
///< Gets the device with the given Index.
///< \param Index must be in the range 0..numDevices-1.
///< \return A pointer to the device, or NULL if the Index was invalid.
- static cDevice *GetDevice(const cChannel *Channel, int Priority, bool LiveView);
+ static cDevice *QueryDevice(const cChannel *Channel, int Priority, bool LiveView, const cChannel *&foundChannelRef, bool allowAlternatives = true);
+ ///< Search for a device providing the given channel Channel. If other
+ ///< receivers would get detached, the alternative channels gets queried.
+ ///< The returned device doesn't have to provide the given channel. It
+ ///< will provide the returned channel foundChannelRef
+ static cDevice *GetDevice(const cChannel *Channel, int Priority, bool LiveView, bool DetachingAllowed = true);
///< Returns a device that is able to receive the given Channel at the
///< given Priority, with the least impact on active recordings and
///< live viewing. The LiveView parameter tells whether the device will
@@ -218,7 +223,9 @@ public:
// Channel facilities
protected:
- static int currentChannel;
+ static int currentSelectedChannel;
+
+ static int currentReceivingChannel;
public:
virtual bool ProvidesSource(int Source) const;
///< Returns true if this device can provide the given source.
@@ -275,9 +282,16 @@ protected:
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
///< Sets the device to the given channel (actual physical setup).
public:
- static int CurrentChannel(void) { return primaryDevice ? currentChannel : 0; }
- ///< Returns the number of the current channel on the primary device.
- static void SetCurrentChannel(const cChannel *Channel) { currentChannel = Channel ? Channel->Number() : 0; }
+ static cChannelConfig CurrentChannelConfig(void) { return primaryDevice ? cChannelConfig(currentSelectedChannel, currentReceivingChannel) : cChannelConfig(0,0); }
+ static int CurrentChannel(void) { return primaryDevice ? currentSelectedChannel:0; }
+ ///< Returns the number of the current selected channel on the primary device.
+ static int CurrentReceivingChannel(void) { return primaryDevice ? currentReceivingChannel : 0; }
+ ///< Returns the number of the current receiving channel on the primary device.
+ static void SetCurrentChannel(const cChannel *Channel) { currentSelectedChannel = Channel ? Channel->Number() : 0; }
+ ///< Sets the number of the current channel on the primary device, without
+ ///< actually switching to it. This can be used to correct the current
+ ///< channel number while replaying.
+ static void SetReceivingChannel(const cChannel *Channel) { currentReceivingChannel = Channel ? Channel->Number() : 0; }
///< Sets the number of the current channel on the primary device, without
///< actually switching to it. This can be used to correct the current
///< channel number while replaying.
@@ -20,6 +20,7 @@
#include "dvbci.h"
#include "menuitems.h"
#include "sourceparams.h"
+#include "sources.h"
#define FE_CAN_TURBO_FEC 0x8000000 // TODO: remove this once it is defined in the driver
@@ -155,7 +155,7 @@ void cEITScanner::Process(void)
if (!MaySwitchTransponder) {
if (Device == cDevice::ActualDevice() && !currentChannel) {
cDevice::PrimaryDevice()->StopReplay(); // stop transfer mode
- currentChannel = Device->CurrentChannel();
+ currentChannel = Device->CurrentChannelConfig().selected();
Skins.Message(mtInfo, tr("Starting EPG scan"));
}
}
@@ -399,7 +399,7 @@ void cMenuChannels::Setup(void)
{
cChannel *currentChannel = GetChannel(Current());
if (!currentChannel)
- currentChannel = Channels.GetByNumber(cDevice::CurrentChannel());
+ currentChannel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
cMenuChannelItem *currentItem = NULL;
Clear();
for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel)) {
@@ -486,7 +486,7 @@ eOSState cMenuChannels::New(void)
eOSState cMenuChannels::Delete(void)
{
if (!HasSubMenu() && Count() > 0) {
- int CurrentChannelNr = cDevice::CurrentChannel();
+ int CurrentChannelNr = cDevice::CurrentChannelConfig().selected();
cChannel *CurrentChannel = Channels.GetByNumber(CurrentChannelNr);
int Index = Current();
cChannel *channel = GetChannel(Current());
@@ -504,6 +504,7 @@ eOSState cMenuChannels::Delete(void)
CurrentChannel = Channels.Get(n);
CurrentChannelNr = 0; // triggers channel switch below
}
+ ::Setup.Del(channel);
Channels.Del(channel);
cOsdMenu::Del(Index);
Propagate();
@@ -522,8 +523,10 @@ eOSState cMenuChannels::Delete(void)
void cMenuChannels::Move(int From, int To)
{
- int CurrentChannelNr = cDevice::CurrentChannel();
+ int CurrentChannelNr = cDevice::CurrentChannelConfig().selected();
+ int ReceivingChannelNr = cDevice::CurrentChannelConfig().receiving();
cChannel *CurrentChannel = Channels.GetByNumber(CurrentChannelNr);
+ cChannel *ReceivingChannel = Channels.GetByNumber(ReceivingChannelNr);
cChannel *FromChannel = GetChannel(From);
cChannel *ToChannel = GetChannel(To);
if (FromChannel && ToChannel) {
@@ -534,11 +537,16 @@ void cMenuChannels::Move(int From, int To)
Propagate();
Channels.SetModified(true);
isyslog("channel %d moved to %d", FromNumber, ToNumber);
- if (CurrentChannel && CurrentChannel->Number() != CurrentChannelNr) {
+ if (CurrentChannel && ReceivingChannel && (
+ CurrentChannel->Number() != CurrentChannelNr ||
+ ReceivingChannel->Number() != ReceivingChannelNr)
+ ) {
if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
Channels.SwitchTo(CurrentChannel->Number());
- else
+ else {
cDevice::SetCurrentChannel(CurrentChannel);
+ cDevice::SetReceivingChannel(ReceivingChannel);
+ }
}
}
}
@@ -1547,7 +1555,7 @@ cMenuSchedule::cMenuSchedule(void)
timerState = 0;
Timers.Modified(timerState);
cMenuScheduleItem::SetSortMode(cMenuScheduleItem::ssmAllThis);
- cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
+ cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
if (channel) {
cMenuWhatsOn::SetCurrentChannel(channel->Number());
schedules = cSchedules::Schedules(schedulesLock);
@@ -1674,7 +1682,7 @@ eOSState cMenuSchedule::Number(void)
Channel = Channels.GetByChannelID(Event->ChannelID(), true);
}
else
- Channel = Channels.GetByNumber(cDevice::CurrentChannel());
+ Channel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
switch (cMenuScheduleItem::SortMode()) {
case cMenuScheduleItem::ssmAllThis: PrepareScheduleAllThis(Event, Channel); break;
case cMenuScheduleItem::ssmThisThis: PrepareScheduleThisThis(Event, Channel); break;
@@ -1778,7 +1786,7 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
if (channel) {
cMenuScheduleItem::SetSortMode(cMenuScheduleItem::ssmAllThis);
PrepareScheduleAllThis(NULL, channel);
- if (channel->Number() != cDevice::CurrentChannel()) {
+ if (channel->Number() != cDevice::CurrentChannelConfig().selected()) {
otherChannel = channel->Number();
SetHelp(Count() ? tr("Button$Record") : NULL, tr("Button$Now"), tr("Button$Next"), tr("Button$Switch"));
}
@@ -3166,6 +3174,284 @@ eOSState cMenuSetupPlugins::ProcessKey(eKeys Key)
return state;
}
+// --- SelectChannelMenu -----------------------------------------------------
+
+class SelectChannelMenu : public cOsdMenu {
+private:
+ bool menuClosed;
+ static const cChannel *selectedChannel;
+public:
+ SelectChannelMenu();
+ static const cChannel *getSelectedChannel();
+ bool menuHasToBeClosed();;
+ virtual eOSState ProcessKey(eKeys Key);
+};
+
+const cChannel *SelectChannelMenu::selectedChannel = NULL;
+
+SelectChannelMenu::SelectChannelMenu() : cOsdMenu(tr("select channel"))
+{
+ menuClosed = false;
+ selectedChannel = NULL;
+ if (Channels.Count() > 0) {
+ const cChannel *channel = Channels.First();
+ while(true) {
+ Add(new cOsdItem(strdup(channel->Name()), osUnknown, true));
+ if (channel == Channels.Last())
+ break;
+ channel = Channels.Next(channel);
+ }
+ }
+}
+
+eOSState SelectChannelMenu::ProcessKey(eKeys Key) {
+ eOSState state = osUnknown;
+ if (Key == kOk) {
+ if (Channels.Count() > 0) {
+ selectedChannel = Channels.Get(Current());
+ }
+ state = osBack;
+ } else if (Key == kBack) {
+ state = osBack;
+ } else {
+ cOsdMenu::ProcessKey(Key);
+ }
+ return state;
+}
+
+bool SelectChannelMenu::menuHasToBeClosed() {
+ return menuClosed;
+}
+
+const cChannel *SelectChannelMenu::getSelectedChannel() {
+ return selectedChannel;
+}
+
+
+// --- cMenuSetupAlternativeMenuItem -----------------------------------------------------
+
+class cMenuSetupAlternativeMenuItem : public cOsdItem {
+ const cChannel *channel;
+public:
+ cMenuSetupAlternativeMenuItem(const cChannel *alternative, bool selectable = false);
+ const cChannel *getChannel();
+};
+
+cMenuSetupAlternativeMenuItem::cMenuSetupAlternativeMenuItem(const cChannel *alternative, bool selectable) : cOsdItem(NULL, osUnknown, selectable) {
+ char buf[128];
+ strcpy(buf, " ");
+ strcat(buf, alternative->Name());
+ SetText(buf, true /* copy the string */);
+ this->channel = alternative;
+}
+
+const cChannel *cMenuSetupAlternativeMenuItem::getChannel() {
+ return channel;
+}
+
+// --- AltEditAlternative -----------------------------------------------------
+
+class cMenuSetupEditAlternative : public cOsdMenu {
+private:
+ cAlternative *alternative;
+ bool closeMenu;
+ void refreshHelp();
+ void refreshMenu();
+ bool IsDeletionEnabled();
+ void refreshAll();
+ SelectChannelMenu *selectChannelSubmenu;
+
+public:
+ cMenuSetupEditAlternative(cAlternative *alternative);
+ virtual eOSState ProcessKey(eKeys Key);
+ bool menuHasToBeClosed();
+};
+
+cMenuSetupEditAlternative::cMenuSetupEditAlternative(cAlternative *alternative) : cOsdMenu(tr("Edit Alternatives"))
+{
+ this->alternative = alternative;
+ selectChannelSubmenu = NULL;
+ refreshAll();
+ closeMenu = false;
+}
+
+bool cMenuSetupEditAlternative::IsDeletionEnabled()
+{
+ return alternative->GetAlternativeChannels().Count() > 0;
+}
+
+void cMenuSetupEditAlternative::refreshAll() {
+ refreshHelp();
+ refreshMenu();
+}
+
+void cMenuSetupEditAlternative::refreshHelp() {
+ if (IsDeletionEnabled()) {
+ SetHelp(tr("Add Channel"), tr("Remove Channel"));
+ } else {
+ SetHelp(tr("Add Channel"));
+ }
+}
+
+bool cMenuSetupEditAlternative::menuHasToBeClosed() {
+ return closeMenu;
+}
+
+void cMenuSetupEditAlternative::refreshMenu() {
+ Clear();
+ Add(new cOsdItem(alternative->GetMaster()->Name(), osUnknown, false));
+ cList<cAlternativeContainer>& ref = alternative->GetAlternativeChannels();
+ for(cAlternativeContainer *next = ref.First() ; next ; next = ref.Next(next)) {
+ Add(new cMenuSetupAlternativeMenuItem(next->channel, true));
+ }
+ RefreshCurrent();
+ Display();
+}
+
+eOSState cMenuSetupEditAlternative::ProcessKey(eKeys Key) {
+ eOSState state = osUnknown;
+ if (HasSubMenu()) {
+ state = cOsdMenu::ProcessKey(Key);
+ if (!HasSubMenu()) {
+ const cChannel *selected = SelectChannelMenu::getSelectedChannel();
+ if (selected) {
+ alternative->AddAlternativeChannel(selected);
+ }
+ refreshAll();
+ state = osContinue;
+ }
+ } else {
+ if (Key == kRed) {
+ AddSubMenu(selectChannelSubmenu = new SelectChannelMenu());
+ } else if (Key == kGreen) {
+ if (IsDeletionEnabled()) {
+ cMenuSetupAlternativeMenuItem *selected = static_cast<cMenuSetupAlternativeMenuItem *>(Get(Current()));
+ alternative->RemoveAlternativeChannel(selected->getChannel());
+ refreshAll();
+ }
+ } else {
+ state = cOsdMenu::ProcessKey(Key);
+ }
+ }
+ return state;
+}
+
+// --- MasterMenuItem -----------------------------------------------------
+
+class cMenuSetupAlternativeMasterMenuItem : public cOsdItem {
+private:
+ cAlternative* alternative;
+public:
+ cMenuSetupAlternativeMasterMenuItem(cAlternative *alternative);
+ cAlternative *getAlternative();
+};
+
+cMenuSetupAlternativeMasterMenuItem::cMenuSetupAlternativeMasterMenuItem(cAlternative *alternatives) : cOsdItem(alternatives->GetMaster()->Name(), osUnknown, true) {
+ this->alternative = alternatives;
+}
+
+cAlternative *cMenuSetupAlternativeMasterMenuItem::getAlternative() {
+ return alternative;
+}
+
+
+// --- cMenuSetupAlternative -----------------------------------------------------
+
+class cMenuSetupAlternative : public cMenuSetupBase {
+private:
+ SelectChannelMenu *selectChannelSubmenu;
+ cMenuSetupEditAlternative *editAlternative;
+
+protected:
+ virtual void Store(void);
+ void update();
+public:
+ cMenuSetupAlternative();
+ virtual eOSState ProcessKey(eKeys Key);
+};
+
+cMenuSetupAlternative::cMenuSetupAlternative() {
+ update();
+ selectChannelSubmenu = NULL;
+ editAlternative = NULL;
+}
+
+void cMenuSetupAlternative::Store() {
+ cMenuSetupBase::Store();
+}
+
+eOSState cMenuSetupAlternative::ProcessKey(eKeys Key) {
+ eOSState state = osContinue;
+ if (HasSubMenu()) {
+ state = cMenuSetupPage::ProcessKey(Key);
+ if (!HasSubMenu()) { // submenu closed ?
+ if (selectChannelSubmenu) {
+ selectChannelSubmenu = NULL;
+ const cChannel *master = SelectChannelMenu::getSelectedChannel();
+ if (master != NULL) data.getAllAlternatives().CreateAlternative(master);
+ update();
+ } else if (editAlternative) {
+ editAlternative = NULL;
+ update();
+ }
+ state = osContinue;
+ }
+ } else {
+ switch (Key) {
+ case kRed:
+ AddSubMenu(selectChannelSubmenu = new SelectChannelMenu());
+ break;
+ case kGreen:
+ if (data.getAllAlternatives().CountAlternatives() > 0) {
+ cMenuSetupAlternativeMasterMenuItem *master = static_cast<cMenuSetupAlternativeMasterMenuItem *>(Get(Current()));
+ data.getAllAlternatives().RemoveAlternative(master->getAlternative());
+ }
+ update();
+ break;
+ case kYellow:
+ {
+ cMenuSetupAlternativeMasterMenuItem *item = static_cast<cMenuSetupAlternativeMasterMenuItem *>(Get(Current()));
+ AddSubMenu(editAlternative = new cMenuSetupEditAlternative(item->getAlternative()));
+ break;
+ }
+ case kBack:
+ {
+ if (Setup.Alternatives == data.Alternatives) {
+ state = cMenuSetupPage::ProcessKey(Key);
+ }
+ else {
+ if (Interface->Confirm(tr("Cancel without saving ?")))
+ state = cMenuSetupPage::ProcessKey(Key);
+ }
+ break;
+ }
+ default:
+ state = cMenuSetupPage::ProcessKey(Key);
+ }
+ }
+ return state;
+}
+
+void cMenuSetupAlternative::update() {
+ Clear();
+ for(int i = 0 ; i < data.getAllAlternatives().CountAlternatives() ; i++) {
+ cAlternative *alternative = data.getAllAlternatives().GetAlternative(i);
+ Add(new cMenuSetupAlternativeMasterMenuItem(alternative));
+ cList<cAlternativeContainer>& ref = alternative->GetAlternativeChannels();
+ for(cAlternativeContainer *next = ref.First() ; next ; next = ref.Next(next)) {
+ Add(new cMenuSetupAlternativeMenuItem(next->channel));
+ }
+ }
+ if (data.getAllAlternatives().CountAlternatives() == 0)
+ SetHelp(tr("New Alternative"));
+ else {
+ SetHelp(tr("New Alternative"), tr("Delete Alternative"), tr("Edit Alternative"));
+ }
+ RefreshCurrent();
+ Display();
+}
+
+
// --- cMenuSetup ------------------------------------------------------------
class cMenuSetup : public cOsdMenu {
@@ -3198,9 +3484,10 @@ void cMenuSetup::Set(void)
Add(new cOsdItem(hk(tr("Recording")), osUser6));
Add(new cOsdItem(hk(tr("Replay")), osUser7));
Add(new cOsdItem(hk(tr("Miscellaneous")), osUser8));
+ Add(new cOsdItem(hk(tr("Alternatives")), osUser9));
if (cPluginManager::HasPlugins())
- Add(new cOsdItem(hk(tr("Plugins")), osUser9));
- Add(new cOsdItem(hk(tr("Restart")), osUser10));
+ Add(new cOsdItem(hk(tr("Plugins")), osUser10));
+ Add(new cOsdItem(hk(tr("Restart")), osUser11));
}
eOSState cMenuSetup::Restart(void)
@@ -3226,8 +3513,9 @@ eOSState cMenuSetup::ProcessKey(eKeys Key)
case osUser6: return AddSubMenu(new cMenuSetupRecord);
case osUser7: return AddSubMenu(new cMenuSetupReplay);
case osUser8: return AddSubMenu(new cMenuSetupMisc);
- case osUser9: return AddSubMenu(new cMenuSetupPlugins);
- case osUser10: return Restart();
+ case osUser9: return AddSubMenu(new cMenuSetupAlternative);
+ case osUser10: return AddSubMenu(new cMenuSetupPlugins);
+ case osUser11: return Restart();
default: ;
}
if (I18nCurrentLanguage() != osdLanguage) {
@@ -3519,7 +3807,7 @@ static void SetTrackDescriptions(int LiveChannel)
cDisplayChannel *cDisplayChannel::currentDisplayChannel = NULL;
-cDisplayChannel::cDisplayChannel(int Number, bool Switched)
+cDisplayChannel::cDisplayChannel(int Number, int NumberReceiving, bool Switched)
:cOsdObject(true)
{
currentDisplayChannel = this;
@@ -3528,9 +3816,10 @@ cDisplayChannel::cDisplayChannel(int Number, bool Switched)
displayChannel = Skins.Current()->DisplayChannel(withInfo);
number = 0;
timeout = Switched || Setup.TimeoutRequChInfo;
- channel = Channels.GetByNumber(Number);
+ selectedChannel = Channels.GetByNumber(Number);
+ receivingChannel = Channels.GetByNumber(NumberReceiving);
lastPresent = lastFollowing = NULL;
- if (channel) {
+ if (selectedChannel) {
DisplayChannel();
DisplayInfo();
displayChannel->Flush();
@@ -3549,7 +3838,8 @@ cDisplayChannel::cDisplayChannel(eKeys FirstKey)
lastTime.Set();
withInfo = Setup.ShowInfoOnChSwitch;
displayChannel = Skins.Current()->DisplayChannel(withInfo);
- channel = Channels.GetByNumber(cDevice::CurrentChannel());
+ selectedChannel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
+ receivingChannel = Channels.GetByNumber(cDevice::CurrentChannelConfig().receiving());
ProcessKey(FirstKey);
}
@@ -3562,23 +3852,24 @@ cDisplayChannel::~cDisplayChannel()
void cDisplayChannel::DisplayChannel(void)
{
- displayChannel->SetChannel(channel, number);
- cStatus::MsgOsdChannel(ChannelString(channel, number));
+ cChannelConfig cc(selectedChannel->Number(), receivingChannel->Number());
+ displayChannel->SetChannel(cc, number);
+ cStatus::MsgOsdChannel(ChannelString(cc, number));
lastPresent = lastFollowing = NULL;
}
void cDisplayChannel::DisplayInfo(void)
{
- if (withInfo && channel) {
+ if (withInfo && selectedChannel) {
cSchedulesLock SchedulesLock;
const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
if (Schedules) {
- const cSchedule *Schedule = Schedules->GetSchedule(channel);
+ const cSchedule *Schedule = Schedules->GetSchedule(selectedChannel);
if (Schedule) {
const cEvent *Present = Schedule->GetPresentEvent();
const cEvent *Following = Schedule->GetFollowingEvent();
if (Present != lastPresent || Following != lastFollowing) {
- SetTrackDescriptions(channel->Number());
+ SetTrackDescriptions(receivingChannel->Number());
displayChannel->SetEvents(Present, Following);
cStatus::MsgOsdProgramme(Present ? Present->StartTime() : 0, Present ? Present->Title() : NULL, Present ? Present->ShortText() : NULL, Following ? Following->StartTime() : 0, Following ? Following->Title() : NULL, Following ? Following->ShortText() : NULL);
lastPresent = Present;
@@ -3595,15 +3886,18 @@ void cDisplayChannel::Refresh(void)
displayChannel->SetEvents(NULL, NULL);
}
-cChannel *cDisplayChannel::NextAvailableChannel(cChannel *Channel, int Direction)
+cChannel *cDisplayChannel::NextAvailableChannel(cChannel *Channel, int Direction, const cChannel *&RefReceiving)
{
if (Direction) {
while (Channel) {
Channel = Direction > 0 ? Channels.Next(Channel) : Channels.Prev(Channel);
if (!Channel && Setup.ChannelsWrap)
Channel = Direction > 0 ? Channels.First() : Channels.Last();
- if (Channel && !Channel->GroupSep() && cDevice::GetDevice(Channel, 0, true))
+ const cChannel *PtrAlternative = NULL;
+ if (Channel && !Channel->GroupSep() && cDevice::QueryDevice(Channel, 0, true, PtrAlternative)) {
+ RefReceiving = PtrAlternative;
return Channel;
+ }
}
}
return NULL;
@@ -3628,13 +3922,13 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
number = Key - k0;
else
number = number * 10 + Key - k0;
- channel = Channels.GetByNumber(number);
+ receivingChannel = selectedChannel = Channels.GetByNumber(number); // also assign receiving for hiding parenthese
Refresh();
withInfo = false;
// Lets see if there can be any useful further input:
- int n = channel ? number * 10 : 0;
+ int n = selectedChannel ? number * 10 : 0;
int m = 10;
- cChannel *ch = channel;
+ cChannel *ch = selectedChannel;
while (ch && (ch = Channels.Next(ch)) != NULL) {
if (!ch->GroupSep()) {
if (n <= ch->Number() && ch->Number() < n + m) {
@@ -3649,7 +3943,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
}
if (n > 0) {
// This channel is the only one that fits the input, so let's take it right away:
- NewChannel = channel;
+ NewChannel = selectedChannel;
withInfo = true;
number = 0;
Refresh();
@@ -3667,7 +3961,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
withInfo = false;
number = 0;
if (group < 0) {
- cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
+ cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
if (channel)
group = channel->Index();
}
@@ -3679,10 +3973,10 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
group = Channels.GetPrevGroup(group < 1 ? 1 : group);
if (group < 0)
group = SaveGroup;
- channel = Channels.Get(group);
- if (channel) {
+ selectedChannel = Channels.Get(group);
+ if (selectedChannel) {
Refresh();
- if (!channel->GroupSep())
+ if (!selectedChannel->GroupSep())
group = -1;
}
}
@@ -3696,10 +3990,13 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
case kChanDn|k_Repeat:
case kChanDn: {
eKeys k = NORMALKEY(Key);
- cChannel *ch = NextAvailableChannel(channel, (k == kUp || k == kChanUp) ? 1 : -1);
- if (ch)
- channel = ch;
- else if (channel && channel->Number() != cDevice::CurrentChannel())
+ const cChannel *rec = NULL;
+ cChannel *ch = NextAvailableChannel(selectedChannel, (k == kUp || k == kChanUp) ? 1 : -1, rec);
+ if (ch) {
+ selectedChannel = ch;
+ receivingChannel = ch; // the correct channel will be set later after the break
+ }
+ else if (selectedChannel && selectedChannel->Number() != cDevice::CurrentChannelConfig().selected())
Key = k; // immediately switches channel when hitting the beginning/end of the channel list with k_Repeat
}
// no break here
@@ -3709,8 +4006,8 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
case kChanDn|k_Release:
case kNext|k_Release:
case kPrev|k_Release:
- if (!(Key & k_Repeat) && channel && channel->Number() != cDevice::CurrentChannel())
- NewChannel = channel;
+ if (!(Key & k_Repeat) && selectedChannel && selectedChannel->Number() != cDevice::CurrentChannelConfig().selected())
+ NewChannel = selectedChannel;
withInfo = true;
group = -1;
number = 0;
@@ -3718,9 +4015,9 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
break;
case kNone:
if (number && Setup.ChannelEntryTimeout && int(lastTime.Elapsed()) > Setup.ChannelEntryTimeout) {
- channel = Channels.GetByNumber(number);
- if (channel)
- NewChannel = channel;
+ selectedChannel = Channels.GetByNumber(number);
+ if (selectedChannel)
+ NewChannel = selectedChannel;
withInfo = true;
number = 0;
Refresh();
@@ -3732,17 +4029,17 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
//XXX case kYellow: return osEventNext;
case kOk:
if (group >= 0) {
- channel = Channels.Get(Channels.GetNextNormal(group));
- if (channel)
- NewChannel = channel;
+ selectedChannel = Channels.Get(Channels.GetNextNormal(group));
+ if (selectedChannel)
+ NewChannel = selectedChannel;
withInfo = true;
group = -1;
Refresh();
}
else if (number > 0) {
- channel = Channels.GetByNumber(number);
- if (channel)
- NewChannel = channel;
+ selectedChannel = Channels.GetByNumber(number);
+ if (selectedChannel)
+ NewChannel = selectedChannel;
withInfo = true;
number = 0;
Refresh();
@@ -3757,9 +4054,9 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
}
};
if (!timeout || lastTime.Elapsed() < (uint64_t)(Setup.ChannelInfoTime * 1000)) {
- if (Key == kNone && !number && group < 0 && !NewChannel && channel && channel->Number() != cDevice::CurrentChannel()) {
+ if (Key == kNone && !number && group < 0 && !NewChannel && selectedChannel && selectedChannel->Number() != cDevice::CurrentChannelConfig().selected()) {
// makes sure a channel switch through the SVDRP CHAN command is displayed
- channel = Channels.GetByNumber(cDevice::CurrentChannel());
+ selectedChannel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
Refresh();
lastTime.Set();
}
@@ -3769,7 +4066,9 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
SetTrackDescriptions(NewChannel->Number()); // to make them immediately visible in the channel display
Channels.SwitchTo(NewChannel->Number());
SetTrackDescriptions(NewChannel->Number()); // switching the channel has cleared them
- channel = NewChannel;
+ selectedChannel = NewChannel;
+ receivingChannel = Channels.Get(cDevice::CurrentChannelConfig().receiving()-1); // .Get is zero-based
+ Refresh();
}
return osContinue;
}
@@ -3853,7 +4152,7 @@ cDisplayTracks::cDisplayTracks(void)
:cOsdObject(true)
{
cDevice::PrimaryDevice()->EnsureAudioTrack();
- SetTrackDescriptions(!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring() ? cDevice::CurrentChannel() : 0);
+ SetTrackDescriptions(!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring() ? cDevice::CurrentChannelConfig().receiving() : 0);
currentDisplayTracks = this;
numTracks = track = 0;
audioChannel = cDevice::PrimaryDevice()->GetAudioChannel();
@@ -3972,7 +4271,7 @@ cDisplaySubtitleTracks *cDisplaySubtitleTracks::currentDisplayTracks = NULL;
cDisplaySubtitleTracks::cDisplaySubtitleTracks(void)
:cOsdObject(true)
{
- SetTrackDescriptions(!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring() ? cDevice::CurrentChannel() : 0);
+ SetTrackDescriptions(!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring() ? cDevice::CurrentChannelConfig().receiving() : 0);
currentDisplayTracks = this;
numTracks = track = 0;
types[numTracks] = ttNone;
@@ -4219,13 +4518,16 @@ bool cRecordControls::Start(cTimer *Timer, bool Pause)
LastNoDiskSpaceMessage = 0;
ChangeState();
- int ch = Timer ? Timer->Channel()->Number() : cDevice::CurrentChannel();
+ int ch = Timer ? Timer->Channel()->Number() : cDevice::CurrentChannelConfig().selected();
cChannel *channel = Channels.GetByNumber(ch);
if (channel) {
int Priority = Timer ? Timer->Priority() : Pause ? Setup.PausePriority : Setup.DefaultPriority;
- cDevice *device = cDevice::GetDevice(channel, Priority, false);
+ const cChannel *receivingChannel = NULL;
+ cDevice *device = cDevice::QueryDevice(channel, Priority, false, receivingChannel);
if (device) {
+ channel = Channels.Get(receivingChannel->Number()-1); // receivingChannel is const, channel not
+ if (Timer) Timer->SetChannel(channel);
dsyslog("switching device %d to channel %d", device->DeviceNumber() + 1, channel->Number());
if (!device->SwitchChannel(channel, false)) {
ShutdownHandler.RequestEmergencyExit();
@@ -119,16 +119,17 @@ private:
cTimeMs lastTime;
int number;
bool timeout;
- cChannel *channel;
+ cChannel *selectedChannel;
+ const cChannel *receivingChannel;
const cEvent *lastPresent;
const cEvent *lastFollowing;
static cDisplayChannel *currentDisplayChannel;
void DisplayChannel(void);
void DisplayInfo(void);
void Refresh(void);
- cChannel *NextAvailableChannel(cChannel *Channel, int Direction);
+ cChannel *NextAvailableChannel(cChannel *Channel, int Direction, const cChannel *&RefReceiving);
public:
- cDisplayChannel(int Number, bool Switched);
+ cDisplayChannel(int Number, int NumberReceiving, bool Switched);
cDisplayChannel(eKeys FirstKey);
virtual ~cDisplayChannel();
virtual eOSState ProcessKey(eKeys Key);
@@ -15,6 +15,7 @@
#include "libsi/section.h"
#include "libsi/descriptor.h"
#include "tools.h"
+#include "sources.h"
cNitFilter::cNitFilter(void)
{
@@ -44,6 +44,11 @@ enum eOSState { osUnknown,
osUser8,
osUser9,
osUser10,
+ osUser11,
+ osUser12,
+ osUser13,
+ osUser14,
+ osUser15,
};
class cOsdItem : public cListObject {
@@ -320,7 +320,7 @@ bool cRcuRemote::DetectCode(unsigned char *Code)
void cRcuRemote::ChannelSwitch(const cDevice *Device, int ChannelNumber)
{
if (ChannelNumber && Device->IsPrimaryDevice())
- SetNumber(cDevice::CurrentChannel());
+ SetNumber(cDevice::CurrentChannelConfig().selected());
}
void cRcuRemote::Recording(const cDevice *Device, const char *Name, const char *FileName, bool On)
@@ -12,6 +12,7 @@
#include "config.h"
#include "libsi/section.h"
#include "libsi/descriptor.h"
+#include "sources.h"
// --- cSdtFilter ------------------------------------------------------------
@@ -83,7 +83,7 @@ private:
public:
cSkinClassicDisplayChannel(bool WithInfo);
virtual ~cSkinClassicDisplayChannel();
- virtual void SetChannel(const cChannel *Channel, int Number);
+ virtual void SetChannel(cChannelConfig channelConfig, int Number);
virtual void SetEvents(const cEvent *Present, const cEvent *Following);
virtual void SetMessage(eMessageType Type, const char *Text);
virtual void Flush(void);
@@ -112,10 +112,10 @@ cSkinClassicDisplayChannel::~cSkinClassicDisplayChannel()
delete osd;
}
-void cSkinClassicDisplayChannel::SetChannel(const cChannel *Channel, int Number)
+void cSkinClassicDisplayChannel::SetChannel(cChannelConfig channelConfig, int Number)
{
osd->DrawRectangle(0, 0, osd->Width() - 1, lineHeight - 1, Theme.Color(clrBackground));
- osd->DrawText(TextFrame, 0, ChannelString(Channel, Number), Theme.Color(clrChannelName), Theme.Color(clrBackground), cFont::GetFont(fontOsd));
+ osd->DrawText(TextFrame, 0, ChannelString(channelConfig, Number), Theme.Color(clrChannelName), Theme.Color(clrBackground), cFont::GetFont(fontOsd));
lastDate = NULL;
}
@@ -50,7 +50,7 @@ class cSkinDisplayChannel : public cSkinDisplay {
///< the present and following EPG even. How and to what extent this
///< is done is totally up to the derived class.
public:
- virtual void SetChannel(const cChannel *Channel, int Number) = 0;
+ virtual void SetChannel(cChannelConfig channelConfig, int Number) = 0;
///< Sets the current channel to Channel. If Number is not 0, the
///< user is in the process of entering a channel number, which must
///< be displayed accordingly.
@@ -7,7 +7,7 @@
* $Id: skinsttng.c 2.5 2010/02/13 13:30:59 kls Exp $
*/
-// Star Trek: The Next Generation® is a registered trademark of Paramount Pictures
+// Star Trek: The Next Generationᅵ is a registered trademark of Paramount Pictures
// registered in the United States Patent and Trademark Office.
// No infringement intended.
@@ -139,7 +139,7 @@ private:
public:
cSkinSTTNGDisplayChannel(bool WithInfo);
virtual ~cSkinSTTNGDisplayChannel();
- virtual void SetChannel(const cChannel *Channel, int Number);
+ virtual void SetChannel(cChannelConfig channelConfig, int Number);
virtual void SetEvents(const cEvent *Present, const cEvent *Following);
virtual void SetMessage(eMessageType Type, const char *Text);
virtual void Flush(void);
@@ -240,10 +240,11 @@ cSkinSTTNGDisplayChannel::~cSkinSTTNGDisplayChannel()
delete osd;
}
-void cSkinSTTNGDisplayChannel::SetChannel(const cChannel *Channel, int Number)
+void cSkinSTTNGDisplayChannel::SetChannel(cChannelConfig channelConfig, int Number)
{
osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
int x = x4 - SymbolSpacing;
+ const cChannel *Channel = Channels.Get(channelConfig.selected());
if (Channel && !Channel->GroupSep()) {
bool rec = cRecordControls::Active();
x -= bmRecording.Width() + SymbolSpacing;
@@ -263,7 +264,7 @@ void cSkinSTTNGDisplayChannel::SetChannel(const cChannel *Channel, int Number)
osd->DrawBitmap(x, y0 + (y1 - y0 - bmRadio.Height()) / 2, bmRadio, Theme.Color(clrChannelSymbolOn), frameColor);
}
}
- osd->DrawText(x3 + TextFrame, y0, ChannelString(Channel, Number), Theme.Color(clrChannelName), frameColor, cFont::GetFont(fontOsd), x - x3 - TextFrame);
+ osd->DrawText(x3 + TextFrame, y0, ChannelString(channelConfig, Number), Theme.Color(clrChannelName), frameColor, cFont::GetFont(fontOsd), x - x3 - TextFrame);
}
void cSkinSTTNGDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
@@ -10,6 +10,7 @@
#ifndef __SOURCES_H
#define __SOURCES_H
+#include "tools.h"
#include "config.h"
class cSource : public cListObject {
@@ -488,14 +488,14 @@ void cSVDRP::CmdCHAN(const char *Option)
n = o;
}
else if (strcmp(Option, "-") == 0) {
- n = cDevice::CurrentChannel();
+ n = cDevice::CurrentChannelConfig().selected();
if (n > 1) {
n--;
d = -1;
}
}
else if (strcmp(Option, "+") == 0) {
- n = cDevice::CurrentChannel();
+ n = cDevice::CurrentChannelConfig().selected();
if (n < Channels.MaxNumber()) {
n++;
d = 1;
@@ -536,11 +536,11 @@ void cSVDRP::CmdCHAN(const char *Option)
else
cDevice::SwitchChannel(d);
}
- cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
+ cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
if (channel)
Reply(250, "%d %s", channel->Number(), channel->Name());
else
- Reply(550, "Unable to find channel \"%d\"", cDevice::CurrentChannel());
+ Reply(550, "Unable to find channel \"%d\"", cDevice::CurrentChannelConfig().selected());
}
void cSVDRP::CmdCLRE(const char *Option)
@@ -613,7 +613,7 @@ void cSVDRP::CmdDELC(const char *Option)
return;
}
}
- int CurrentChannelNr = cDevice::CurrentChannel();
+ int CurrentChannelNr = cDevice::CurrentChannelConfig().selected();
cChannel *CurrentChannel = Channels.GetByNumber(CurrentChannelNr);
if (CurrentChannel && channel == CurrentChannel) {
int n = Channels.GetNextNormal(CurrentChannel->Index());
@@ -1214,7 +1214,7 @@ void cSVDRP::CmdMOVC(const char *Option)
tail = skipspace(tail);
if (tail && tail != Option) {
int To = strtol(tail, NULL, 10);
- int CurrentChannelNr = cDevice::CurrentChannel();
+ int CurrentChannelNr = cDevice::CurrentChannelConfig().selected();
cChannel *CurrentChannel = Channels.GetByNumber(CurrentChannelNr);
cChannel *FromChannel = Channels.GetByNumber(From);
if (FromChannel) {
@@ -33,7 +33,7 @@ cTimer::cTimer(bool Instant, bool Pause, cChannel *Channel)
flags = tfNone;
if (Instant)
SetFlags(tfActive | tfInstant);
- channel = Channel ? Channel : Channels.GetByNumber(cDevice::CurrentChannel());
+ channel = Channel ? Channel : Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
time_t t = time(NULL);
struct tm tm_r;
struct tm *now = localtime_r(&t, &tm_r);
@@ -771,3 +771,7 @@ void cTimers::DeleteExpired(void)
}
lastDeleteExpired = time(NULL);
}
+
+void cTimer::SetChannel(cChannel *channel) {
+ this->channel = channel;
+}
@@ -92,6 +92,7 @@ public:
void Skip(void);
void OnOff(void);
cString PrintFirstDay(void) const;
+ void SetChannel(cChannel *channel);
static int TimeToInt(int t);
static bool ParseDay(const char *s, time_t &Day, int &WeekDays);
static cString PrintDay(time_t Day, int WeekDays, bool SingleByteChars);
@@ -747,9 +747,10 @@ int main(int argc, char *argv[])
if (!EITScanner.Active() && cDevice::PrimaryDevice()->HasDecoder() && !cDevice::PrimaryDevice()->HasProgramme()) {
static time_t lastTime = 0;
if ((!Menu || CheckHasProgramme) && Now - lastTime > MINCHANNELWAIT) { // !Menu to avoid interfering with the CAM if a CAM menu is open
- cChannel *Channel = Channels.GetByNumber(cDevice::CurrentChannel());
+ cChannel *Channel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
if (Channel && (Channel->Vpid() || Channel->Apid(0))) {
- if (!Channels.SwitchTo(cDevice::CurrentChannel()) // try to switch to the original channel...
+ /// TODO: search for an alternative
+ if (!Channels.SwitchTo(Channel->Number()) // try to switch to the original channel...
&& !(LastTimerChannel > 0 && Channels.SwitchTo(LastTimerChannel))) // ...or the one used by the last timer...
;
}
@@ -795,7 +796,7 @@ int main(int argc, char *argv[])
for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
if (Channel->Modification(CHANNELMOD_RETUNE)) {
cRecordControls::ChannelDataModified(Channel);
- if (Channel->Number() == cDevice::CurrentChannel()) {
+ if (Channel->Number() == cDevice::CurrentChannelConfig().receiving()) {
if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring()) {
if (cDevice::ActualDevice()->ProvidesTransponder(Channel)) { // avoids retune on devices that don't really access the transponder
isyslog("retuning due to modification of channel %d", Channel->Number());
@@ -809,10 +810,10 @@ int main(int argc, char *argv[])
}
}
// Channel display:
- if (!EITScanner.Active() && cDevice::CurrentChannel() != LastChannel) {
+ if (!EITScanner.Active() && cDevice::CurrentChannelConfig().selected() != LastChannel) {
if (!Menu)
- Menu = new cDisplayChannel(cDevice::CurrentChannel(), LastChannel >= 0);
- LastChannel = cDevice::CurrentChannel();
+ Menu = new cDisplayChannel(cDevice::CurrentChannelConfig().selected(), cDevice::CurrentChannelConfig().receiving(), LastChannel >= 0);
+ LastChannel = cDevice::CurrentChannelConfig().selected();
LastChannelChanged = Now;
}
if (Now - LastChannelChanged >= Setup.ZapTimeout && LastChannel != PreviousChannel[PreviousChannelIndex])
@@ -903,7 +904,8 @@ int main(int argc, char *argv[])
if (cDevice::PrimaryDevice()->HasDecoder() && !cDevice::PrimaryDevice()->HasProgramme()) {
// the previous SwitchChannel() has switched away the current live channel
cDevice::SetAvoidDevice(Device);
- if (!Channels.SwitchTo(cDevice::CurrentChannel())) // try to switch to the original channel on a different device...
+ /// TODO: search for an alternative
+ if (!Channels.SwitchTo(cDevice::CurrentChannelConfig().selected())) // try to switch to the original channel on a different device...
Channels.SwitchTo(Timer->Channel()->Number()); // ...or avoid toggling between old channel and black screen
Skins.Message(mtInfo, tr("Upcoming recording!"));
}
@@ -1306,7 +1308,7 @@ Exit:
Skins.Clear();
SourceParams.Clear();
if (ShutdownHandler.GetExitCode() != 2) {
- Setup.CurrentChannel = cDevice::CurrentChannel();
+ Setup.CurrentChannel = cDevice::CurrentChannelConfig().selected();
Setup.CurrentVolume = cDevice::CurrentVolume();
Setup.Save();
}