Streamdev-server compatibility with VDR 2.3.1 (fixes #2249)

This commit is contained in:
Frank Schmirler 2016-03-21 00:28:02 +01:00
parent d66c635a80
commit 674bb5b331
18 changed files with 538 additions and 4 deletions

View File

@ -245,3 +245,9 @@ Toerless Eckert
Tomasz Maciej Nowak
for providing Polish language texts
Christopher Reimer
for providing an initial compatibility patch for VDR 2.3.1
Matthias Senzel
for refining the compatibility patch for VDR 2.3.1

View File

@ -1,6 +1,8 @@
VDR Plugin 'streamdev' Revision History
---------------------------------------
- server compatibility with VDR 2.3.1 (thanks to Christopher Reimer and
Matthias Senzel)
- client compatibility with VDR 2.3.1
- use cReceiver::SetPriority(...) in VDR 2.1.4+
- doubled size of client's filter buffer (suggested by Toerless Eckert)

View File

@ -105,7 +105,11 @@ cComponentIGMP::~cComponentIGMP(void)
{
}
#if APIVERSNUM >= 20300
cMulticastGroup* cComponentIGMP::FindGroup(in_addr_t Group)
#else
cMulticastGroup* cComponentIGMP::FindGroup(in_addr_t Group) const
#endif
{
cMulticastGroup *group = m_Groups.First();
while (group && group->group != Group)
@ -117,7 +121,12 @@ bool cComponentIGMP::Initialize(void)
{
if (cServerComponent::Initialize() && IGMPMembership(IGMP_ALL_ROUTER))
{
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
for (const cChannel *channel = Channels->First(); channel; channel = Channels->Next(channel))
#else
for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
#endif
{
if (channel->GroupSep())
continue;
@ -146,7 +155,12 @@ void cComponentIGMP::Destruct(void)
Cancel(-1);
m_CondWait.Signal();
Cancel(2);
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
for (const cChannel *channel = Channels->First(); channel; channel = Channels->Next(channel))
#else
for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
#endif
{
if (channel->GroupSep())
continue;
@ -432,9 +446,18 @@ cServerConnection* cComponentIGMP::IGMPStartMulticast(cMulticastGroup* Group)
in_addr_t g = ntohl(Group->group);
if (g > MULTICAST_PRIV_MIN && g <= MULTICAST_PRIV_MAX) {
cThreadLock lock;
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
const cChannel *channel = Channels->GetByNumber(g - MULTICAST_PRIV_MIN);
#else
cChannel *channel = Channels.GetByNumber(g - MULTICAST_PRIV_MIN);
#endif
const cList<cServerConnection>& clients = cStreamdevServer::Clients(lock);
#if APIVERSNUM >= 20300
const cServerConnection *s = clients.First();
#else
cServerConnection *s = clients.First();
#endif
while (s) {
if (s->RemoteIpAddr() == Group->group)
break;
@ -453,7 +476,11 @@ cServerConnection* cComponentIGMP::IGMPStartMulticast(cMulticastGroup* Group)
void cComponentIGMP::IGMPStopMulticast(cMulticastGroup* Group)
{
cThreadLock lock;
#if APIVERSNUM >= 20300
cList<cServerConnection>& clients = cStreamdevServer::Clients(lock);
#else
const cList<cServerConnection>& clients = cStreamdevServer::Clients(lock);
#endif
for (cServerConnection *s = clients.First(); s; s = clients.Next(s)) {
if (s->RemoteIpAddr() == Group->group)
s->Close();

View File

@ -9,6 +9,7 @@
#include <time.h>
#include <vdr/thread.h>
#include "server/component.h"
#include "../common.h"
class cMulticastGroup;
@ -23,7 +24,11 @@ private:
bool m_Querier;
cCondWait m_CondWait;
#if APIVERSNUM >= 20300
cMulticastGroup* FindGroup(in_addr_t Group);
#else
cMulticastGroup* FindGroup(in_addr_t Group) const;
#endif
/* Add or remove local host to multicast group */
bool IGMPMembership(in_addr_t Group, bool Add = true);

View File

@ -46,14 +46,29 @@ const cChannel* cServerConnection::ChannelFromString(const char *String, int *Ap
int temp = strtol(String, NULL, 10);
if (temp == 0)
temp = cDevice::CurrentChannel();
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
if (temp >= 1 && temp <= Channels->MaxNumber())
channel = Channels->GetByNumber(temp);
#else
if (temp >= 1 && temp <= Channels.MaxNumber())
channel = Channels.GetByNumber(temp);
#endif
} else {
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
channel = Channels->GetByChannelID(tChannelID::FromString(string));
#else
channel = Channels.GetByChannelID(tChannelID::FromString(string));
#endif
if (channel == NULL) {
int i = 1;
#if APIVERSNUM >= 20300
while ((channel = Channels->GetByNumber(i, 1)) != NULL) {
#else
while ((channel = Channels.GetByNumber(i, 1)) != NULL) {
#endif
if (String == channel->Name())
break;

View File

@ -523,8 +523,13 @@ RecPlayer* cConnectionHTTP::RecPlayerFromString(const char *FileBase, const char
ino_t inode = (ino_t) strtoull(p + 1, &p, 0);
if (*p == 0 && inode > 0) {
struct stat st;
#if APIVERSNUM >= 20300
LOCK_RECORDINGS_READ;
for (const cRecording *rec = Recordings->First(); rec; rec = Recordings->Next(rec)) {
#else
cThreadLock RecordingsLock(&Recordings);
for (cRecording *rec = Recordings.First(); rec; rec = Recordings.Next(rec)) {
#endif
if (stat(rec->FileName(), &st) == 0 && st.st_dev == (dev_t) l && st.st_ino == inode)
recPlayer = new RecPlayer(rec->FileName());
}
@ -532,8 +537,13 @@ RecPlayer* cConnectionHTTP::RecPlayerFromString(const char *FileBase, const char
}
else if (*p == 0) {
// get recording by index
#if APIVERSNUM >= 20300
LOCK_RECORDINGS_READ;
const cRecording *rec = Recordings->Get((int) l - 1);
#else
cThreadLock RecordingsLock(&Recordings);
cRecording *rec = Recordings.Get((int) l - 1);
#endif
if (rec)
recPlayer = new RecPlayer(rec->FileName());
}

View File

@ -21,7 +21,11 @@ cConnectionIGMP::~cConnectionIGMP()
{
}
#if APIVERSNUM >= 20300
bool cConnectionIGMP::SetChannel(const cChannel *Channel, in_addr_t Dst)
#else
bool cConnectionIGMP::SetChannel(cChannel *Channel, in_addr_t Dst)
#endif
{
if (Channel) {
m_Channel = Channel;

View File

@ -19,13 +19,21 @@ class cConnectionIGMP: public cServerConnection {
private:
int m_ClientPort;
eStreamType m_StreamType;
#if APIVERSNUM >= 20300
const cChannel *m_Channel;
#else
cChannel *m_Channel;
#endif
public:
cConnectionIGMP(const char* Name, int ClientPort, eStreamType StreamType);
virtual ~cConnectionIGMP();
#if APIVERSNUM >= 20300
bool SetChannel(const cChannel *Channel, in_addr_t Dst);
#else
bool SetChannel(cChannel *Channel, in_addr_t Dst);
#endif
virtual void Welcome(void);
virtual cString ToText(char Delimiter = ' ') const;

View File

@ -58,8 +58,10 @@ public:
cLSTEHandler::cLSTEHandler(cConnectionVTP *Client, const char *Option):
m_Client(Client),
#if APIVERSNUM < 20300
m_SchedulesLock(new cSchedulesLock(false, 500)),
m_Schedules(cSchedules::Schedules(*m_SchedulesLock)),
#endif
m_Schedule(NULL),
m_Event(NULL),
m_Errno(0),
@ -131,11 +133,20 @@ cLSTEHandler::cLSTEHandler(cConnectionVTP *Client, const char *Option):
break;
}
} else if (!m_Schedule) {
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
const cChannel* Channel = NULL;
if (isnumber(p))
Channel = Channels->GetByNumber(strtol(Option, NULL, 10));
else
Channel = Channels->GetByChannelID(tChannelID::FromString(
#else
cChannel* Channel = NULL;
if (isnumber(p))
Channel = Channels.GetByNumber(strtol(Option, NULL, 10));
else
Channel = Channels.GetByChannelID(tChannelID::FromString(
#endif
Option));
if (Channel) {
m_Schedule = m_Schedules->GetSchedule(Channel->GetChannelID());
@ -215,7 +226,12 @@ bool cLSTEHandler::Next(bool &Last)
switch (m_State) {
case Channel:
if (m_Schedule != NULL) {
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
const cChannel *channel = Channels->GetByChannelID(m_Schedule->ChannelID(),
#else
cChannel *channel = Channels.GetByChannelID(m_Schedule->ChannelID(),
#endif
true);
if (channel != NULL) {
m_State = Event;
@ -371,12 +387,21 @@ cLSTCHandler::cLSTCHandler(cConnectionVTP *Client, const char *Option):
m_Errno(0),
m_Traverse(false)
{
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
if (!Channels) {
#else
if (!Channels.Lock(false, 500)) {
#endif
m_Errno = 451;
m_Error = "Channels are being modified - try again";
} else if (*Option) {
if (isnumber(Option)) {
#if APIVERSNUM >= 20300
m_Channel = Channels->GetByNumber(strtol(Option, NULL, 10));
#else
m_Channel = Channels.GetByNumber(strtol(Option, NULL, 10));
#endif
if (m_Channel == NULL) {
m_Errno = 501;
m_Error = cString::sprintf("Channel \"%s\" not defined", Option);
@ -386,21 +411,35 @@ cLSTCHandler::cLSTCHandler(cConnectionVTP *Client, const char *Option):
int i = 1;
m_Traverse = true;
m_Option = strdup(Option);
#if APIVERSNUM >= 20300
while (i <= Channels->MaxNumber()) {
m_Channel = Channels->GetByNumber(i, 1);
#else
while (i <= Channels.MaxNumber()) {
m_Channel = Channels.GetByNumber(i, 1);
#endif
if (strcasestr(m_Channel->Name(), Option) != NULL)
break;
i = m_Channel->Number() + 1;
}
#if APIVERSNUM >= 20300
if (i > Channels->MaxNumber()) {
#else
if (i > Channels.MaxNumber()) {
#endif
m_Errno = 501;
m_Error = cString::sprintf("Channel \"%s\" not defined", Option);
return;
}
}
#if APIVERSNUM >= 20300
} else if (Channels->MaxNumber() >= 1) {
m_Channel = Channels->GetByNumber(1, 1);
#else
} else if (Channels.MaxNumber() >= 1) {
m_Channel = Channels.GetByNumber(1, 1);
#endif
m_Traverse = true;
} else {
m_Errno = 550;
@ -410,7 +449,9 @@ cLSTCHandler::cLSTCHandler(cConnectionVTP *Client, const char *Option):
cLSTCHandler::~cLSTCHandler()
{
#if APIVERSNUM < 20300
Channels.Unlock();
#endif
if (m_Option != NULL)
free(m_Option);
}
@ -435,8 +476,14 @@ bool cLSTCHandler::Next(bool &Last)
Last = true;
if (m_Traverse) {
int i = m_Channel->Number() + 1;
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
while (i <= Channels->MaxNumber()) {
m_Channel = Channels->GetByNumber(i, 1);
#else
while (i <= Channels.MaxNumber()) {
m_Channel = Channels.GetByNumber(i, 1);
#endif
if (m_Channel != NULL) {
if (m_Option == NULL || strcasestr(m_Channel->Name(),
m_Option) != NULL)
@ -448,7 +495,11 @@ bool cLSTCHandler::Next(bool &Last)
}
}
#if APIVERSNUM >= 20300
if (i < Channels->MaxNumber() + 1)
#else
if (i < Channels.MaxNumber() + 1)
#endif
Last = false;
}
@ -461,7 +512,11 @@ class cLSTTHandler
{
private:
cConnectionVTP *m_Client;
#if APIVERSNUM >= 20300
const cTimer *m_Timer;
#else
cTimer *m_Timer;
#endif
int m_Index;
int m_Errno;
cString m_Error;
@ -479,9 +534,16 @@ cLSTTHandler::cLSTTHandler(cConnectionVTP *Client, const char *Option):
m_Errno(0),
m_Traverse(false)
{
#if APIVERSNUM >= 20300
LOCK_TIMERS_READ;
#endif
if (*Option) {
if (isnumber(Option)) {
#if APIVERSNUM >= 20300
m_Timer = Timers->Get(strtol(Option, NULL, 10) - 1);
#else
m_Timer = Timers.Get(strtol(Option, NULL, 10) - 1);
#endif
if (m_Timer == NULL) {
m_Errno = 501;
m_Error = cString::sprintf("Timer \"%s\" not defined", Option);
@ -490,10 +552,18 @@ cLSTTHandler::cLSTTHandler(cConnectionVTP *Client, const char *Option):
m_Errno = 501;
m_Error = cString::sprintf("Error in timer number \"%s\"", Option);
}
#if APIVERSNUM >= 20300
} else if (Timers->Count()) {
#else
} else if (Timers.Count()) {
#endif
m_Traverse = true;
m_Index = 0;
#if APIVERSNUM >= 20300
m_Timer = Timers->Get(m_Index);
#else
m_Timer = Timers.Get(m_Index);
#endif
if (m_Timer == NULL) {
m_Errno = 501;
m_Error = cString::sprintf("Timer \"%d\" not found", m_Index + 1);
@ -519,7 +589,12 @@ bool cLSTTHandler::Next(bool &Last)
bool result;
char *buffer;
#if APIVERSNUM >= 20300
LOCK_TIMERS_READ;
Last = !m_Traverse || m_Index >= Timers->Count() - 1;
#else
Last = !m_Traverse || m_Index >= Timers.Count() - 1;
#endif
buffer = strdup(*m_Timer->ToText());
buffer[strlen(buffer) - 1] = '\0'; // strip \n
result = m_Client->Respond(Last ? 250 : -250, "%d %s", m_Timer->Index() + 1,
@ -527,7 +602,11 @@ bool cLSTTHandler::Next(bool &Last)
free(buffer);
if (m_Traverse && !Last) {
#if APIVERSNUM >= 20300
m_Timer = Timers->Get(++m_Index);
#else
m_Timer = Timers.Get(++m_Index);
#endif
if (m_Timer == NULL) {
m_Errno = 501;
m_Error = cString::sprintf("Timer \"%d\" not found", m_Index + 1);
@ -544,7 +623,11 @@ private:
enum eStates { Recording, Event, Title, Subtitle, Description, Components, Vps,
EndRecording };
cConnectionVTP *m_Client;
#if APIVERSNUM >= 20300
const cRecording *m_Recording;
#else
cRecording *m_Recording;
#endif
const cEvent *m_Event;
int m_Index;
int m_Errno;
@ -570,9 +653,16 @@ cLSTRHandler::cLSTRHandler(cConnectionVTP *Client, const char *Option):
m_State(Recording),
m_CurrentComponent(0)
{
#if APIVERSNUM >= 20300
LOCK_RECORDINGS_READ;
#endif
if (*Option) {
if (isnumber(Option)) {
#if APIVERSNUM >= 20300
m_Recording = Recordings->Get(strtol(Option, NULL, 10) - 1);
#else
m_Recording = Recordings.Get(strtol(Option, NULL, 10) - 1);
#endif
m_Event = m_Recording->Info()->GetEvent();
m_Info = true;
if (m_Recording == NULL) {
@ -585,10 +675,18 @@ cLSTRHandler::cLSTRHandler(cConnectionVTP *Client, const char *Option):
m_Error = cString::sprintf("Error in Recording number \"%s\"", Option);
}
}
#if APIVERSNUM >= 20300
else if (Recordings->Count()) {
#else
else if (Recordings.Count()) {
#endif
m_Traverse = true;
m_Index = 0;
#if APIVERSNUM >= 20300
m_Recording = Recordings->Get(m_Index);
#else
m_Recording = Recordings.Get(m_Index);
#endif
if (m_Recording == NULL) {
m_Errno = 501;
m_Error = cString::sprintf("Recording \"%d\" not found", m_Index + 1);
@ -691,11 +789,20 @@ bool cLSTRHandler::Next(bool &Last)
}
else {
bool result;
#if APIVERSNUM >= 20300
LOCK_RECORDINGS_READ;
Last = !m_Traverse || m_Index >= Recordings->Count() - 1;
#else
Last = !m_Traverse || m_Index >= Recordings.Count() - 1;
#endif
result = m_Client->Respond(Last ? 250 : -250, "%d %s", m_Recording->Index() + 1, m_Recording->Title(' ', true));
if (m_Traverse && !Last) {
#if APIVERSNUM >= 20300
m_Recording = Recordings->Get(++m_Index);
#else
m_Recording = Recordings.Get(++m_Index);
#endif
if (m_Recording == NULL) {
m_Errno = 501;
m_Error = cString::sprintf("Recording \"%d\" not found", m_Index + 1);
@ -1145,7 +1252,12 @@ bool cConnectionVTP::CmdPLAY(char *Opts)
{
if (*Opts) {
if (isnumber(Opts)) {
#if APIVERSNUM >= 20300
LOCK_RECORDINGS_READ;
const cRecording *recording = Recordings->Get(strtol(Opts, NULL, 10) - 1);
#else
cRecording *recording = Recordings.Get(strtol(Opts, NULL, 10) - 1);
#endif
if (recording) {
if (m_RecPlayer) {
delete m_RecPlayer;
@ -1391,10 +1503,17 @@ bool cConnectionVTP::CmdSTAT(const char *Option)
Reply(250, "VDR: %s | Streamdev: %s", VDRVERSION, VERSION);
}
else if (strcasecmp(Option, "RECORDS") == 0) {
#if APIVERSNUM >= 20300
LOCK_RECORDINGS_WRITE;
Recordings->Sort();
if (Recordings) {
cRecording *recording = Recordings->Last();
#else
bool recordings = Recordings.Load();
Recordings.Sort();
if (recordings) {
cRecording *recording = Recordings.Last();
#endif
Reply(250, "%d", recording->Index() + 1);
}
else {
@ -1402,10 +1521,20 @@ bool cConnectionVTP::CmdSTAT(const char *Option)
}
}
else if (strcasecmp(Option, "CHANNELS") == 0) {
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
Reply(250, "%d", Channels->MaxNumber());
#else
Reply(250, "%d", Channels.MaxNumber());
#endif
}
else if (strcasecmp(Option, "TIMERS") == 0) {
#if APIVERSNUM >= 20300
LOCK_TIMERS_READ;
Reply(250, "%d", Timers->Count());
#else
Reply(250, "%d", Timers.Count());
#endif
}
else if (strcasecmp(Option, "CHARSET") == 0) {
Reply(250, "%s", cCharSetConv::SystemCharacterTable());
@ -1433,7 +1562,12 @@ bool cConnectionVTP::CmdMODT(const char *Option)
int n = strtol(Option, &tail, 10);
if (tail && tail != Option) {
tail = skipspace(tail);
#if APIVERSNUM >= 20300
LOCK_TIMERS_WRITE;
cTimer *timer = Timers->Get(n - 1);
#else
cTimer *timer = Timers.Get(n - 1);
#endif
if (timer) {
cTimer t = *timer;
if (strcasecmp(tail, "ON") == 0)
@ -1445,7 +1579,11 @@ bool cConnectionVTP::CmdMODT(const char *Option)
EXIT_WRAPPER();
}
*timer = t;
#if APIVERSNUM >= 20300
Timers->SetModified();
#else
Timers.SetModified();
#endif
isyslog("timer %s modified (%s)", *timer->ToDescr(),
timer->HasFlags(tfActive) ? "active" : "inactive");
Reply(250, "%d %s", timer->Index() + 1, *timer->ToText());
@ -1464,10 +1602,18 @@ bool cConnectionVTP::CmdNEWT(const char *Option)
if (*Option) {
cTimer *timer = new cTimer;
if (timer->Parse(Option)) {
#if APIVERSNUM >= 20300
LOCK_TIMERS_WRITE;
cTimer *t = Timers->GetTimer(timer);
if (!t) {
Timers->Add(timer);
Timers->SetModified();
#else
cTimer *t = Timers.GetTimer(timer);
if (!t) {
Timers.Add(timer);
Timers.SetModified();
#endif
isyslog("timer %s added", *timer->ToDescr());
Reply(250, "%d %s", timer->Index() + 1, *timer->ToText());
EXIT_WRAPPER();
@ -1512,21 +1658,39 @@ bool cConnectionVTP::CmdDELT(const char *Option)
}
}
#if APIVERSNUM >= 20300
LOCK_TIMERS_WRITE;
cTimer *Timer = Timers->Get(number);
if (Timer) {
if (Timer->Recording()) {
if (force) {
if (!Timer->Remote()) {
Timer->Skip();
cRecordControls::Process(Timers, time(NULL));
}
#else
cTimer *timer = Timers.Get(number);
if (timer) {
if (timer->Recording()) {
if (force) {
timer->Skip();
cRecordControls::Process(time(NULL));
#endif
}
else {
Reply(550, "Timer \"%i\" is recording", number);
EXIT_WRAPPER();
}
}
#if APIVERSNUM >= 20300
isyslog("deleting timer %s", *Timer->ToDescr());
Timers->Del(Timer);
Timers->SetModified();
#else
isyslog("deleting timer %s", *timer->ToDescr());
Timers.Del(timer);
Timers.SetModified();
#endif
Reply(250, "Timer \"%i\" deleted", number);
} else
Reply(501, "Timer \"%i\" not defined", number);
@ -1538,7 +1702,12 @@ bool cConnectionVTP::CmdDELT(const char *Option)
bool cConnectionVTP::CmdNEXT(const char *Option)
{
INIT_WRAPPER();
#if APIVERSNUM >= 20300
LOCK_TIMERS_READ;
const cTimer *t = Timers->GetNextActiveTimer();
#else
cTimer *t = Timers.GetNextActiveTimer();
#endif
if (t) {
time_t Start = t->StartTime();
int Number = t->Index() + 1;
@ -1562,12 +1731,23 @@ bool cConnectionVTP::CmdNEWC(const char *Option)
if (*Option) {
cChannel ch;
if (ch.Parse(Option)) {
#if APIVERSNUM >= 20300
LOCK_CHANNELS_WRITE;
if (Channels->HasUniqueChannelID(&ch)) {
#else
if (Channels.HasUniqueChannelID(&ch)) {
#endif
cChannel *channel = new cChannel;
*channel = ch;
#if APIVERSNUM >= 20300
Channels->Add(channel);
Channels->ReNumber();
Channels->SetModified();
#else
Channels.Add(channel);
Channels.ReNumber();
Channels.SetModified(true);
#endif
isyslog("new channel %d %s", channel->Number(), *channel->ToText());
Reply(250, "%d %s", channel->Number(), *channel->ToText());
}
@ -1593,15 +1773,28 @@ bool cConnectionVTP::CmdMODC(const char *Option)
int n = strtol(Option, &tail, 10);
if (tail && tail != Option) {
tail = skipspace(tail);
#if APIVERSNUM >= 20300
LOCK_CHANNELS_WRITE;
Channels->SetExplicitModify();
cChannel *channel = Channels->GetByNumber(n);
#else
if (!Channels.BeingEdited()) {
cChannel *channel = Channels.GetByNumber(n);
#endif
if (channel) {
cChannel ch;
if (ch.Parse(tail)) {
#if APIVERSNUM >= 20300
if (Channels->HasUniqueChannelID(&ch, channel)) {
*channel = ch;
Channels->ReNumber();
Channels->SetModified();
#else
if (Channels.HasUniqueChannelID(&ch, channel)) {
*channel = ch;
Channels.ReNumber();
Channels.SetModified(true);
#endif
isyslog("modifed channel %d %s", channel->Number(), *channel->ToText());
Reply(250, "%d %s", channel->Number(), *channel->ToText());
}
@ -1616,10 +1809,12 @@ bool cConnectionVTP::CmdMODC(const char *Option)
else {
Reply(501, "Channel \"%d\" not defined", n);
}
#if APIVERSNUM < 20300
}
else {
Reply(550, "Channels are being edited - try again later");
}
#endif
}
else {
Reply(501, "Error in channel number");
@ -1635,7 +1830,14 @@ bool cConnectionVTP::CmdMOVC(const char *Option)
{
INIT_WRAPPER();
if (*Option) {
#if APIVERSNUM >= 20300
LOCK_CHANNELS_WRITE;
Channels->SetExplicitModify();
// LOCK_TIMERS_WRITE;
// Timers->SetExplicitModify();
#else
if (!Channels.BeingEdited() && !Timers.BeingEdited()) {
#endif
char *tail;
int From = strtol(Option, &tail, 10);
if (tail && tail != Option) {
@ -1643,20 +1845,37 @@ bool cConnectionVTP::CmdMOVC(const char *Option)
if (tail && tail != Option) {
int To = strtol(tail, NULL, 10);
int CurrentChannelNr = cDevice::CurrentChannel();
#if APIVERSNUM >= 20300
cChannel *CurrentChannel = Channels->GetByNumber(CurrentChannelNr);
cChannel *FromChannel = Channels->GetByNumber(From);
if (FromChannel) {
cChannel *ToChannel = Channels->GetByNumber(To);
#else
cChannel *CurrentChannel = Channels.GetByNumber(CurrentChannelNr);
cChannel *FromChannel = Channels.GetByNumber(From);
if (FromChannel) {
cChannel *ToChannel = Channels.GetByNumber(To);
#endif
if (ToChannel) {
int FromNumber = FromChannel->Number();
int ToNumber = ToChannel->Number();
if (FromNumber != ToNumber) {
#if APIVERSNUM >= 20300
Channels->Move(FromChannel, ToChannel);
Channels->ReNumber();
Channels->SetModified();
#else
Channels.Move(FromChannel, ToChannel);
Channels.ReNumber();
Channels.SetModified(true);
#endif
if (CurrentChannel && CurrentChannel->Number() != CurrentChannelNr) {
if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring()) {
#if APIVERSNUM >= 20300
Channels->SwitchTo(CurrentChannel->Number());
#else
Channels.SwitchTo(CurrentChannel->Number());
#endif
}
else {
cDevice::SetCurrentChannel(CurrentChannel);
@ -1684,10 +1903,12 @@ bool cConnectionVTP::CmdMOVC(const char *Option)
else {
Reply(501, "Error in channel number");
}
#if APIVERSNUM < 20300
}
else {
Reply(550, "Channels or timers are being edited - try again later");
}
#endif
}
else {
Reply(501, "Missing channel number");
@ -1700,31 +1921,63 @@ bool cConnectionVTP::CmdDELC(const char *Option)
INIT_WRAPPER();
if (*Option) {
if (isnumber(Option)) {
#if APIVERSNUM >= 20300
LOCK_CHANNELS_WRITE;
Channels->SetExplicitModify();
cChannel *channel = Channels->GetByNumber(strtol(Option, NULL, 10));
#else
if (!Channels.BeingEdited()) {
cChannel *channel = Channels.GetByNumber(strtol(Option, NULL, 10));
#endif
if (channel) {
#if APIVERSNUM >= 20300
LOCK_TIMERS_READ;
for (const cTimer *timer = Timers->First(); timer; timer = Timers->Next(timer)) {
#else
for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) {
#endif
if (timer->Channel() == channel) {
Reply(550, "Channel \"%s\" is in use by timer %d", Option, timer->Index() + 1);
return false;
}
}
int CurrentChannelNr = cDevice::CurrentChannel();
#if APIVERSNUM >= 20300
cChannel *CurrentChannel = Channels->GetByNumber(CurrentChannelNr);
#else
cChannel *CurrentChannel = Channels.GetByNumber(CurrentChannelNr);
#endif
if (CurrentChannel && channel == CurrentChannel) {
#if APIVERSNUM >= 20300
int n = Channels->GetNextNormal(CurrentChannel->Index());
if (n < 0)
n = Channels->GetPrevNormal(CurrentChannel->Index());
CurrentChannel = Channels->Get(n);
#else
int n = Channels.GetNextNormal(CurrentChannel->Index());
if (n < 0)
n = Channels.GetPrevNormal(CurrentChannel->Index());
CurrentChannel = Channels.Get(n);
#endif
CurrentChannelNr = 0; // triggers channel switch below
}
#if APIVERSNUM >= 20300
Channels->Del(channel);
Channels->ReNumber();
Channels->SetModified();
#else
Channels.Del(channel);
Channels.ReNumber();
Channels.SetModified(true);
#endif
isyslog("channel %s deleted", Option);
if (CurrentChannel && CurrentChannel->Number() != CurrentChannelNr) {
if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
#if APIVERSNUM >= 20300
Channels->SwitchTo(CurrentChannel->Number());
#else
Channels.SwitchTo(CurrentChannel->Number());
#endif
else
cDevice::SetCurrentChannel(CurrentChannel);
}
@ -1733,9 +1986,11 @@ bool cConnectionVTP::CmdDELC(const char *Option)
else
Reply(501, "Channel \"%s\" not defined", Option);
}
#if APIVERSNUM < 20300
else
Reply(550, "Channels are being edited - try again later");
}
#endif
else
Reply(501, "Error in channel number \"%s\"", Option);
}
@ -1750,13 +2005,22 @@ bool cConnectionVTP::CmdDELR(const char *Option)
INIT_WRAPPER();
if (*Option) {
if (isnumber(Option)) {
#if APIVERSNUM >= 20300
LOCK_RECORDINGS_WRITE;
cRecording *recording = Recordings->Get(strtol(Option, NULL, 10) - 1);
#else
cRecording *recording = Recordings.Get(strtol(Option, NULL, 10) - 1);
#endif
if (recording) {
cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
if (!rc) {
if (recording->Delete()) {
Reply(250, "Recording \"%s\" deleted", Option);
#if APIVERSNUM >= 20300
Recordings->DelByName(recording->FileName());
#else
::Recordings.DelByName(recording->FileName());
#endif
}
else
Reply(554, "Error while deleting recording!");
@ -1765,7 +2029,11 @@ bool cConnectionVTP::CmdDELR(const char *Option)
Reply(550, "Recording \"%s\" is in use by timer %d", Option, rc->Timer()->Index() + 1);
}
else
#if APIVERSNUM >= 20300
Reply(550, "Recording \"%s\" not found%s", Option, Recordings->Count() ? "" : " (use LSTR before deleting)");
#else
Reply(550, "Recording \"%s\" not found%s", Option, Recordings.Count() ? "" : " (use LSTR before deleting)");
#endif
}
else
Reply(501, "Error in recording number \"%s\"", Option);

View File

@ -31,7 +31,11 @@ private:
cStreamdevLiveStreamer *m_Streamer;
protected:
#if APIVERSNUM >= 20300
virtual void Receive(const uchar *Data, int Length);
#else
virtual void Receive(uchar *Data, int Length);
#endif
public:
cStreamdevLiveReceiver(cStreamdevLiveStreamer *Streamer, const cChannel *Channel, int Priority, const int *Pids);
@ -53,7 +57,11 @@ cStreamdevLiveReceiver::~cStreamdevLiveReceiver()
Detach();
}
#if APIVERSNUM >= 20300
void cStreamdevLiveReceiver::Receive(const uchar *Data, int Length) {
#else
void cStreamdevLiveReceiver::Receive(uchar *Data, int Length) {
#endif
m_Streamer->Receive(Data, Length);
}
@ -250,7 +258,12 @@ void cStreamdevPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, i
SI::PAT::Association assoc;
for (SI::Loop::Iterator it; pat.associationLoop.getNext(assoc, it); ) {
if (!assoc.isNITPid()) {
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
const cChannel *Channel = Channels->GetByServiceID(Source(), Transponder(), assoc.getServiceId());
#else
const cChannel *Channel = Channels.GetByServiceID(Source(), Transponder(), assoc.getServiceId());
#endif
if (Channel && (Channel == m_Channel)) {
int prevPmtPid = pmtPid;
if (0 != (pmtPid = assoc.getPid())) {
@ -547,7 +560,11 @@ bool cStreamdevLiveStreamer::SetChannel(eStreamType StreamType, const int* Apid,
}
}
#if APIVERSNUM >= 20300
void cStreamdevLiveStreamer::Receive(const uchar *Data, int Length)
#else
void cStreamdevLiveStreamer::Receive(uchar *Data, int Length)
#endif
{
int p = m_ReceiveBuffer->PutTS(Data, Length);
if (p != Length)
@ -688,9 +705,16 @@ void cStreamdevLiveStreamer::MainThreadHook()
}
if (m_SwitchLive) {
// switched away live TV. Try previous channel on other device first
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
if (!Channels->SwitchTo(cDevice::CurrentChannel())) {
// switch to streamdev channel otherwise
Channels->SwitchTo(m_Channel->Number());
#else
if (!Channels.SwitchTo(cDevice::CurrentChannel())) {
// switch to streamdev channel otherwise
Channels.SwitchTo(m_Channel->Number());
#endif
Skins.Message(mtInfo, tr("Streaming active"));
}
if (m_Device)

View File

@ -64,7 +64,11 @@ public:
void GetSignal(int *DevNum, int *Strength, int *Quality) const;
virtual cString ToText() const;
#if APIVERSNUM >= 20300
void Receive(const uchar *Data, int Length);
#else
void Receive(uchar *Data, int Length);
#endif
virtual bool IsReceiving(void) const;
virtual void Attach(void);

View File

@ -13,7 +13,11 @@
cStreamdevServerMenu::cStreamdevServerMenu(): cOsdMenu(tr("Streamdev Connections"), 4, 20) {
cThreadLock lock;
#if APIVERSNUM >= 20300
cList<cServerConnection>& clients = cStreamdevServer::Clients(lock);
#else
const cList<cServerConnection>& clients = cStreamdevServer::Clients(lock);
#endif
for (cServerConnection *s = clients.First(); s; s = clients.Next(s))
Add(new cOsdItem(s->ToText('\t')));
SetHelpKeys();
@ -31,7 +35,11 @@ eOSState cStreamdevServerMenu::Disconnect() {
cOsdItem *item = Get(Current());
if (item) {
cThreadLock lock;
#if APIVERSNUM >= 20300
cList<cServerConnection>& clients = cStreamdevServer::Clients(lock);
#else
const cList<cServerConnection>& clients = cStreamdevServer::Clients(lock);
#endif
const char *text = item->Text();
for (cServerConnection *s = clients.First(); s; s = clients.Next(s)) {
if (!strcmp(text, s->ToText('\t'))) {

View File

@ -6,10 +6,19 @@
#include "server/menuHTTP.h"
//**************************** cRecordingIterator **************
#if APIVERSNUM >= 20300
cRecordingsIterator::cRecordingsIterator(eStreamType StreamType)
#else
cRecordingsIterator::cRecordingsIterator(eStreamType StreamType): RecordingsLock(&Recordings)
#endif
{
streamType = StreamType;
#if APIVERSNUM >= 20300
LOCK_RECORDINGS_READ;
first = NextSuitable(Recordings->First());
#else
first = NextSuitable(Recordings.First());
#endif
current = NULL;
}
@ -20,20 +29,32 @@ const cRecording* cRecordingsIterator::NextSuitable(const cRecording *Recording)
bool isPes = Recording->IsPesRecording();
if (!isPes || (isPes && streamType == stPES))
break;
#if APIVERSNUM >= 20300
LOCK_RECORDINGS_READ;
Recording = Recordings->Next(Recording);
#else
Recording = Recordings.Next(Recording);
#endif
}
return Recording;
}
bool cRecordingsIterator::Next()
{
#if APIVERSNUM >= 20300
LOCK_RECORDINGS_READ;
#endif
if (first)
{
current = first;
first = NULL;
}
else
#if APIVERSNUM >= 20300
current = NextSuitable(Recordings->Next(current));
#else
current = NextSuitable(Recordings.Next(current));
#endif
return current;
}
@ -71,9 +92,16 @@ const cString cChannelIterator::ItemId() const
if (current->GroupSep())
{
int index = 0;
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
for (int curr = Channels->GetNextGroup(-1); curr >= 0; curr = Channels->GetNextGroup(curr))
{
if (Channels->Get(curr) == current)
#else
for (int curr = Channels.GetNextGroup(-1); curr >= 0; curr = Channels.GetNextGroup(curr))
{
if (Channels.Get(curr) == current)
#endif
return itoa(index);
index++;
}
@ -89,47 +117,111 @@ const cString cChannelIterator::ItemId() const
const cChannel* cChannelIterator::GetGroup(const char* GroupId)
{
int group = -1;
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
#endif
if (GroupId)
{
int Index = atoi(GroupId);
#if APIVERSNUM >= 20300
group = Channels->GetNextGroup(-1);
while (Index-- && group >= 0)
group = Channels->GetNextGroup(group);
}
return group >= 0 ? Channels->Get(group) : NULL;
#else
group = Channels.GetNextGroup(-1);
while (Index-- && group >= 0)
group = Channels.GetNextGroup(group);
}
return group >= 0 ? Channels.Get(group) : NULL;
#endif
}
const cChannel* cChannelIterator::FirstChannel()
{
const cChannel *Channel;
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
Channel = Channels->First();
#else
Channel = Channels.First();
#endif
return Channel;
}
const cChannel* cChannelIterator::NextNormal()
{
const cChannel *Channel;
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
Channel = Channels->Get(Channels->GetNextNormal(-1));
#else
Channel = Channels.Get(Channels.GetNextNormal(-1));
#endif
return Channel;
}
const cChannel* cChannelIterator::NextGroup()
{
const cChannel *Channel;
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
Channel = Channels->Get(Channels->GetNextGroup(-1));
#else
Channel = Channels.Get(Channels.GetNextGroup(-1));
#endif
return Channel;
}
//**************************** cListAll **************
cListAll::cListAll(): cChannelIterator(Channels.First())
cListAll::cListAll(): cChannelIterator(FirstChannel())
{}
const cChannel* cListAll::NextChannel(const cChannel *Channel)
{
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
if (Channel)
Channel = SkipFakeGroups(Channels->Next(Channel));
#else
if (Channel)
Channel = SkipFakeGroups(Channels.Next(Channel));
#endif
return Channel;
}
//**************************** cListChannels **************
cListChannels::cListChannels(): cChannelIterator(Channels.Get(Channels.GetNextNormal(-1)))
cListChannels::cListChannels(): cChannelIterator(NextNormal())
{}
const cChannel* cListChannels::NextChannel(const cChannel *Channel)
{
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
if (Channel)
Channel = Channels->Get(Channels->GetNextNormal(Channel->Index()));
#else
if (Channel)
Channel = Channels.Get(Channels.GetNextNormal(Channel->Index()));
#endif
return Channel;
}
// ********************* cListGroups ****************
cListGroups::cListGroups(): cChannelIterator(Channels.Get(Channels.GetNextGroup(-1)))
cListGroups::cListGroups(): cChannelIterator(NextGroup())
{}
const cChannel* cListGroups::NextChannel(const cChannel *Channel)
{
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
if (Channel)
Channel = Channels->Get(Channels->GetNextGroup(Channel->Index()));
#else
if (Channel)
Channel = Channels.Get(Channels.GetNextGroup(Channel->Index()));
#endif
return Channel;
}
//
@ -139,8 +231,14 @@ cListGroup::cListGroup(const char *GroupId): cChannelIterator(GetNextChannelInGr
const cChannel* cListGroup::GetNextChannelInGroup(const cChannel *Channel)
{
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
if (Channel)
Channel = SkipFakeGroups(Channels->Next(Channel));
#else
if (Channel)
Channel = SkipFakeGroups(Channels.Next(Channel));
#endif
return Channel && !Channel->GroupSep() ? Channel : NULL;
}
@ -150,25 +248,42 @@ const cChannel* cListGroup::NextChannel(const cChannel *Channel)
}
//
// ********************* cListTree ****************
cListTree::cListTree(const char *SelectedGroupId): cChannelIterator(Channels.Get(Channels.GetNextGroup(-1)))
cListTree::cListTree(const char *SelectedGroupId): cChannelIterator(NextGroup())
{
selectedGroup = GetGroup(SelectedGroupId);
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
currentGroup = Channels->Get(Channels->GetNextGroup(-1));
#else
currentGroup = Channels.Get(Channels.GetNextGroup(-1));
#endif
}
const cChannel* cListTree::NextChannel(const cChannel *Channel)
{
if (currentGroup == selectedGroup)
{
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
if (Channel)
Channel = SkipFakeGroups(Channels->Next(Channel));
#else
if (Channel)
Channel = SkipFakeGroups(Channels.Next(Channel));
#endif
if (Channel && Channel->GroupSep())
currentGroup = Channel;
}
else
{
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
if (Channel)
Channel = Channels->Get(Channels->GetNextGroup(Channel->Index()));
#else
if (Channel)
Channel = Channels.Get(Channels.GetNextGroup(Channel->Index()));
#endif
currentGroup = Channel;
}
return Channel;

View File

@ -48,6 +48,9 @@ class cChannelIterator: public cItemIterator
const cChannel *first;
const cChannel *current;
protected:
virtual const cChannel* FirstChannel();
virtual const cChannel* NextNormal();
virtual const cChannel* NextGroup();
virtual const cChannel* NextChannel(const cChannel *Channel) = 0;
static inline const cChannel* SkipFakeGroups(const cChannel *Channel);
// Helper which returns the group by its index
@ -208,8 +211,15 @@ class cRssMenuList: public cMenuList
inline const cChannel* cChannelIterator::SkipFakeGroups(const cChannel* Group)
{
#if APIVERSNUM >= 20300
LOCK_CHANNELS_READ;
#endif
while (Group && Group->GroupSep() && !*Group->Name())
#if APIVERSNUM >= 20300
Group = Channels->Next(Group);
#else
Group = Channels.Next(Group);
#endif
return Group;
}

View File

@ -177,7 +177,11 @@ void cStreamdevServer::Action(void)
}
}
#if APIVERSNUM >= 20300
cList<cServerConnection>& cStreamdevServer::Clients(cThreadLock& Lock)
#else
const cList<cServerConnection>& cStreamdevServer::Clients(cThreadLock& Lock)
#endif
{
Lock.Lock(m_Instance);
return m_Clients;

View File

@ -37,7 +37,11 @@ public:
static void Destruct(void);
static bool Active(void);
#if APIVERSNUM >= 20300
static cList<cServerConnection>& Clients(cThreadLock& Lock);
#else
static const cList<cServerConnection>& Clients(cThreadLock& Lock);
#endif
};
inline bool cStreamdevServer::Active(void)

View File

@ -21,7 +21,11 @@
cList<cMainThreadHookSubscriber> cMainThreadHookSubscriber::m_Subscribers;
cMutex cMainThreadHookSubscriber::m_Mutex;
#if APIVERSNUM >= 20300
cList<cMainThreadHookSubscriber>& cMainThreadHookSubscriber::Subscribers(cMutexLock& Lock)
#else
const cList<cMainThreadHookSubscriber>& cMainThreadHookSubscriber::Subscribers(cMutexLock& Lock)
#endif
{
Lock.Lock(&m_Mutex);
return m_Subscribers;
@ -163,7 +167,11 @@ void cPluginStreamdevServer::MainThreadHook(void)
}
cMutexLock lock;
#if APIVERSNUM >= 20300
cList<cMainThreadHookSubscriber>& subs = cMainThreadHookSubscriber::Subscribers(lock);
#else
const cList<cMainThreadHookSubscriber>& subs = cMainThreadHookSubscriber::Subscribers(lock);
#endif
for (cMainThreadHookSubscriber *s = subs.First(); s; s = subs.Next(s))
s->MainThreadHook();
}
@ -199,7 +207,11 @@ cString cPluginStreamdevServer::SVDRPCommand(const char *Command, const char *Op
{
reply = "";
cThreadLock lock;
#if APIVERSNUM >= 20300
cList<cServerConnection>& clients = cStreamdevServer::Clients(lock);
#else
const cList<cServerConnection>& clients = cStreamdevServer::Clients(lock);
#endif
cServerConnection *s = clients.First();
if (!s)
{
@ -223,7 +235,11 @@ cString cPluginStreamdevServer::SVDRPCommand(const char *Command, const char *Op
} else
{
cThreadLock lock;
#if APIVERSNUM >= 20300
cList<cServerConnection>& clients = cStreamdevServer::Clients(lock);
#else
const cList<cServerConnection>& clients = cStreamdevServer::Clients(lock);
#endif
cServerConnection *s = clients.First();
for (; s && s != client; s = clients.Next(s));

View File

@ -15,7 +15,11 @@ private:
static cList<cMainThreadHookSubscriber> m_Subscribers;
static cMutex m_Mutex;
public:
#if APIVERSNUM >= 20300
static cList<cMainThreadHookSubscriber>& Subscribers(cMutexLock& Lock);
#else
static const cList<cMainThreadHookSubscriber>& Subscribers(cMutexLock& Lock);
#endif
virtual void MainThreadHook() = 0;