mirror of
https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
synced 2023-10-10 17:16:51 +00:00
- resurrected clients "Suspend Server" menu item as its mainmenu entry
- dropped unused code for remote timers/recordings on client side - dropped unused files client/{assembler,menu,remote}.[hc] - dropped unused files in libdvbmpeg (reported by tobi)
This commit is contained in:
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* $Id: assembler.c,v 1.3 2008/04/07 14:27:28 schmirl 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)
|
||||
:cThread("Streamdev: UDP-TS Assembler")
|
||||
{
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cStreamdevAssembler::WaitForFill(void) {
|
||||
m_WaitFill.Wait(m_Mutex);
|
||||
m_Mutex.Unlock();
|
||||
}
|
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* $Id: assembler.h,v 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.16 2008/04/07 14:27:28 schmirl Exp $
|
||||
* $Id: device.c,v 1.17 2008/04/07 14:40:39 schmirl Exp $
|
||||
*/
|
||||
|
||||
#include "client/device.h"
|
||||
#include "client/setup.h"
|
||||
#include "client/assembler.h"
|
||||
#include "client/filter.h"
|
||||
|
||||
#include "tools/select.h"
|
||||
@@ -26,11 +25,9 @@ cStreamdevDevice *cStreamdevDevice::m_Device = NULL;
|
||||
cStreamdevDevice::cStreamdevDevice(void) {
|
||||
m_Channel = NULL;
|
||||
m_TSBuffer = NULL;
|
||||
m_Assembler = NULL;
|
||||
|
||||
m_Filters = new cStreamdevFilters;
|
||||
StartSectionHandler();
|
||||
cSchedules::Read();
|
||||
|
||||
m_Device = this;
|
||||
m_Pids = 0;
|
||||
@@ -54,7 +51,6 @@ cStreamdevDevice::~cStreamdevDevice() {
|
||||
|
||||
DELETENULL(m_Filters);
|
||||
DELETENULL(m_TSBuffer);
|
||||
delete m_Assembler;
|
||||
}
|
||||
|
||||
bool cStreamdevDevice::ProvidesSource(int Source) const {
|
||||
@@ -283,7 +279,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.6 2008/04/07 14:27:28 schmirl Exp $
|
||||
* $Id: device.h,v 1.7 2008/04/07 14:40:39 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,7 +20,6 @@ class cStreamdevDevice: public cDevice {
|
||||
private:
|
||||
const cChannel *m_Channel;
|
||||
cTSBuffer *m_TSBuffer;
|
||||
cStreamdevAssembler *m_Assembler;
|
||||
cStreamdevFilters *m_Filters;
|
||||
int m_Pids;
|
||||
bool m_DvrClosed;
|
||||
|
802
client/menu.c
802
client/menu.c
@@ -1,802 +0,0 @@
|
||||
/*
|
||||
* $Id: menu.c,v 1.5 2008/04/07 14:27:28 schmirl Exp $
|
||||
*/
|
||||
|
||||
#include <vdr/menuitems.h>
|
||||
#include <vdr/interface.h>
|
||||
|
||||
#include "client/menu.h"
|
||||
#include "client/socket.h"
|
||||
#include "i18n.h"
|
||||
|
||||
#define CHNUMWIDTH (numdigits(Channels.MaxNumber()) + 1)
|
||||
|
||||
// --- cMenuText -------------------------------------------------------------
|
||||
|
||||
class cMenuText : public cOsdMenu {
|
||||
public:
|
||||
cMenuText(const char *Title, const char *Text, eDvbFont Font = fontOsd);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
// --- cStreamdevMenu --------------------------------------------------------
|
||||
|
||||
cStreamdevMenu::cStreamdevMenu(void):
|
||||
cOsdMenu(tr("Streaming Control")) {
|
||||
SetHasHotkeys();
|
||||
Add(new cOsdItem(hk(tr("Remote Schedule")), (eOSState)subSchedule));
|
||||
Add(new cOsdItem(hk(tr("Remote Timers")), (eOSState)subTimers));
|
||||
Add(new cOsdItem(hk(tr("Remote Recordings")), (eOSState)subRecordings));
|
||||
Add(new cOsdItem(hk(tr("Suspend Server")), (eOSState)subSuspend));
|
||||
Add(new cOsdItem(hk(tr("Synchronize EPG")), (eOSState)subSyncEPG));
|
||||
}
|
||||
|
||||
cStreamdevMenu::~cStreamdevMenu() {
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenu::ProcessKey(eKeys Key) {
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
switch (state) {
|
||||
case subSchedule: return AddSubMenu(new cStreamdevMenuSchedule);
|
||||
case subTimers: return AddSubMenu(new cStreamdevMenuTimers);
|
||||
case subRecordings: return AddSubMenu(new cStreamdevMenuRecordings);
|
||||
case subSuspend: SuspendServer(); return osEnd;
|
||||
case subSyncEPG: ClientSocket.SynchronizeEPG(); return osEnd;
|
||||
default: return state;
|
||||
}
|
||||
}
|
||||
|
||||
void cStreamdevMenu::SuspendServer(void) {
|
||||
if (ClientSocket.SuspendServer())
|
||||
INFO(tr("Server is suspended"));
|
||||
else
|
||||
ERROR(tr("Couldn't suspend Server!"));
|
||||
}
|
||||
|
||||
// --- cStreamdevMenuEditTimer -----------------------------------------------
|
||||
|
||||
class cStreamdevMenuEditTimer : public cOsdMenu {
|
||||
private:
|
||||
int m_Channel;
|
||||
bool m_AddIfConfirmed;
|
||||
cRemoteTimer *m_Timer;
|
||||
cRemoteTimer m_Data;
|
||||
cMenuEditDateItem *m_FirstDay;
|
||||
|
||||
protected:
|
||||
void SetFirstDayItem(void);
|
||||
|
||||
public:
|
||||
cStreamdevMenuEditTimer(cRemoteTimer *Timer, bool New = false);
|
||||
virtual ~cStreamdevMenuEditTimer();
|
||||
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
cStreamdevMenuEditTimer::cStreamdevMenuEditTimer(cRemoteTimer *Timer, bool New):
|
||||
cOsdMenu(tr("Edit remote timer"), 12) {
|
||||
m_FirstDay = NULL;
|
||||
m_Timer = Timer;
|
||||
m_AddIfConfirmed = New;
|
||||
|
||||
if (m_Timer) {
|
||||
m_Data = *m_Timer;
|
||||
if (New)
|
||||
m_Data.m_Active = 1;
|
||||
m_Channel = m_Data.Channel()->Number();
|
||||
Add(new cMenuEditBitItem( tr("Active"), &m_Data.m_Active, tfActive));
|
||||
Add(new cMenuEditChanItem(tr("Channel"), &m_Channel));
|
||||
Add(new cMenuEditDayItem( tr("Day"), &m_Data.m_Day));
|
||||
Add(new cMenuEditTimeItem(tr("Start"), &m_Data.m_Start));
|
||||
Add(new cMenuEditTimeItem(tr("Stop"), &m_Data.m_Stop));
|
||||
Add(new cMenuEditBitItem( tr("VPS"), &m_Data.m_Active, tfVps));
|
||||
Add(new cMenuEditIntItem( tr("Priority"), &m_Data.m_Priority, 0,
|
||||
MAXPRIORITY));
|
||||
Add(new cMenuEditIntItem( tr("Lifetime"), &m_Data.m_Lifetime, 0,
|
||||
MAXLIFETIME));
|
||||
Add(new cMenuEditStrItem( tr("File"), m_Data.m_File,
|
||||
sizeof(m_Data.m_File), tr(FileNameChars)));
|
||||
SetFirstDayItem();
|
||||
}
|
||||
}
|
||||
|
||||
cStreamdevMenuEditTimer::~cStreamdevMenuEditTimer() {
|
||||
if (m_Timer && m_AddIfConfirmed) {
|
||||
Dprintf("SOMETHING GETS DELETED\n");
|
||||
delete m_Timer; // apparently it wasn't confirmed
|
||||
}
|
||||
}
|
||||
|
||||
void cStreamdevMenuEditTimer::SetFirstDayItem(void) {
|
||||
if (!m_FirstDay && !m_Data.IsSingleEvent()) {
|
||||
Add(m_FirstDay = new cMenuEditDateItem(tr("First day"),&m_Data.m_FirstDay));
|
||||
Display();
|
||||
} else if (m_FirstDay && m_Data.IsSingleEvent()) {
|
||||
Del(m_FirstDay->Index());
|
||||
m_FirstDay = NULL;
|
||||
m_Data.m_FirstDay = 0;
|
||||
Display();
|
||||
}
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuEditTimer::ProcessKey(eKeys Key) {
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
|
||||
if (state == osUnknown) {
|
||||
switch (Key) {
|
||||
case kOk:
|
||||
{
|
||||
cChannel *ch = Channels.GetByNumber(m_Channel);
|
||||
if (ch)
|
||||
m_Data.m_Channel = ch;
|
||||
else {
|
||||
ERROR(tr("*** Invalid Channel ***"));
|
||||
break;
|
||||
}
|
||||
if (!*m_Data.m_File)
|
||||
strcpy(m_Data.m_File, m_Data.Channel()->Name());
|
||||
if (m_Timer) {
|
||||
bool success = true;
|
||||
if (m_Data != *m_Timer) {
|
||||
// Timer has changed
|
||||
if ((success = ClientSocket.SaveTimer(m_Timer, m_Data))) {
|
||||
*m_Timer = m_Data;
|
||||
if (m_Timer->m_Active)
|
||||
m_Timer->m_Active = 1;
|
||||
// allows external programs to mark active timers with
|
||||
// values > 1 and recognize if the user has modified them
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
if (m_AddIfConfirmed)
|
||||
RemoteTimers.Add(m_Timer);
|
||||
isyslog("timer %d %s (%s)", m_Timer->Index() + 1,
|
||||
m_AddIfConfirmed ? "added" : "modified",
|
||||
m_Timer->m_Active ? "active" : "inactive");
|
||||
m_AddIfConfirmed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return osBack;
|
||||
|
||||
case kRed:
|
||||
case kGreen:
|
||||
case kYellow:
|
||||
case kBlue: return osContinue;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (Key != kNone)
|
||||
SetFirstDayItem();
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cMenuWhatsOnItem ------------------------------------------------------
|
||||
|
||||
class cMenuWhatsOnItem : public cOsdItem {
|
||||
public:
|
||||
const cEvent *event;
|
||||
const cChannel *channel;
|
||||
cMenuWhatsOnItem(const cEvent *Event, cChannel *Channel); //, bool Now = false);
|
||||
};
|
||||
|
||||
// --- cMenuEvent ------------------------------------------------------------
|
||||
|
||||
class cMenuEvent : public cOsdMenu {
|
||||
private:
|
||||
const cEvent *event;
|
||||
public:
|
||||
cMenuEvent(const cEvent *Event, bool CanSwitch = false);
|
||||
virtual void Display(void);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
// --- cStreamdevMenuWhatsOn -------------------------------------------------
|
||||
|
||||
int cStreamdevMenuWhatsOn::m_CurrentChannel = 0;
|
||||
const cEvent *cStreamdevMenuWhatsOn::m_ScheduleEventInfo = NULL;
|
||||
|
||||
cStreamdevMenuWhatsOn::cStreamdevMenuWhatsOn(const cSchedules *Schedules,
|
||||
bool Now, int CurrentChannel):
|
||||
cOsdMenu(Now ? tr("What's on now?") : tr("What's on next?"), CHNUMWIDTH,
|
||||
7, 6) {
|
||||
for (cChannel *Channel = Channels.First(); Channel;
|
||||
Channel = Channels.Next(Channel)) {
|
||||
if (!Channel->GroupSep()) {
|
||||
const cSchedule *Schedule
|
||||
= Schedules->GetSchedule(Channel->GetChannelID());
|
||||
if (Schedule) {
|
||||
const cEvent *Event = Now ? Schedule->GetPresentEvent()
|
||||
: Schedule->GetFollowingEvent();
|
||||
if (Event)
|
||||
Add(new cMenuWhatsOnItem(Event, Channel),
|
||||
Channel->Number() == CurrentChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_CurrentChannel = CurrentChannel;
|
||||
SetHelp(Count() ? tr("Record") : NULL, Now ? tr("Next") : tr("Now"),
|
||||
tr("Schedule"), tr("Switch"));
|
||||
}
|
||||
|
||||
const cEvent *cStreamdevMenuWhatsOn::ScheduleEventInfo(void) {
|
||||
const cEvent *ei = m_ScheduleEventInfo;
|
||||
m_ScheduleEventInfo = NULL;
|
||||
return ei;
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuWhatsOn::Switch(void) {
|
||||
cMenuWhatsOnItem *item = (cMenuWhatsOnItem*)Get(Current());
|
||||
if (item) {
|
||||
cChannel *channel
|
||||
= Channels.GetByChannelID(item->event->ChannelID(), true);
|
||||
if (channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true))
|
||||
return osEnd;
|
||||
}
|
||||
ERROR(tr("Can't switch channel!"));
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuWhatsOn::Record(void) {
|
||||
cMenuWhatsOnItem *item = (cMenuWhatsOnItem*)Get(Current());
|
||||
if (item) {
|
||||
cRemoteTimer *timer
|
||||
= new cRemoteTimer(item->event);
|
||||
return AddSubMenu(new cStreamdevMenuEditTimer(timer));
|
||||
// Load remote timers and see if timer exists before editing
|
||||
}
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuWhatsOn::ProcessKey(eKeys Key) {
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
if (state == osUnknown) {
|
||||
switch (Key) {
|
||||
case kRecord:
|
||||
case kRed:
|
||||
return Record();
|
||||
|
||||
case kYellow:
|
||||
state = osBack;
|
||||
case kGreen:
|
||||
{
|
||||
cMenuWhatsOnItem *mi = (cMenuWhatsOnItem*)Get(Current());
|
||||
if (mi) {
|
||||
m_ScheduleEventInfo = mi->event;
|
||||
m_CurrentChannel = mi->channel->Number();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kBlue:
|
||||
return Switch();
|
||||
|
||||
case kOk:
|
||||
if (Count())
|
||||
return AddSubMenu(new cMenuEvent(
|
||||
((cMenuWhatsOnItem*)Get(Current()))->event, true));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cMenuScheduleItem -----------------------------------------------------
|
||||
|
||||
class cMenuScheduleItem : public cOsdItem {
|
||||
public:
|
||||
const cEvent *event;
|
||||
cMenuScheduleItem(const cEvent *Event);
|
||||
};
|
||||
|
||||
// --- cStreamdevMenuSchedule ------------------------------------------------
|
||||
|
||||
cStreamdevMenuSchedule::cStreamdevMenuSchedule(void):
|
||||
cOsdMenu("", 7, 6, 4)
|
||||
{
|
||||
m_Now = false;
|
||||
m_Next = false;
|
||||
m_OtherChannel = -1;
|
||||
m_Schedules = NULL;
|
||||
|
||||
cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
|
||||
if (channel) {
|
||||
m_Schedules = cSchedules::Schedules(m_Lock);
|
||||
PrepareSchedule(channel);
|
||||
SetHelp(Count() ? tr("Record") : NULL, tr("Now"), tr("Next"));
|
||||
}
|
||||
}
|
||||
|
||||
cStreamdevMenuSchedule::~cStreamdevMenuSchedule() {
|
||||
}
|
||||
|
||||
void cStreamdevMenuSchedule::PrepareSchedule(cChannel *Channel) {
|
||||
Clear();
|
||||
char *buffer = NULL;
|
||||
asprintf(&buffer, tr("Schedule - %s"), Channel->Name());
|
||||
SetTitle(buffer);
|
||||
free(buffer);
|
||||
if (m_Schedules) {
|
||||
const cSchedule *Schedule = m_Schedules->GetSchedule(Channel->GetChannelID());
|
||||
if (Schedule) {
|
||||
const cEvent *PresentEvent = Schedule->GetPresentEvent(Channel->Number() == cDevice::CurrentChannel());
|
||||
time_t now = time(NULL) - Setup.EPGLinger * 60;
|
||||
for (const cEvent *Event = Schedule->Events()->First(); Event; Event = Schedule->Events()->Next(Event)) {
|
||||
if (Event->EndTime() > now || Event == PresentEvent)
|
||||
Add(new cMenuScheduleItem(Event), Event == PresentEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuSchedule::Switch(void) {
|
||||
if (m_OtherChannel) {
|
||||
if (Channels.SwitchTo(m_OtherChannel))
|
||||
return osEnd;
|
||||
}
|
||||
ERROR(tr("Can't switch channel!"));
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuSchedule::Record(void) {
|
||||
cMenuScheduleItem *item = (cMenuScheduleItem*)Get(Current());
|
||||
if (item) {
|
||||
cRemoteTimer *timer
|
||||
= new cRemoteTimer(item->event);
|
||||
return AddSubMenu(new cStreamdevMenuEditTimer(timer));
|
||||
// Load remote timers and see if timer exists before editing
|
||||
}
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuSchedule::ProcessKey(eKeys Key) {
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
if (state == osUnknown) {
|
||||
switch (Key) {
|
||||
case kRecord:
|
||||
case kRed:
|
||||
return Record();
|
||||
|
||||
case kGreen:
|
||||
if (m_Schedules) {
|
||||
if (!m_Now && !m_Next) {
|
||||
int channelnr = 0;
|
||||
if (Count()) {
|
||||
cChannel *channel
|
||||
= Channels.GetByChannelID(
|
||||
((cMenuScheduleItem*)Get(Current()))->event->ChannelID(), true);
|
||||
if (channel)
|
||||
channelnr = channel->Number();
|
||||
}
|
||||
m_Now = true;
|
||||
return AddSubMenu(new cStreamdevMenuWhatsOn(m_Schedules, true,
|
||||
channelnr));
|
||||
}
|
||||
m_Now = !m_Now;
|
||||
m_Next = !m_Next;
|
||||
return AddSubMenu(new cStreamdevMenuWhatsOn(m_Schedules, m_Now,
|
||||
cStreamdevMenuWhatsOn::CurrentChannel()));
|
||||
}
|
||||
|
||||
case kYellow:
|
||||
if (m_Schedules)
|
||||
return AddSubMenu(new cStreamdevMenuWhatsOn(m_Schedules, false,
|
||||
cStreamdevMenuWhatsOn::CurrentChannel()));
|
||||
break;
|
||||
|
||||
case kBlue:
|
||||
if (Count())
|
||||
return Switch();
|
||||
break;
|
||||
|
||||
case kOk:
|
||||
if (Count())
|
||||
return AddSubMenu(new cMenuEvent(
|
||||
((cMenuScheduleItem*)Get(Current()))->event, m_OtherChannel));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (!HasSubMenu()) {
|
||||
m_Now = false;
|
||||
m_Next = false;
|
||||
const cEvent *ei
|
||||
= cStreamdevMenuWhatsOn::ScheduleEventInfo();
|
||||
if (ei) {
|
||||
cChannel *channel
|
||||
= Channels.GetByChannelID(ei->ChannelID(), true);
|
||||
if (channel) {
|
||||
PrepareSchedule(channel);
|
||||
if (channel->Number() != cDevice::CurrentChannel()) {
|
||||
m_OtherChannel = channel->Number();
|
||||
SetHelp(Count() ? tr("Record") : NULL, tr("Now"), tr("Next"),
|
||||
tr("Switch"));
|
||||
}
|
||||
Display();
|
||||
}
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cStreamdevMenuRecordingItem -------------------------------------------
|
||||
|
||||
class cStreamdevMenuRecordingItem: public cOsdItem {
|
||||
private:
|
||||
int m_Total;
|
||||
int m_New;
|
||||
char *m_FileName;
|
||||
char *m_Name;
|
||||
|
||||
public:
|
||||
cStreamdevMenuRecordingItem(cRemoteRecording *Recording, int Level);
|
||||
virtual ~cStreamdevMenuRecordingItem();
|
||||
|
||||
void IncrementCounter(bool New);
|
||||
const char *Name(void) const { return m_Name; }
|
||||
const char *FileName(void) const { return m_FileName; }
|
||||
bool IsDirectory(void) const { return m_Name != NULL; }
|
||||
};
|
||||
|
||||
cStreamdevMenuRecordingItem::cStreamdevMenuRecordingItem(
|
||||
cRemoteRecording *Recording, int Level) {
|
||||
m_FileName = strdup(Recording->Name());
|
||||
m_Name = NULL;
|
||||
m_Total = m_New = 0;
|
||||
SetText(Recording->Title('\t', true, Level));
|
||||
if (*Text() == '\t')
|
||||
m_Name = strdup(Text() + 2);
|
||||
}
|
||||
|
||||
cStreamdevMenuRecordingItem::~cStreamdevMenuRecordingItem() {
|
||||
}
|
||||
|
||||
void cStreamdevMenuRecordingItem::IncrementCounter(bool New) {
|
||||
++m_Total;
|
||||
if (New) ++m_New;
|
||||
char *buffer = NULL;
|
||||
asprintf(&buffer, "%d\t%d\t%s", m_Total, m_New, m_Name);
|
||||
SetText(buffer, false);
|
||||
}
|
||||
|
||||
// --- cStreamdevMenuRecordings ----------------------------------------------
|
||||
|
||||
cRemoteRecordings cStreamdevMenuRecordings::Recordings;
|
||||
int cStreamdevMenuRecordings::HelpKeys = -1;
|
||||
|
||||
cStreamdevMenuRecordings::cStreamdevMenuRecordings(const char *Base, int Level,
|
||||
bool OpenSubMenus):
|
||||
cOsdMenu(Base ? Base : tr("Remote Recordings"), 6, 6) {
|
||||
m_Base = Base ? strdup(Base) : NULL;
|
||||
m_Level = Setup.RecordingDirs ? Level : -1;
|
||||
|
||||
Display(); // this keeps the higher level menus from showing up briefly when
|
||||
// pressing 'Back' during replay
|
||||
|
||||
if (!Base) {
|
||||
STATUS(tr("Fetching recordings..."));
|
||||
FLUSH();
|
||||
}
|
||||
|
||||
if (Base || Recordings.Load()) {
|
||||
cStreamdevMenuRecordingItem *LastItem = NULL;
|
||||
char *LastItemText = NULL;
|
||||
for (cRemoteRecording *r = Recordings.First(); r; r = Recordings.Next(r)) {
|
||||
if (!Base || (strstr(r->Name(), Base) == r->Name()
|
||||
&& r->Name()[strlen(Base)] == '~')) {
|
||||
cStreamdevMenuRecordingItem *Item = new cStreamdevMenuRecordingItem(r,
|
||||
m_Level);
|
||||
if (*Item->Text() && (!LastItem || strcmp(Item->Text(), LastItemText)
|
||||
!= 0)) {
|
||||
Add(Item);
|
||||
LastItem = Item;
|
||||
free(LastItemText);
|
||||
LastItemText = strdup(LastItem->Text());
|
||||
} else
|
||||
delete Item;
|
||||
|
||||
if (LastItem) {
|
||||
if (LastItem->IsDirectory())
|
||||
LastItem->IncrementCounter(r->IsNew());
|
||||
}
|
||||
}
|
||||
}
|
||||
free(LastItemText);
|
||||
if (Current() < 0)
|
||||
SetCurrent(First());
|
||||
else if (OpenSubMenus && Open(true))
|
||||
return;
|
||||
}
|
||||
|
||||
STATUS(NULL);
|
||||
FLUSH();
|
||||
|
||||
SetHelpKeys();
|
||||
}
|
||||
|
||||
cStreamdevMenuRecordings::~cStreamdevMenuRecordings() {
|
||||
if (m_Base != NULL) free(m_Base);
|
||||
HelpKeys = -1;
|
||||
}
|
||||
|
||||
void cStreamdevMenuRecordings::SetHelpKeys(void) {
|
||||
cStreamdevMenuRecordingItem *ri =(cStreamdevMenuRecordingItem*)Get(Current());
|
||||
int NewHelpKeys = HelpKeys;
|
||||
if (ri) {
|
||||
if (ri->IsDirectory())
|
||||
NewHelpKeys = 1;
|
||||
else {
|
||||
NewHelpKeys = 2;
|
||||
cRemoteRecording *recording = GetRecording(ri);
|
||||
if (recording && recording->Summary())
|
||||
NewHelpKeys = 3;
|
||||
}
|
||||
}
|
||||
if (NewHelpKeys != HelpKeys) {
|
||||
switch (NewHelpKeys) {
|
||||
case 0: SetHelp(NULL); break;
|
||||
case 1: SetHelp(tr("Open")); break;
|
||||
case 2:
|
||||
case 3: SetHelp(NULL, NULL, tr("Delete"), NewHelpKeys == 3 ? tr("Summary") : NULL);
|
||||
//SetHelp(tr("Play"), tr("Rewind"), tr("Delete"), NewHelpKeys == 3 ? tr("Summary") : NULL); XXX
|
||||
}
|
||||
HelpKeys = NewHelpKeys;
|
||||
}
|
||||
}
|
||||
|
||||
cRemoteRecording *cStreamdevMenuRecordings::GetRecording(
|
||||
cStreamdevMenuRecordingItem *Item) {
|
||||
Dprintf("looking for %s\n", Item->FileName());
|
||||
cRemoteRecording *recording = Recordings.GetByName(Item->FileName());
|
||||
if (!recording)
|
||||
ERROR(tr("Error while accessing recording!"));
|
||||
return recording;
|
||||
}
|
||||
|
||||
bool cStreamdevMenuRecordings::Open(bool OpenSubMenus) {
|
||||
cStreamdevMenuRecordingItem *ri
|
||||
= (cStreamdevMenuRecordingItem*)Get(Current());
|
||||
|
||||
if (ri && ri->IsDirectory()) {
|
||||
const char *t = ri->Name();
|
||||
char *buffer = NULL;
|
||||
if (m_Base) {
|
||||
asprintf(&buffer, "%s~%s", m_Base, t);
|
||||
t = buffer;
|
||||
}
|
||||
AddSubMenu(new cStreamdevMenuRecordings(t, m_Level + 1, OpenSubMenus));
|
||||
if (buffer != NULL) free(buffer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuRecordings::Select(void) {
|
||||
cStreamdevMenuRecordingItem *ri
|
||||
= (cStreamdevMenuRecordingItem*)Get(Current());
|
||||
|
||||
if (ri) {
|
||||
if (ri->IsDirectory())
|
||||
Open();
|
||||
/*else {
|
||||
cControl::Launch(new cStreamdevPlayerControl(ri->FileName()));
|
||||
return osEnd;
|
||||
} XXX */
|
||||
}
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuRecordings::Delete(void) {
|
||||
if (HasSubMenu() || Count() == 0)
|
||||
return osContinue;
|
||||
cStreamdevMenuRecordingItem *ri
|
||||
= (cStreamdevMenuRecordingItem*)Get(Current());
|
||||
if (ri && !ri->IsDirectory()) {
|
||||
if (Interface->Confirm(tr("Delete recording?"))) {
|
||||
cRemoteRecording *recording = GetRecording(ri);
|
||||
if (recording) {
|
||||
if (ClientSocket.DeleteRecording(recording)) {
|
||||
cOsdMenu::Del(Current());
|
||||
Recordings.Del(recording);
|
||||
Display();
|
||||
if (!Count())
|
||||
return osBack;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuRecordings::Summary(void) {
|
||||
if (HasSubMenu() || Count() == 0)
|
||||
return osContinue;
|
||||
cStreamdevMenuRecordingItem *ri=(cStreamdevMenuRecordingItem *)Get(Current());
|
||||
if (ri && !ri->IsDirectory()) {
|
||||
cRemoteRecording *recording = GetRecording(ri);
|
||||
if (recording && recording->Summary() && *recording->Summary())
|
||||
return AddSubMenu(new cMenuText(tr("Summary"), recording->Summary()));
|
||||
}
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuRecordings::ProcessKey(eKeys Key) {
|
||||
bool HadSubMenu = HasSubMenu();
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
|
||||
if (state == osUnknown) {
|
||||
switch (Key) {
|
||||
case kOk:
|
||||
case kRed: return Select();
|
||||
case kYellow: return Delete();
|
||||
case kBlue: return Summary();
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Key == kYellow && HadSubMenu && !HasSubMenu()) {
|
||||
cOsdMenu::Del(Current());
|
||||
if (!Count())
|
||||
return osBack;
|
||||
Display();
|
||||
}
|
||||
|
||||
if (!HasSubMenu() && Key != kNone)
|
||||
SetHelpKeys();
|
||||
return state;
|
||||
}
|
||||
|
||||
// --- cStreamdevMenuTimerItem -----------------------------------------------
|
||||
|
||||
class cStreamdevMenuTimerItem: public cOsdItem {
|
||||
private:
|
||||
cRemoteTimer *m_Timer;
|
||||
|
||||
public:
|
||||
cStreamdevMenuTimerItem(cRemoteTimer *Timer);
|
||||
virtual ~cStreamdevMenuTimerItem();
|
||||
|
||||
virtual void Set(void);
|
||||
|
||||
cRemoteTimer *Timer(void) const { return m_Timer; }
|
||||
};
|
||||
|
||||
cStreamdevMenuTimerItem::cStreamdevMenuTimerItem(cRemoteTimer *Timer) {
|
||||
m_Timer = Timer;
|
||||
Set();
|
||||
}
|
||||
|
||||
cStreamdevMenuTimerItem::~cStreamdevMenuTimerItem() {
|
||||
}
|
||||
|
||||
void cStreamdevMenuTimerItem::Set(void) {
|
||||
char *buffer = NULL;
|
||||
asprintf(&buffer, "%c\t%d\t%s\t%02d:%02d\t%02d:%02d\t%s",
|
||||
!m_Timer->Active() ? ' ' :
|
||||
m_Timer->FirstDay() ? '!' :
|
||||
/*m_Timer->Recording() ? '#' :*/ '>',
|
||||
m_Timer->Channel()->Number(),
|
||||
m_Timer->PrintDay(m_Timer->Day()),
|
||||
m_Timer->Start() / 100,
|
||||
m_Timer->Start() % 100,
|
||||
m_Timer->Stop() / 100,
|
||||
m_Timer->Stop() % 100,
|
||||
m_Timer->File());
|
||||
SetText(buffer, false);
|
||||
}
|
||||
|
||||
// --- cStreamdevMenuTimers --------------------------------------------------
|
||||
|
||||
cStreamdevMenuTimers::cStreamdevMenuTimers(void):
|
||||
cOsdMenu(tr("Remote Timers"), 2, CHNUMWIDTH, 10, 6, 6) {
|
||||
Refresh();
|
||||
SetHelp(tr("Edit"), tr("New"), tr("Delete"), tr("On/Off"));
|
||||
}
|
||||
|
||||
cStreamdevMenuTimers::~cStreamdevMenuTimers() {
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuTimers::ProcessKey(eKeys Key) {
|
||||
int timerNum = HasSubMenu() ? Count() : -1;
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
|
||||
if (state == osUnknown) {
|
||||
switch (Key) {
|
||||
case kOk: return Summary();
|
||||
case kRed: return Edit();
|
||||
case kGreen: return New();
|
||||
case kYellow: return Delete();
|
||||
case kBlue: OnOff(); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
if (timerNum >= 0 && !HasSubMenu()) {
|
||||
Refresh();
|
||||
Display();
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuTimers::Edit(void) {
|
||||
if (HasSubMenu() || Count() == 0)
|
||||
return osContinue;
|
||||
isyslog("Streamdev: Editing remote timer %d", CurrentTimer()->Index() + 1);
|
||||
return AddSubMenu(new cStreamdevMenuEditTimer(CurrentTimer()));
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuTimers::New(void) {
|
||||
if (HasSubMenu())
|
||||
return osContinue;
|
||||
return AddSubMenu(new cStreamdevMenuEditTimer(new cRemoteTimer, true));
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuTimers::Delete(void) {
|
||||
cRemoteTimer *ti = CurrentTimer();
|
||||
if (ti) {
|
||||
if (Interface->Confirm(tr("Delete timer?"))) {
|
||||
int idx = ti->Index();
|
||||
if (ClientSocket.DeleteTimer(ti)) {
|
||||
RemoteTimers.Del(ti);
|
||||
cOsdMenu::Del(Current());
|
||||
isyslog("Streamdev: Remote timer %d deleted", idx + 1);
|
||||
}
|
||||
Refresh();
|
||||
Display();
|
||||
}
|
||||
}
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuTimers::OnOff(void) {
|
||||
cRemoteTimer *timer = CurrentTimer();
|
||||
if (timer) {
|
||||
cRemoteTimer data = *timer;
|
||||
data.OnOff();
|
||||
if (data.FirstDay())
|
||||
isyslog("Streamdev: Remote timer %d first day set to %s",
|
||||
data.Index() + 1, data.PrintFirstDay());
|
||||
else
|
||||
isyslog("Streamdev: Remote timer %d %sactivated", data.Index() + 1,
|
||||
data.Active() ? "" : "de");
|
||||
|
||||
if (ClientSocket.SaveTimer(timer, data)) {
|
||||
*timer = data;
|
||||
RefreshCurrent();
|
||||
DisplayCurrent(true);
|
||||
} else {
|
||||
Refresh();
|
||||
Display();
|
||||
}
|
||||
}
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
eOSState cStreamdevMenuTimers::Summary(void) {
|
||||
if (HasSubMenu() || Count() == 0)
|
||||
return osContinue;
|
||||
|
||||
cRemoteTimer *ti = CurrentTimer();
|
||||
if (ti && ti->Summary() != "")
|
||||
return AddSubMenu(new cMenuText(tr("Summary"), ti->Summary().c_str()));
|
||||
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
cRemoteTimer *cStreamdevMenuTimers::CurrentTimer(void) {
|
||||
cStreamdevMenuTimerItem *item = (cStreamdevMenuTimerItem*)Get(Current());
|
||||
return item ? item->Timer() : NULL;
|
||||
}
|
||||
|
||||
void cStreamdevMenuTimers::Refresh(void) {
|
||||
Clear();
|
||||
if (RemoteTimers.Load()) {
|
||||
for (cRemoteTimer *t = RemoteTimers.First(); t; t = RemoteTimers.Next(t)) {
|
||||
Add(new cStreamdevMenuTimerItem(t));
|
||||
}
|
||||
}
|
||||
}
|
132
client/menu.h
132
client/menu.h
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* $Id: menu.h,v 1.2 2008/04/07 14:27:28 schmirl 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;
|
||||
cSchedulesLock m_Lock;
|
||||
|
||||
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;
|
||||
static const cEvent *m_ScheduleEventInfo;
|
||||
|
||||
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; }
|
||||
static const cEvent *ScheduleEventInfo(void);
|
||||
|
||||
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
|
||||
|
465
client/remote.c
465
client/remote.c
@@ -1,465 +0,0 @@
|
||||
/*
|
||||
* $Id: remote.c,v 1.5 2008/04/07 14:27:28 schmirl 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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
123
client/remote.h
123
client/remote.h
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* $Id: remote.h,v 1.3 2008/04/07 14:27:28 schmirl Exp $
|
||||
*/
|
||||
|
||||
#ifndef VDR_STREAMDEV_REMOTE_H
|
||||
#define VDR_STREAMDEV_REMOTE_H
|
||||
|
||||
#include <vdr/config.h>
|
||||
#include <string>
|
||||
|
||||
class cEvent;
|
||||
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);
|
||||
cRemoteTimer(const cEvent *Event);
|
||||
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,5 +1,5 @@
|
||||
/*
|
||||
* $Id: setup.c,v 1.3 2008/04/07 14:27:28 schmirl Exp $
|
||||
* $Id: setup.c,v 1.4 2008/04/07 14:40:40 schmirl Exp $
|
||||
*/
|
||||
|
||||
#include <vdr/menuitems.h>
|
||||
@@ -52,7 +52,7 @@ void cStreamdevClientMenuSetupPage::Store(void) {
|
||||
if (m_NewSetup.StartClient)
|
||||
cStreamdevDevice::Init();
|
||||
else
|
||||
INFO(tr("Please restart VDR to activate changes"));
|
||||
Skins.Message(mtInfo, tr("Please restart VDR to activate changes"));
|
||||
}
|
||||
|
||||
SetupStore("StartClient", m_NewSetup.StartClient);
|
||||
|
230
client/socket.c
230
client/socket.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: socket.c,v 1.10 2008/04/07 14:27:28 schmirl Exp $
|
||||
* $Id: socket.c,v 1.11 2008/04/07 14:40:40 schmirl Exp $
|
||||
*/
|
||||
|
||||
#include <tools/select.h>
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include "client/socket.h"
|
||||
#include "client/setup.h"
|
||||
#include "client/remote.h"
|
||||
#include "common.h"
|
||||
#include "i18n.h"
|
||||
|
||||
@@ -362,128 +361,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;
|
||||
|
||||
@@ -496,108 +373,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.5 2008/04/07 14:27:28 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 {
|
||||
@@ -53,13 +49,6 @@ public:
|
||||
bool SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On);
|
||||
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