mirror of
https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
synced 2023-10-10 19:16:51 +02:00
1046 lines
28 KiB
C
1046 lines
28 KiB
C
/*
|
|
* $Id: menu.c,v 1.4 2005/03/12 12:54:19 lordjaxom 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!"));
|
|
}
|
|
|
|
#if VDRVERSNUM < 10307
|
|
// --- cMenuEditChanItem -----------------------------------------------------
|
|
|
|
class cMenuEditChanItem : public cMenuEditIntItem {
|
|
protected:
|
|
virtual void Set(void);
|
|
public:
|
|
cMenuEditChanItem(const char *Name, int *Value);
|
|
virtual eOSState ProcessKey(eKeys Key);
|
|
};
|
|
|
|
// --- cMenuEditDateItem -----------------------------------------------------
|
|
|
|
class cMenuEditDateItem : public cMenuEditItem {
|
|
protected:
|
|
time_t *value;
|
|
virtual void Set(void);
|
|
public:
|
|
cMenuEditDateItem(const char *Name, time_t *Value);
|
|
virtual eOSState ProcessKey(eKeys Key);
|
|
};
|
|
|
|
// --- cMenuEditDayItem ------------------------------------------------------
|
|
|
|
class cMenuEditDayItem : public cMenuEditIntItem {
|
|
protected:
|
|
static int days[];
|
|
int d;
|
|
virtual void Set(void);
|
|
public:
|
|
cMenuEditDayItem(const char *Name, int *Value);
|
|
virtual eOSState ProcessKey(eKeys Key);
|
|
};
|
|
|
|
// --- cMenuEditTimeItem -----------------------------------------------------
|
|
|
|
class cMenuEditTimeItem : public cMenuEditItem {
|
|
protected:
|
|
int *value;
|
|
int hh, mm;
|
|
int pos;
|
|
virtual void Set(void);
|
|
public:
|
|
cMenuEditTimeItem(const char *Name, int *Value);
|
|
virtual eOSState ProcessKey(eKeys Key);
|
|
};
|
|
#endif // VDRVERSNUM < 10307
|
|
|
|
// --- 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();
|
|
#if VDRVERSNUM < 10300
|
|
Add(new cMenuEditBoolItem(tr("Active"), &m_Data.m_Active));
|
|
#else
|
|
Add(new cMenuEditBitItem( tr("Active"), &m_Data.m_Active, tfActive));
|
|
#endif
|
|
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));
|
|
#if VDRVERSNUM >= 10300
|
|
Add(new cMenuEditBitItem( tr("VPS"), &m_Data.m_Active, tfVps));
|
|
#endif
|
|
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 ------------------------------------------------------
|
|
|
|
#if VDRVERSNUM < 10300
|
|
class cMenuWhatsOnItem : public cOsdItem {
|
|
public:
|
|
const cEventInfo *eventInfo;
|
|
# ifdef HAVE_BEAUTYPATCH
|
|
cMenuWhatsOnItem(const cEventInfo *EventInfo, bool ShowProgressBar);
|
|
~cMenuWhatsOnItem();
|
|
virtual void Display(int Offset= -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
|
|
protected:
|
|
cBitmap *progressBar;
|
|
bool showProgressBar;
|
|
float percent;
|
|
private:
|
|
void DrawProgressBar(eDvbColor FgColor, eDvbColor BgColor);
|
|
# else
|
|
cMenuWhatsOnItem(const cEventInfo *EventInfo);
|
|
# endif
|
|
};
|
|
#else
|
|
class cMenuWhatsOnItem : public cOsdItem {
|
|
public:
|
|
const cEvent *event;
|
|
const cChannel *channel;
|
|
cMenuWhatsOnItem(const cEvent *Event, cChannel *Channel); //, bool Now = false);
|
|
};
|
|
#endif
|
|
|
|
// --- cMenuEvent ------------------------------------------------------------
|
|
|
|
#if VDRVERSNUM < 10300
|
|
class cMenuEvent : public cOsdMenu {
|
|
private:
|
|
const cEventInfo *eventInfo;
|
|
public:
|
|
cMenuEvent(const cEventInfo *EventInfo, bool CanSwitch = false);
|
|
cMenuEvent(bool Now);
|
|
virtual eOSState ProcessKey(eKeys Key);
|
|
};
|
|
#elif VDRVERSNUM < 10307
|
|
class cMenuEvent : public cOsdMenu {
|
|
private:
|
|
const cEvent *event;
|
|
public:
|
|
cMenuEvent(const cEvent *Event, bool CanSwitch = false);
|
|
cMenuEvent(bool Now);
|
|
virtual eOSState ProcessKey(eKeys Key);
|
|
};
|
|
#else
|
|
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);
|
|
};
|
|
#endif
|
|
|
|
// --- cStreamdevMenuWhatsOn -------------------------------------------------
|
|
|
|
int cStreamdevMenuWhatsOn::m_CurrentChannel = 0;
|
|
#if VDRVERSNUM < 10300
|
|
const cEventInfo *cStreamdevMenuWhatsOn::m_ScheduleEventInfo = NULL;
|
|
#else
|
|
const cEvent *cStreamdevMenuWhatsOn::m_ScheduleEventInfo = NULL;
|
|
#endif
|
|
|
|
#if VDRVERSNUM < 10300
|
|
static int CompareEventChannel(const void *p1, const void *p2) {
|
|
return (int)((*(const cEventInfo**)p1)->GetChannelNumber()
|
|
- (*(const cEventInfo**)p2)->GetChannelNumber());
|
|
}
|
|
#endif
|
|
|
|
cStreamdevMenuWhatsOn::cStreamdevMenuWhatsOn(const cSchedules *Schedules,
|
|
bool Now, int CurrentChannel):
|
|
cOsdMenu(Now ? tr("What's on now?") : tr("What's on next?"), CHNUMWIDTH,
|
|
7, 6) {
|
|
#if VDRVERSNUM < 10300
|
|
const cSchedule *Schedule = Schedules->First();
|
|
const cEventInfo **pArray = NULL;
|
|
int num = 0;
|
|
|
|
while (Schedule) {
|
|
pArray=(const cEventInfo**)realloc(pArray, (num + 1) * sizeof(cEventInfo*));
|
|
pArray[num] = Now ? Schedule->GetPresentEvent()
|
|
: Schedule->GetFollowingEvent();
|
|
if (pArray[num]) {
|
|
cChannel *channel
|
|
= Channels.GetByChannelID(pArray[num]->GetChannelID(), true);
|
|
if (channel)
|
|
pArray[num++]->SetChannelNumber(channel->Number());
|
|
}
|
|
Schedule = Schedules->Next(Schedule);
|
|
}
|
|
|
|
qsort(pArray, num, sizeof(cEventInfo*), CompareEventChannel);
|
|
for (int a = 0; a < num; ++a) {
|
|
int channelnr = pArray[a]->GetChannelNumber();
|
|
# ifdef HAVE_BEAUTYPATCH
|
|
Add(new cMenuWhatsOnItem(pArray[a],Now), channelnr == CurrentChannel);
|
|
# else
|
|
Add(new cMenuWhatsOnItem(pArray[a]), channelnr == CurrentChannel);
|
|
# endif
|
|
}
|
|
|
|
free(pArray);
|
|
#else
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
m_CurrentChannel = CurrentChannel;
|
|
SetHelp(Count() ? tr("Record") : NULL, Now ? tr("Next") : tr("Now"),
|
|
tr("Schedule"), tr("Switch"));
|
|
}
|
|
|
|
#if VDRVERSNUM < 10300
|
|
const cEventInfo *cStreamdevMenuWhatsOn::ScheduleEventInfo(void) {
|
|
const cEventInfo *ei = m_ScheduleEventInfo;
|
|
m_ScheduleEventInfo = NULL;
|
|
return ei;
|
|
}
|
|
#else
|
|
const cEvent *cStreamdevMenuWhatsOn::ScheduleEventInfo(void) {
|
|
const cEvent *ei = m_ScheduleEventInfo;
|
|
m_ScheduleEventInfo = NULL;
|
|
return ei;
|
|
}
|
|
#endif
|
|
|
|
eOSState cStreamdevMenuWhatsOn::Switch(void) {
|
|
cMenuWhatsOnItem *item = (cMenuWhatsOnItem*)Get(Current());
|
|
if (item) {
|
|
cChannel *channel
|
|
#if VDRVERSNUM < 10300
|
|
= Channels.GetByChannelID(item->eventInfo->GetChannelID(), true);
|
|
#else
|
|
= Channels.GetByChannelID(item->event->ChannelID(), true);
|
|
#endif
|
|
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
|
|
#if VDRVERSNUM < 10300
|
|
= new cRemoteTimer(item->eventInfo);
|
|
#else
|
|
= new cRemoteTimer(item->event);
|
|
#endif
|
|
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) {
|
|
#if VDRVERSNUM < 10300
|
|
m_ScheduleEventInfo = mi->eventInfo;
|
|
m_CurrentChannel = mi->eventInfo->GetChannelNumber();
|
|
#else
|
|
m_ScheduleEventInfo = mi->event;
|
|
m_CurrentChannel = mi->channel->Number();
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
|
|
case kBlue:
|
|
return Switch();
|
|
|
|
case kOk:
|
|
if (Count())
|
|
#if VDRVERSNUM < 10300
|
|
return AddSubMenu(new cMenuEvent(
|
|
((cMenuWhatsOnItem*)Get(Current()))->eventInfo, true));
|
|
#else
|
|
return AddSubMenu(new cMenuEvent(
|
|
((cMenuWhatsOnItem*)Get(Current()))->event, true));
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return state;
|
|
}
|
|
|
|
// --- cMenuScheduleItem -----------------------------------------------------
|
|
|
|
#if VDRVERSNUM < 10300
|
|
class cMenuScheduleItem : public cOsdItem {
|
|
public:
|
|
const cEventInfo *eventInfo;
|
|
cMenuScheduleItem(const cEventInfo *EventInfo);
|
|
};
|
|
#else
|
|
class cMenuScheduleItem : public cOsdItem {
|
|
public:
|
|
const cEvent *event;
|
|
cMenuScheduleItem(const cEvent *Event);
|
|
};
|
|
#endif
|
|
|
|
// --- cStreamdevMenuSchedule ------------------------------------------------
|
|
|
|
cStreamdevMenuSchedule::cStreamdevMenuSchedule(void):
|
|
#if VDRVERSNUM < 10300
|
|
cOsdMenu("", 6, 6)
|
|
#else
|
|
cOsdMenu("", 7, 6, 4)
|
|
#endif
|
|
{
|
|
m_Now = false;
|
|
m_Next = false;
|
|
m_OtherChannel = -1;
|
|
m_Schedules = NULL;
|
|
|
|
cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
|
|
if (channel) {
|
|
#if VDRVERSNUM < 10300
|
|
m_Schedules = cSIProcessor::Schedules(m_Lock);
|
|
#else
|
|
m_Schedules = cSchedules::Schedules(m_Lock);
|
|
#endif
|
|
PrepareSchedule(channel);
|
|
SetHelp(Count() ? tr("Record") : NULL, tr("Now"), tr("Next"));
|
|
}
|
|
}
|
|
|
|
cStreamdevMenuSchedule::~cStreamdevMenuSchedule() {
|
|
}
|
|
|
|
#if VDRVERSNUM < 10307
|
|
static int CompareEventTime(const void *p1, const void *p2) {
|
|
#if VDRVERSNUM < 10300
|
|
return (int)((*(cEventInfo **)p1)->GetTime()
|
|
- (*(cEventInfo **)p2)->GetTime());
|
|
#else
|
|
return (int)((*(cEvent**)p1)->StartTime()
|
|
- (*(cEvent**)p2)->StartTime());
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
void cStreamdevMenuSchedule::PrepareSchedule(cChannel *Channel) {
|
|
#if VDRVERSNUM < 10300
|
|
cTBString buffer;
|
|
Clear();
|
|
buffer.Format(tr("Schedule - %s"), Channel->Name());
|
|
SetTitle(buffer);
|
|
if (m_Schedules) {
|
|
const cSchedule *Schedule=m_Schedules->GetSchedule(Channel->GetChannelID());
|
|
if (Schedule) {
|
|
int num = Schedule->NumEvents();
|
|
const cEventInfo **pArray = MALLOC(const cEventInfo*, num);
|
|
if (pArray) {
|
|
time_t now = time(NULL);
|
|
int numreal = 0;
|
|
for (int a = 0; a < num; ++a) {
|
|
const cEventInfo *EventInfo = Schedule->GetEventNumber(a);
|
|
if (EventInfo->GetTime() + EventInfo->GetDuration() > now)
|
|
pArray[numreal++] = EventInfo;
|
|
}
|
|
|
|
qsort(pArray, numreal, sizeof(cEventInfo*), CompareEventTime);
|
|
for (int a = 0; a < numreal; ++a)
|
|
Add(new cMenuScheduleItem(pArray[a]));
|
|
free(pArray);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
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
|
|
#if VDRVERSNUM < 10300
|
|
= new cRemoteTimer(item->eventInfo);
|
|
#else
|
|
= new cRemoteTimer(item->event);
|
|
#endif
|
|
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
|
|
#if VDRVERSNUM < 10300
|
|
= Channels.GetByChannelID(
|
|
((cMenuScheduleItem*)Get(Current()))->eventInfo->GetChannelID(),
|
|
true);
|
|
#else
|
|
= Channels.GetByChannelID(
|
|
((cMenuScheduleItem*)Get(Current()))->event->ChannelID(), true);
|
|
#endif
|
|
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())
|
|
#if VDRVERSNUM < 10300
|
|
return AddSubMenu(new cMenuEvent(
|
|
((cMenuScheduleItem*)Get(Current()))->eventInfo, m_OtherChannel));
|
|
#else
|
|
return AddSubMenu(new cMenuEvent(
|
|
((cMenuScheduleItem*)Get(Current()))->event, m_OtherChannel));
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
} else if (!HasSubMenu()) {
|
|
m_Now = false;
|
|
m_Next = false;
|
|
#if VDRVERSNUM < 10300
|
|
const cEventInfo *ei
|
|
#else
|
|
const cEvent *ei
|
|
#endif
|
|
= cStreamdevMenuWhatsOn::ScheduleEventInfo();
|
|
if (ei) {
|
|
cChannel *channel
|
|
#if VDRVERSNUM < 10300
|
|
= Channels.GetByChannelID(ei->GetChannelID(), true);
|
|
#else
|
|
= Channels.GetByChannelID(ei->ChannelID(), true);
|
|
#endif
|
|
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;
|
|
}
|
|
|
|
#if VDRVERSNUM >= 10307
|
|
STATUS(NULL);
|
|
FLUSH();
|
|
#endif
|
|
|
|
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));
|
|
}
|
|
}
|
|
}
|