mirror of
https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
synced 2023-10-10 17:16:51 +00:00
Snapshot 2009-06-11
This commit is contained in:
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* $Id: assembler.c,v 1.2 2005/01/25 14:14:43 lordjaxom Exp $
|
||||
*/
|
||||
|
||||
#include "client/assembler.h"
|
||||
#include "common.h"
|
||||
|
||||
#include "tools/socket.h"
|
||||
#include "tools/select.h"
|
||||
|
||||
#include <vdr/tools.h>
|
||||
#include <vdr/device.h>
|
||||
#include <vdr/ringbuffer.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
cStreamdevAssembler::cStreamdevAssembler(cTBSocket *Socket)
|
||||
#if VDRVERSNUM >= 10300
|
||||
:cThread("Streamdev: UDP-TS Assembler")
|
||||
#endif
|
||||
{
|
||||
m_Socket = Socket;
|
||||
if (pipe(m_Pipe) != 0) {
|
||||
esyslog("streamdev-client: Couldn't open assembler pipe: %m");
|
||||
return;
|
||||
}
|
||||
fcntl(m_Pipe[0], F_SETFL, O_NONBLOCK);
|
||||
fcntl(m_Pipe[1], F_SETFL, O_NONBLOCK);
|
||||
m_Mutex.Lock();
|
||||
Start();
|
||||
}
|
||||
|
||||
cStreamdevAssembler::~cStreamdevAssembler() {
|
||||
if (m_Active) {
|
||||
m_Active = false;
|
||||
/* WakeUp();*/
|
||||
Cancel(3);
|
||||
}
|
||||
close(m_Pipe[0]);
|
||||
close(m_Pipe[1]);
|
||||
}
|
||||
|
||||
void cStreamdevAssembler::Action(void) {
|
||||
cTBSelect sel;
|
||||
uchar buffer[2048];
|
||||
bool fillup = true;
|
||||
|
||||
const int rbsize = TS_SIZE * 5600;
|
||||
const int rbmargin = TS_SIZE * 2;
|
||||
const int rbminfill = rbmargin * 50;
|
||||
cRingBufferLinear ringbuf(rbsize, rbmargin, true);
|
||||
|
||||
#if VDRVERSNUM < 10300
|
||||
isyslog("streamdev-client: UDP-TS Assembler thread started (pid=%d)",
|
||||
getpid());
|
||||
#endif
|
||||
|
||||
m_Mutex.Lock();
|
||||
|
||||
m_Active = true;
|
||||
while (m_Active) {
|
||||
sel.Clear();
|
||||
|
||||
if (ringbuf.Available() < rbsize * 80 / 100)
|
||||
sel.Add(*m_Socket, false);
|
||||
if (ringbuf.Available() > rbminfill) {
|
||||
if (fillup) {
|
||||
Dprintf("giving signal\n");
|
||||
m_WaitFill.Broadcast();
|
||||
m_Mutex.Unlock();
|
||||
fillup = false;
|
||||
}
|
||||
sel.Add(m_Pipe[1], true);
|
||||
}
|
||||
|
||||
if (sel.Select(1500) < 0) {
|
||||
if (!m_Active) // Exit was requested
|
||||
break;
|
||||
esyslog("streamdev-client: Fatal error: %m");
|
||||
Dprintf("streamdev-client: select failed (%m)\n");
|
||||
m_Active = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sel.CanRead(*m_Socket)) {
|
||||
int b;
|
||||
if ((b = m_Socket->Read(buffer, sizeof(buffer))) < 0) {
|
||||
esyslog("streamdev-client: Couldn't read from server: %m");
|
||||
Dprintf("streamdev-client: read failed (%m)\n");
|
||||
m_Active = false;
|
||||
break;
|
||||
}
|
||||
if (b == 0)
|
||||
m_Active = false;
|
||||
else
|
||||
ringbuf.Put(buffer, b);
|
||||
}
|
||||
|
||||
if (sel.CanWrite(m_Pipe[1])) {
|
||||
int recvd;
|
||||
const uchar *block = ringbuf.Get(recvd);
|
||||
if (block && recvd > 0) {
|
||||
int result;
|
||||
if (recvd > ringbuf.Available() - rbminfill)
|
||||
recvd = ringbuf.Available() - rbminfill;
|
||||
if ((result = write(m_Pipe[1], block, recvd)) == -1) {
|
||||
esyslog("streamdev-client: Couldn't write to VDR: %m"); // TODO
|
||||
Dprintf("streamdev-client: write failed (%m)\n");
|
||||
m_Active = false;
|
||||
break;
|
||||
}
|
||||
ringbuf.Del(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if VDRVERSNUM < 10300
|
||||
isyslog("streamdev-client: UDP-TS Assembler thread stopped", getpid());
|
||||
#endif
|
||||
}
|
||||
|
||||
void cStreamdevAssembler::WaitForFill(void) {
|
||||
m_WaitFill.Wait(m_Mutex);
|
||||
m_Mutex.Unlock();
|
||||
}
|
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* $Id: assembler.h,v 1.1.1.1 2004/12/30 22:44:04 lordjaxom Exp $
|
||||
*/
|
||||
|
||||
#ifndef VDR_STREAMDEV_ASSEMBLER_H
|
||||
#define VDR_STREAMDEV_ASSEMBLER_H
|
||||
|
||||
#include <vdr/config.h>
|
||||
#include <vdr/thread.h>
|
||||
|
||||
class cTBSocket;
|
||||
|
||||
class cStreamdevAssembler: public cThread {
|
||||
private:
|
||||
cTBSocket *m_Socket;
|
||||
cMutex m_Mutex;
|
||||
cCondVar m_WaitFill;
|
||||
int m_Pipe[2];
|
||||
bool m_Active;
|
||||
protected:
|
||||
virtual void Action(void);
|
||||
|
||||
public:
|
||||
cStreamdevAssembler(cTBSocket *Socket);
|
||||
virtual ~cStreamdevAssembler();
|
||||
|
||||
int ReadPipe(void) const { return m_Pipe[0]; }
|
||||
void WaitForFill(void);
|
||||
};
|
||||
|
||||
#endif // VDR_STREAMDEV_ASSEMBLER_H
|
||||
|
@@ -1,10 +1,9 @@
|
||||
/*
|
||||
* $Id: device.c,v 1.15 2007/12/12 12:22:45 schmirl Exp $
|
||||
* $Id: device.c,v 1.23 2009/04/06 06:48:59 schmirl Exp $
|
||||
*/
|
||||
|
||||
#include "client/device.h"
|
||||
#include "client/setup.h"
|
||||
#include "client/assembler.h"
|
||||
#include "client/filter.h"
|
||||
|
||||
#include "tools/select.h"
|
||||
@@ -26,20 +25,10 @@ cStreamdevDevice *cStreamdevDevice::m_Device = NULL;
|
||||
cStreamdevDevice::cStreamdevDevice(void) {
|
||||
m_Channel = NULL;
|
||||
m_TSBuffer = NULL;
|
||||
m_Assembler = NULL;
|
||||
|
||||
#if VDRVERSNUM < 10300
|
||||
# if defined(HAVE_AUTOPID)
|
||||
(void)new cSIProcessor(new cSectionsScanner(""));
|
||||
# else
|
||||
(void)new cSIProcessor("");
|
||||
# endif
|
||||
cSIProcessor::Read();
|
||||
#else
|
||||
m_Filters = new cStreamdevFilters;
|
||||
StartSectionHandler();
|
||||
cSchedules::Read();
|
||||
#endif
|
||||
isyslog("streamdev-client: got device number %d", CardIndex() + 1);
|
||||
|
||||
m_Device = this;
|
||||
m_Pids = 0;
|
||||
@@ -61,11 +50,11 @@ cStreamdevDevice::~cStreamdevDevice() {
|
||||
|
||||
Cancel(3);
|
||||
|
||||
#if VDRVERSNUM >= 10300
|
||||
DELETENULL(m_Filters);
|
||||
#if APIVERSNUM >= 10515
|
||||
StopSectionHandler();
|
||||
#endif
|
||||
DELETENULL(m_Filters);
|
||||
DELETENULL(m_TSBuffer);
|
||||
delete m_Assembler;
|
||||
}
|
||||
|
||||
bool cStreamdevDevice::ProvidesSource(int Source) const {
|
||||
@@ -93,8 +82,25 @@ bool cStreamdevDevice::ProvidesChannel(const cChannel *Channel, int Priority,
|
||||
bool res = false;
|
||||
bool prio = Priority < 0 || Priority > this->Priority();
|
||||
bool ndr = false;
|
||||
|
||||
if (!StreamdevClientSetup.StartClient)
|
||||
return false;
|
||||
|
||||
Dprintf("ProvidesChannel, Channel=%s, Prio=%d\n", Channel->Name(), Priority);
|
||||
|
||||
if (StreamdevClientSetup.MinPriority <= StreamdevClientSetup.MaxPriority)
|
||||
{
|
||||
if (Priority < StreamdevClientSetup.MinPriority ||
|
||||
Priority > StreamdevClientSetup.MaxPriority)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Priority < StreamdevClientSetup.MinPriority &&
|
||||
Priority > StreamdevClientSetup.MaxPriority)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ClientSocket.DataSocket(siLive) != NULL
|
||||
&& TRANSPONDER(Channel, m_Channel))
|
||||
res = true;
|
||||
@@ -117,23 +123,14 @@ bool cStreamdevDevice::SetChannelDevice(const cChannel *Channel,
|
||||
if (LiveView)
|
||||
return false;
|
||||
|
||||
#if 0
|
||||
if (ClientSocket.DataSocket(siLive) != NULL
|
||||
&& TRANSPONDER(Channel, m_Channel))
|
||||
&& TRANSPONDER(Channel, m_Channel)
|
||||
&& Channel->Ca() < CA_ENCRYPTED_MIN)
|
||||
return true;
|
||||
|
||||
#if VDRVERSNUM < 10338
|
||||
DetachAll(pidHandles[ptAudio].pid);
|
||||
DetachAll(pidHandles[ptVideo].pid);
|
||||
DetachAll(pidHandles[ptPcr].pid);
|
||||
DetachAll(pidHandles[ptTeletext].pid);
|
||||
DelPid(pidHandles[ptAudio].pid);
|
||||
DelPid(pidHandles[ptVideo].pid);
|
||||
DelPid(pidHandles[ptPcr].pid, ptPcr);
|
||||
DelPid(pidHandles[ptTeletext].pid);
|
||||
DelPid(pidHandles[ptDolby].pid);
|
||||
#else
|
||||
DetachAllReceivers();
|
||||
#endif
|
||||
|
||||
DetachAllReceivers();
|
||||
m_Channel = Channel;
|
||||
bool r = ClientSocket.SetChannelDevice(m_Channel);
|
||||
Dprintf("setchanneldevice r=%d\n", r);
|
||||
@@ -212,16 +209,11 @@ void cStreamdevDevice::CloseDvrInt(void) {
|
||||
}
|
||||
|
||||
Dprintf("cStreamdevDevice::CloseDvrInt(): Closing DVR connection\n");
|
||||
#if VDRVERSNUM < 10500
|
||||
DELETENULL(m_TSBuffer);
|
||||
ClientSocket.CloseDvr();
|
||||
#else
|
||||
// Hack for VDR 1.5.x clients (sometimes sending ABRT after TUNE)
|
||||
// TODO: Find a clean solution to fix this
|
||||
ClientSocket.SetChannelDevice(m_Channel);
|
||||
ClientSocket.CloseDvr();
|
||||
DELETENULL(m_TSBuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
void cStreamdevDevice::CloseDvr(void) {
|
||||
@@ -268,7 +260,6 @@ esyslog("cStreamDevice::GetTSPacket: GetChecked: NOTHING (%d)", m_TSFails);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if VDRVERSNUM >= 10300
|
||||
int cStreamdevDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask) {
|
||||
Dprintf("OpenFilter\n");
|
||||
|
||||
@@ -290,7 +281,6 @@ int cStreamdevDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool cStreamdevDevice::Init(void) {
|
||||
if (m_Device == NULL && StreamdevClientSetup.StartClient)
|
||||
@@ -308,7 +298,6 @@ bool cStreamdevDevice::ReInit(void) {
|
||||
ClientSocket.Reset();
|
||||
if (m_Device != NULL) {
|
||||
//DELETENULL(m_Device->m_TSBuffer);
|
||||
DELETENULL(m_Device->m_Assembler);
|
||||
m_Device->Unlock();
|
||||
}
|
||||
return StreamdevClientSetup.StartClient ? Init() : true;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: device.h,v 1.5 2007/04/24 10:43:40 schmirl Exp $
|
||||
* $Id: device.h,v 1.8 2008/10/02 07:14:47 schmirl Exp $
|
||||
*/
|
||||
|
||||
#ifndef VDR_STREAMDEV_DEVICE_H
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <vdr/device.h>
|
||||
|
||||
#include "client/socket.h"
|
||||
#include "client/assembler.h"
|
||||
#include "client/filter.h"
|
||||
|
||||
class cTBString;
|
||||
@@ -21,10 +20,7 @@ class cStreamdevDevice: public cDevice {
|
||||
private:
|
||||
const cChannel *m_Channel;
|
||||
cTSBuffer *m_TSBuffer;
|
||||
cStreamdevAssembler *m_Assembler;
|
||||
#if VDRVERSNUM >= 10307
|
||||
cStreamdevFilters *m_Filters;
|
||||
#endif
|
||||
int m_Pids;
|
||||
bool m_DvrClosed;
|
||||
|
||||
@@ -47,14 +43,13 @@ protected:
|
||||
virtual void CloseDvr(void);
|
||||
virtual bool GetTSPacket(uchar *&Data);
|
||||
|
||||
#if VDRVERSNUM >= 10300
|
||||
virtual int OpenFilter(u_short Pid, u_char Tid, u_char Mask);
|
||||
#endif
|
||||
|
||||
public:
|
||||
cStreamdevDevice(void);
|
||||
virtual ~cStreamdevDevice();
|
||||
|
||||
virtual bool HasInternalCam(void) { return true; }
|
||||
virtual bool ProvidesSource(int Source) const;
|
||||
virtual bool ProvidesTransponder(const cChannel *Channel) const;
|
||||
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1,
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: filter.c,v 1.11 2007/04/24 11:23:16 schmirl Exp $
|
||||
* $Id: filter.c,v 1.14 2009/02/13 13:02:39 schmirl Exp $
|
||||
*/
|
||||
|
||||
#include "client/filter.h"
|
||||
@@ -9,8 +9,7 @@
|
||||
|
||||
#include <vdr/device.h>
|
||||
|
||||
#if VDRVERSNUM >= 10300
|
||||
|
||||
#define PID_MASK_HI 0x1F
|
||||
// --- cStreamdevFilter ------------------------------------------------------
|
||||
|
||||
class cStreamdevFilter: public cListObject {
|
||||
@@ -228,6 +227,7 @@ void cStreamdevFilters::Action(void) {
|
||||
u_short pid = (((u_short)block[1] & PID_MASK_HI) << 8) | block[2];
|
||||
u_char tid = block[3];
|
||||
bool Pusi = block[1] & 0x40;
|
||||
// proprietary extension
|
||||
int len = block[4];
|
||||
#if 0
|
||||
if (block[1] == 0xff &&
|
||||
@@ -290,5 +290,3 @@ void cStreamdevFilters::Action(void) {
|
||||
DELETENULL(m_TSBuffer);
|
||||
dsyslog("StreamdevFilters::Action() ended");
|
||||
}
|
||||
|
||||
#endif // VDRVERSNUM >= 10300
|
||||
|
@@ -1,14 +1,11 @@
|
||||
/*
|
||||
* $Id: filter.h,v 1.4 2007/04/24 11:23:16 schmirl Exp $
|
||||
* $Id: filter.h,v 1.5 2008/04/07 14:27:28 schmirl Exp $
|
||||
*/
|
||||
|
||||
#ifndef VDR_STREAMDEV_FILTER_H
|
||||
#define VDR_STREAMDEV_FILTER_H
|
||||
|
||||
#include <vdr/config.h>
|
||||
|
||||
# if VDRVERSNUM >= 10300
|
||||
|
||||
#include <vdr/tools.h>
|
||||
#include <vdr/thread.h>
|
||||
|
||||
@@ -33,5 +30,4 @@ public:
|
||||
int OpenFilter(u_short Pid, u_char Tid, u_char Mask);
|
||||
};
|
||||
|
||||
# endif // VDRVERSNUM >= 10300
|
||||
#endif // VDR_STREAMDEV_FILTER_H
|
||||
|
1045
client/menu.c
1045
client/menu.c
File diff suppressed because it is too large
Load Diff
144
client/menu.h
144
client/menu.h
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* $Id: menu.h,v 1.1.1.1 2004/12/30 22:44:02 lordjaxom Exp $
|
||||
*/
|
||||
|
||||
#ifndef VDR_STREAMDEV_MENU_H
|
||||
#define VDR_STREAMDEV_MENU_H
|
||||
|
||||
#include <vdr/osd.h>
|
||||
|
||||
#include "client/remote.h"
|
||||
|
||||
class cStreamdevMenuRecordingItem;
|
||||
|
||||
// --- cStreamdevMenu --------------------------------------------------------
|
||||
|
||||
class cStreamdevMenu: public cOsdMenu {
|
||||
private:
|
||||
enum eSubmenus {
|
||||
sub_Start = os_User,
|
||||
subSchedule,
|
||||
subTimers,
|
||||
subRecordings,
|
||||
subSuspend,
|
||||
subSyncEPG
|
||||
};
|
||||
|
||||
protected:
|
||||
void SuspendServer(void);
|
||||
|
||||
public:
|
||||
cStreamdevMenu(void);
|
||||
virtual ~cStreamdevMenu(void);
|
||||
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
// --- cStreamdevMenuSchedule ------------------------------------------------
|
||||
|
||||
class cStreamdevMenuSchedule: public cOsdMenu {
|
||||
private:
|
||||
bool m_Now;
|
||||
bool m_Next;
|
||||
int m_OtherChannel;
|
||||
const cSchedules *m_Schedules;
|
||||
#if VDRVERSNUM < 10300
|
||||
cMutexLock m_Lock;
|
||||
#else
|
||||
cSchedulesLock m_Lock;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void PrepareSchedule(cChannel *Channel);
|
||||
|
||||
eOSState Switch(void);
|
||||
eOSState Record(void);
|
||||
|
||||
public:
|
||||
cStreamdevMenuSchedule(void);
|
||||
virtual ~cStreamdevMenuSchedule(void);
|
||||
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
// --- cStreamdevMenuWhatsOn -------------------------------------------------
|
||||
|
||||
class cStreamdevMenuWhatsOn: public cOsdMenu {
|
||||
private:
|
||||
static int m_CurrentChannel;
|
||||
#if VDRVERSNUM < 10300
|
||||
static const cEventInfo *m_ScheduleEventInfo;
|
||||
#else
|
||||
static const cEvent *m_ScheduleEventInfo;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
eOSState Switch(void);
|
||||
eOSState Record(void);
|
||||
|
||||
public:
|
||||
cStreamdevMenuWhatsOn(const cSchedules *Schedules, bool Now,
|
||||
int CurrentChannel);
|
||||
|
||||
static int CurrentChannel(void) { return m_CurrentChannel; }
|
||||
static void SetCurrentChannel(int Channel) { m_CurrentChannel = Channel; }
|
||||
#if VDRVERSNUM < 10300
|
||||
static const cEventInfo *ScheduleEventInfo(void);
|
||||
#else
|
||||
static const cEvent *ScheduleEventInfo(void);
|
||||
#endif
|
||||
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
// --- cStreamdevMenuRecordings ----------------------------------------------
|
||||
|
||||
class cStreamdevMenuRecordings: public cOsdMenu {
|
||||
private:
|
||||
char *m_Base;
|
||||
int m_Level;
|
||||
|
||||
static int HelpKeys;
|
||||
static cRemoteRecordings Recordings;
|
||||
|
||||
protected:
|
||||
bool Open(bool OpenSubMenus = false);
|
||||
void SetHelpKeys();
|
||||
cRemoteRecording *cStreamdevMenuRecordings::GetRecording(
|
||||
cStreamdevMenuRecordingItem *Item);
|
||||
|
||||
eOSState Select(void);
|
||||
eOSState Delete(void);
|
||||
eOSState Summary(void);
|
||||
|
||||
public:
|
||||
cStreamdevMenuRecordings(const char *Base = NULL, int Level = 0,
|
||||
bool OpenSubMenus = false);
|
||||
virtual ~cStreamdevMenuRecordings();
|
||||
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
// --- cStreamdevMenuTimers --------------------------------------------------
|
||||
|
||||
class cStreamdevMenuTimers: public cOsdMenu {
|
||||
protected:
|
||||
eOSState Edit(void);
|
||||
eOSState New(void);
|
||||
eOSState Delete(void);
|
||||
eOSState OnOff(void);
|
||||
eOSState Summary(void);
|
||||
|
||||
cRemoteTimer *CurrentTimer(void);
|
||||
|
||||
void Refresh(void);
|
||||
|
||||
public:
|
||||
cStreamdevMenuTimers(void);
|
||||
virtual ~cStreamdevMenuTimers();
|
||||
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
#endif // VDR_STREAMDEV_MENU_H
|
||||
|
476
client/remote.c
476
client/remote.c
@@ -1,476 +0,0 @@
|
||||
/*
|
||||
* $Id: remote.c,v 1.4 2005/04/24 16:26:14 lordjaxom Exp $
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "client/remote.h"
|
||||
#include "client/device.h"
|
||||
#include "common.h"
|
||||
|
||||
cRemoteTimers RemoteTimers;
|
||||
|
||||
// --- cRemoteRecording ------------------------------------------------------
|
||||
|
||||
cRemoteRecording::cRemoteRecording(const char *Text) {
|
||||
m_IsValid = false;
|
||||
m_Index = -1;
|
||||
m_IsNew = false;
|
||||
m_TitleBuffer = NULL;
|
||||
|
||||
char *ptr;
|
||||
char *timestr;
|
||||
int idx;
|
||||
|
||||
Dprintf("text: %s\n", Text);
|
||||
|
||||
m_Index = strtoul(Text, &ptr, 10);
|
||||
Dprintf("index: %d\n", m_Index);
|
||||
if (*ptr == '\0' || *++ptr == '\0' ) return;
|
||||
timestr = ptr;
|
||||
while (*ptr != '\0' && !isspace(*ptr)) ++ptr;
|
||||
if (*ptr == '\0' || *++ptr == '\0') return;
|
||||
while (*ptr != '\0' && *ptr != '*' && !isspace(*ptr)) ++ptr;
|
||||
if (*ptr == '*') m_IsNew = true;
|
||||
Dprintf("new: %d\n", m_IsNew);
|
||||
*(ptr++) = '\0';
|
||||
m_StartTime = timestr;
|
||||
idx = -1;
|
||||
while ((idx = m_StartTime.find(' ', idx + 1)) != -1) m_StartTime[idx] = '\t';
|
||||
Dprintf("m_Start: %s\n", m_StartTime.c_str());
|
||||
if (*ptr == 0) return;
|
||||
if (isspace(*ptr)) ++ptr;
|
||||
if (*ptr == 0) return;
|
||||
m_Name = ptr;
|
||||
Dprintf("file: %s\n", m_Name.c_str());
|
||||
m_IsValid = true;
|
||||
}
|
||||
|
||||
cRemoteRecording::~cRemoteRecording(void) {
|
||||
}
|
||||
|
||||
bool cRemoteRecording::operator==(const cRemoteRecording &Recording) {
|
||||
return m_IsValid == Recording.m_IsValid
|
||||
&& m_Index == Recording.m_Index
|
||||
&& m_StartTime == Recording.m_StartTime
|
||||
&& m_Name == Recording.m_Name;
|
||||
}
|
||||
|
||||
void cRemoteRecording::ParseInfo(const char *Text) {
|
||||
m_Summary = strreplace(strdup(Text), '|', '\n');
|
||||
}
|
||||
|
||||
const char *cRemoteRecording::Title(char Delimiter, bool NewIndicator,
|
||||
int Level) {
|
||||
char New = NewIndicator && IsNew() ? '*' : ' ';
|
||||
|
||||
if (m_TitleBuffer != NULL) {
|
||||
free(m_TitleBuffer);
|
||||
m_TitleBuffer = NULL;
|
||||
}
|
||||
|
||||
if (Level < 0 || Level == HierarchyLevels()) {
|
||||
char *s;
|
||||
const char *t;
|
||||
if (Level > 0 && (t = strrchr(m_Name.c_str(), '~')) != NULL)
|
||||
t++;
|
||||
else
|
||||
t = m_Name.c_str();
|
||||
|
||||
asprintf(&m_TitleBuffer, "%s%c%c%s", m_StartTime.c_str(), New, Delimiter, t);
|
||||
// let's not display a trailing '~':
|
||||
stripspace(m_TitleBuffer);
|
||||
s = &m_TitleBuffer[strlen(m_TitleBuffer) - 1];
|
||||
if (*s == '~')
|
||||
*s = 0;
|
||||
} else if (Level < HierarchyLevels()) {
|
||||
const char *s = m_Name.c_str();
|
||||
const char *p = s;
|
||||
while (*++s) {
|
||||
if (*s == '~') {
|
||||
if (Level--)
|
||||
p = s + 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_TitleBuffer = MALLOC(char, s - p + 3);
|
||||
*m_TitleBuffer = Delimiter;
|
||||
*(m_TitleBuffer + 1) = Delimiter;
|
||||
strn0cpy(m_TitleBuffer + 2, p, s - p + 1);
|
||||
} else
|
||||
return "";
|
||||
return m_TitleBuffer;
|
||||
}
|
||||
|
||||
int cRemoteRecording::HierarchyLevels(void)
|
||||
{
|
||||
const char *s = m_Name.c_str();
|
||||
int level = 0;
|
||||
while (*++s) {
|
||||
if (*s == '~') ++level;
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
// --- cRemoteRecordings -----------------------------------------------------
|
||||
|
||||
bool cRemoteRecordings::Load(void) {
|
||||
Clear();
|
||||
return ClientSocket.LoadRecordings(*this);
|
||||
}
|
||||
|
||||
cRemoteRecording *cRemoteRecordings::GetByName(const char *Name) {
|
||||
for (cRemoteRecording *r = First(); r; r = Next(r))
|
||||
if (strcmp(r->Name(), Name) == 0)
|
||||
return r;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// --- cRemoteTimer ----------------------------------------------------------
|
||||
|
||||
cRemoteTimer::cRemoteTimer(const char *Text) {
|
||||
m_IsValid = false;
|
||||
m_Index = -1;
|
||||
m_Active = -1;
|
||||
m_Day = -1;
|
||||
m_Start = -1;
|
||||
m_Stop = -1;
|
||||
m_StartTime = 0;
|
||||
m_StopTime = 0;
|
||||
m_Priority = -1;
|
||||
m_Lifetime = -1;
|
||||
m_File[0] = '\0';
|
||||
m_FirstDay = 0;
|
||||
m_Buffer = NULL;
|
||||
m_Channel = NULL;
|
||||
|
||||
char *tmpbuf;
|
||||
char *ptr;
|
||||
|
||||
Dprintf("text: %s\n", Text);
|
||||
|
||||
m_Index = strtoul(Text, &ptr, 10);
|
||||
Dprintf("index: %d\n", m_Index);
|
||||
if (*ptr == '\0' || *++ptr == '\0') return;
|
||||
m_Active = strtoul(ptr, &ptr, 10);
|
||||
Dprintf("m_Active: %d\n", m_Active);
|
||||
if (*ptr == '\0' || *++ptr == '\0') return;
|
||||
|
||||
tmpbuf = ptr;
|
||||
while (*ptr != '\0' && *ptr != ':') ++ptr;
|
||||
if (*ptr == '\0') return;
|
||||
*(ptr++)= '\0';
|
||||
if (isnumber(tmpbuf))
|
||||
m_Channel = Channels.GetByNumber(strtoul(tmpbuf, NULL, 10));
|
||||
else
|
||||
m_Channel = Channels.GetByChannelID(tChannelID::FromString(tmpbuf));
|
||||
Dprintf("channel no.: %d\n", m_Channel->Number());
|
||||
|
||||
tmpbuf = ptr;
|
||||
while (*ptr != '\0' && *ptr != ':') ++ptr;
|
||||
if (*ptr == '\0') return;
|
||||
*(ptr++) = '\0';
|
||||
m_Day = ParseDay(tmpbuf, &m_FirstDay);
|
||||
Dprintf("Day: %d\n", m_Day);
|
||||
m_Start = strtoul(ptr, &ptr, 10);
|
||||
Dprintf("Start: %d\n", m_Start);
|
||||
if (*ptr == '\0' || *++ptr == '\0') return;
|
||||
m_Stop = strtoul(ptr, &ptr, 10);
|
||||
Dprintf("Stop: %d\n", m_Stop);
|
||||
if (*ptr == '\0' || *++ptr == '\0') return;
|
||||
m_Priority = strtoul(ptr, &ptr, 10);
|
||||
Dprintf("Prio: %d\n", m_Priority);
|
||||
if (*ptr == '\0' || *++ptr == '\0') return;
|
||||
m_Lifetime = strtoul(ptr, &ptr, 10);
|
||||
Dprintf("Lifetime: %d\n", m_Lifetime);
|
||||
if (*ptr == '\0' || *++ptr == '\0') return;
|
||||
tmpbuf = ptr;
|
||||
while (*ptr != '\0' && *ptr != ':') ++ptr;
|
||||
if (*ptr == '\0') return;
|
||||
*(ptr++) = '\0';
|
||||
strncpy(m_File, tmpbuf, MaxFileName);
|
||||
Dprintf("file: %s\n", m_File);
|
||||
if (*ptr != '\0') m_Summary = ptr;
|
||||
Dprintf("summary: %s\n", m_Summary.c_str());
|
||||
m_IsValid = true;
|
||||
}
|
||||
|
||||
#if VDRVERSNUM < 10300
|
||||
cRemoteTimer::cRemoteTimer(const cEventInfo *EventInfo) {
|
||||
time_t tstart = EventInfo->GetTime();
|
||||
time_t tstop = tstart + EventInfo->GetDuration() + Setup.MarginStop * 60;
|
||||
tstart -= Setup.MarginStart * 60;
|
||||
struct tm tm_r;
|
||||
struct tm *time = localtime_r(&tstart, &tm_r);
|
||||
const char *title = EventInfo->GetTitle();
|
||||
cChannel *channel = Channels.GetByChannelID(EventInfo->GetChannelID(), true);
|
||||
#else
|
||||
cRemoteTimer::cRemoteTimer(const cEvent *Event) {
|
||||
time_t tstart = Event->StartTime();
|
||||
time_t tstop = tstart + Event->Duration() + Setup.MarginStop * 60;
|
||||
tstart -= Setup.MarginStart * 60;
|
||||
struct tm tm_r;
|
||||
struct tm *time = localtime_r(&tstart, &tm_r);
|
||||
const char *title = Event->Title();
|
||||
cChannel *channel = Channels.GetByChannelID(Event->ChannelID(), true);
|
||||
#endif
|
||||
|
||||
m_IsValid = true;
|
||||
m_Index = -1;
|
||||
m_Active = true;
|
||||
m_Day = time->tm_mday;
|
||||
m_Start = time->tm_hour * 100 + time->tm_min;
|
||||
time = localtime_r(&tstop, &tm_r);
|
||||
m_Stop = time->tm_hour * 100 + time->tm_min;
|
||||
m_StartTime = 0;
|
||||
m_StopTime = 0;
|
||||
if (m_Stop >= 2400) m_Stop -= 2400;
|
||||
m_Priority = Setup.DefaultPriority;
|
||||
m_Lifetime = Setup.DefaultLifetime;
|
||||
m_File[0] = '\0';
|
||||
if (!isempty(title))
|
||||
strn0cpy(m_File, title, sizeof(m_File));
|
||||
m_FirstDay = 0;
|
||||
m_Channel = channel;
|
||||
}
|
||||
|
||||
cRemoteTimer::cRemoteTimer(void) {
|
||||
time_t t = time(NULL);
|
||||
struct tm tm_r;
|
||||
struct tm *now = localtime_r(&t, &tm_r);
|
||||
|
||||
m_IsValid = true;
|
||||
m_Index = -1;
|
||||
m_Active = -1;
|
||||
m_Day = now->tm_mday;
|
||||
m_Start = now->tm_hour * 100 + now->tm_min;
|
||||
m_Stop = now->tm_hour * 60 + now->tm_min + Setup.InstantRecordTime;
|
||||
m_Stop = (m_Stop / 60) * 100 + (m_Stop % 60);
|
||||
if (m_Stop >= 2400) m_Stop -= 2400;
|
||||
m_StartTime = 0;
|
||||
m_StopTime = 0;
|
||||
m_Priority = Setup.DefaultPriority;
|
||||
m_Lifetime = Setup.DefaultLifetime;
|
||||
m_File[0] = '\0';
|
||||
m_FirstDay = 0;
|
||||
m_Buffer = NULL;
|
||||
m_Channel = Channels.GetByNumber(cDevice::CurrentChannel());
|
||||
}
|
||||
|
||||
cRemoteTimer::~cRemoteTimer() {
|
||||
if (m_Buffer != NULL) free(m_Buffer);
|
||||
}
|
||||
|
||||
cRemoteTimer &cRemoteTimer::operator=(const cRemoteTimer &Timer) {
|
||||
Dprintf("\n\n\n\nOP<EFBFBD>ERATHVBD<EFBFBD>LJVG\n\n\n");
|
||||
m_IsValid = Timer.m_IsValid;
|
||||
m_Index = Timer.m_Index;
|
||||
m_Active = Timer.m_Active;
|
||||
m_Day = Timer.m_Day;
|
||||
m_Start = Timer.m_Start;
|
||||
m_Stop = Timer.m_Stop;
|
||||
m_Priority = Timer.m_Priority;
|
||||
m_Lifetime = Timer.m_Lifetime;
|
||||
m_FirstDay = Timer.m_FirstDay;
|
||||
m_Channel = Timer.m_Channel;
|
||||
m_Summary = Timer.m_Summary;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool cRemoteTimer::operator==(const cRemoteTimer &Timer) {
|
||||
return m_IsValid == Timer.m_IsValid
|
||||
&& m_Index == Timer.m_Index
|
||||
&& m_Active == Timer.m_Active
|
||||
&& m_Day == Timer.m_Day
|
||||
&& m_Start == Timer.m_Start
|
||||
&& m_Stop == Timer.m_Stop
|
||||
&& m_Priority == Timer.m_Priority
|
||||
&& m_Lifetime == Timer.m_Lifetime
|
||||
&& m_FirstDay == Timer.m_FirstDay
|
||||
&& m_Channel == Timer.m_Channel
|
||||
&& strcmp(m_File, Timer.m_File) == 0
|
||||
&& m_Summary == Timer.m_Summary;
|
||||
}
|
||||
|
||||
int cRemoteTimer::ParseDay(const char *s, time_t *FirstDay) {
|
||||
char *tail;
|
||||
int d = strtol(s, &tail, 10);
|
||||
if (FirstDay)
|
||||
*FirstDay = 0;
|
||||
if (tail && *tail) {
|
||||
d = 0;
|
||||
if (tail == s) {
|
||||
const char *first = strchr(s, '@');
|
||||
int l = first ? first - s : strlen(s);
|
||||
if (l == 7) {
|
||||
for (const char *p = s + 6; p >= s; p--) {
|
||||
d <<= 1;
|
||||
d |= (*p != '-');
|
||||
}
|
||||
d |= 0x80000000;
|
||||
}
|
||||
if (FirstDay && first) {
|
||||
++first;
|
||||
if (strlen(first) == 10) {
|
||||
struct tm tm_r;
|
||||
if (3 == sscanf(first, "%d-%d-%d", &tm_r.tm_year, &tm_r.tm_mon, &tm_r.tm_mday)) {
|
||||
tm_r.tm_year -= 1900;
|
||||
tm_r.tm_mon--;
|
||||
tm_r.tm_hour = tm_r.tm_min = tm_r.tm_sec = 0;
|
||||
tm_r.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
|
||||
*FirstDay = mktime(&tm_r);
|
||||
}
|
||||
}
|
||||
else
|
||||
d = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (d < 1 || d > 31)
|
||||
d = 0;
|
||||
return d;
|
||||
}
|
||||
|
||||
const char *cRemoteTimer::PrintDay(int d, time_t FirstDay) {
|
||||
#define DAYBUFFERSIZE 32
|
||||
static char buffer[DAYBUFFERSIZE];
|
||||
if ((d & 0x80000000) != 0) {
|
||||
char *b = buffer;
|
||||
const char *w = tr("MTWTFSS");
|
||||
while (*w) {
|
||||
*b++ = (d & 1) ? *w : '-';
|
||||
d >>= 1;
|
||||
w++;
|
||||
}
|
||||
if (FirstDay) {
|
||||
struct tm tm_r;
|
||||
localtime_r(&FirstDay, &tm_r);
|
||||
b += strftime(b, DAYBUFFERSIZE - (b - buffer), "@%Y-%m-%d", &tm_r);
|
||||
}
|
||||
*b = 0;
|
||||
}
|
||||
else
|
||||
sprintf(buffer, "%d", d);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char *cRemoteTimer::PrintFirstDay(void) const {
|
||||
if (m_FirstDay) {
|
||||
const char *s = PrintDay(m_Day, m_FirstDay);
|
||||
if (strlen(s) == 18)
|
||||
return s + 8;
|
||||
}
|
||||
return ""; // not NULL, so the caller can always use the result
|
||||
}
|
||||
|
||||
void cRemoteTimer::OnOff(void) {
|
||||
if (IsSingleEvent())
|
||||
m_Active = !m_Active;
|
||||
else if (m_FirstDay) {
|
||||
m_FirstDay = 0;
|
||||
m_Active = false;
|
||||
}
|
||||
else if (m_Active)
|
||||
Skip();
|
||||
else
|
||||
m_Active = true;
|
||||
Matches(); // refresh m_Start and end time
|
||||
}
|
||||
|
||||
time_t cRemoteTimer::SetTime(time_t t, int SecondsFromMidnight) {
|
||||
struct tm tm_r;
|
||||
tm tm = *localtime_r(&t, &tm_r);
|
||||
tm.tm_hour = SecondsFromMidnight / 3600;
|
||||
tm.tm_min = (SecondsFromMidnight % 3600) / 60;
|
||||
tm.tm_sec = SecondsFromMidnight % 60;
|
||||
tm.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
|
||||
return mktime(&tm);
|
||||
}
|
||||
|
||||
bool cRemoteTimer::Matches(time_t t) {
|
||||
m_StartTime = m_StopTime = 0;
|
||||
if (t == 0)
|
||||
t = time(NULL);
|
||||
|
||||
int begin = TimeToInt(m_Start); // seconds from midnight
|
||||
int length = TimeToInt(m_Stop) - begin;
|
||||
if (length < 0)
|
||||
length += SECSINDAY;
|
||||
|
||||
int DaysToCheck = IsSingleEvent() ? 61 : 7; // 61 to handle months with 31/30/31
|
||||
for (int i = -1; i <= DaysToCheck; i++) {
|
||||
time_t t0 = IncDay(t, i);
|
||||
if (DayMatches(t0)) {
|
||||
time_t a = SetTime(t0, begin);
|
||||
time_t b = a + length;
|
||||
if ((!m_FirstDay || a >= m_FirstDay) && t <= b) {
|
||||
m_StartTime = a;
|
||||
m_StopTime = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!m_StartTime)
|
||||
m_StartTime = m_FirstDay; // just to have something that's more than a week in the future
|
||||
else if (t > m_StartTime || t > m_FirstDay + SECSINDAY + 3600) // +3600 in case of DST change
|
||||
m_FirstDay = 0;
|
||||
return m_Active && m_StartTime <= t && t < m_StopTime; // must m_Stop *before* m_StopTime to allow adjacent timers
|
||||
}
|
||||
|
||||
bool cRemoteTimer::DayMatches(time_t t) {
|
||||
return IsSingleEvent()
|
||||
? GetMDay(t) == m_Day
|
||||
: (m_Day & (1 << GetWDay(t))) != 0;
|
||||
}
|
||||
|
||||
int cRemoteTimer::GetMDay(time_t t)
|
||||
{
|
||||
struct tm tm_r;
|
||||
return localtime_r(&t, &tm_r)->tm_mday;
|
||||
}
|
||||
|
||||
int cRemoteTimer::GetWDay(time_t t)
|
||||
{
|
||||
struct tm tm_r;
|
||||
int weekday = localtime_r(&t, &tm_r)->tm_wday;
|
||||
return weekday == 0 ? 6 : weekday - 1; // we start with monday==0!
|
||||
}
|
||||
|
||||
time_t cRemoteTimer::IncDay(time_t t, int Days) {
|
||||
struct tm tm_r;
|
||||
tm tm = *localtime_r(&t, &tm_r);
|
||||
tm.tm_mday += Days; // now tm_mday may be out of its valid range
|
||||
int h = tm.tm_hour; // save original hour to compensate for DST change
|
||||
tm.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
|
||||
t = mktime(&tm); // normalize all values
|
||||
tm.tm_hour = h; // compensate for DST change
|
||||
return mktime(&tm); // calculate final result
|
||||
}
|
||||
|
||||
const char *cRemoteTimer::ToText(void) {
|
||||
char *summary = NULL;
|
||||
|
||||
if (m_Buffer != NULL) free(m_Buffer);
|
||||
|
||||
strreplace(m_File, ':', '|');
|
||||
if (m_Summary != "")
|
||||
summary = strreplace(strdup(m_Summary.c_str()), ':', '|');
|
||||
|
||||
asprintf(&m_Buffer, "%d:%s:%s:%04d:%04d:%d:%d:%s:%s", m_Active,
|
||||
(const char*)Channel()->GetChannelID().ToString(), PrintDay(m_Day, m_FirstDay),
|
||||
m_Start, m_Stop, m_Priority, m_Lifetime, m_File, summary ? summary : "");
|
||||
|
||||
if (summary != NULL)
|
||||
free(summary);
|
||||
strreplace(m_File, '|', ':');
|
||||
return m_Buffer;
|
||||
}
|
||||
|
||||
// --- cRemoteTimers ---------------------------------------------------------
|
||||
|
||||
bool cRemoteTimers::Load(void) {
|
||||
Clear();
|
||||
return ClientSocket.LoadTimers(*this);
|
||||
}
|
||||
|
131
client/remote.h
131
client/remote.h
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* $Id: remote.h,v 1.2 2005/02/08 17:22:35 lordjaxom Exp $
|
||||
*/
|
||||
|
||||
#ifndef VDR_STREAMDEV_REMOTE_H
|
||||
#define VDR_STREAMDEV_REMOTE_H
|
||||
|
||||
#include <vdr/config.h>
|
||||
#include <string>
|
||||
|
||||
#if VDRVERSNUM < 10300
|
||||
class cEventInfo;
|
||||
#else
|
||||
class cEvent;
|
||||
#endif
|
||||
class cChannel;
|
||||
|
||||
class cRemoteRecording: public cListObject {
|
||||
private:
|
||||
bool m_IsValid;
|
||||
int m_Index;
|
||||
bool m_IsNew;
|
||||
char *m_TitleBuffer;
|
||||
std::string m_StartTime;
|
||||
std::string m_Name;
|
||||
std::string m_Summary;
|
||||
|
||||
public:
|
||||
cRemoteRecording(const char *Text);
|
||||
~cRemoteRecording();
|
||||
|
||||
bool operator==(const cRemoteRecording &Recording);
|
||||
bool operator!=(const cRemoteRecording &Recording);
|
||||
|
||||
void ParseInfo(const char *Text);
|
||||
|
||||
bool IsValid(void) const { return m_IsValid; }
|
||||
int Index(void) const { return m_Index; }
|
||||
const char *StartTime(void) const { return m_StartTime.c_str(); }
|
||||
bool IsNew(void) const { return m_IsNew; }
|
||||
const char *Name(void) const { return m_Name.c_str(); }
|
||||
const char *Summary(void) const { return m_Summary.c_str(); }
|
||||
const char *Title(char Delimiter, bool NewIndicator, int Level);
|
||||
int HierarchyLevels(void);
|
||||
};
|
||||
|
||||
inline bool cRemoteRecording::operator!=(const cRemoteRecording &Recording) {
|
||||
return !operator==(Recording);
|
||||
}
|
||||
|
||||
class cRemoteRecordings: public cList<cRemoteRecording> {
|
||||
public:
|
||||
bool Load(void);
|
||||
cRemoteRecording *GetByName(const char *Name);
|
||||
};
|
||||
|
||||
class cRemoteTimer: public cListObject {
|
||||
friend class cStreamdevMenuEditTimer;
|
||||
|
||||
private:
|
||||
bool m_IsValid;
|
||||
int m_Index;
|
||||
int m_Active;
|
||||
int m_Day;
|
||||
int m_Start;
|
||||
int m_Stop;
|
||||
time_t m_StartTime;
|
||||
time_t m_StopTime;
|
||||
int m_Priority;
|
||||
int m_Lifetime;
|
||||
char m_File[MaxFileName];
|
||||
time_t m_FirstDay;
|
||||
std::string m_Summary;
|
||||
char *m_Buffer;
|
||||
const cChannel *m_Channel;
|
||||
|
||||
public:
|
||||
cRemoteTimer(const char *Text);
|
||||
#if VDRVERSNUM < 10300
|
||||
cRemoteTimer(const cEventInfo *EventInfo);
|
||||
#else
|
||||
cRemoteTimer(const cEvent *Event);
|
||||
#endif
|
||||
cRemoteTimer(void);
|
||||
~cRemoteTimer();
|
||||
|
||||
cRemoteTimer &operator=(const cRemoteTimer &Timer);
|
||||
bool operator==(const cRemoteTimer &Timer);
|
||||
bool operator!=(const cRemoteTimer &Timer) { return !operator==(Timer); }
|
||||
|
||||
static int ParseDay(const char *s, time_t *FirstDay);
|
||||
static const char *PrintDay(int d, time_t FirstDay = 0);
|
||||
static time_t SetTime(time_t t, int SecondsFromMidnight);
|
||||
static time_t IncDay(time_t t, int Days);
|
||||
static int TimeToInt(int t) { return (t / 100 * 60 + t % 100) * 60; }
|
||||
|
||||
const char *PrintFirstDay(void) const;
|
||||
void OnOff(void);
|
||||
bool IsSingleEvent(void) const { return (m_Day & 0x80000000) == 0; }
|
||||
void Skip(void) { m_FirstDay = IncDay(SetTime(StartTime(), 0), 1); }
|
||||
bool Matches(time_t t = 0);
|
||||
bool DayMatches(time_t t = 0);
|
||||
int GetMDay(time_t t);
|
||||
int GetWDay(time_t t);
|
||||
|
||||
bool IsValid(void) const { return m_IsValid; }
|
||||
int Index(void) const { return m_Index; }
|
||||
int Active(void) const { return m_Active; }
|
||||
int Day(void) const { return m_Day; }
|
||||
int Start(void) const { return m_Start; }
|
||||
int Stop(void) const { return m_Stop; }
|
||||
time_t StartTime(void) { if (!m_StartTime) Matches(); return m_StartTime; }
|
||||
time_t StopTime(void) { if (!m_StopTime) Matches(); return m_StopTime; }
|
||||
int Priority(void) const { return m_Priority; }
|
||||
int Lifetime(void) const { return m_Lifetime; }
|
||||
const char *File(void) const { return m_File; }
|
||||
time_t FirstDay(void) const { return m_FirstDay; }
|
||||
const std::string &Summary(void) const { return m_Summary; }
|
||||
const cChannel *Channel(void) const { return m_Channel; }
|
||||
|
||||
const char *ToText(void);
|
||||
};
|
||||
|
||||
class cRemoteTimers: public cList<cRemoteTimer> {
|
||||
public:
|
||||
bool Load(void);
|
||||
};
|
||||
|
||||
extern cRemoteTimers RemoteTimers;
|
||||
|
||||
#endif // VDR_STREAMDEV_REMOTE_H
|
@@ -1,22 +1,22 @@
|
||||
/*
|
||||
* $Id: setup.c,v 1.2 2005/02/08 15:34:38 lordjaxom Exp $
|
||||
* $Id: setup.c,v 1.8 2009/02/03 10:26:21 schmirl Exp $
|
||||
*/
|
||||
|
||||
#include <vdr/menuitems.h>
|
||||
|
||||
#include "client/setup.h"
|
||||
#include "client/device.h"
|
||||
#include "i18n.h"
|
||||
|
||||
cStreamdevClientSetup StreamdevClientSetup;
|
||||
|
||||
cStreamdevClientSetup::cStreamdevClientSetup(void) {
|
||||
StartClient = false;
|
||||
RemotePort = 2004;
|
||||
#if VDRVERSNUM >= 10300
|
||||
StreamFilters = false;
|
||||
#endif
|
||||
SyncEPG = false;
|
||||
HideMenuEntry = false;
|
||||
MinPriority = -1;
|
||||
MaxPriority = MAXPRIORITY;
|
||||
strcpy(RemoteIp, "");
|
||||
}
|
||||
|
||||
@@ -29,10 +29,11 @@ bool cStreamdevClientSetup::SetupParse(const char *Name, const char *Value) {
|
||||
strcpy(RemoteIp, Value);
|
||||
}
|
||||
else if (strcmp(Name, "RemotePort") == 0) RemotePort = atoi(Value);
|
||||
#if VDRVERSNUM >= 10300
|
||||
else if (strcmp(Name, "StreamFilters") == 0) StreamFilters = atoi(Value);
|
||||
#endif
|
||||
else if (strcmp(Name, "SyncEPG") == 0) SyncEPG = atoi(Value);
|
||||
else if (strcmp(Name, "HideMenuEntry") == 0) HideMenuEntry = atoi(Value);
|
||||
else if (strcmp(Name, "MinPriority") == 0) MinPriority = atoi(Value);
|
||||
else if (strcmp(Name, "MaxPriority") == 0) MaxPriority = atoi(Value);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
@@ -40,13 +41,14 @@ bool cStreamdevClientSetup::SetupParse(const char *Name, const char *Value) {
|
||||
cStreamdevClientMenuSetupPage::cStreamdevClientMenuSetupPage(void) {
|
||||
m_NewSetup = StreamdevClientSetup;
|
||||
|
||||
AddBoolEdit (tr("Hide Mainmenu Entry"),m_NewSetup.HideMenuEntry);
|
||||
AddBoolEdit (tr("Start Client"), m_NewSetup.StartClient);
|
||||
AddIpEdit (tr("Remote IP"), m_NewSetup.RemoteIp);
|
||||
AddShortEdit(tr("Remote Port"), m_NewSetup.RemotePort);
|
||||
#if VDRVERSNUM >= 10300
|
||||
AddBoolEdit (tr("Filter Streaming"), m_NewSetup.StreamFilters);
|
||||
#endif
|
||||
AddBoolEdit (tr("Synchronize EPG"), m_NewSetup.SyncEPG);
|
||||
AddRangeEdit (tr("Minimum Priority"), m_NewSetup.MinPriority, -1, MAXPRIORITY);
|
||||
AddRangeEdit (tr("Maximum Priority"), m_NewSetup.MaxPriority, -1, MAXPRIORITY);
|
||||
SetCurrent(Get(0));
|
||||
}
|
||||
|
||||
@@ -57,8 +59,6 @@ void cStreamdevClientMenuSetupPage::Store(void) {
|
||||
if (m_NewSetup.StartClient != StreamdevClientSetup.StartClient) {
|
||||
if (m_NewSetup.StartClient)
|
||||
cStreamdevDevice::Init();
|
||||
else
|
||||
INFO(tr("Please restart VDR to activate changes"));
|
||||
}
|
||||
|
||||
SetupStore("StartClient", m_NewSetup.StartClient);
|
||||
@@ -67,10 +67,11 @@ void cStreamdevClientMenuSetupPage::Store(void) {
|
||||
else
|
||||
SetupStore("RemoteIp", m_NewSetup.RemoteIp);
|
||||
SetupStore("RemotePort", m_NewSetup.RemotePort);
|
||||
#if VDRVERSNUM >= 10300
|
||||
SetupStore("StreamFilters", m_NewSetup.StreamFilters);
|
||||
#endif
|
||||
SetupStore("SyncEPG", m_NewSetup.SyncEPG);
|
||||
SetupStore("HideMenuEntry", m_NewSetup.HideMenuEntry);
|
||||
SetupStore("MinPriority", m_NewSetup.MinPriority);
|
||||
SetupStore("MaxPriority", m_NewSetup.MaxPriority);
|
||||
|
||||
StreamdevClientSetup = m_NewSetup;
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: setup.h,v 1.2 2005/02/08 15:34:38 lordjaxom Exp $
|
||||
* $Id: setup.h,v 1.5 2009/01/29 07:48:59 schmirl Exp $
|
||||
*/
|
||||
|
||||
#ifndef VDR_STREAMDEV_SETUPCLIENT_H
|
||||
@@ -15,10 +15,11 @@ struct cStreamdevClientSetup {
|
||||
int StartClient;
|
||||
char RemoteIp[20];
|
||||
int RemotePort;
|
||||
#if VDRVERSNUM >= 10300
|
||||
int StreamFilters;
|
||||
#endif
|
||||
int SyncEPG;
|
||||
int HideMenuEntry;
|
||||
int MinPriority;
|
||||
int MaxPriority;
|
||||
};
|
||||
|
||||
extern cStreamdevClientSetup StreamdevClientSetup;
|
||||
|
239
client/socket.c
239
client/socket.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: socket.c,v 1.9 2008/03/13 16:01:17 schmirl Exp $
|
||||
* $Id: socket.c,v 1.12 2008/04/08 14:18:16 schmirl Exp $
|
||||
*/
|
||||
|
||||
#include <tools/select.h>
|
||||
@@ -13,9 +13,7 @@
|
||||
|
||||
#include "client/socket.h"
|
||||
#include "client/setup.h"
|
||||
#include "client/remote.h"
|
||||
#include "common.h"
|
||||
#include "i18n.h"
|
||||
|
||||
cClientSocket ClientSocket;
|
||||
|
||||
@@ -141,10 +139,8 @@ bool cClientSocket::CheckConnection(void) {
|
||||
}
|
||||
|
||||
const char *Filters = "";
|
||||
#if VDRVERSNUM >= 10300
|
||||
if(Command("CAPS FILTERS", 220))
|
||||
Filters = ",FILTERS";
|
||||
#endif
|
||||
|
||||
isyslog("Streamdev: Connected to server %s:%d using capabilities TSPIDS%s",
|
||||
RemoteIp().c_str(), RemotePort(), Filters);
|
||||
@@ -270,7 +266,6 @@ bool cClientSocket::SetPid(int Pid, bool On) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if VDRVERSNUM >= 10300
|
||||
bool cClientSocket::SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On) {
|
||||
if (!CheckConnection()) return false;
|
||||
|
||||
@@ -286,7 +281,6 @@ bool cClientSocket::SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool cClientSocket::CloseDvr(void) {
|
||||
if (!CheckConnection()) return false;
|
||||
@@ -342,11 +336,7 @@ bool cClientSocket::SynchronizeEPG(void) {
|
||||
|
||||
rewind(epgfd);
|
||||
if (cSchedules::Read(epgfd))
|
||||
#if VDRVERSNUM < 10300
|
||||
cSIProcessor::TriggerDump();
|
||||
#else
|
||||
cSchedules::Cleanup(true);
|
||||
#endif
|
||||
else {
|
||||
esyslog("ERROR: Streamdev: Parsing EPG data failed");
|
||||
fclose(epgfd);
|
||||
@@ -370,128 +360,6 @@ bool cClientSocket::Quit(void) {
|
||||
return res;
|
||||
}
|
||||
|
||||
bool cClientSocket::LoadRecordings(cRemoteRecordings &Recordings) {
|
||||
bool res;
|
||||
|
||||
if (!CheckConnection()) return false;
|
||||
|
||||
CMD_LOCK;
|
||||
|
||||
if (!Command("LSTR"))
|
||||
return false;
|
||||
|
||||
std::string buffer;
|
||||
while ((res = Expect(250, &buffer))) {
|
||||
cRemoteRecording *rec = new cRemoteRecording(buffer.c_str() + 4);
|
||||
Dprintf("recording valid: %d\n", rec->IsValid());
|
||||
if (rec->IsValid())
|
||||
Recordings.Add(rec);
|
||||
else
|
||||
delete rec;
|
||||
if (buffer[3] == ' ') break;
|
||||
}
|
||||
|
||||
if (!res && buffer.substr(0, 3) != "550") {
|
||||
if (errno == 0)
|
||||
esyslog("ERROR: Streamdev: Couldn't fetch recordings from %s:%d",
|
||||
RemoteIp().c_str(), RemotePort());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (cRemoteRecording *r = Recordings.First(); r; r = Recordings.Next(r)) {
|
||||
std::string command = (std::string)"LSTR " + (const char*)itoa(r->Index());
|
||||
if (!Command(command))
|
||||
return false;
|
||||
|
||||
if (Expect(250, &buffer))
|
||||
r->ParseInfo(buffer.c_str() + 4);
|
||||
else if (buffer.substr(0, 3) != "550") {
|
||||
if (errno == 0)
|
||||
esyslog("ERROR: Streamdev: Couldn't fetch details for recording from %s:%d",
|
||||
RemoteIp().c_str(), RemotePort());
|
||||
return false;
|
||||
}
|
||||
Dprintf("recording complete: %d\n", r->Index());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool cClientSocket::StartReplay(const char *Filename) {
|
||||
if (!CheckConnection()) return false;
|
||||
|
||||
CMD_LOCK;
|
||||
|
||||
std::string command = (std::string)"PLAY " + Filename;
|
||||
if (!Command(command, 220)) {
|
||||
if (errno == 0)
|
||||
esyslog("ERROR: Streamdev: Couldn't replay \"%s\" from %s:%d",
|
||||
Filename, RemoteIp().c_str(), RemotePort());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cClientSocket::AbortReplay(void) {
|
||||
if (!CheckConnection()) return false;
|
||||
|
||||
CMD_LOCK;
|
||||
|
||||
if (m_DataSockets[siReplay] != NULL) {
|
||||
std::string command = (std::string)"ABRT " + (const char*)itoa(siReplay);
|
||||
if (!Command(command, 220)) {
|
||||
if (errno == 0)
|
||||
esyslog("ERROR: Streamdev: Couldn't cleanly close data connection");
|
||||
return false;
|
||||
}
|
||||
|
||||
DELETENULL(m_DataSockets[siReplay]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cClientSocket::DeleteRecording(cRemoteRecording *Recording) {
|
||||
bool res;
|
||||
cRemoteRecording *rec = NULL;
|
||||
|
||||
if (!CheckConnection())
|
||||
return false;
|
||||
|
||||
CMD_LOCK;
|
||||
|
||||
if (!Command("LSTR"))
|
||||
return false;
|
||||
|
||||
std::string buffer;
|
||||
while ((res = Expect(250, &buffer))) {
|
||||
if (rec == NULL) {
|
||||
rec = new cRemoteRecording(buffer.c_str() + 4);
|
||||
if (!rec->IsValid() || rec->Index() != Recording->Index())
|
||||
DELETENULL(rec);
|
||||
}
|
||||
if (buffer[3] == ' ') break;
|
||||
}
|
||||
|
||||
if (!res && buffer.substr(0, 3) != "550") {
|
||||
if (errno == 0)
|
||||
esyslog("ERROR: Streamdev: Couldn't fetch recordings from %s:%d",
|
||||
RemoteIp().c_str(), RemotePort());
|
||||
if (rec != NULL) delete rec;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rec == NULL || *rec != *Recording) {
|
||||
ERROR(tr("Recordings not in sync! Try again..."));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string command = (std::string)"DELR " + (const char*)itoa(Recording->Index());
|
||||
if (!Command(command, 250)) {
|
||||
ERROR(tr("Couldn't delete recording! Try again..."));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cClientSocket::SuspendServer(void) {
|
||||
if (!CheckConnection()) return false;
|
||||
|
||||
@@ -504,108 +372,3 @@ bool cClientSocket::SuspendServer(void) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cClientSocket::LoadTimers(cRemoteTimers &Timers) {
|
||||
if (!CheckConnection()) return false;
|
||||
|
||||
CMD_LOCK;
|
||||
|
||||
if (!Command("LSTT"))
|
||||
return false;
|
||||
|
||||
bool res;
|
||||
std::string buffer;
|
||||
while ((res = Expect(250, &buffer))) {
|
||||
cRemoteTimer *timer = new cRemoteTimer(buffer.c_str() + 4);
|
||||
Dprintf("timer valid: %d\n", timer->IsValid());
|
||||
if (timer->IsValid())
|
||||
Timers.Add(timer);
|
||||
if (buffer[3] == ' ') break;
|
||||
}
|
||||
|
||||
if (!res && buffer.substr(0, 3) != "550") {
|
||||
if (errno == 0)
|
||||
esyslog("ERROR: Streamdev: Couldn't fetch recordings from %s:%d",
|
||||
RemoteIp().c_str(), RemotePort());
|
||||
return false;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool cClientSocket::SaveTimer(cRemoteTimer *Old, cRemoteTimer &New) {
|
||||
if (!CheckConnection()) return false;
|
||||
|
||||
CMD_LOCK;
|
||||
|
||||
if (New.Index() == -1) { // New timer
|
||||
std::string command = (std::string)"NEWT " + (const char*)New.ToText();
|
||||
if (!Command(command, 250)) {
|
||||
ERROR(tr("Couldn't save timer! Try again..."));
|
||||
return false;
|
||||
}
|
||||
} else { // Modified timer
|
||||
std::string command = (std::string)"LSTT " + (const char*)itoa(New.Index());
|
||||
if (!Command(command))
|
||||
return false;
|
||||
|
||||
std::string buffer;
|
||||
if (!Expect(250, &buffer)) {
|
||||
if (errno == 0)
|
||||
ERROR(tr("Timers not in sync! Try again..."));
|
||||
else
|
||||
ERROR(tr("Server error! Try again..."));
|
||||
return false;
|
||||
}
|
||||
|
||||
cRemoteTimer oldstate(buffer.c_str() + 4);
|
||||
if (oldstate != *Old) {
|
||||
/*Dprintf("old timer: %d,%d,%d,%d,%d,%d,%s,%d,%s,%d\n", oldstate.m_Index,
|
||||
oldstate.m_Active,oldstate.m_Day,oldstate.m_Start,oldstate.m_StartTime,oldstate.m_Priority,oldstate.m_File,oldstate.m_FirstDay,(const char*)oldstate.m_Summary,oldstate.m_Channel->Number());
|
||||
Dprintf("new timer: %d,%d,%d,%d,%d,%d,%s,%d,%s,%d\n", Old->m_Index,
|
||||
Old->m_Active,Old->m_Day,Old->m_Start,Old->m_StartTime,Old->m_Priority,Old->m_File,Old->m_FirstDay,(const char*)Old->m_Summary,Old->m_Channel->Number());*/
|
||||
ERROR(tr("Timers not in sync! Try again..."));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
command = (std::string)"MODT " + (const char*)itoa(New.Index()) + " "
|
||||
+ (const char*)New.ToText();
|
||||
if (!Command(command, 250)) {
|
||||
ERROR(tr("Couldn't save timer! Try again..."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cClientSocket::DeleteTimer(cRemoteTimer *Timer) {
|
||||
if (!CheckConnection()) return false;
|
||||
|
||||
CMD_LOCK;
|
||||
|
||||
std::string command = (std::string)"LSTT " + (const char*)itoa(Timer->Index());
|
||||
if (!Command(command))
|
||||
return false;
|
||||
|
||||
std::string buffer;
|
||||
if (!Expect(250, &buffer)) {
|
||||
if (errno == 0)
|
||||
ERROR(tr("Timers not in sync! Try again..."));
|
||||
else
|
||||
ERROR(tr("Server error! Try again..."));
|
||||
return false;
|
||||
}
|
||||
|
||||
cRemoteTimer oldstate(buffer.c_str() + 4);
|
||||
if (oldstate != *Timer) {
|
||||
ERROR(tr("Timers not in sync! Try again..."));
|
||||
return false;
|
||||
}
|
||||
|
||||
command = (std::string)"DELT " + (const char*)itoa(Timer->Index());
|
||||
if (!Command(command, 250)) {
|
||||
ERROR(tr("Couldn't delete timer! Try again..."));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: socket.h,v 1.4 2007/04/24 10:57:34 schmirl Exp $
|
||||
* $Id: socket.h,v 1.6 2008/04/07 14:40:40 schmirl Exp $
|
||||
*/
|
||||
|
||||
#ifndef VDR_STREAMDEV_CLIENT_CONNECTION_H
|
||||
@@ -13,10 +13,6 @@
|
||||
|
||||
#define CMD_LOCK cMutexLock CmdLock((cMutex*)&m_Mutex)
|
||||
|
||||
class cRemoteRecordings;
|
||||
class cRemoteRecording;
|
||||
class cRemoteTimers;
|
||||
class cRemoteTimer;
|
||||
class cPES2TSRemux;
|
||||
|
||||
class cClientSocket: public cTBSocket {
|
||||
@@ -50,18 +46,9 @@ public:
|
||||
bool CloseDataConnection(eSocketId Id);
|
||||
bool SetChannelDevice(const cChannel *Channel);
|
||||
bool SetPid(int Pid, bool On);
|
||||
#if VDRVERSNUM >= 10300
|
||||
bool SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On);
|
||||
#endif
|
||||
bool CloseDvr(void);
|
||||
bool SynchronizeEPG(void);
|
||||
bool LoadRecordings(cRemoteRecordings &Recordings);
|
||||
bool StartReplay(const char *Filename);
|
||||
bool AbortReplay(void);
|
||||
bool DeleteRecording(cRemoteRecording *Recording);
|
||||
bool LoadTimers(cRemoteTimers &Timers);
|
||||
bool SaveTimer(cRemoteTimer *Old, cRemoteTimer &New);
|
||||
bool DeleteTimer(cRemoteTimer *Timer);
|
||||
bool SuspendServer(void);
|
||||
bool Quit(void);
|
||||
|
||||
|
Reference in New Issue
Block a user