The main menu now dynamically updates its contents

This commit is contained in:
Klaus Schmidinger 2005-12-24 15:53:53 +01:00
parent 60d56fceb9
commit 186a3213d0
4 changed files with 120 additions and 43 deletions

View File

@ -3963,7 +3963,7 @@ Video Disk Recorder Revision History
commands may now be executed at any time, and the message will be displayed commands may now be executed at any time, and the message will be displayed
(no more "pending message"). (no more "pending message").
2005-12-18: Version 1.3.38 2005-12-24: Version 1.3.38
- Fixed handling second audio and Dolby Digital PIDs for encrypted channels - Fixed handling second audio and Dolby Digital PIDs for encrypted channels
(was broken in version 1.3.37). (was broken in version 1.3.37).
@ -3989,3 +3989,5 @@ Video Disk Recorder Revision History
- Fixed handling OSD areas that have invalid sizes (thanks to Marco Schlüßler). - Fixed handling OSD areas that have invalid sizes (thanks to Marco Schlüßler).
- Added a mutex to AssertFreeDiskSpace() to make sure calls from foreground - Added a mutex to AssertFreeDiskSpace() to make sure calls from foreground
and background threads won't interfere. and background threads won't interfere.
- The main menu now dynamically updates its contents in case an instant
recording or replay stops, etc.

137
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.c 1.376 2005/11/05 17:29:22 kls Exp $ * $Id: menu.c 1.377 2005/12/24 15:50:01 kls Exp $
*/ */
#include "menu.h" #include "menu.h"
@ -31,6 +31,7 @@
#define MAXWAIT4EPGINFO 3 // seconds #define MAXWAIT4EPGINFO 3 // seconds
#define MODETIMEOUT 3 // seconds #define MODETIMEOUT 3 // seconds
#define DISKSPACECHEK 5 // seconds between disk space checks in the main menu
#define MAXRECORDCONTROLS (MAXDEVICES * MAXRECEIVERS) #define MAXRECORDCONTROLS (MAXDEVICES * MAXRECEIVERS)
#define MAXINSTANTRECTIME (24 * 60 - 1) // 23:59 hours #define MAXINSTANTRECTIME (24 * 60 - 1) // 23:59 hours
@ -2473,10 +2474,16 @@ cMenuPluginItem::cMenuPluginItem(const char *Name, int Index)
cOsdObject *cMenuMain::pluginOsdObject = NULL; cOsdObject *cMenuMain::pluginOsdObject = NULL;
cMenuMain::cMenuMain(bool Replaying, eOSState State) cMenuMain::cMenuMain(eOSState State)
:cOsdMenu("") :cOsdMenu("")
{ {
replaying = Replaying; lastDiskSpaceCheck = 0;
lastFreeMB = 0;
replaying = false;
stopReplayItem = NULL;
cancelEditingItem = NULL;
stopRecordingItem = NULL;
recordControlsState = 0;
Set(); Set();
// Initial submenus: // Initial submenus:
@ -2502,23 +2509,9 @@ cOsdObject *cMenuMain::PluginOsdObject(void)
void cMenuMain::Set(void) void cMenuMain::Set(void)
{ {
Clear(); Clear();
//XXX //SetTitle("VDR"); // this is done below, including disk usage SetTitle("VDR");
SetHasHotkeys(); SetHasHotkeys();
// Title with disk usage:
#define MB_PER_MINUTE 25.75 // this is just an estimate!
char buffer[40];
int FreeMB;
int Percent = VideoDiskSpace(&FreeMB);
int Minutes = int(double(FreeMB) / MB_PER_MINUTE);
int Hours = Minutes / 60;
Minutes %= 60;
snprintf(buffer, sizeof(buffer), "%s - %s %d%% - %2d:%02d %s", tr("VDR"), tr("Disk"), Percent, Hours, Minutes, tr("free"));
//XXX -> skin function!!!
SetTitle(buffer);
// Basic menu items: // Basic menu items:
Add(new cOsdItem(hk(tr("Schedule")), osSchedule)); Add(new cOsdItem(hk(tr("Schedule")), osSchedule));
@ -2545,11 +2538,6 @@ void cMenuMain::Set(void)
if (Commands.Count()) if (Commands.Count())
Add(new cOsdItem(hk(tr("Commands")), osCommands)); Add(new cOsdItem(hk(tr("Commands")), osCommands));
// Replay control:
if (replaying)
Add(new cOsdItem(tr(" Stop replaying"), osStopReplay));
// Record control: // Record control:
if (cRecordControls::StopPrimary()) { if (cRecordControls::StopPrimary()) {
@ -2559,23 +2547,82 @@ void cMenuMain::Set(void)
free(buffer); free(buffer);
} }
const char *s = NULL; Update(true);
while ((s = cRecordControls::GetInstantId(s)) != NULL) {
char *buffer = NULL; Display();
asprintf(&buffer, "%s%s", STOP_RECORDING, s); }
Add(new cOsdItem(buffer, osStopRecord));
free(buffer); #define MB_PER_MINUTE 25.75 // this is just an estimate!
bool cMenuMain::Update(bool Force)
{
bool result = false;
// Title with disk usage:
if (Force || time(NULL) - lastDiskSpaceCheck > DISKSPACECHEK) {
int FreeMB;
int Percent = VideoDiskSpace(&FreeMB);
if (Force || FreeMB != lastFreeMB) {
int Minutes = int(double(FreeMB) / MB_PER_MINUTE);
int Hours = Minutes / 60;
Minutes %= 60;
char buffer[40];
snprintf(buffer, sizeof(buffer), "%s - %s %d%% - %2d:%02d %s", tr("VDR"), tr("Disk"), Percent, Hours, Minutes, tr("free"));
//XXX -> skin function!!!
SetTitle(buffer);
result = true;
} }
lastDiskSpaceCheck = time(NULL);
}
bool NewReplaying = cControl::Control() != NULL;
if (Force || NewReplaying != replaying) {
replaying = NewReplaying;
// Replay control:
if (replaying && !stopReplayItem)
Add(stopReplayItem = new cOsdItem(tr(" Stop replaying"), osStopReplay));
else if (stopReplayItem && !replaying) {
Del(stopReplayItem->Index());
stopReplayItem = NULL;
}
// Color buttons:
SetHelp(!replaying ? tr("Record") : NULL, tr("Audio"), replaying ? NULL : tr("Pause"), replaying ? tr("Button$Stop") : cReplayControl::LastReplayed() ? tr("Resume") : NULL);
result = true;
}
// Editing control: // Editing control:
bool CutterActive = cCutter::Active();
if (CutterActive && !cancelEditingItem) {
Add(cancelEditingItem = new cOsdItem(tr(" Cancel editing"), osCancelEdit));
result = true;
}
else if (cancelEditingItem && !CutterActive) {
Del(cancelEditingItem->Index());
cancelEditingItem = NULL;
result = true;
}
if (cCutter::Active()) // Record control:
Add(new cOsdItem(tr(" Cancel editing"), osCancelEdit)); if (cRecordControls::StateChanged(recordControlsState)) {
while (stopRecordingItem) {
cOsdItem *it = Next(stopRecordingItem);
Del(stopRecordingItem->Index());
stopRecordingItem = it;
}
const char *s = NULL;
while ((s = cRecordControls::GetInstantId(s)) != NULL) {
char *buffer = NULL;
asprintf(&buffer, "%s%s", STOP_RECORDING, s);
cOsdItem *item = new cOsdItem(osStopRecord);
item->SetText(buffer, false);
Add(item);
if (!stopRecordingItem)
stopRecordingItem = item;
}
result = true;
}
// Color buttons: return result;
SetHelp(!replaying ? tr("Record") : NULL, tr("Audio"), replaying ? NULL : tr("Pause"), replaying ? tr("Button$Stop") : cReplayControl::LastReplayed() ? tr("Resume") : NULL);
Display();
} }
eOSState cMenuMain::ProcessKey(eKeys Key) eOSState cMenuMain::ProcessKey(eKeys Key)
@ -2647,6 +2694,8 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
default: break; default: break;
} }
} }
if (!HasSubMenu() && Update())
Display();
if (Key != kNone) { if (Key != kNone) {
if (Setup.OSDLanguage != osdLanguage) { if (Setup.OSDLanguage != osdLanguage) {
Set(); Set();
@ -3222,9 +3271,11 @@ bool cRecordControl::Process(time_t t)
// --- cRecordControls ------------------------------------------------------- // --- cRecordControls -------------------------------------------------------
cRecordControl *cRecordControls::RecordControls[MAXRECORDCONTROLS] = { NULL }; cRecordControl *cRecordControls::RecordControls[MAXRECORDCONTROLS] = { NULL };
int cRecordControls::state = 0;
bool cRecordControls::Start(cTimer *Timer, bool Pause) bool cRecordControls::Start(cTimer *Timer, bool Pause)
{ {
ChangeState();
int ch = Timer ? Timer->Channel()->Number() : cDevice::CurrentChannel(); int ch = Timer ? Timer->Channel()->Number() : cDevice::CurrentChannel();
cChannel *channel = Channels.GetByNumber(ch); cChannel *channel = Channels.GetByNumber(ch);
@ -3262,6 +3313,7 @@ bool cRecordControls::Start(cTimer *Timer, bool Pause)
void cRecordControls::Stop(const char *InstantId) void cRecordControls::Stop(const char *InstantId)
{ {
ChangeState();
for (int i = 0; i < MAXRECORDCONTROLS; i++) { for (int i = 0; i < MAXRECORDCONTROLS; i++) {
if (RecordControls[i]) { if (RecordControls[i]) {
const char *id = RecordControls[i]->InstantId(); const char *id = RecordControls[i]->InstantId();
@ -3281,6 +3333,7 @@ void cRecordControls::Stop(const char *InstantId)
void cRecordControls::Stop(cDevice *Device) void cRecordControls::Stop(cDevice *Device)
{ {
ChangeState();
for (int i = 0; i < MAXRECORDCONTROLS; i++) { for (int i = 0; i < MAXRECORDCONTROLS; i++) {
if (RecordControls[i]) { if (RecordControls[i]) {
if (RecordControls[i]->Device() == Device) { if (RecordControls[i]->Device() == Device) {
@ -3349,8 +3402,10 @@ void cRecordControls::Process(time_t t)
{ {
for (int i = 0; i < MAXRECORDCONTROLS; i++) { for (int i = 0; i < MAXRECORDCONTROLS; i++) {
if (RecordControls[i]) { if (RecordControls[i]) {
if (!RecordControls[i]->Process(t)) if (!RecordControls[i]->Process(t)) {
DELETENULL(RecordControls[i]); DELETENULL(RecordControls[i]);
ChangeState();
}
} }
} }
} }
@ -3365,6 +3420,7 @@ void cRecordControls::ChannelDataModified(cChannel *Channel)
RecordControls[i]->Stop(); RecordControls[i]->Stop();
// This will restart the recording, maybe even from a different // This will restart the recording, maybe even from a different
// device in case conditional access has changed. // device in case conditional access has changed.
ChangeState();
} }
} }
} }
@ -3384,6 +3440,15 @@ void cRecordControls::Shutdown(void)
{ {
for (int i = 0; i < MAXRECORDCONTROLS; i++) for (int i = 0; i < MAXRECORDCONTROLS; i++)
DELETENULL(RecordControls[i]); DELETENULL(RecordControls[i]);
ChangeState();
}
bool cRecordControls::StateChanged(int &State)
{
int NewState = state;
bool Result = State != NewState;
State = state;
return Result;
} }
// --- cReplayControl -------------------------------------------------------- // --- cReplayControl --------------------------------------------------------

14
menu.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.h 1.77 2005/11/05 17:26:09 kls Exp $ * $Id: menu.h 1.78 2005/12/24 15:44:56 kls Exp $
*/ */
#ifndef __MENU_H #ifndef __MENU_H
@ -55,11 +55,18 @@ public:
class cMenuMain : public cOsdMenu { class cMenuMain : public cOsdMenu {
private: private:
time_t lastDiskSpaceCheck;
int lastFreeMB;
bool replaying; bool replaying;
cOsdItem *stopReplayItem;
cOsdItem *cancelEditingItem;
cOsdItem *stopRecordingItem;
int recordControlsState;
static cOsdObject *pluginOsdObject; static cOsdObject *pluginOsdObject;
void Set(void); void Set(void);
bool Update(bool Force = false);
public: public:
cMenuMain(bool Replaying, eOSState State = osUnknown); cMenuMain(eOSState State = osUnknown);
virtual eOSState ProcessKey(eKeys Key); virtual eOSState ProcessKey(eKeys Key);
static cOsdObject *PluginOsdObject(void); static cOsdObject *PluginOsdObject(void);
}; };
@ -189,6 +196,7 @@ public:
class cRecordControls { class cRecordControls {
private: private:
static cRecordControl *RecordControls[]; static cRecordControl *RecordControls[];
static int state;
public: public:
static bool Start(cTimer *Timer = NULL, bool Pause = false); static bool Start(cTimer *Timer = NULL, bool Pause = false);
static void Stop(const char *InstantId); static void Stop(const char *InstantId);
@ -201,6 +209,8 @@ public:
static void ChannelDataModified(cChannel *Channel); static void ChannelDataModified(cChannel *Channel);
static bool Active(void); static bool Active(void);
static void Shutdown(void); static void Shutdown(void);
static void ChangeState(void) { state++; }
static bool StateChanged(int &State);
}; };
class cReplayControl : public cDvbPlayerControl { class cReplayControl : public cDvbPlayerControl {

8
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.cadsoft.de/vdr * The project's page is at http://www.cadsoft.de/vdr
* *
* $Id: vdr.c 1.221 2005/12/18 10:33:37 kls Exp $ * $Id: vdr.c 1.222 2005/12/18 14:38:30 kls Exp $
*/ */
#include <getopt.h> #include <getopt.h>
@ -702,14 +702,14 @@ int main(int argc, char *argv[])
} }
if (cControl::Control()) if (cControl::Control())
cControl::Control()->Hide(); cControl::Control()->Hide();
Menu = new cMenuMain(cControl::Control()); Menu = new cMenuMain;
Temp = NULL; Temp = NULL;
break; break;
#define DirectMainFunction(function)\ #define DirectMainFunction(function)\
DELETENULL(Menu);\ DELETENULL(Menu);\
if (cControl::Control())\ if (cControl::Control())\
cControl::Control()->Hide();\ cControl::Control()->Hide();\
Menu = new cMenuMain(cControl::Control(), function);\ Menu = new cMenuMain(function);\
Temp = NULL;\ Temp = NULL;\
key = kNone; // nobody else needs to see this key key = kNone; // nobody else needs to see this key
case kSchedule: DirectMainFunction(osSchedule); break; case kSchedule: DirectMainFunction(osSchedule); break;
@ -848,7 +848,7 @@ int main(int argc, char *argv[])
DELETENULL(Menu); DELETENULL(Menu);
cControl::Shutdown(); cControl::Shutdown();
Temp = NULL; Temp = NULL;
Menu = new cMenuMain(false, osRecordings); Menu = new cMenuMain(osRecordings);
break; break;
case osReplay: DELETENULL(Menu); case osReplay: DELETENULL(Menu);
cControl::Shutdown(); cControl::Shutdown();