mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Menu uses colors; support for RGYB buttons; fixed DEBUG_REMOTE; Add, Del and Move for channels and timers; basic record/play file handling
This commit is contained in:
parent
4a9d9c5876
commit
571686d909
12
HISTORY
Normal file
12
HISTORY
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
Video Disk Recorder OSM Revision History
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
2000-02-19: Version 0.01 (Initial revision).
|
||||||
|
|
||||||
|
2000-03-11: Version 0.02
|
||||||
|
|
||||||
|
- Fixed compilation with only DEBUG_REMOTE=1.
|
||||||
|
- Menus now use colors.
|
||||||
|
- Support for "Red", "Green", "Yellow", "Blue" buttons.
|
||||||
|
- Channels and Timers can now be added, deleted and moved.
|
||||||
|
- Basic record/play file handling support (no actual record/playback yet).
|
11
Makefile
11
Makefile
@ -4,9 +4,9 @@
|
|||||||
# See the main source file 'osm.c' for copyright information and
|
# See the main source file 'osm.c' for copyright information and
|
||||||
# how to reach the author.
|
# how to reach the author.
|
||||||
#
|
#
|
||||||
# $Id: Makefile 1.1 2000/02/19 13:36:48 kls Exp $
|
# $Id: Makefile 1.2 2000/03/05 13:51:57 kls Exp $
|
||||||
|
|
||||||
OBJS = config.o dvbapi.o interface.o menu.o osd.o remote.o tools.o osm.o
|
OBJS = config.o dvbapi.o interface.o menu.o osd.o recording.o remote.o tools.o osm.o
|
||||||
|
|
||||||
ifdef DEBUG_REMOTE
|
ifdef DEBUG_REMOTE
|
||||||
DEFINES += -DDEBUG_REMOTE
|
DEFINES += -DDEBUG_REMOTE
|
||||||
@ -24,9 +24,10 @@ all: osm
|
|||||||
config.o : config.c config.h dvbapi.h interface.h tools.h
|
config.o : config.c config.h dvbapi.h interface.h tools.h
|
||||||
dvbapi.o : dvbapi.c config.h dvbapi.h interface.h tools.h
|
dvbapi.o : dvbapi.c config.h dvbapi.h interface.h tools.h
|
||||||
interface.o: interface.c config.h dvbapi.h interface.h remote.h tools.h
|
interface.o: interface.c config.h dvbapi.h interface.h remote.h tools.h
|
||||||
menu.o : menu.c config.h dvbapi.h interface.h menu.h osd.h tools.h
|
menu.o : menu.c config.h dvbapi.h interface.h menu.h osd.h recording.h tools.h
|
||||||
osd.o : osd.c config.h interface.h osd.h tools.h
|
osd.o : osd.c config.h dvbapi.h interface.h osd.h tools.h
|
||||||
osm.o : osm.c config.h dvbapi.h interface.h menu.h osd.h tools.h
|
osm.o : osm.c config.h dvbapi.h interface.h menu.h osd.h recording.h tools.h
|
||||||
|
recording.o: recording.c config.h dvbapi.h interface.h recording.h tools.h
|
||||||
remote.o : remote.c remote.h tools.h
|
remote.o : remote.c remote.h tools.h
|
||||||
tools.o : tools.c tools.h
|
tools.o : tools.c tools.h
|
||||||
|
|
||||||
|
36
README
36
README
@ -36,10 +36,34 @@ about that driver). For example, if the DVB driver was
|
|||||||
extracted into the directory /home/kls/vdr/DVB, then this
|
extracted into the directory /home/kls/vdr/DVB, then this
|
||||||
package should be extracted into /home/kls/vdr/OSM.
|
package should be extracted into /home/kls/vdr/OSM.
|
||||||
|
|
||||||
|
In order for the menu colors to work correctly you may want
|
||||||
|
to replace the function RGB2YUV() in DVB/driver/dvb.c with
|
||||||
|
|
||||||
|
static u32 RGB2YUV(u16 R, u16 G, u16 B)
|
||||||
|
{
|
||||||
|
u16 y, u, v;
|
||||||
|
u16 Y, Cr, Cb;
|
||||||
|
|
||||||
|
y = R * 77 + G * 150 + B * 29; // Luma=0.299R+0.587G+0.114B 0..65535
|
||||||
|
u = 2048+B * 8 -(y>>5); // Cr 0..4095
|
||||||
|
v = 2048+R * 8 -(y>>5); // Cb 0..4095
|
||||||
|
|
||||||
|
Y = y >> 8;
|
||||||
|
Cb= u >> 4;
|
||||||
|
Cr= v >> 4;
|
||||||
|
|
||||||
|
return Cr|(Cb<<16)|(Y<<8);
|
||||||
|
}
|
||||||
|
|
||||||
|
(this may no longer be necessary with driver versions after 0.03c).
|
||||||
|
|
||||||
After extracting the package, change into the OSM directory
|
After extracting the package, change into the OSM directory
|
||||||
and type 'make'. This should produce an executable file
|
and type 'make'. This should produce an executable file
|
||||||
named 'osm', which can be run after the DVB driver has been
|
named 'osm', which can be run after the DVB driver has been
|
||||||
installed.
|
installed. There may be several warnings about "implicit declaration
|
||||||
|
of function `int asprintf(...)'" during the compilation, which I was
|
||||||
|
unable to avoid (anybody know how to avoid them?). Just ignore them,
|
||||||
|
the program will work, anyway.
|
||||||
|
|
||||||
There are two macros you can use to customize the 'osm' program
|
There are two macros you can use to customize the 'osm' program
|
||||||
at compile time. Adding "DEBUG_REMOTE=1" to the 'make' call
|
at compile time. Adding "DEBUG_REMOTE=1" to the 'make' call
|
||||||
@ -75,10 +99,10 @@ this package contains the codes for the "d-box" remote control unit.
|
|||||||
If you want to use a different remote control unit, simply delete
|
If you want to use a different remote control unit, simply delete
|
||||||
the file 'keys.conf' and restart the 'osm' program. The program will
|
the file 'keys.conf' and restart the 'osm' program. The program will
|
||||||
then start a key learning session in which it first attempts to determine
|
then start a key learning session in which it first attempts to determine
|
||||||
the basic data tranfer mode and timing of your remote control unit,
|
the basic data transfer mode and timing of your remote control unit,
|
||||||
and then will ask you to press one key after the other so that it can
|
and then will ask you to press one key after the other so that it can
|
||||||
learn the various key codes. You will at least need to provide an "Up"
|
learn the various key codes. You will at least need to provide an "Up"
|
||||||
and a "Down" key, so that you can switch channels. The rest os the key
|
and a "Down" key, so that you can switch channels. The rest of the key
|
||||||
definitions is optional, but the more keys you define, the more you
|
definitions is optional, but the more keys you define, the more you
|
||||||
will be able to navigate through the menus.
|
will be able to navigate through the menus.
|
||||||
|
|
||||||
@ -97,9 +121,6 @@ confirms any changes (or switches to a channel in the "Channels" menu).
|
|||||||
The "Back" key goes back one level in the menu structure, discarding
|
The "Back" key goes back one level in the menu structure, discarding
|
||||||
any changes that might have been made in the current menu.
|
any changes that might have been made in the current menu.
|
||||||
|
|
||||||
In the "Channels" menu, the current channel can be edited by pressing
|
|
||||||
the "Right" key.
|
|
||||||
|
|
||||||
In the "Timers" menu, the current timer can be enabled or disabled with
|
In the "Timers" menu, the current timer can be enabled or disabled with
|
||||||
the "Right" or "Left" key, respectively (enabled timers are marked with ">").
|
the "Right" or "Left" key, respectively (enabled timers are marked with ">").
|
||||||
"Ok" here opens the "Edit timer" menu.
|
"Ok" here opens the "Edit timer" menu.
|
||||||
@ -110,6 +131,9 @@ character as in "[R]TL"), selecting the desired character position with
|
|||||||
"Left" and "Right", and changing the character with the "Up" and "Down"
|
"Left" and "Right", and changing the character with the "Up" and "Down"
|
||||||
keys. "Ok" then confirms the changes.
|
keys. "Ok" then confirms the changes.
|
||||||
|
|
||||||
|
The "Red", "Green", "Yellow" and "Blue" buttons have special meanings
|
||||||
|
in the various menus and are listed at the bottom of the on-screen-display.
|
||||||
|
|
||||||
At any point in the menu system, pressing the "Menu" key again will
|
At any point in the menu system, pressing the "Menu" key again will
|
||||||
immediately leave the menu system.
|
immediately leave the menu system.
|
||||||
|
|
||||||
|
5
TODO
5
TODO
@ -1,13 +1,12 @@
|
|||||||
TODO list for the Video Disk Recorder project
|
TODO list for the Video Disk Recorder project
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
* Implement a way to add and delete channels and timers.
|
|
||||||
* Implement recording to disk and playback from disk.
|
* Implement recording to disk and playback from disk.
|
||||||
* Implement disk file management (delete old/viewed files to make
|
|
||||||
room for new recordings if necessary).
|
|
||||||
* Make it work with two DVB-S PCI cards to allow simultaneous
|
* Make it work with two DVB-S PCI cards to allow simultaneous
|
||||||
recording of one programme, while replaying another programme
|
recording of one programme, while replaying another programme
|
||||||
(or maybe the same one, but time delayed).
|
(or maybe the same one, but time delayed).
|
||||||
|
Maybe we can do this with only a single card, if the card
|
||||||
|
driver/firmware allows simultaneuos record/playback?
|
||||||
* Implement "on-disk editing" to allow "cutting out" of certain
|
* Implement "on-disk editing" to allow "cutting out" of certain
|
||||||
scenes in order to archive them (or, reversely, cut out
|
scenes in order to archive them (or, reversely, cut out
|
||||||
commercial breaks).
|
commercial breaks).
|
||||||
|
@ -42,7 +42,7 @@ B1:12722:h:1:22000:601:602
|
|||||||
ARD Online-Kanal:12722:h:1:22000:8191:701
|
ARD Online-Kanal:12722:h:1:22000:8191:701
|
||||||
Premiere World Promo:11798:h:1:27500:255:256
|
Premiere World Promo:11798:h:1:27500:255:256
|
||||||
TV Niepokalanow:11876:h:1:27500:305:321
|
TV Niepokalanow:11876:h:1:27500:305:321
|
||||||
test card:11876:h:1:27500:306:322
|
test card:11798:h:1:27500:511:512
|
||||||
Mosaico:11934:v:1:27500:165:100
|
Mosaico:11934:v:1:27500:165:100
|
||||||
Andalucia TV:11934:v:1:27500:166:104
|
Andalucia TV:11934:v:1:27500:166:104
|
||||||
TVC Internacional:11934:v:1:27500:167:108
|
TVC Internacional:11934:v:1:27500:167:108
|
||||||
|
118
config.c
118
config.c
@ -4,37 +4,40 @@
|
|||||||
* See the main source file 'osm.c' for copyright information and
|
* See the main source file 'osm.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: config.c 1.1 2000/02/19 13:36:48 kls Exp $
|
* $Id: config.c 1.2 2000/03/05 16:14:27 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
|
||||||
#include "dvbapi.h"
|
#include "dvbapi.h"
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
|
|
||||||
// -- cKeys ------------------------------------------------------------------
|
// -- cKeys ------------------------------------------------------------------
|
||||||
|
|
||||||
tKey keyTable[] = { // "Up" and "Down" must be the first two keys!
|
tKey keyTable[] = { // "Up" and "Down" must be the first two keys!
|
||||||
{ kUp, "Up", 0 },
|
{ kUp, "Up", 0 },
|
||||||
{ kDown, "Down", 0 },
|
{ kDown, "Down", 0 },
|
||||||
{ kMenu, "Menu", 0 },
|
{ kMenu, "Menu", 0 },
|
||||||
{ kOk, "Ok", 0 },
|
{ kOk, "Ok", 0 },
|
||||||
{ kBack, "Back", 0 },
|
{ kBack, "Back", 0 },
|
||||||
{ kLeft, "Left", 0 },
|
{ kLeft, "Left", 0 },
|
||||||
{ kRight, "Right", 0 },
|
{ kRight, "Right", 0 },
|
||||||
{ k0, "0", 0 },
|
{ k0, "0", 0 },
|
||||||
{ k1, "1", 0 },
|
{ k1, "1", 0 },
|
||||||
{ k2, "2", 0 },
|
{ k2, "2", 0 },
|
||||||
{ k3, "3", 0 },
|
{ k3, "3", 0 },
|
||||||
{ k4, "4", 0 },
|
{ k4, "4", 0 },
|
||||||
{ k5, "5", 0 },
|
{ k5, "5", 0 },
|
||||||
{ k6, "6", 0 },
|
{ k6, "6", 0 },
|
||||||
{ k7, "7", 0 },
|
{ k7, "7", 0 },
|
||||||
{ k8, "8", 0 },
|
{ k8, "8", 0 },
|
||||||
{ k9, "9", 0 },
|
{ k9, "9", 0 },
|
||||||
{ kNone, "", 0 },
|
{ kRed, "Red", 0 },
|
||||||
|
{ kGreen, "Green", 0 },
|
||||||
|
{ kYellow, "Yellow", 0 },
|
||||||
|
{ kBlue, "Blue", 0 },
|
||||||
|
{ kNone, "", 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
cKeys::cKeys(void)
|
cKeys::cKeys(void)
|
||||||
@ -160,6 +163,17 @@ cChannel::cChannel(void)
|
|||||||
*name = 0;
|
*name = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cChannel::cChannel(const cChannel *Channel)
|
||||||
|
{
|
||||||
|
strcpy(name, Channel ? Channel->name : "Pro7");
|
||||||
|
frequency = Channel ? Channel->frequency : 12480;
|
||||||
|
polarization = Channel ? Channel->polarization : 'v';
|
||||||
|
diseqc = Channel ? Channel->diseqc : 1;
|
||||||
|
srate = Channel ? Channel->srate : 27500;
|
||||||
|
vpid = Channel ? Channel->vpid : 255;
|
||||||
|
apid = Channel ? Channel->apid : 256;
|
||||||
|
}
|
||||||
|
|
||||||
bool cChannel::Parse(char *s)
|
bool cChannel::Parse(char *s)
|
||||||
{
|
{
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
@ -203,6 +217,17 @@ bool cChannel::SwitchTo(int i)
|
|||||||
|
|
||||||
cTimer::cTimer(void)
|
cTimer::cTimer(void)
|
||||||
{
|
{
|
||||||
|
startTime = stopTime = 0;
|
||||||
|
recording = false;
|
||||||
|
active = 1;
|
||||||
|
channel = CurrentChannel + 1;
|
||||||
|
day = 1; //XXX today!
|
||||||
|
start = 0; //XXX now!
|
||||||
|
stop = 0; //XXX now + 2h!
|
||||||
|
//TODO VPS???
|
||||||
|
quality = 'H';
|
||||||
|
priority = 99;
|
||||||
|
lifetime = 99;
|
||||||
*file = 0;
|
*file = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,6 +236,13 @@ int cTimer::TimeToInt(int t)
|
|||||||
return (t / 100 * 60 + t % 100) * 60;
|
return (t / 100 * 60 + t % 100) * 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t cTimer::Day(time_t t)
|
||||||
|
{
|
||||||
|
struct tm d = *localtime(&t);
|
||||||
|
d.tm_hour = d.tm_min = d.tm_sec = 0;
|
||||||
|
return mktime(&d);
|
||||||
|
}
|
||||||
|
|
||||||
int cTimer::ParseDay(char *s)
|
int cTimer::ParseDay(char *s)
|
||||||
{
|
{
|
||||||
char *tail;
|
char *tail;
|
||||||
@ -270,13 +302,17 @@ bool cTimer::Save(FILE *f)
|
|||||||
return fprintf(f, "%d:%d:%s:%d:%d:%c:%d:%d:%s\n", active, channel, PrintDay(day), start, stop, quality, priority, lifetime, file) > 0;
|
return fprintf(f, "%d:%d:%s:%d:%d:%c:%d:%d:%s\n", active, channel, PrintDay(day), start, stop, quality, priority, lifetime, file) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cTimer::IsSingleEvent(void)
|
||||||
|
{
|
||||||
|
return (day & 0x80000000) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool cTimer::Matches(void)
|
bool cTimer::Matches(void)
|
||||||
{
|
{
|
||||||
if (active) {
|
if (active) {
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
struct tm *now = localtime(&t);
|
struct tm now = *localtime(&t);
|
||||||
int weekday = now->tm_wday == 0 ? 6 : now->tm_wday - 1; // we start with monday==0!
|
int weekday = now.tm_wday == 0 ? 6 : now.tm_wday - 1; // we start with monday==0!
|
||||||
int current = (now->tm_hour * 60 + now->tm_min) * 60 + now->tm_sec;
|
|
||||||
int begin = TimeToInt(start);
|
int begin = TimeToInt(start);
|
||||||
int end = TimeToInt(stop);
|
int end = TimeToInt(stop);
|
||||||
bool twoDays = (end < begin);
|
bool twoDays = (end < begin);
|
||||||
@ -291,20 +327,44 @@ bool cTimer::Matches(void)
|
|||||||
yesterdayMatches = true;
|
yesterdayMatches = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (day == now->tm_mday)
|
else if (day == now.tm_mday)
|
||||||
todayMatches = true;
|
todayMatches = true;
|
||||||
else if (twoDays) {
|
else if (twoDays) {
|
||||||
t -= 86400;
|
time_t ty = t - SECSINDAY;
|
||||||
now = localtime(&t);
|
if (day == localtime(&ty)->tm_mday)
|
||||||
if (day == now->tm_mday)
|
|
||||||
yesterdayMatches = true;
|
yesterdayMatches = true;
|
||||||
}
|
}
|
||||||
return (todayMatches && current >= begin && (current <= end || twoDays))
|
if (todayMatches || (twoDays && yesterdayMatches)) {
|
||||||
|| (twoDays && yesterdayMatches && current <= end);
|
startTime = Day(t - (yesterdayMatches ? SECSINDAY : 0)) + begin;
|
||||||
|
stopTime = startTime + (twoDays ? SECSINDAY - begin + end : end - begin);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
startTime = stopTime = 0;
|
||||||
|
return startTime <= t && t <= stopTime;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t cTimer::StartTime(void)
|
||||||
|
{
|
||||||
|
if (!startTime)
|
||||||
|
Matches();
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t cTimer::StopTime(void)
|
||||||
|
{
|
||||||
|
if (!stopTime)
|
||||||
|
Matches();
|
||||||
|
return stopTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cTimer::SetRecording(bool Recording)
|
||||||
|
{
|
||||||
|
recording = Recording;
|
||||||
|
isyslog(LOG_INFO, "timer %d %s", Index() + 1, recording ? "start" : "stop");
|
||||||
|
}
|
||||||
|
|
||||||
cTimer *cTimer::GetMatch(void)
|
cTimer *cTimer::GetMatch(void)
|
||||||
{
|
{
|
||||||
cTimer *t = (cTimer *)Timers.First();
|
cTimer *t = (cTimer *)Timers.First();
|
||||||
|
16
config.h
16
config.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'osm.c' for copyright information and
|
* See the main source file 'osm.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: config.h 1.1 2000/02/19 13:36:48 kls Exp $
|
* $Id: config.h 1.2 2000/03/05 14:58:23 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __CONFIG_H
|
#ifndef __CONFIG_H
|
||||||
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
#define MaxBuffer 1000
|
#define MaxBuffer 1000
|
||||||
@ -25,6 +26,10 @@ enum eKeys { // "Up" and "Down" must be the first two keys!
|
|||||||
kLeft,
|
kLeft,
|
||||||
kRight,
|
kRight,
|
||||||
k0, k1, k2, k3, k4, k5, k6, k7, k8, k9,
|
k0, k1, k2, k3, k4, k5, k6, k7, k8, k9,
|
||||||
|
kRed,
|
||||||
|
kGreen,
|
||||||
|
kYellow,
|
||||||
|
kBlue,
|
||||||
kNone
|
kNone
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -60,6 +65,7 @@ public:
|
|||||||
int vpid;
|
int vpid;
|
||||||
int apid;
|
int apid;
|
||||||
cChannel(void);
|
cChannel(void);
|
||||||
|
cChannel(const cChannel *Channel);
|
||||||
bool Parse(char *s);
|
bool Parse(char *s);
|
||||||
bool Save(FILE *f);
|
bool Save(FILE *f);
|
||||||
bool Switch(void);
|
bool Switch(void);
|
||||||
@ -67,8 +73,11 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class cTimer : public cListObject {
|
class cTimer : public cListObject {
|
||||||
|
private:
|
||||||
|
time_t startTime, stopTime;
|
||||||
public:
|
public:
|
||||||
enum { MaxFileName = 256 };
|
enum { MaxFileName = 256 };
|
||||||
|
bool recording;
|
||||||
int active;
|
int active;
|
||||||
int channel;
|
int channel;
|
||||||
int day;
|
int day;
|
||||||
@ -82,9 +91,14 @@ public:
|
|||||||
cTimer(void);
|
cTimer(void);
|
||||||
bool Parse(char *s);
|
bool Parse(char *s);
|
||||||
bool Save(FILE *f);
|
bool Save(FILE *f);
|
||||||
|
bool IsSingleEvent(void);
|
||||||
bool Matches(void);
|
bool Matches(void);
|
||||||
|
time_t StartTime(void);
|
||||||
|
time_t StopTime(void);
|
||||||
|
void SetRecording(bool Recording);
|
||||||
static cTimer *GetMatch(void);
|
static cTimer *GetMatch(void);
|
||||||
static int TimeToInt(int t);
|
static int TimeToInt(int t);
|
||||||
|
static time_t Day(time_t t);
|
||||||
static int ParseDay(char *s);
|
static int ParseDay(char *s);
|
||||||
static char *PrintDay(int d);
|
static char *PrintDay(int d);
|
||||||
};
|
};
|
||||||
|
168
dvbapi.c
168
dvbapi.c
@ -4,20 +4,14 @@
|
|||||||
* See the main source file 'osm.c' for copyright information and
|
* See the main source file 'osm.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: dvbapi.c 1.1 2000/02/19 13:36:48 kls Exp $
|
* $Id: dvbapi.c 1.2 2000/03/11 10:39:09 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// FIXME: these should be defined in ../DVB/driver/dvb.h!!!
|
|
||||||
typedef unsigned int u32;
|
|
||||||
typedef unsigned short u16;
|
|
||||||
typedef unsigned char u8;
|
|
||||||
|
|
||||||
#include "dvbapi.h"
|
#include "dvbapi.h"
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "../DVB/driver/dvb.h"
|
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
@ -60,6 +54,7 @@ bool DvbSetChannel(int FrequencyMHz, char Polarization, int Diseqc, int Srate, i
|
|||||||
|
|
||||||
cDvbRecorder::cDvbRecorder(void)
|
cDvbRecorder::cDvbRecorder(void)
|
||||||
{
|
{
|
||||||
|
recording = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cDvbRecorder::~cDvbRecorder()
|
cDvbRecorder::~cDvbRecorder()
|
||||||
@ -67,18 +62,41 @@ cDvbRecorder::~cDvbRecorder()
|
|||||||
Stop();
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cDvbRecorder::Recording(void)
|
||||||
|
{
|
||||||
|
return recording;
|
||||||
|
}
|
||||||
|
|
||||||
bool cDvbRecorder::Record(const char *FileName, char Quality)
|
bool cDvbRecorder::Record(const char *FileName, char Quality)
|
||||||
{
|
{
|
||||||
isyslog(LOG_INFO, "record %s (%c)", FileName, Quality);
|
isyslog(LOG_INFO, "record %s (%c)", FileName, Quality);
|
||||||
return true;
|
if (MakeDirs(FileName)) {
|
||||||
|
FILE *f = fopen(FileName, "a");
|
||||||
|
if (f) {
|
||||||
|
fprintf(f, "%s, %c\n", FileName, Quality);
|
||||||
|
fclose(f);
|
||||||
|
recording = true;
|
||||||
|
// TODO
|
||||||
|
Interface.Error("Recording not yet implemented!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Interface.Error("Can't write to file!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
// TODO
|
// TODO
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cDvbRecorder::Play(const char *FileName, int Frame)
|
bool cDvbRecorder::Play(const char *FileName, int Frame)
|
||||||
{
|
{
|
||||||
isyslog(LOG_INFO, "play %s (%d)", FileName, Frame);
|
if (!recording) {
|
||||||
// TODO
|
isyslog(LOG_INFO, "play %s (%d)", FileName, Frame);
|
||||||
|
// TODO
|
||||||
|
Interface.Error("Playback not yet implemented!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,6 +124,7 @@ bool cDvbRecorder::Pause(void)
|
|||||||
void cDvbRecorder::Stop(void)
|
void cDvbRecorder::Stop(void)
|
||||||
{
|
{
|
||||||
isyslog(LOG_INFO, "stop");
|
isyslog(LOG_INFO, "stop");
|
||||||
|
recording = false;
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,9 +135,57 @@ int cDvbRecorder::Frame(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// --- cDvbOsd ---------------------------------------------------------------
|
||||||
|
|
||||||
static void DvbOsdCmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, void *data = NULL)
|
cDvbOsd::cDvbOsd(void)
|
||||||
|
{
|
||||||
|
cols = rows = 0;
|
||||||
|
#ifdef DEBUG_OSD
|
||||||
|
memset(&colorPairs, 0, sizeof(colorPairs));
|
||||||
|
initscr();
|
||||||
|
start_color();
|
||||||
|
keypad(stdscr, TRUE);
|
||||||
|
nonl();
|
||||||
|
cbreak();
|
||||||
|
noecho();
|
||||||
|
timeout(1000);
|
||||||
|
leaveok(stdscr, TRUE);
|
||||||
|
window = stdscr;
|
||||||
|
#endif
|
||||||
|
#ifdef DEBUG_REMOTE
|
||||||
|
initscr();
|
||||||
|
keypad(stdscr, TRUE);
|
||||||
|
nonl();
|
||||||
|
cbreak();
|
||||||
|
noecho();
|
||||||
|
timeout(1000);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
cDvbOsd::~cDvbOsd()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_OSD
|
||||||
|
void cDvbOsd::SetColor(eDvbColor colorFg, eDvbColor colorBg)
|
||||||
|
{
|
||||||
|
int color = (colorBg << 16) | colorFg | 0x80000000;
|
||||||
|
for (int i = 0; i < MaxColorPairs; i++) {
|
||||||
|
if (!colorPairs[i]) {
|
||||||
|
colorPairs[i] = color;
|
||||||
|
init_pair(i + 1, colorFg, colorBg);
|
||||||
|
wattrset(window, COLOR_PAIR(i + 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (color == colorPairs[i]) {
|
||||||
|
wattrset(window, COLOR_PAIR(i + 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, const void *data)
|
||||||
{
|
{
|
||||||
int v = open(VIDEODEVICE, O_RDWR);
|
int v = open(VIDEODEVICE, O_RDWR);
|
||||||
|
|
||||||
@ -130,37 +197,88 @@ static void DvbOsdCmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, in
|
|||||||
dc.y0 = y0;
|
dc.y0 = y0;
|
||||||
dc.x1 = x1;
|
dc.x1 = x1;
|
||||||
dc.y1 = y1;
|
dc.y1 = y1;
|
||||||
dc.data = data;
|
dc.data = (void *)data;
|
||||||
ioctl(v, VIDIOCSOSDCOMMAND, &dc);
|
ioctl(v, VIDIOCSOSDCOMMAND, &dc);
|
||||||
close(v);
|
close(v);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Interface.Error("can't open VIDEODEVICE");//XXX
|
Interface.Error("can't open VIDEODEVICE");//XXX
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void DvbOsdOpen(int x, int y, int w, int h)
|
void cDvbOsd::Open(int w, int h)
|
||||||
{
|
{
|
||||||
DvbOsdCmd(OSD_Open, 1, x, y, x + w - 1, y + h - 1);
|
cols = w;
|
||||||
DvbOsdCmd(OSD_SetColor, 0, 0, 0, 0, 127); // background 50% gray
|
rows = h;
|
||||||
DvbOsdCmd(OSD_SetColor, 1, 255, 255, 255, 255); // text white
|
#ifdef DEBUG_OSD
|
||||||
|
//XXX size...
|
||||||
|
#define B2C(b) (((b) * 1000) / 255)
|
||||||
|
#define SETCOLOR(n, r, g, b, o) init_color(n, B2C(r), B2C(g), B2C(b))
|
||||||
|
#else
|
||||||
|
w *= charWidth;
|
||||||
|
h *= lineHeight;
|
||||||
|
int x = (720 - w) / 2; //TODO PAL vs. NTSC???
|
||||||
|
int y = (576 - h) / 2;
|
||||||
|
Cmd(OSD_Open, 4, x, y, x + w - 1, y + h - 1);
|
||||||
|
#define SETCOLOR(n, r, g, b, o) Cmd(OSD_SetColor, n, r, g, b, o)
|
||||||
|
#endif
|
||||||
|
SETCOLOR(clrBackground, 0x00, 0x00, 0x00, 127); // background 50% gray
|
||||||
|
SETCOLOR(clrBlack, 0x00, 0x00, 0x00, 255);
|
||||||
|
SETCOLOR(clrRed, 0xFC, 0x14, 0x14, 255);
|
||||||
|
SETCOLOR(clrGreen, 0x24, 0xFC, 0x24, 255);
|
||||||
|
SETCOLOR(clrYellow, 0xFC, 0xC0, 0x24, 255);
|
||||||
|
SETCOLOR(clrBlue, 0x00, 0x00, 0xFC, 255);
|
||||||
|
SETCOLOR(clrCyan, 0x00, 0xFC, 0xFC, 255);
|
||||||
|
SETCOLOR(clrMagenta, 0xB0, 0x00, 0xFC, 255);
|
||||||
|
SETCOLOR(clrWhite, 0xFC, 0xFC, 0xFC, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DvbOsdClose(void)
|
void cDvbOsd::Close(void)
|
||||||
{
|
{
|
||||||
DvbOsdCmd(OSD_Close);
|
#ifndef DEBUG_OSD
|
||||||
|
Cmd(OSD_Close);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void DvbOsdClear(void)
|
void cDvbOsd::Clear(void)
|
||||||
{
|
{
|
||||||
DvbOsdCmd(OSD_Clear);
|
#ifdef DEBUG_OSD
|
||||||
|
SetColor(clrBackground, clrBackground);
|
||||||
|
Fill(0, 0, cols, rows, clrBackground);
|
||||||
|
#else
|
||||||
|
Cmd(OSD_Clear);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void DvbOsdClrEol(int x, int y)
|
void cDvbOsd::Fill(int x, int y, int w, int h, eDvbColor color)
|
||||||
{
|
{
|
||||||
DvbOsdCmd(OSD_FillBlock, 0, x, y * DvbOsdLineHeight, x + 490, (y + 1) * DvbOsdLineHeight);//XXX
|
if (x < 0) x = cols + x;
|
||||||
|
if (y < 0) y = rows + y;
|
||||||
|
#ifdef DEBUG_OSD
|
||||||
|
SetColor(color, color);
|
||||||
|
for (int r = 0; r < h; r++) {
|
||||||
|
wmove(window, y + r, x); // ncurses wants 'y' before 'x'!
|
||||||
|
whline(window, ' ', w);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
Cmd(OSD_FillBlock, color, x * charWidth, y * lineHeight, (x + w) * charWidth - 1, (y + h) * lineHeight - 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void DvbOsdText(int x, int y, char *s)
|
void cDvbOsd::ClrEol(int x, int y, eDvbColor color)
|
||||||
{
|
{
|
||||||
DvbOsdCmd(OSD_Text, 1, x, y, 1, 0, s);
|
Fill(x, y, cols - x, 1, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cDvbOsd::Text(int x, int y, const char *s, eDvbColor colorFg, eDvbColor colorBg)
|
||||||
|
{
|
||||||
|
if (x < 0) x = cols + x;
|
||||||
|
if (y < 0) y = rows + y;
|
||||||
|
#ifdef DEBUG_OSD
|
||||||
|
SetColor(colorFg, colorBg);
|
||||||
|
wmove(window, y, x); // ncurses wants 'y' before 'x'!
|
||||||
|
waddstr(window, s);
|
||||||
|
#else
|
||||||
|
Cmd(OSD_Text, (int(colorBg) << 16) | colorFg, x * charWidth, y * lineHeight, 1, 0, s);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
68
dvbapi.h
68
dvbapi.h
@ -4,23 +4,51 @@
|
|||||||
* See the main source file 'osm.c' for copyright information and
|
* See the main source file 'osm.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: dvbapi.h 1.1 2000/02/19 13:36:48 kls Exp $
|
* $Id: dvbapi.h 1.2 2000/03/06 19:47:20 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DVBAPI_H
|
#ifndef __DVBAPI_H
|
||||||
#define __DVBAPI_H
|
#define __DVBAPI_H
|
||||||
|
|
||||||
const int DvbOsdCharWidth = 12; //XXX
|
// FIXME: these should be defined in ../DVB/driver/dvb.h!!!
|
||||||
const int DvbOsdLineHeight = 25;
|
typedef unsigned int u32;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
typedef unsigned char u8;
|
||||||
|
|
||||||
|
#if defined(DEBUG_OSD) || defined(DEBUG_REMOTE)
|
||||||
|
#include <ncurses.h>
|
||||||
|
#endif
|
||||||
|
#include "../DVB/driver/dvb.h"
|
||||||
|
|
||||||
|
enum eDvbColor { clrBackground,
|
||||||
|
#ifndef DEBUG_OSD
|
||||||
|
clrOBSOLETE, //FIXME apparently color '1' can't be used as FgColor with e.g. clrRed as BgColor???
|
||||||
|
clrBlack,
|
||||||
|
#else
|
||||||
|
clrBlack = clrBackground,
|
||||||
|
#endif
|
||||||
|
clrRed,
|
||||||
|
clrGreen,
|
||||||
|
clrYellow,
|
||||||
|
clrBlue,
|
||||||
|
clrMagenta,
|
||||||
|
clrCyan,
|
||||||
|
clrWhite,
|
||||||
|
};
|
||||||
|
|
||||||
extern const char *DvbQuality; // Low, Medium, High
|
extern const char *DvbQuality; // Low, Medium, High
|
||||||
|
|
||||||
bool DvbSetChannel(int FrequencyMHz, char Polarization, int Diseqc, int Srate, int Vpid, int Apid);
|
bool DvbSetChannel(int FrequencyMHz, char Polarization, int Diseqc, int Srate, int Vpid, int Apid);
|
||||||
|
|
||||||
class cDvbRecorder {
|
class cDvbRecorder {
|
||||||
|
private:
|
||||||
|
bool recording;
|
||||||
public:
|
public:
|
||||||
cDvbRecorder(void);
|
cDvbRecorder(void);
|
||||||
~cDvbRecorder();
|
~cDvbRecorder();
|
||||||
|
bool Recording(void);
|
||||||
|
// Returns true if this recorder is currently recording, false if it
|
||||||
|
// is playing back or does nothing.
|
||||||
bool Record(const char *FileName, char Quality);
|
bool Record(const char *FileName, char Quality);
|
||||||
// Starts recording the current channel into the given file, with the
|
// Starts recording the current channel into the given file, with the
|
||||||
// given quality level. Any existing file will be overwritten.
|
// given quality level. Any existing file will be overwritten.
|
||||||
@ -30,8 +58,9 @@ public:
|
|||||||
bool Play(const char *FileName, int Frame = 0);
|
bool Play(const char *FileName, int Frame = 0);
|
||||||
// Starts playback of the given file, at the optional Frame (default
|
// Starts playback of the given file, at the optional Frame (default
|
||||||
// is the beginning of the file). If Frame is beyond the last recorded
|
// is the beginning of the file). If Frame is beyond the last recorded
|
||||||
// frame in the file, or if it is negative, playback will be positioned
|
// frame in the file (or if it is negative), playback will be positioned
|
||||||
// to the last frame in the file and will do an implicit Pause() there.
|
// to the last frame in the file (or the frame with the absolute value of
|
||||||
|
// Frame) and will do an implicit Pause() there.
|
||||||
// If there is already a playback session active, it will be stopped
|
// If there is already a playback session active, it will be stopped
|
||||||
// and the new file or frame (which may be in the same file) will
|
// and the new file or frame (which may be in the same file) will
|
||||||
// be played back.
|
// be played back.
|
||||||
@ -56,10 +85,29 @@ public:
|
|||||||
// The very first frame has the number 1.
|
// The very first frame has the number 1.
|
||||||
};
|
};
|
||||||
|
|
||||||
void DvbOsdOpen(int x, int y, int w, int h);
|
class cDvbOsd {
|
||||||
void DvbOsdClose(void);
|
private:
|
||||||
void DvbOsdClear(void);
|
enum { charWidth = 12, // average character width
|
||||||
void DvbOsdClrEol(int x, int y);
|
lineHeight = 27 // smallest text height
|
||||||
void DvbOsdText(int x, int y, char *s);
|
};
|
||||||
|
#ifdef DEBUG_OSD
|
||||||
|
WINDOW *window;
|
||||||
|
enum { MaxColorPairs = 16 };
|
||||||
|
int colorPairs[MaxColorPairs];
|
||||||
|
void SetColor(eDvbColor colorFg, eDvbColor colorBg = clrBackground);
|
||||||
|
#else
|
||||||
|
void Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = NULL);
|
||||||
|
#endif
|
||||||
|
int cols, rows;
|
||||||
|
public:
|
||||||
|
cDvbOsd(void);
|
||||||
|
~cDvbOsd();
|
||||||
|
void Open(int w, int h);
|
||||||
|
void Close(void);
|
||||||
|
void Clear(void);
|
||||||
|
void Fill(int x, int y, int w, int h, eDvbColor color = clrBackground);
|
||||||
|
void ClrEol(int x, int y, eDvbColor color = clrBackground);
|
||||||
|
void Text(int x, int y, const char *s, eDvbColor colorFg = clrWhite, eDvbColor colorBg = clrBackground);
|
||||||
|
};
|
||||||
|
|
||||||
#endif //__DVBAPI_H
|
#endif //__DVBAPI_H
|
||||||
|
202
interface.c
202
interface.c
@ -4,20 +4,21 @@
|
|||||||
* See the main source file 'osm.c' for copyright information and
|
* See the main source file 'osm.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: interface.c 1.1 2000/02/19 13:36:48 kls Exp $
|
* $Id: interface.c 1.2 2000/03/06 19:45:03 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
#include <ncurses.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "dvbapi.h"
|
|
||||||
#include "remote.h"
|
#include "remote.h"
|
||||||
|
|
||||||
|
#define MenuLines 15
|
||||||
|
#define MenuColumns 40
|
||||||
|
|
||||||
#ifndef DEBUG_REMOTE
|
#ifndef DEBUG_REMOTE
|
||||||
cRcIo RcIo("/dev/ttyS1");//XXX
|
cRcIo RcIo("/dev/ttyS1");//XXX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
WINDOW *window;
|
cDvbOsd DvbOsd; //XXX member of cInterface???
|
||||||
|
|
||||||
cInterface Interface;
|
cInterface Interface;
|
||||||
|
|
||||||
@ -25,16 +26,6 @@ cInterface::cInterface(void)
|
|||||||
{
|
{
|
||||||
open = 0;
|
open = 0;
|
||||||
cols[0] = 0;
|
cols[0] = 0;
|
||||||
#ifdef DEBUG_OSD
|
|
||||||
initscr();
|
|
||||||
keypad(stdscr, TRUE);
|
|
||||||
nonl();
|
|
||||||
cbreak();
|
|
||||||
noecho();
|
|
||||||
leaveok(stdscr, TRUE);
|
|
||||||
window = stdscr;
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cInterface::Init(void)
|
void cInterface::Init(void)
|
||||||
@ -46,24 +37,14 @@ void cInterface::Init(void)
|
|||||||
|
|
||||||
void cInterface::Open(void)
|
void cInterface::Open(void)
|
||||||
{
|
{
|
||||||
if (!open++) {
|
if (!open++)
|
||||||
#ifdef DEBUG_OSD
|
DvbOsd.Open(MenuColumns, MenuLines);
|
||||||
#else
|
|
||||||
//TODO
|
|
||||||
DvbOsdOpen(100, 100, 500, 400);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cInterface::Close(void)
|
void cInterface::Close(void)
|
||||||
{
|
{
|
||||||
if (!--open) {
|
if (!--open)
|
||||||
#ifdef DEBUG_OSD
|
DvbOsd.Close();
|
||||||
#else
|
|
||||||
//TODO
|
|
||||||
DvbOsdClose();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int cInterface::GetCh(void)
|
unsigned int cInterface::GetCh(void)
|
||||||
@ -71,9 +52,9 @@ unsigned int cInterface::GetCh(void)
|
|||||||
#ifdef DEBUG_REMOTE
|
#ifdef DEBUG_REMOTE
|
||||||
return getch();
|
return getch();
|
||||||
#else
|
#else
|
||||||
#ifdef DEBUG_OSD
|
//XXX #ifdef DEBUG_OSD
|
||||||
wrefresh(window);//XXX
|
//XXX wrefresh(window);//XXX
|
||||||
#endif
|
//XXX #endif
|
||||||
unsigned int Command;
|
unsigned int Command;
|
||||||
return RcIo.GetCommand(&Command) ? Command : 0;
|
return RcIo.GetCommand(&Command) ? Command : 0;
|
||||||
#endif
|
#endif
|
||||||
@ -84,16 +65,28 @@ eKeys cInterface::GetKey(void)
|
|||||||
return Keys.Get(GetCh());
|
return Keys.Get(GetCh());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eKeys cInterface::Wait(int Seconds)
|
||||||
|
{
|
||||||
|
int t0 = time_ms();
|
||||||
|
|
||||||
|
while (time_ms() - t0 < Seconds * 1000) {
|
||||||
|
eKeys Key = GetKey();
|
||||||
|
if (Key != kNone)
|
||||||
|
return Key;
|
||||||
|
}
|
||||||
|
return kNone;
|
||||||
|
}
|
||||||
|
|
||||||
void cInterface::Clear(void)
|
void cInterface::Clear(void)
|
||||||
{
|
{
|
||||||
if (open) {
|
if (open)
|
||||||
#ifdef DEBUG_OSD
|
DvbOsd.Clear();
|
||||||
wclear(window);
|
}
|
||||||
#else
|
|
||||||
//TODO
|
void cInterface::ClearEol(int x, int y, eDvbColor Color)
|
||||||
DvbOsdClear();
|
{
|
||||||
#endif
|
if (open)
|
||||||
}
|
DvbOsd.ClrEol(x, y, Color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cInterface::SetCols(int *c)
|
void cInterface::SetCols(int *c)
|
||||||
@ -105,34 +98,22 @@ void cInterface::SetCols(int *c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cInterface::Write(int x, int y, char *s)
|
void cInterface::Write(int x, int y, const char *s, eDvbColor FgColor, eDvbColor BgColor)
|
||||||
{
|
{
|
||||||
if (open) {
|
if (open)
|
||||||
#ifdef DEBUG_OSD
|
DvbOsd.Text(x, y, s, FgColor, BgColor);
|
||||||
wmove(window, y, x); // ncurses wants 'y' before 'x'!
|
|
||||||
waddstr(window, s);
|
|
||||||
#else
|
|
||||||
DvbOsdText(x * DvbOsdCharWidth, y * DvbOsdLineHeight, s);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cInterface::WriteText(int x, int y, char *s, bool Current)
|
void cInterface::WriteText(int x, int y, const char *s, bool Current)
|
||||||
{
|
{
|
||||||
if (open) {
|
if (open) {
|
||||||
#ifdef DEBUG_OSD
|
eDvbColor FgColor = Current ? clrBlack : clrWhite;
|
||||||
wmove(window, y, x); // ncurses wants 'y' before 'x'!
|
eDvbColor BgColor = Current ? clrCyan : clrBackground;
|
||||||
wclrtoeol(window);//XXX
|
ClearEol(x, y, BgColor);
|
||||||
#else
|
|
||||||
//TODO
|
|
||||||
DvbOsdClrEol(x * DvbOsdCharWidth, y);//XXX
|
|
||||||
#endif
|
|
||||||
Write(x, y, Current ? "*" : " ");
|
|
||||||
x++;
|
|
||||||
int col = 0;
|
int col = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char *t = strchr(s, '\t');
|
const char *t = strchr(s, '\t');
|
||||||
char *p = s;
|
const char *p = s;
|
||||||
char buf[1000];
|
char buf[1000];
|
||||||
if (t && col < MaxCols && cols[col] > 0) {
|
if (t && col < MaxCols && cols[col] > 0) {
|
||||||
unsigned int n = t - s;
|
unsigned int n = t - s;
|
||||||
@ -143,7 +124,7 @@ void cInterface::WriteText(int x, int y, char *s, bool Current)
|
|||||||
p = buf;
|
p = buf;
|
||||||
s = t + 1;
|
s = t + 1;
|
||||||
}
|
}
|
||||||
Write(x, y, p);
|
Write(x, y, p, FgColor, BgColor);
|
||||||
if (p == s)
|
if (p == s)
|
||||||
break;
|
break;
|
||||||
x += cols[col++];
|
x += cols[col++];
|
||||||
@ -151,38 +132,74 @@ void cInterface::WriteText(int x, int y, char *s, bool Current)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cInterface::Info(char *s)
|
void cInterface::Title(const char *s)
|
||||||
|
{
|
||||||
|
int x = (MenuColumns - strlen(s)) / 2;
|
||||||
|
if (x < 0)
|
||||||
|
x = 0;
|
||||||
|
ClearEol(0, 0, clrCyan);
|
||||||
|
Write(x, 0, s, clrBlack, clrCyan);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cInterface::Status(const char *s, eDvbColor FgColor, eDvbColor BgColor)
|
||||||
|
{
|
||||||
|
ClearEol(0, -3, s ? BgColor : clrBackground);
|
||||||
|
if (s)
|
||||||
|
Write(0, -3, s, FgColor, BgColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cInterface::Info(const char *s)
|
||||||
{
|
{
|
||||||
Open();
|
Open();
|
||||||
isyslog(LOG_ERR, s);
|
isyslog(LOG_INFO, s);
|
||||||
WriteText(0, 11, s);//TODO
|
Status(s, clrWhite, clrGreen);
|
||||||
#ifdef DEBUG_OSD
|
Wait();
|
||||||
wrefresh(window);//XXX
|
Status(NULL);
|
||||||
#endif
|
|
||||||
sleep(1);
|
|
||||||
WriteText(0, 11, "");//TODO
|
|
||||||
#ifdef DEBUG_OSD
|
|
||||||
wrefresh(window);//XXX
|
|
||||||
#endif
|
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cInterface::Error(char *s)
|
void cInterface::Error(const char *s)
|
||||||
{
|
{
|
||||||
Open();
|
Open();
|
||||||
esyslog(LOG_ERR, s);
|
esyslog(LOG_ERR, s);
|
||||||
WriteText(0, 12, s);//TODO
|
Status(s, clrWhite, clrRed);
|
||||||
#ifdef DEBUG_OSD
|
Wait();
|
||||||
wrefresh(window);//XXX
|
Status(NULL);
|
||||||
#endif
|
|
||||||
sleep(1);
|
|
||||||
WriteText(0, 12, "");//TODO
|
|
||||||
#ifdef DEBUG_OSD
|
|
||||||
wrefresh(window);//XXX
|
|
||||||
#endif
|
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cInterface::Confirm(const char *s)
|
||||||
|
{
|
||||||
|
Open();
|
||||||
|
isyslog(LOG_INFO, "confirm: %s", s);
|
||||||
|
Status(s, clrBlack, clrGreen);
|
||||||
|
bool result = Wait(10) == kOk;
|
||||||
|
Status(NULL);
|
||||||
|
Close();
|
||||||
|
isyslog(LOG_INFO, "%sconfirmed", result ? "" : "not ");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cInterface::HelpButton(int Index, const char *Text, eDvbColor FgColor, eDvbColor BgColor)
|
||||||
|
{
|
||||||
|
if (open && Text) {
|
||||||
|
const int w = MenuColumns / 4;
|
||||||
|
int l = (w - strlen(Text)) / 2;
|
||||||
|
if (l < 0)
|
||||||
|
l = 0;
|
||||||
|
DvbOsd.Fill(Index * w, -1, w, 1, BgColor);
|
||||||
|
DvbOsd.Text(Index * w + l, -1, Text, FgColor, BgColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cInterface::Help(const char *Red, const char *Green, const char *Yellow, const char *Blue)
|
||||||
|
{
|
||||||
|
HelpButton(0, Red, clrBlack, clrRed);
|
||||||
|
HelpButton(1, Green, clrBlack, clrGreen);
|
||||||
|
HelpButton(2, Yellow, clrBlack, clrYellow);
|
||||||
|
HelpButton(3, Blue, clrWhite, clrBlue);
|
||||||
|
}
|
||||||
|
|
||||||
void cInterface::QueryKeys(void)
|
void cInterface::QueryKeys(void)
|
||||||
{
|
{
|
||||||
Keys.Clear();
|
Keys.Clear();
|
||||||
@ -205,8 +222,8 @@ void cInterface::QueryKeys(void)
|
|||||||
WriteText(1, 5, "RC code detected!");
|
WriteText(1, 5, "RC code detected!");
|
||||||
WriteText(1, 6, "Do not press any key...");
|
WriteText(1, 6, "Do not press any key...");
|
||||||
RcIo.Flush(3);
|
RcIo.Flush(3);
|
||||||
WriteText(1, 5, "");
|
ClearEol(0, 5);
|
||||||
WriteText(1, 6, "");
|
ClearEol(0, 6);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -229,8 +246,8 @@ void cInterface::QueryKeys(void)
|
|||||||
case kDown: if (k > Keys.keys + 1) {
|
case kDown: if (k > Keys.keys + 1) {
|
||||||
WriteText(1, 5, "Press 'Up' to confirm");
|
WriteText(1, 5, "Press 'Up' to confirm");
|
||||||
WriteText(1, 6, "Press 'Down' to continue");
|
WriteText(1, 6, "Press 'Down' to continue");
|
||||||
WriteText(1, 7, "");
|
ClearEol(0, 7);
|
||||||
WriteText(1, 8, "");
|
ClearEol(0, 8);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
eKeys key = GetKey();
|
eKeys key = GetKey();
|
||||||
if (key == kUp) {
|
if (key == kUp) {
|
||||||
@ -238,7 +255,7 @@ void cInterface::QueryKeys(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (key == kDown) {
|
else if (key == kDown) {
|
||||||
WriteText(1, 6, "");
|
ClearEol(0, 6);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,17 +272,18 @@ void cInterface::QueryKeys(void)
|
|||||||
if (k > Keys.keys)
|
if (k > Keys.keys)
|
||||||
WriteText(1, 7, "(press 'Up' to go back)");
|
WriteText(1, 7, "(press 'Up' to go back)");
|
||||||
else
|
else
|
||||||
WriteText(1, 7, "");
|
ClearEol(0, 7);
|
||||||
if (k > Keys.keys + 1)
|
if (k > Keys.keys + 1)
|
||||||
WriteText(1, 8, "(press 'Down' to end key definition)");
|
WriteText(1, 8, "(press 'Down' to end key definition)");
|
||||||
else
|
else
|
||||||
WriteText(1, 8, "");
|
ClearEol(0, 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cInterface::LearnKeys(void)
|
void cInterface::LearnKeys(void)
|
||||||
{
|
{
|
||||||
isyslog(LOG_INFO, "learning keys");
|
isyslog(LOG_INFO, "learning keys");
|
||||||
|
Open();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Clear();
|
Clear();
|
||||||
QueryKeys();
|
QueryKeys();
|
||||||
@ -277,19 +295,19 @@ void cInterface::LearnKeys(void)
|
|||||||
eKeys key = GetKey();
|
eKeys key = GetKey();
|
||||||
if (key == kUp) {
|
if (key == kUp) {
|
||||||
Keys.Save();
|
Keys.Save();
|
||||||
Clear();
|
Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (key == kDown) {
|
else if (key == kDown) {
|
||||||
Keys.Load();
|
Keys.Load();
|
||||||
Clear();
|
Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cInterface::DisplayChannel(int Number, char *Name)
|
void cInterface::DisplayChannel(int Number, const char *Name)
|
||||||
{
|
{
|
||||||
//TODO
|
//TODO
|
||||||
#ifndef DEBUG_REMOTE
|
#ifndef DEBUG_REMOTE
|
||||||
|
20
interface.h
20
interface.h
@ -4,13 +4,14 @@
|
|||||||
* See the main source file 'osm.c' for copyright information and
|
* See the main source file 'osm.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: interface.h 1.1 2000/02/19 13:36:48 kls Exp $
|
* $Id: interface.h 1.2 2000/02/27 14:54:02 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __INTERFACE_H
|
#ifndef __INTERFACE_H
|
||||||
#define __INTERFACE_H
|
#define __INTERFACE_H
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "dvbapi.h"
|
||||||
|
|
||||||
class cInterface {
|
class cInterface {
|
||||||
public:
|
public:
|
||||||
@ -20,7 +21,8 @@ private:
|
|||||||
int cols[MaxCols];
|
int cols[MaxCols];
|
||||||
unsigned int GetCh(void);
|
unsigned int GetCh(void);
|
||||||
void QueryKeys(void);
|
void QueryKeys(void);
|
||||||
void Write(int x, int y, char *s);
|
void HelpButton(int Index, const char *Text, eDvbColor FgColor, eDvbColor BgColor);
|
||||||
|
eKeys Wait(int Seconds = 1);
|
||||||
public:
|
public:
|
||||||
cInterface(void);
|
cInterface(void);
|
||||||
void Init(void);
|
void Init(void);
|
||||||
@ -28,12 +30,18 @@ public:
|
|||||||
void Close(void);
|
void Close(void);
|
||||||
eKeys GetKey(void);
|
eKeys GetKey(void);
|
||||||
void Clear(void);
|
void Clear(void);
|
||||||
|
void ClearEol(int x, int y, eDvbColor Color = clrBackground);
|
||||||
void SetCols(int *c);
|
void SetCols(int *c);
|
||||||
void WriteText(int x, int y, char *s, bool Current = false);
|
void Write(int x, int y, const char *s, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
|
||||||
void Info(char *s);
|
void WriteText(int x, int y, const char *s, bool Current = false);
|
||||||
void Error(char *s);
|
void Title(const char *s);
|
||||||
|
void Status(const char *s, eDvbColor FgColor = clrBlack, eDvbColor BgColor = clrCyan);
|
||||||
|
void Info(const char *s);
|
||||||
|
void Error(const char *s);
|
||||||
|
bool Confirm(const char *s);
|
||||||
|
void Help(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
||||||
void LearnKeys(void);
|
void LearnKeys(void);
|
||||||
void DisplayChannel(int Number, char *Name);
|
void DisplayChannel(int Number, const char *Name);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern cInterface Interface;
|
extern cInterface Interface;
|
||||||
|
BIN
keys-pc.conf
BIN
keys-pc.conf
Binary file not shown.
@ -17,3 +17,7 @@ Right 000045E2
|
|||||||
7 00000FE2
|
7 00000FE2
|
||||||
8 000077E2
|
8 000077E2
|
||||||
9 000037E2
|
9 000037E2
|
||||||
|
Red 000025E2
|
||||||
|
Green 00002AE2
|
||||||
|
Yellow 00005AE2
|
||||||
|
Blue 00000000
|
||||||
|
454
menu.c
454
menu.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'osm.c' for copyright information and
|
* See the main source file 'osm.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: menu.c 1.1 2000/02/19 13:36:48 kls Exp $
|
* $Id: menu.c 1.2 2000/03/05 15:37:31 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
@ -13,8 +13,9 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "dvbapi.h"
|
#include "dvbapi.h"
|
||||||
|
#include "recording.h"
|
||||||
|
|
||||||
const char *FileNameChars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789/-.# ";//TODO more?
|
const char *FileNameChars = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789-.# ";
|
||||||
|
|
||||||
// --- cMenuEditItem ---------------------------------------------------------
|
// --- cMenuEditItem ---------------------------------------------------------
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ protected:
|
|||||||
virtual void Set(void);
|
virtual void Set(void);
|
||||||
public:
|
public:
|
||||||
cMenuEditIntItem(const char *Name, int *Value, int Min = 0, int Max = INT_MAX);
|
cMenuEditIntItem(const char *Name, int *Value, int Min = 0, int Max = INT_MAX);
|
||||||
virtual eOSStatus ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
cMenuEditIntItem::cMenuEditIntItem(const char *Name, int *Value, int Min, int Max)
|
cMenuEditIntItem::cMenuEditIntItem(const char *Name, int *Value, int Min, int Max)
|
||||||
@ -78,11 +79,11 @@ void cMenuEditIntItem::Set(void)
|
|||||||
SetValue(buf);
|
SetValue(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSStatus cMenuEditIntItem::ProcessKey(eKeys Key)
|
eOSState cMenuEditIntItem::ProcessKey(eKeys Key)
|
||||||
{
|
{
|
||||||
eOSStatus status = cMenuEditItem::ProcessKey(Key);
|
eOSState state = cMenuEditItem::ProcessKey(Key);
|
||||||
|
|
||||||
if (status == osUnknown) {
|
if (state == osUnknown) {
|
||||||
int newValue;
|
int newValue;
|
||||||
if (k0 <= Key && Key <= k9) {
|
if (k0 <= Key && Key <= k9) {
|
||||||
if (fresh) {
|
if (fresh) {
|
||||||
@ -100,14 +101,14 @@ eOSStatus cMenuEditIntItem::ProcessKey(eKeys Key)
|
|||||||
fresh = true;
|
fresh = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return status;
|
return state;
|
||||||
if ((!fresh || min <= newValue) && newValue <= max) {
|
if ((!fresh || min <= newValue) && newValue <= max) {
|
||||||
*value = newValue;
|
*value = newValue;
|
||||||
Set();
|
Set();
|
||||||
}
|
}
|
||||||
status = osContinue;
|
state = osContinue;
|
||||||
}
|
}
|
||||||
return status;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cMenuEditBoolItem -----------------------------------------------------
|
// --- cMenuEditBoolItem -----------------------------------------------------
|
||||||
@ -167,7 +168,7 @@ protected:
|
|||||||
virtual void Set(void);
|
virtual void Set(void);
|
||||||
public:
|
public:
|
||||||
cMenuEditDayItem(const char *Name, int *Value);
|
cMenuEditDayItem(const char *Name, int *Value);
|
||||||
virtual eOSStatus ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
int cMenuEditDayItem::days[] ={ cTimer::ParseDay("M------"),
|
int cMenuEditDayItem::days[] ={ cTimer::ParseDay("M------"),
|
||||||
@ -205,7 +206,7 @@ void cMenuEditDayItem::Set(void)
|
|||||||
SetValue(cTimer::PrintDay(*value));
|
SetValue(cTimer::PrintDay(*value));
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSStatus cMenuEditDayItem::ProcessKey(eKeys Key)
|
eOSState cMenuEditDayItem::ProcessKey(eKeys Key)
|
||||||
{
|
{
|
||||||
switch (Key) {
|
switch (Key) {
|
||||||
case kLeft: if (d > 0)
|
case kLeft: if (d > 0)
|
||||||
@ -252,7 +253,7 @@ protected:
|
|||||||
virtual void Set(void);
|
virtual void Set(void);
|
||||||
public:
|
public:
|
||||||
cMenuEditTimeItem(const char *Name, int *Value);
|
cMenuEditTimeItem(const char *Name, int *Value);
|
||||||
virtual eOSStatus ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
cMenuEditTimeItem::cMenuEditTimeItem(const char *Name, int *Value)
|
cMenuEditTimeItem::cMenuEditTimeItem(const char *Name, int *Value)
|
||||||
@ -272,11 +273,11 @@ void cMenuEditTimeItem::Set(void)
|
|||||||
SetValue(buf);
|
SetValue(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSStatus cMenuEditTimeItem::ProcessKey(eKeys Key)
|
eOSState cMenuEditTimeItem::ProcessKey(eKeys Key)
|
||||||
{
|
{
|
||||||
eOSStatus status = cMenuEditItem::ProcessKey(Key);
|
eOSState state = cMenuEditItem::ProcessKey(Key);
|
||||||
|
|
||||||
if (status == osUnknown) {
|
if (state == osUnknown) {
|
||||||
if (k0 <= Key && Key <= k9) {
|
if (k0 <= Key && Key <= k9) {
|
||||||
if (fresh || pos > 3) {
|
if (fresh || pos > 3) {
|
||||||
pos = 0;
|
pos = 0;
|
||||||
@ -324,12 +325,12 @@ eOSStatus cMenuEditTimeItem::ProcessKey(eKeys Key)
|
|||||||
fresh = true;
|
fresh = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return status;
|
return state;
|
||||||
*value = hh * 100 + mm;
|
*value = hh * 100 + mm;
|
||||||
Set();
|
Set();
|
||||||
status = osContinue;
|
state = osContinue;
|
||||||
}
|
}
|
||||||
return status;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cMenuEditChrItem ------------------------------------------------------
|
// --- cMenuEditChrItem ------------------------------------------------------
|
||||||
@ -343,7 +344,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
cMenuEditChrItem(const char *Name, char *Value, const char *Allowed);
|
cMenuEditChrItem(const char *Name, char *Value, const char *Allowed);
|
||||||
~cMenuEditChrItem();
|
~cMenuEditChrItem();
|
||||||
virtual eOSStatus ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
cMenuEditChrItem::cMenuEditChrItem(const char *Name, char *Value, const char *Allowed)
|
cMenuEditChrItem::cMenuEditChrItem(const char *Name, char *Value, const char *Allowed)
|
||||||
@ -369,11 +370,11 @@ void cMenuEditChrItem::Set(void)
|
|||||||
SetValue(buf);
|
SetValue(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSStatus cMenuEditChrItem::ProcessKey(eKeys Key)
|
eOSState cMenuEditChrItem::ProcessKey(eKeys Key)
|
||||||
{
|
{
|
||||||
eOSStatus status = cMenuEditItem::ProcessKey(Key);
|
eOSState state = cMenuEditItem::ProcessKey(Key);
|
||||||
|
|
||||||
if (status == osUnknown) {
|
if (state == osUnknown) {
|
||||||
if (Key == kLeft) {
|
if (Key == kLeft) {
|
||||||
if (current > allowed)
|
if (current > allowed)
|
||||||
current--;
|
current--;
|
||||||
@ -383,12 +384,12 @@ eOSStatus cMenuEditChrItem::ProcessKey(eKeys Key)
|
|||||||
current++;
|
current++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return status;
|
return state;
|
||||||
*value = *current;
|
*value = *current;
|
||||||
Set();
|
Set();
|
||||||
status = osContinue;
|
state = osContinue;
|
||||||
}
|
}
|
||||||
return status;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cMenuEditStrItem ------------------------------------------------------
|
// --- cMenuEditStrItem ------------------------------------------------------
|
||||||
@ -404,7 +405,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed);
|
cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed);
|
||||||
~cMenuEditStrItem();
|
~cMenuEditStrItem();
|
||||||
virtual eOSStatus ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
cMenuEditStrItem::cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed)
|
cMenuEditStrItem::cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed)
|
||||||
@ -449,7 +450,7 @@ char cMenuEditStrItem::Inc(char c, bool Up)
|
|||||||
return *p;
|
return *p;
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSStatus cMenuEditStrItem::ProcessKey(eKeys Key)
|
eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
|
||||||
{
|
{
|
||||||
switch (Key) {
|
switch (Key) {
|
||||||
case kLeft: if (pos > 0) {
|
case kLeft: if (pos > 0) {
|
||||||
@ -492,11 +493,11 @@ private:
|
|||||||
cChannel data;
|
cChannel data;
|
||||||
public:
|
public:
|
||||||
cMenuEditChannel(int Index);
|
cMenuEditChannel(int Index);
|
||||||
virtual eOSStatus ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
cMenuEditChannel::cMenuEditChannel(int Index)
|
cMenuEditChannel::cMenuEditChannel(int Index)
|
||||||
:cOsdMenu("Edit channel", 14)
|
:cOsdMenu("Edit Channel", 14)
|
||||||
{
|
{
|
||||||
channel = Channels.Get(Index);
|
channel = Channels.Get(Index);
|
||||||
if (channel) {
|
if (channel) {
|
||||||
@ -511,19 +512,19 @@ cMenuEditChannel::cMenuEditChannel(int Index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSStatus cMenuEditChannel::ProcessKey(eKeys Key)
|
eOSState cMenuEditChannel::ProcessKey(eKeys Key)
|
||||||
{
|
{
|
||||||
eOSStatus status = cOsdMenu::ProcessKey(Key);
|
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||||
|
|
||||||
if (status == osUnknown) {
|
if (state == osUnknown) {
|
||||||
if (Key == kOk) {
|
if (Key == kOk) {
|
||||||
if (channel)
|
if (channel)
|
||||||
*channel = data;
|
*channel = data;
|
||||||
Channels.Save();
|
Channels.Save();
|
||||||
status = osBack;
|
state = osBack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return status;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cMenuChannelItem ------------------------------------------------------
|
// --- cMenuChannelItem ------------------------------------------------------
|
||||||
@ -535,6 +536,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
cMenuChannelItem(int Index, cChannel *Channel);
|
cMenuChannelItem(int Index, cChannel *Channel);
|
||||||
virtual void Set(void);
|
virtual void Set(void);
|
||||||
|
void SetIndex(int Index);
|
||||||
};
|
};
|
||||||
|
|
||||||
cMenuChannelItem::cMenuChannelItem(int Index, cChannel *Channel)
|
cMenuChannelItem::cMenuChannelItem(int Index, cChannel *Channel)
|
||||||
@ -551,12 +553,24 @@ void cMenuChannelItem::Set(void)
|
|||||||
SetText(buffer, false);
|
SetText(buffer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cMenuChannelItem::SetIndex(int Index)
|
||||||
|
{
|
||||||
|
index = Index;
|
||||||
|
Set();
|
||||||
|
}
|
||||||
|
|
||||||
// --- cMenuChannels ---------------------------------------------------------
|
// --- cMenuChannels ---------------------------------------------------------
|
||||||
|
|
||||||
class cMenuChannels : public cOsdMenu {
|
class cMenuChannels : public cOsdMenu {
|
||||||
|
protected:
|
||||||
|
eOSState Switch(void);
|
||||||
|
eOSState Edit(void);
|
||||||
|
eOSState New(void);
|
||||||
|
eOSState Del(void);
|
||||||
|
virtual void Move(int From, int To);
|
||||||
public:
|
public:
|
||||||
cMenuChannels(void);
|
cMenuChannels(void);
|
||||||
virtual eOSStatus ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
cMenuChannels::cMenuChannels(void)
|
cMenuChannels::cMenuChannels(void)
|
||||||
@ -570,26 +584,124 @@ cMenuChannels::cMenuChannels(void)
|
|||||||
Add(new cMenuChannelItem(i, channel), i == CurrentChannel);
|
Add(new cMenuChannelItem(i, channel), i == CurrentChannel);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
SetHelp("Edit", "New", "Delete", "Mark");
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSStatus cMenuChannels::ProcessKey(eKeys Key)
|
eOSState cMenuChannels::Switch(void)
|
||||||
{
|
{
|
||||||
eOSStatus status = cOsdMenu::ProcessKey(Key);
|
cChannel *ch = Channels.Get(Current());
|
||||||
|
if (ch)
|
||||||
|
ch->Switch();
|
||||||
|
return osEnd;
|
||||||
|
}
|
||||||
|
|
||||||
if (status == osUnknown) {
|
eOSState cMenuChannels::Edit(void)
|
||||||
|
{
|
||||||
|
if (HasSubMenu() || Count() == 0)
|
||||||
|
return osContinue;
|
||||||
|
isyslog(LOG_INFO, "editing timer %d", Current() + 1);
|
||||||
|
return AddSubMenu(new cMenuEditChannel(Current()));
|
||||||
|
}
|
||||||
|
|
||||||
|
eOSState cMenuChannels::New(void)
|
||||||
|
{
|
||||||
|
if (HasSubMenu())
|
||||||
|
return osContinue;
|
||||||
|
cChannel *channel = new cChannel(Channels.Get(Current()));
|
||||||
|
Channels.Add(channel);
|
||||||
|
Add(new cMenuChannelItem(channel->Index()/*XXX*/, channel), true);
|
||||||
|
Channels.Save();
|
||||||
|
isyslog(LOG_INFO, "channel %d added", channel->Index() + 1);
|
||||||
|
return AddSubMenu(new cMenuEditChannel(Current()));
|
||||||
|
}
|
||||||
|
|
||||||
|
eOSState cMenuChannels::Del(void)
|
||||||
|
{
|
||||||
|
if (Count() > 0) {
|
||||||
|
int Index = Current();
|
||||||
|
// Check if there is a timer using this channel:
|
||||||
|
for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
|
||||||
|
if (ti->channel == Index + 1) {
|
||||||
|
Interface.Error("Channel is being used by a timer!");
|
||||||
|
return osContinue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Interface.Confirm("Delete Channel?")) {
|
||||||
|
// Move and renumber the channels:
|
||||||
|
Channels.Del(Channels.Get(Index));
|
||||||
|
cOsdMenu::Del(Index);
|
||||||
|
int i = 0;
|
||||||
|
for (cMenuChannelItem *ci = (cMenuChannelItem *)First(); ci; ci = (cMenuChannelItem *)ci->Next())
|
||||||
|
ci->SetIndex(i++);
|
||||||
|
Channels.Save();
|
||||||
|
isyslog(LOG_INFO, "channel %d deleted", Index + 1);
|
||||||
|
// Fix the timers:
|
||||||
|
bool TimersModified = false;
|
||||||
|
Index++; // user visible channel numbers start with '1'
|
||||||
|
for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
|
||||||
|
int OldChannel = ti->channel;
|
||||||
|
if (ti->channel > Index)
|
||||||
|
ti->channel--;
|
||||||
|
if (ti->channel != OldChannel) {
|
||||||
|
TimersModified = true;
|
||||||
|
isyslog(LOG_INFO, "timer %d: channel changed from %d to %d", ti->Index() + 1, OldChannel, ti->channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (TimersModified)
|
||||||
|
Timers.Save();
|
||||||
|
Display();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return osContinue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cMenuChannels::Move(int From, int To)
|
||||||
|
{
|
||||||
|
// Move and renumber the channels:
|
||||||
|
Channels.Move(From, To);
|
||||||
|
cOsdMenu::Move(From, To);
|
||||||
|
int i = 0;
|
||||||
|
for (cMenuChannelItem *ci = (cMenuChannelItem *)First(); ci; ci = (cMenuChannelItem *)ci->Next())
|
||||||
|
ci->SetIndex(i++);
|
||||||
|
Channels.Save();
|
||||||
|
isyslog(LOG_INFO, "channel %d moved to %d", From + 1, To + 1);
|
||||||
|
// Fix the timers:
|
||||||
|
bool TimersModified = false;
|
||||||
|
From++; // user visible channel numbers start with '1'
|
||||||
|
To++;
|
||||||
|
for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
|
||||||
|
int OldChannel = ti->channel;
|
||||||
|
if (ti->channel == From)
|
||||||
|
ti->channel = To;
|
||||||
|
else if (ti->channel > From && ti->channel <= To)
|
||||||
|
ti->channel--;
|
||||||
|
else if (ti->channel < From && ti->channel >= To)
|
||||||
|
ti->channel++;
|
||||||
|
if (ti->channel != OldChannel) {
|
||||||
|
TimersModified = true;
|
||||||
|
isyslog(LOG_INFO, "timer %d: channel changed from %d to %d", ti->Index() + 1, OldChannel, ti->channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (TimersModified)
|
||||||
|
Timers.Save();
|
||||||
|
Display();
|
||||||
|
}
|
||||||
|
|
||||||
|
eOSState cMenuChannels::ProcessKey(eKeys Key)
|
||||||
|
{
|
||||||
|
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||||
|
|
||||||
|
if (state == osUnknown) {
|
||||||
switch (Key) {
|
switch (Key) {
|
||||||
//TODO need to block this if we are already editing a channel!
|
case kOk: return Switch();
|
||||||
case kRight: return AddSubMenu(new cMenuEditChannel(Current()));
|
case kRed: return Edit();
|
||||||
case kOk: {
|
case kGreen: return New();
|
||||||
cChannel *ch = Channels.Get(Current());
|
case kYellow: return Del();
|
||||||
if (ch)
|
case kBlue: Mark(); break;
|
||||||
ch->Switch();
|
|
||||||
return osEnd;
|
|
||||||
}
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return status;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cMenuEditTimer --------------------------------------------------------
|
// --- cMenuEditTimer --------------------------------------------------------
|
||||||
@ -600,11 +712,11 @@ private:
|
|||||||
cTimer data;
|
cTimer data;
|
||||||
public:
|
public:
|
||||||
cMenuEditTimer(int Index);
|
cMenuEditTimer(int Index);
|
||||||
virtual eOSStatus ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
cMenuEditTimer::cMenuEditTimer(int Index)
|
cMenuEditTimer::cMenuEditTimer(int Index)
|
||||||
:cOsdMenu("Edit timer", 10)
|
:cOsdMenu("Edit Timer", 10)
|
||||||
{
|
{
|
||||||
timer = Timers.Get(Index);
|
timer = Timers.Get(Index);
|
||||||
if (timer) {
|
if (timer) {
|
||||||
@ -622,21 +734,23 @@ cMenuEditTimer::cMenuEditTimer(int Index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSStatus cMenuEditTimer::ProcessKey(eKeys Key)
|
eOSState cMenuEditTimer::ProcessKey(eKeys Key)
|
||||||
{
|
{
|
||||||
eOSStatus status = cOsdMenu::ProcessKey(Key);
|
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||||
|
|
||||||
if (status == osUnknown) {
|
if (state == osUnknown) {
|
||||||
if (Key == kOk) {
|
if (Key == kOk) {
|
||||||
|
if (!*data.file)
|
||||||
|
strcpy(data.file, "unnamed");
|
||||||
if (timer && memcmp(timer, &data, sizeof(data)) != 0) {
|
if (timer && memcmp(timer, &data, sizeof(data)) != 0) {
|
||||||
*timer = data;
|
*timer = data;
|
||||||
Timers.Save();
|
Timers.Save();
|
||||||
isyslog(LOG_INFO, "timer %d modified (%s)", timer->Index() + 1, timer->active ? "active" : "inactive");
|
isyslog(LOG_INFO, "timer %d modified (%s)", timer->Index() + 1, timer->active ? "active" : "inactive");
|
||||||
}
|
}
|
||||||
status = osBack;
|
state = osBack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return status;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cMenuTimerItem --------------------------------------------------------
|
// --- cMenuTimerItem --------------------------------------------------------
|
||||||
@ -660,27 +774,34 @@ cMenuTimerItem::cMenuTimerItem(int Index, cTimer *Timer)
|
|||||||
void cMenuTimerItem::Set(void)
|
void cMenuTimerItem::Set(void)
|
||||||
{
|
{
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
asprintf(&buffer, "%d\t%c\t%d\t%s\t%02d:%02d\t%02d:%02d", index + 1,
|
asprintf(&buffer, "%c\t%d\t%s\t%02d:%02d\t%02d:%02d\t%s",
|
||||||
timer->active ? '>' : ' ',
|
timer->active ? '>' : ' ',
|
||||||
timer->channel,
|
timer->channel,
|
||||||
timer->PrintDay(timer->day),
|
timer->PrintDay(timer->day),
|
||||||
timer->start / 100,
|
timer->start / 100,
|
||||||
timer->start % 100,
|
timer->start % 100,
|
||||||
timer->stop / 100,
|
timer->stop / 100,
|
||||||
timer->stop % 100); // user visible timer numbers start with '1'
|
timer->stop % 100,
|
||||||
|
timer->file);
|
||||||
SetText(buffer, false);
|
SetText(buffer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cMenuTimer ------------------------------------------------------------
|
// --- cMenuTimers -----------------------------------------------------------
|
||||||
|
|
||||||
class cMenuTimer : public cOsdMenu {
|
class cMenuTimers : public cOsdMenu {
|
||||||
|
private:
|
||||||
|
eOSState Activate(bool On);
|
||||||
|
eOSState Edit(void);
|
||||||
|
eOSState New(void);
|
||||||
|
eOSState Del(void);
|
||||||
|
virtual void Move(int From, int To);
|
||||||
public:
|
public:
|
||||||
cMenuTimer(void);
|
cMenuTimers(void);
|
||||||
virtual eOSStatus ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
cMenuTimer::cMenuTimer(void)
|
cMenuTimers::cMenuTimers(void)
|
||||||
:cOsdMenu("Timer", 3, 2, 4, 10, 6)
|
:cOsdMenu("Timer", 2, 4, 10, 6, 6)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
cTimer *timer;
|
cTimer *timer;
|
||||||
@ -689,34 +810,190 @@ cMenuTimer::cMenuTimer(void)
|
|||||||
Add(new cMenuTimerItem(i, timer));
|
Add(new cMenuTimerItem(i, timer));
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
SetHelp("Edit", "New", "Delete", "Mark");
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSStatus cMenuTimer::ProcessKey(eKeys Key)
|
eOSState cMenuTimers::Activate(bool On)
|
||||||
{
|
{
|
||||||
eOSStatus status = cOsdMenu::ProcessKey(Key);
|
cTimer *timer = Timers.Get(Current());
|
||||||
|
if (timer && timer->active != On) {
|
||||||
|
timer->active = On;
|
||||||
|
RefreshCurrent();
|
||||||
|
DisplayCurrent(true);
|
||||||
|
isyslog(LOG_INFO, "timer %d %sactivated", timer->Index() + 1, timer->active ? "" : "de");
|
||||||
|
Timers.Save();
|
||||||
|
}
|
||||||
|
return osContinue;
|
||||||
|
}
|
||||||
|
|
||||||
if (status == osUnknown) {
|
eOSState cMenuTimers::Edit(void)
|
||||||
|
{
|
||||||
|
if (HasSubMenu() || Count() == 0)
|
||||||
|
return osContinue;
|
||||||
|
isyslog(LOG_INFO, "editing timer %d", Current() + 1);
|
||||||
|
return AddSubMenu(new cMenuEditTimer(Current()));
|
||||||
|
}
|
||||||
|
|
||||||
|
eOSState cMenuTimers::New(void)
|
||||||
|
{
|
||||||
|
if (HasSubMenu())
|
||||||
|
return osContinue;
|
||||||
|
cTimer *timer = new cTimer;
|
||||||
|
Timers.Add(timer);
|
||||||
|
Add(new cMenuTimerItem(timer->Index()/*XXX*/, timer), true);
|
||||||
|
Timers.Save();
|
||||||
|
isyslog(LOG_INFO, "timer %d added", timer->Index() + 1);
|
||||||
|
return AddSubMenu(new cMenuEditTimer(Current()));
|
||||||
|
}
|
||||||
|
|
||||||
|
eOSState cMenuTimers::Del(void)
|
||||||
|
{
|
||||||
|
// Check if this timer is active:
|
||||||
|
int Index = Current();
|
||||||
|
cTimer *ti = Timers.Get(Index);
|
||||||
|
if (ti) {
|
||||||
|
if (!ti->recording) {
|
||||||
|
if (Interface.Confirm("Delete Timer?")) {
|
||||||
|
Timers.Del(Timers.Get(Index));
|
||||||
|
cOsdMenu::Del(Index);
|
||||||
|
Timers.Save();
|
||||||
|
Display();
|
||||||
|
isyslog(LOG_INFO, "timer %d deleted", Index + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Interface.Error("Timer is recording!");
|
||||||
|
}
|
||||||
|
return osContinue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cMenuTimers::Move(int From, int To)
|
||||||
|
{
|
||||||
|
Timers.Move(From, To);
|
||||||
|
cOsdMenu::Move(From, To);
|
||||||
|
Timers.Save();
|
||||||
|
Display();
|
||||||
|
isyslog(LOG_INFO, "timer %d moved to %d", From + 1, To + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
eOSState cMenuTimers::ProcessKey(eKeys Key)
|
||||||
|
{
|
||||||
|
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||||
|
|
||||||
|
if (state == osUnknown) {
|
||||||
switch (Key) {
|
switch (Key) {
|
||||||
//TODO need to block this if we are already editing a channel!
|
|
||||||
case kOk: return AddSubMenu(new cMenuEditTimer(Current()));
|
|
||||||
//TODO new timer
|
|
||||||
//TODO delete timer
|
|
||||||
case kLeft:
|
case kLeft:
|
||||||
case kRight:
|
case kRight: return Activate(Key == kRight);
|
||||||
{
|
case kOk:
|
||||||
cTimer *timer = Timers.Get(Current());
|
case kRed: return Edit();
|
||||||
if (timer) {
|
case kGreen: return New();
|
||||||
timer->active = (Key == kRight);
|
case kYellow: return Del();
|
||||||
isyslog(LOG_INFO, "timer %d %sactivated", timer->Index() + 1, timer->active ? "" : "de");
|
case kBlue: Mark(); break;
|
||||||
RefreshCurrent();
|
|
||||||
DisplayCurrent(true);
|
|
||||||
Timers.Save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return status;
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- cMenuRecordingItem ----------------------------------------------------
|
||||||
|
|
||||||
|
class cMenuRecordingItem : public cOsdItem {
|
||||||
|
public:
|
||||||
|
cRecording *recording;
|
||||||
|
cMenuRecordingItem(cRecording *Recording);
|
||||||
|
virtual void Set(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
cMenuRecordingItem::cMenuRecordingItem(cRecording *Recording)
|
||||||
|
{
|
||||||
|
recording = Recording;
|
||||||
|
Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cMenuRecordingItem::Set(void)
|
||||||
|
{
|
||||||
|
char *buffer = NULL;
|
||||||
|
struct tm *t = localtime(&recording->start);
|
||||||
|
asprintf(&buffer, "%02d.%02d.%04d\t%02d:%02d\t%s",
|
||||||
|
t->tm_mday,
|
||||||
|
t->tm_mon + 1,
|
||||||
|
t->tm_year + 1900,
|
||||||
|
t->tm_hour,
|
||||||
|
t->tm_min,
|
||||||
|
recording->name);
|
||||||
|
SetText(buffer, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- cMenuRecordings -------------------------------------------------------
|
||||||
|
|
||||||
|
class cMenuRecordings : public cOsdMenu {
|
||||||
|
private:
|
||||||
|
cRecordings Recordings;
|
||||||
|
eOSState Play(void);
|
||||||
|
eOSState Del(void);
|
||||||
|
public:
|
||||||
|
cMenuRecordings(void);
|
||||||
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
|
};
|
||||||
|
|
||||||
|
cMenuRecordings::cMenuRecordings(void)
|
||||||
|
:cOsdMenu("Recordings", 11, 6)
|
||||||
|
{
|
||||||
|
if (Recordings.Load()) {
|
||||||
|
cRecording *recording = Recordings.First();
|
||||||
|
while (recording) {
|
||||||
|
Add(new cMenuRecordingItem(recording));
|
||||||
|
recording = Recordings.Next(recording);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetHelp("Play", NULL/*XXX"Resume"*/, "Delete");
|
||||||
|
}
|
||||||
|
|
||||||
|
eOSState cMenuRecordings::Play(void)
|
||||||
|
{
|
||||||
|
cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current());
|
||||||
|
if (ri) {
|
||||||
|
//XXX what if this recording's file is currently in use???
|
||||||
|
if (ri->recording->Play())
|
||||||
|
return osEnd;
|
||||||
|
}
|
||||||
|
return osContinue;
|
||||||
|
}
|
||||||
|
|
||||||
|
eOSState cMenuRecordings::Del(void)
|
||||||
|
{
|
||||||
|
cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current());
|
||||||
|
if (ri) {
|
||||||
|
//XXX what if this recording's file is currently in use???
|
||||||
|
//XXX if (!ti->recording) {
|
||||||
|
if (Interface.Confirm("Delete Recording?")) {
|
||||||
|
if (ri->recording->Delete()) {
|
||||||
|
cOsdMenu::Del(Current());
|
||||||
|
Display();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Interface.Error("Error while deleting recording!");
|
||||||
|
}
|
||||||
|
//XXX }
|
||||||
|
//XXX else
|
||||||
|
//XXX Interface.Error("Timer is recording!");
|
||||||
|
}
|
||||||
|
return osContinue;
|
||||||
|
}
|
||||||
|
|
||||||
|
eOSState cMenuRecordings::ProcessKey(eKeys Key)
|
||||||
|
{
|
||||||
|
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||||
|
|
||||||
|
if (state == osUnknown) {
|
||||||
|
switch (Key) {
|
||||||
|
case kOk:
|
||||||
|
case kRed: return Play();
|
||||||
|
case kYellow: return Del();
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cMenuMain -------------------------------------------------------------
|
// --- cMenuMain -------------------------------------------------------------
|
||||||
@ -724,22 +1001,21 @@ eOSStatus cMenuTimer::ProcessKey(eKeys Key)
|
|||||||
cMenuMain::cMenuMain(void)
|
cMenuMain::cMenuMain(void)
|
||||||
:cOsdMenu("Main")
|
:cOsdMenu("Main")
|
||||||
{
|
{
|
||||||
//TODO
|
|
||||||
Add(new cOsdItem("Channels", osChannels));
|
Add(new cOsdItem("Channels", osChannels));
|
||||||
Add(new cOsdItem("Timer", osTimer));
|
Add(new cOsdItem("Timer", osTimer));
|
||||||
Add(new cOsdItem("Recordings", osRecordings));
|
Add(new cOsdItem("Recordings", osRecordings));
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSStatus cMenuMain::ProcessKey(eKeys Key)
|
eOSState cMenuMain::ProcessKey(eKeys Key)
|
||||||
{
|
{
|
||||||
eOSStatus status = cOsdMenu::ProcessKey(Key);
|
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||||
|
|
||||||
switch (status) {
|
switch (state) {
|
||||||
case osChannels: return AddSubMenu(new cMenuChannels);
|
case osChannels: return AddSubMenu(new cMenuChannels);
|
||||||
case osTimer: return AddSubMenu(new cMenuTimer);
|
case osTimer: return AddSubMenu(new cMenuTimers);
|
||||||
//TODO Replay
|
case osRecordings: return AddSubMenu(new cMenuRecordings);
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
return status;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
menu.h
4
menu.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'osm.c' for copyright information and
|
* See the main source file 'osm.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: menu.h 1.1 2000/02/19 13:36:48 kls Exp $
|
* $Id: menu.h 1.2 2000/03/05 10:57:27 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _MENU_H
|
#ifndef _MENU_H
|
||||||
@ -15,7 +15,7 @@
|
|||||||
class cMenuMain : public cOsdMenu {
|
class cMenuMain : public cOsdMenu {
|
||||||
public:
|
public:
|
||||||
cMenuMain(void);
|
cMenuMain(void);
|
||||||
virtual eOSStatus ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_MENU_H
|
#endif //_MENU_H
|
||||||
|
131
osd.c
131
osd.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'osm.c' for copyright information and
|
* See the main source file 'osm.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: osd.c 1.1 2000/02/19 13:36:48 kls Exp $
|
* $Id: osd.c 1.2 2000/02/27 17:23:07 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "osd.h"
|
#include "osd.h"
|
||||||
@ -13,19 +13,19 @@
|
|||||||
|
|
||||||
// --- cOsdItem --------------------------------------------------------------
|
// --- cOsdItem --------------------------------------------------------------
|
||||||
|
|
||||||
cOsdItem::cOsdItem(eOSStatus Status)
|
cOsdItem::cOsdItem(eOSState State)
|
||||||
{
|
{
|
||||||
text = NULL;
|
text = NULL;
|
||||||
offset = -1;
|
offset = -1;
|
||||||
status = Status;
|
state = State;
|
||||||
fresh = false;
|
fresh = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cOsdItem::cOsdItem(char *Text, eOSStatus Status)
|
cOsdItem::cOsdItem(char *Text, eOSState State)
|
||||||
{
|
{
|
||||||
text = NULL;
|
text = NULL;
|
||||||
offset = -1;
|
offset = -1;
|
||||||
status = Status;
|
state = State;
|
||||||
fresh = false;
|
fresh = false;
|
||||||
SetText(Text);
|
SetText(Text);
|
||||||
}
|
}
|
||||||
@ -52,24 +52,27 @@ void cOsdItem::Display(int Offset, bool Current)
|
|||||||
Interface.WriteText(0, offset + 2, text, Current);
|
Interface.WriteText(0, offset + 2, text, Current);
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSStatus cOsdItem::ProcessKey(eKeys Key)
|
eOSState cOsdItem::ProcessKey(eKeys Key)
|
||||||
{
|
{
|
||||||
return Key == kOk ? status : osUnknown;
|
return Key == kOk ? state : osUnknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cOsdMenu --------------------------------------------------------------
|
// --- cOsdMenu --------------------------------------------------------------
|
||||||
|
|
||||||
cOsdMenu::cOsdMenu(char *Title, int c0, int c1, int c2, int c3, int c4)
|
cOsdMenu::cOsdMenu(char *Title, int c0, int c1, int c2, int c3, int c4)
|
||||||
{
|
{
|
||||||
|
visible = false;
|
||||||
title = strdup(Title);
|
title = strdup(Title);
|
||||||
cols[0] = c0;
|
cols[0] = c0;
|
||||||
cols[1] = c1;
|
cols[1] = c1;
|
||||||
cols[2] = c2;
|
cols[2] = c2;
|
||||||
cols[3] = c3;
|
cols[3] = c3;
|
||||||
cols[4] = c4;
|
cols[4] = c4;
|
||||||
first = count = 0;
|
first = 0;
|
||||||
current = -1;
|
current = marked = -1;
|
||||||
subMenu = NULL;
|
subMenu = NULL;
|
||||||
|
helpRed = helpGreen = helpYellow = helpBlue = NULL;
|
||||||
|
status = NULL;
|
||||||
Interface.Open();
|
Interface.Open();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,40 +80,72 @@ cOsdMenu::~cOsdMenu()
|
|||||||
{
|
{
|
||||||
delete title;
|
delete title;
|
||||||
delete subMenu;
|
delete subMenu;
|
||||||
|
delete status;
|
||||||
Interface.Clear();
|
Interface.Clear();
|
||||||
Interface.Close();
|
Interface.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cOsdMenu::SetStatus(const char *s)
|
||||||
|
{
|
||||||
|
delete status;
|
||||||
|
status = s ? strdup(s) : NULL;
|
||||||
|
if (visible)
|
||||||
|
Interface.Status(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cOsdMenu::SetHelp(const char *Red, const char *Green, const char *Yellow, const char *Blue)
|
||||||
|
{
|
||||||
|
// strings are NOT copied - must be constants!!!
|
||||||
|
helpRed = Red;
|
||||||
|
helpGreen = Green;
|
||||||
|
helpYellow = Yellow;
|
||||||
|
helpBlue = Blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cOsdMenu::Del(int Index)
|
||||||
|
{
|
||||||
|
cList<cOsdItem>::Del(Get(Index));
|
||||||
|
if (current == Count())
|
||||||
|
current--;
|
||||||
|
if (Index == first && first > 0)
|
||||||
|
first--;
|
||||||
|
}
|
||||||
|
|
||||||
void cOsdMenu::Add(cOsdItem *Item, bool Current)
|
void cOsdMenu::Add(cOsdItem *Item, bool Current)
|
||||||
{
|
{
|
||||||
cList<cOsdItem>::Add(Item);
|
cList<cOsdItem>::Add(Item);
|
||||||
count++;
|
if (Current)
|
||||||
if (Current && current < 0)
|
|
||||||
current = Item->Index();
|
current = Item->Index();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cOsdMenu::Display(void)
|
void cOsdMenu::Display(void)
|
||||||
{
|
{
|
||||||
|
visible = true;
|
||||||
Interface.Clear();
|
Interface.Clear();
|
||||||
Interface.SetCols(cols);
|
Interface.SetCols(cols);
|
||||||
Interface.WriteText(0, 0, title);
|
Interface.Title(title);
|
||||||
if (current < 0 && count)
|
Interface.Help(helpRed, helpGreen, helpYellow, helpBlue);
|
||||||
current = 0; // just for safety - there HAS to be a current item!
|
int count = Count();
|
||||||
int n = 0;
|
if (count > 0) {
|
||||||
if (current - first >= MAXOSDITEMS) {
|
if (current < 0)
|
||||||
first = current - MAXOSDITEMS / 2;
|
current = 0; // just for safety - there HAS to be a current item!
|
||||||
if (first + MAXOSDITEMS > count)
|
int n = 0;
|
||||||
first = count - MAXOSDITEMS;
|
if (current - first >= MAXOSDITEMS) {
|
||||||
if (first < 0)
|
first = current - MAXOSDITEMS / 2;
|
||||||
first = 0;
|
if (first + MAXOSDITEMS > count)
|
||||||
|
first = count - MAXOSDITEMS;
|
||||||
|
if (first < 0)
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
for (int i = first; i < count; i++) {
|
||||||
|
cOsdItem *item = Get(i);
|
||||||
|
if (item)
|
||||||
|
item->Display(i - first, i == current);
|
||||||
|
if (++n == MAXOSDITEMS) //TODO get this from Interface!!!
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (int i = first; i < count; i++) {
|
Interface.Status(status);
|
||||||
cOsdItem *item = Get(i);
|
|
||||||
if (item)
|
|
||||||
item->Display(i - first, i == current);
|
|
||||||
if (++n == MAXOSDITEMS) //TODO get this from Interface!!!
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cOsdMenu::RefreshCurrent(void)
|
void cOsdMenu::RefreshCurrent(void)
|
||||||
@ -144,6 +179,7 @@ void cOsdMenu::CursorUp(void)
|
|||||||
|
|
||||||
void cOsdMenu::CursorDown(void)
|
void cOsdMenu::CursorDown(void)
|
||||||
{
|
{
|
||||||
|
int count = Count();
|
||||||
if (current < count - 1) {
|
if (current < count - 1) {
|
||||||
DisplayCurrent(false);
|
DisplayCurrent(false);
|
||||||
if (++current >= first + MAXOSDITEMS) {
|
if (++current >= first + MAXOSDITEMS) {
|
||||||
@ -157,7 +193,15 @@ void cOsdMenu::CursorDown(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSStatus cOsdMenu::AddSubMenu(cOsdMenu *SubMenu)
|
void cOsdMenu::Mark(void)
|
||||||
|
{
|
||||||
|
if (Count() && marked < 0) {
|
||||||
|
marked = current;
|
||||||
|
SetStatus("Up/Dn for new location - OK to move");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eOSState cOsdMenu::AddSubMenu(cOsdMenu *SubMenu)
|
||||||
{
|
{
|
||||||
delete subMenu;
|
delete subMenu;
|
||||||
subMenu = SubMenu;
|
subMenu = SubMenu;
|
||||||
@ -165,31 +209,40 @@ eOSStatus cOsdMenu::AddSubMenu(cOsdMenu *SubMenu)
|
|||||||
return osContinue; // convenience return value (see cMenuMain)
|
return osContinue; // convenience return value (see cMenuMain)
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSStatus cOsdMenu::ProcessKey(eKeys Key)
|
eOSState cOsdMenu::ProcessKey(eKeys Key)
|
||||||
{
|
{
|
||||||
if (subMenu) {
|
if (subMenu) {
|
||||||
eOSStatus status = subMenu->ProcessKey(Key);
|
eOSState state = subMenu->ProcessKey(Key);
|
||||||
if (status == osBack) {
|
if (state == osBack) {
|
||||||
delete subMenu;
|
delete subMenu;
|
||||||
subMenu = NULL;
|
subMenu = NULL;
|
||||||
RefreshCurrent();
|
RefreshCurrent();
|
||||||
Display();
|
Display();
|
||||||
status = osContinue;
|
state = osContinue;
|
||||||
}
|
}
|
||||||
return status;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
cOsdItem *item = Get(current);
|
cOsdItem *item = Get(current);
|
||||||
if (item) {
|
if (marked < 0 && item) {
|
||||||
eOSStatus status = item->ProcessKey(Key);
|
eOSState state = item->ProcessKey(Key);
|
||||||
if (status != osUnknown)
|
if (state != osUnknown)
|
||||||
return status;
|
return state;
|
||||||
}
|
}
|
||||||
switch (Key) {
|
switch (Key) {
|
||||||
case kUp: CursorUp(); break;
|
case kUp: CursorUp(); break;
|
||||||
case kDown: CursorDown(); break;
|
case kDown: CursorDown(); break;
|
||||||
case kBack: return osBack;
|
case kBack: return osBack;
|
||||||
default: return osUnknown;
|
case kOk: if (marked >= 0) {
|
||||||
|
SetStatus(NULL);
|
||||||
|
if (marked != current)
|
||||||
|
Move(marked, current);
|
||||||
|
marked = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// else run into default
|
||||||
|
default: if (marked < 0)
|
||||||
|
return osUnknown;
|
||||||
}
|
}
|
||||||
return osContinue;
|
return osContinue;
|
||||||
}
|
}
|
||||||
|
42
osd.h
42
osd.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'osm.c' for copyright information and
|
* See the main source file 'osm.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: osd.h 1.1 2000/02/19 13:36:48 kls Exp $
|
* $Id: osd.h 1.2 2000/03/05 11:33:11 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __OSD_H
|
#ifndef __OSD_H
|
||||||
@ -16,53 +16,61 @@
|
|||||||
|
|
||||||
#define MAXOSDITEMS 9
|
#define MAXOSDITEMS 9
|
||||||
|
|
||||||
enum eOSStatus { osUnknown,
|
enum eOSState { osUnknown,
|
||||||
osContinue,
|
osContinue,
|
||||||
osProcessed,
|
osProcessed,
|
||||||
osChannels,
|
osChannels,
|
||||||
osTimer,
|
osTimer,
|
||||||
osRecordings,
|
osRecordings,
|
||||||
osBack,
|
osBack,
|
||||||
osEnd,
|
osEnd,
|
||||||
};
|
};
|
||||||
|
|
||||||
class cOsdItem : public cListObject {
|
class cOsdItem : public cListObject {
|
||||||
private:
|
private:
|
||||||
char *text;
|
char *text;
|
||||||
int offset;
|
int offset;
|
||||||
eOSStatus status;
|
eOSState state;
|
||||||
protected:
|
protected:
|
||||||
bool fresh;
|
bool fresh;
|
||||||
public:
|
public:
|
||||||
cOsdItem(eOSStatus Status = osUnknown);
|
cOsdItem(eOSState State = osUnknown);
|
||||||
cOsdItem(char *Text, eOSStatus Status = osUnknown);
|
cOsdItem(char *Text, eOSState State = osUnknown);
|
||||||
virtual ~cOsdItem();
|
virtual ~cOsdItem();
|
||||||
void SetText(char *Text, bool Copy = true);
|
void SetText(char *Text, bool Copy = true);
|
||||||
char *Text(void) { return text; }
|
char *Text(void) { return text; }
|
||||||
void Display(int Offset = -1, bool Current = false);
|
void Display(int Offset = -1, bool Current = false);
|
||||||
virtual void Set(void) {}
|
virtual void Set(void) {}
|
||||||
virtual eOSStatus ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
class cOsdMenu : public cList<cOsdItem> {
|
class cOsdMenu : public cList<cOsdItem> {
|
||||||
private:
|
private:
|
||||||
char *title;
|
char *title;
|
||||||
int cols[cInterface::MaxCols];
|
int cols[cInterface::MaxCols];
|
||||||
int first, current, count;
|
int first, current, marked;
|
||||||
cOsdMenu *subMenu;
|
cOsdMenu *subMenu;
|
||||||
|
const char *helpRed, *helpGreen, *helpYellow, *helpBlue;
|
||||||
|
const char *status;
|
||||||
protected:
|
protected:
|
||||||
|
bool visible;
|
||||||
void RefreshCurrent(void);
|
void RefreshCurrent(void);
|
||||||
void DisplayCurrent(bool Current);
|
void DisplayCurrent(bool Current);
|
||||||
void CursorUp(void);
|
void CursorUp(void);
|
||||||
void CursorDown(void);
|
void CursorDown(void);
|
||||||
eOSStatus AddSubMenu(cOsdMenu *SubMenu);
|
void Mark(void);
|
||||||
|
eOSState AddSubMenu(cOsdMenu *SubMenu);
|
||||||
|
bool HasSubMenu(void) { return subMenu; }
|
||||||
|
void SetStatus(const char *s);
|
||||||
|
void SetHelp(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
||||||
|
virtual void Del(int Index);
|
||||||
public:
|
public:
|
||||||
cOsdMenu(char *Title, int c0 = 0, int c1 = 0, int c2 = 0, int c3 = 0, int c4 = 0);
|
cOsdMenu(char *Title, int c0 = 0, int c1 = 0, int c2 = 0, int c3 = 0, int c4 = 0);
|
||||||
virtual ~cOsdMenu();
|
virtual ~cOsdMenu();
|
||||||
int Current(void) { return current; }
|
int Current(void) { return current; }
|
||||||
void Add(cOsdItem *Item, bool Current = false);
|
void Add(cOsdItem *Item, bool Current = false);
|
||||||
void Display(void);
|
void Display(void);
|
||||||
virtual eOSStatus ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //__OSD_H
|
#endif //__OSD_H
|
||||||
|
57
osm.c
57
osm.c
@ -22,13 +22,13 @@
|
|||||||
*
|
*
|
||||||
* The project's page is at http://www.cadsoft.de/people/kls/vdr
|
* The project's page is at http://www.cadsoft.de/people/kls/vdr
|
||||||
*
|
*
|
||||||
* $Id: osm.c 1.1 2000/02/19 13:36:48 kls Exp $
|
* $Id: osm.c 1.2 2000/03/05 17:18:15 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "dvbapi.h"
|
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
|
#include "recording.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
#ifdef DEBUG_REMOTE
|
#ifdef DEBUG_REMOTE
|
||||||
@ -52,39 +52,39 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
cMenuMain *Menu = NULL;
|
cMenuMain *Menu = NULL;
|
||||||
cTimer *Timer = NULL;
|
cTimer *Timer = NULL;
|
||||||
cDvbRecorder *Recorder = NULL;
|
cRecording *Recording = NULL;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
//TODO check for free disk space and delete files if necessary/possible
|
AssertFreeDiskSpace();
|
||||||
// in case there is an ongoing recording
|
if (!Recording && !Timer && (Timer = cTimer::GetMatch()) != NULL) {
|
||||||
if (!Timer && (Timer = cTimer::GetMatch()) != NULL) {
|
DELETENULL(Menu);
|
||||||
|
// make sure the timer won't be deleted:
|
||||||
|
Timer->SetRecording(true);
|
||||||
// switch to channel:
|
// switch to channel:
|
||||||
isyslog(LOG_INFO, "timer %d start", Timer->Index() + 1);
|
|
||||||
delete Menu;
|
|
||||||
Menu = NULL;
|
|
||||||
cChannel::SwitchTo(Timer->channel - 1);
|
cChannel::SwitchTo(Timer->channel - 1);
|
||||||
ChannelLocked = true;
|
ChannelLocked = true;
|
||||||
// start recording:
|
// start recording:
|
||||||
delete Recorder;
|
Recording = new cRecording(Timer);
|
||||||
Recorder = new cDvbRecorder;
|
if (!Recording->Record())
|
||||||
//TODO special filename handling!!!
|
DELETENULL(Recording);
|
||||||
if (!Recorder->Record(Timer->file, Timer->quality)) {
|
|
||||||
delete Recorder;
|
|
||||||
Recorder = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (Timer) {
|
if (Timer && !Timer->Matches()) {
|
||||||
if (!Timer->Matches()) {
|
// stop recording:
|
||||||
// stop recording:
|
if (Recording) {
|
||||||
if (Recorder)
|
Recording->Stop();
|
||||||
Recorder->Stop();
|
DELETENULL(Recording);
|
||||||
// end timer:
|
|
||||||
ChannelLocked = false;
|
|
||||||
isyslog(LOG_INFO, "timer %d stop", Timer->Index() + 1);
|
|
||||||
Timer = NULL;
|
|
||||||
//TODO switch back to the previous channel???
|
|
||||||
//TODO clear single event timer???
|
|
||||||
}
|
}
|
||||||
|
// release channel and timer:
|
||||||
|
ChannelLocked = false;
|
||||||
|
Timer->SetRecording(false);
|
||||||
|
// clear single event timer:
|
||||||
|
if (Timer->IsSingleEvent()) {
|
||||||
|
DELETENULL(Menu); // must make sure no menu uses it
|
||||||
|
isyslog(LOG_INFO, "deleting timer %d", Timer->Index() + 1);
|
||||||
|
Timers.Del(Timer);
|
||||||
|
Timers.Save();
|
||||||
|
}
|
||||||
|
Timer = NULL;
|
||||||
}
|
}
|
||||||
eKeys key = Interface.GetKey();
|
eKeys key = Interface.GetKey();
|
||||||
if (Menu) {
|
if (Menu) {
|
||||||
@ -92,8 +92,7 @@ int main(int argc, char *argv[])
|
|||||||
default: if (key != kMenu)
|
default: if (key != kMenu)
|
||||||
break;
|
break;
|
||||||
case osBack:
|
case osBack:
|
||||||
case osEnd: delete Menu;
|
case osEnd: DELETENULL(Menu);
|
||||||
Menu = NULL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
238
recording.c
Normal file
238
recording.c
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
/*
|
||||||
|
* recording.h: Recording file handling
|
||||||
|
*
|
||||||
|
* See the main source file 'osm.c' for copyright information and
|
||||||
|
* how to reach the author.
|
||||||
|
*
|
||||||
|
* $Id: recording.c 1.1 2000/03/05 17:16:22 kls Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "recording.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "interface.h"
|
||||||
|
#include "tools.h"
|
||||||
|
|
||||||
|
#define RECEXT ".rec"
|
||||||
|
#define DELEXT ".del"
|
||||||
|
#define DATAFORMAT "%4d-%02d-%02d.%02d:%02d.%c.%02d.%02d" RECEXT
|
||||||
|
#define NAMEFORMAT "%s/%s/" DATAFORMAT
|
||||||
|
|
||||||
|
#define FINDCMD "find %s -type f -name '%s'"
|
||||||
|
|
||||||
|
#define DFCMD "df -m %s"
|
||||||
|
#define MINDISKSPACE 1024 // MB
|
||||||
|
|
||||||
|
const char *BaseDir = "/video";//XXX
|
||||||
|
|
||||||
|
cDvbRecorder *Recorder = NULL;
|
||||||
|
|
||||||
|
static bool LowDiskSpace(void)
|
||||||
|
{
|
||||||
|
//TODO Find a simpler way to determine the amount of free disk space!
|
||||||
|
bool result = true;
|
||||||
|
char *cmd = NULL;
|
||||||
|
asprintf(&cmd, DFCMD, BaseDir);
|
||||||
|
FILE *p = popen(cmd, "r");
|
||||||
|
if (p) {
|
||||||
|
char *s;
|
||||||
|
while ((s = readline(p)) != NULL) {
|
||||||
|
if (*s == '/') {
|
||||||
|
int available;
|
||||||
|
sscanf(s, "%*s %*d %*d %d", &available);
|
||||||
|
result = available < MINDISKSPACE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pclose(p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
esyslog(LOG_ERR, "ERROR: can't open pipe for cmd '%s'", cmd);
|
||||||
|
delete cmd;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssertFreeDiskSpace(void)
|
||||||
|
{
|
||||||
|
// With every call to this function we try to actually remove
|
||||||
|
// a file, or mark a file for removal ("delete" it), so that
|
||||||
|
// it will get removed during the next call.
|
||||||
|
if (Recorder && Recorder->Recording() && LowDiskSpace()) {
|
||||||
|
// Remove the oldest file that has been "deleted":
|
||||||
|
cRecordings Recordings;
|
||||||
|
if (Recordings.Load(true)) {
|
||||||
|
cRecording *r = Recordings.First();
|
||||||
|
cRecording *r0 = r;
|
||||||
|
while (r) {
|
||||||
|
if (r->start < r0->start)
|
||||||
|
r0 = r;
|
||||||
|
r = Recordings.Next(r);
|
||||||
|
}
|
||||||
|
if (r0 && r0->Remove())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// No "deleted" files to remove, so let's see if we can delete a recording:
|
||||||
|
if (Recordings.Load(false)) {
|
||||||
|
cRecording *r = Recordings.First();
|
||||||
|
cRecording *r0 = NULL;
|
||||||
|
while (r) {
|
||||||
|
if ((time(NULL) - r->start) / SECSINDAY > r->lifetime) {
|
||||||
|
if (r0) {
|
||||||
|
if (r->priority < r0->priority)
|
||||||
|
r0 = r;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
r0 = r;
|
||||||
|
}
|
||||||
|
r = Recordings.Next(r);
|
||||||
|
}
|
||||||
|
if (r0 && r0->Delete())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Unable to free disk space, but there's nothing we can do about that...
|
||||||
|
//TODO maybe a log entry - but make sure it doesn't come too often
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- cRecording ------------------------------------------------------------
|
||||||
|
|
||||||
|
cRecording::cRecording(const char *Name, time_t Start, char Quality, int Priority, int LifeTime)
|
||||||
|
{
|
||||||
|
fileName = NULL;
|
||||||
|
name = strdup(Name);
|
||||||
|
start = Start;
|
||||||
|
quality = Quality;
|
||||||
|
priority = Priority;
|
||||||
|
lifetime = LifeTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
cRecording::cRecording(cTimer *Timer)
|
||||||
|
{
|
||||||
|
fileName = NULL;
|
||||||
|
name = strdup(Timer->file);
|
||||||
|
start = Timer->StartTime();
|
||||||
|
quality = Timer->quality;
|
||||||
|
priority = Timer->priority;
|
||||||
|
lifetime = Timer->lifetime;
|
||||||
|
}
|
||||||
|
|
||||||
|
cRecording::cRecording(const char *FileName)
|
||||||
|
{
|
||||||
|
fileName = strdup(FileName);
|
||||||
|
FileName += strlen(BaseDir) + 1;
|
||||||
|
char *p = strrchr(FileName, '/');
|
||||||
|
|
||||||
|
name = NULL;
|
||||||
|
if (p) {
|
||||||
|
time_t now = time(NULL);
|
||||||
|
struct tm t = *localtime(&now); // this initializes the time zone in 't'
|
||||||
|
if (8 == sscanf(p + 1, DATAFORMAT, &t.tm_year, &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min, &quality, &priority, &lifetime)) {
|
||||||
|
t.tm_year -= 1900;
|
||||||
|
t.tm_mon--;
|
||||||
|
t.tm_sec = 0;
|
||||||
|
start = mktime(&t);
|
||||||
|
name = new char[p - FileName + 1];
|
||||||
|
strncpy(name, FileName, p - FileName);
|
||||||
|
name[p - FileName] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cRecording::~cRecording()
|
||||||
|
{
|
||||||
|
delete fileName;
|
||||||
|
delete name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cRecording::FileName(void)
|
||||||
|
{
|
||||||
|
if (!fileName) {
|
||||||
|
struct tm *t = localtime(&start);
|
||||||
|
asprintf(&fileName, NAMEFORMAT, BaseDir, name, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, quality, priority, lifetime);
|
||||||
|
}
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRecording::Delete(void)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
char *NewName = strdup(FileName());
|
||||||
|
char *ext = strrchr(NewName, '.');
|
||||||
|
if (strcmp(ext, RECEXT) == 0) {
|
||||||
|
strncpy(ext, DELEXT, strlen(ext));
|
||||||
|
isyslog(LOG_INFO, "deleting recording %s", FileName());
|
||||||
|
if (rename(FileName(), NewName) == -1) {
|
||||||
|
esyslog(LOG_ERR, "ERROR: %s", strerror(errno));
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete NewName;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRecording::Remove(void)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
isyslog(LOG_INFO, "removing recording %s", FileName());
|
||||||
|
if (remove(FileName()) == -1) {
|
||||||
|
esyslog(LOG_ERR, "ERROR: %s", strerror(errno));
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRecording::AssertRecorder(void)
|
||||||
|
{
|
||||||
|
if (!Recorder || !Recorder->Recording()) {
|
||||||
|
if (!Recorder)
|
||||||
|
Recorder = new cDvbRecorder;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Interface.Error("Recorder is in use!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRecording::Record(void)
|
||||||
|
{
|
||||||
|
return AssertRecorder() && Recorder->Record(FileName(), quality);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRecording::Play(void)
|
||||||
|
{
|
||||||
|
return AssertRecorder() && Recorder->Play(FileName());
|
||||||
|
}
|
||||||
|
|
||||||
|
void cRecording::Stop(void)
|
||||||
|
{
|
||||||
|
if (Recorder)
|
||||||
|
Recorder->Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- cRecordings -----------------------------------------------------------
|
||||||
|
|
||||||
|
bool cRecordings::Load(bool Deleted)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
bool result = false;
|
||||||
|
char *cmd = NULL;
|
||||||
|
asprintf(&cmd, FINDCMD, BaseDir, Deleted ? "*" DELEXT : "*" RECEXT);
|
||||||
|
FILE *p = popen(cmd, "r");
|
||||||
|
if (p) {
|
||||||
|
char *s;
|
||||||
|
while ((s = readline(p)) != NULL) {
|
||||||
|
cRecording *r = new cRecording(s);
|
||||||
|
if (r->name)
|
||||||
|
Add(r);
|
||||||
|
else
|
||||||
|
delete r;
|
||||||
|
}
|
||||||
|
pclose(p);
|
||||||
|
result = Count() > 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Interface.Error("Error while opening pipe!");
|
||||||
|
delete cmd;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
56
recording.h
Normal file
56
recording.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* recording.h: Recording file handling
|
||||||
|
*
|
||||||
|
* See the main source file 'osm.c' for copyright information and
|
||||||
|
* how to reach the author.
|
||||||
|
*
|
||||||
|
* $Id: recording.h 1.1 2000/03/05 15:57:27 kls Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RECORDING_H
|
||||||
|
#define __RECORDING_H
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include "config.h"
|
||||||
|
#include "dvbapi.h"
|
||||||
|
#include "tools.h"
|
||||||
|
|
||||||
|
extern cDvbRecorder *Recorder;
|
||||||
|
|
||||||
|
void AssertFreeDiskSpace(void);
|
||||||
|
|
||||||
|
class cRecording : public cListObject {
|
||||||
|
private:
|
||||||
|
bool AssertRecorder(void);
|
||||||
|
public:
|
||||||
|
char *name;
|
||||||
|
char *fileName;
|
||||||
|
time_t start;
|
||||||
|
char quality;
|
||||||
|
int priority;
|
||||||
|
int lifetime;
|
||||||
|
cRecording(const char *Name, time_t Start, char Quality, int Priority, int LifeTime);
|
||||||
|
cRecording(cTimer *Timer);
|
||||||
|
cRecording(const char *FileName);
|
||||||
|
~cRecording();
|
||||||
|
const char *FileName(void);
|
||||||
|
bool Delete(void);
|
||||||
|
// Changes the file name so that it will no longer be visible in the OSM
|
||||||
|
// Returns false in case of error
|
||||||
|
bool Remove(void);
|
||||||
|
// Actually removes the file from the disk
|
||||||
|
// Returns false in case of error
|
||||||
|
bool Record(void);
|
||||||
|
// Starts recording of the file
|
||||||
|
bool Play(void);
|
||||||
|
// Starts playback of the file
|
||||||
|
void Stop(void);
|
||||||
|
// Stops recording or playback of the file
|
||||||
|
};
|
||||||
|
|
||||||
|
class cRecordings : public cList<cRecording> {
|
||||||
|
public:
|
||||||
|
bool Load(bool Deleted = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__RECORDING_H
|
11
timers.conf
11
timers.conf
@ -1,9 +1,6 @@
|
|||||||
1:2:-----S-:2210:2320:H:99:99:Wochenshow
|
1:2:-----S-:2205:2320:H:99:99:Wochenshow
|
||||||
1:3:M------:2125:2205:H:99:99:Neues
|
0:15:M------:2125:2205:H:99:99:Neues
|
||||||
1:15:MTWTF--:1828:1901:M:10:5:nano
|
1:15:MTWTF--:1828:1901:M:10:5:nano
|
||||||
1:2:-----S-:1737:1827:H:99:99:kls/StarTrek/DS9
|
|
||||||
1:3:M------:2110:2230:H:99:99:SevenDays
|
1:3:M------:2110:2230:H:99:99:SevenDays
|
||||||
1:3:---T---:2215:2300:H:99:99:SwItch
|
1:3:---T---:2215:2300:H:99:99:Switch
|
||||||
0:1:1:0:0:H:99:99:#
|
1:14:------S:2210:2255:H:99:99:Olli
|
||||||
0:1:1:0:0:H:99:99:#
|
|
||||||
0:1:1:0:0:L:0:5:#
|
|
||||||
|
71
tools.c
71
tools.c
@ -4,13 +4,30 @@
|
|||||||
* See the main source file 'osm.c' for copyright information and
|
* See the main source file 'osm.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: tools.c 1.1 2000/02/19 13:36:48 kls Exp $
|
* $Id: tools.c 1.2 2000/03/05 14:33:58 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#define MaxBuffer 1000
|
||||||
|
|
||||||
|
char *readline(FILE *f)
|
||||||
|
{
|
||||||
|
static char buffer[MaxBuffer];
|
||||||
|
if (fgets(buffer, sizeof(buffer), f) > 0) {
|
||||||
|
int l = strlen(buffer) - 1;
|
||||||
|
if (l >= 0 && buffer[l] == '\n')
|
||||||
|
buffer[l] = 0;
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int time_ms(void)
|
int time_ms(void)
|
||||||
{
|
{
|
||||||
struct timeval t;
|
struct timeval t;
|
||||||
@ -19,6 +36,30 @@ int time_ms(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MakeDirs(const char *FileName)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
char *s = strdup(FileName);
|
||||||
|
char *p = s;
|
||||||
|
if (*p == '/')
|
||||||
|
p++;
|
||||||
|
while ((p = strchr(p, '/')) != NULL) {
|
||||||
|
*p = 0;
|
||||||
|
struct stat fs;
|
||||||
|
if (stat(s, &fs) != 0 || !S_ISDIR(fs.st_mode)) {
|
||||||
|
isyslog(LOG_INFO, "creating directory %s", s);
|
||||||
|
if (mkdir(s, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1) {
|
||||||
|
esyslog(LOG_ERR, "ERROR while creating directory %s: %s", s, strerror(errno));
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*p++ = '/';
|
||||||
|
}
|
||||||
|
delete s;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// --- cListObject -----------------------------------------------------------
|
// --- cListObject -----------------------------------------------------------
|
||||||
|
|
||||||
cListObject::cListObject(void)
|
cListObject::cListObject(void)
|
||||||
@ -42,6 +83,7 @@ void cListObject::Unlink(void)
|
|||||||
next->prev = prev;
|
next->prev = prev;
|
||||||
if (prev)
|
if (prev)
|
||||||
prev->next = next;
|
prev->next = next;
|
||||||
|
next = prev = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cListObject::Index(void)
|
int cListObject::Index(void)
|
||||||
@ -92,6 +134,33 @@ void cListBase::Del(cListObject *Object)
|
|||||||
delete Object;
|
delete Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cListBase::Move(int From, int To)
|
||||||
|
{
|
||||||
|
Move(Get(From), Get(To));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cListBase::Move(cListObject *From, cListObject *To)
|
||||||
|
{
|
||||||
|
if (From && To) {
|
||||||
|
if (From->Index() < To->Index())
|
||||||
|
To = To->Next();
|
||||||
|
if (From == objects)
|
||||||
|
objects = From->Next();
|
||||||
|
if (From == lastObject)
|
||||||
|
lastObject = From->Prev();
|
||||||
|
From->Unlink();
|
||||||
|
if (To) {
|
||||||
|
if (To->Prev())
|
||||||
|
To->Prev()->Append(From);
|
||||||
|
From->Append(To);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
lastObject->Append(From);
|
||||||
|
if (!From->Prev())
|
||||||
|
objects = From;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void cListBase::Clear(void)
|
void cListBase::Clear(void)
|
||||||
{
|
{
|
||||||
while (objects) {
|
while (objects) {
|
||||||
|
16
tools.h
16
tools.h
@ -4,12 +4,13 @@
|
|||||||
* See the main source file 'osm.c' for copyright information and
|
* See the main source file 'osm.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: tools.h 1.1 2000/02/19 13:36:48 kls Exp $
|
* $Id: tools.h 1.2 2000/03/05 16:14:05 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TOOLS_H
|
#ifndef __TOOLS_H
|
||||||
#define __TOOLS_H
|
#define __TOOLS_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
@ -17,6 +18,14 @@
|
|||||||
#define esyslog syslog
|
#define esyslog syslog
|
||||||
#define isyslog syslog
|
#define isyslog syslog
|
||||||
|
|
||||||
|
#define SECSINDAY 86400
|
||||||
|
|
||||||
|
#define DELETENULL(p) (delete (p), p = NULL)
|
||||||
|
|
||||||
|
char *readline(FILE *f);
|
||||||
|
int time_ms(void);
|
||||||
|
bool MakeDirs(const char *FileName);
|
||||||
|
|
||||||
class cListObject {
|
class cListObject {
|
||||||
private:
|
private:
|
||||||
cListObject *prev, *next;
|
cListObject *prev, *next;
|
||||||
@ -38,6 +47,8 @@ public:
|
|||||||
virtual ~cListBase();
|
virtual ~cListBase();
|
||||||
void Add(cListObject *Object);
|
void Add(cListObject *Object);
|
||||||
void Del(cListObject *Object);
|
void Del(cListObject *Object);
|
||||||
|
void Move(int From, int To);
|
||||||
|
void Move(cListObject *From, cListObject *To);
|
||||||
void Clear(void);
|
void Clear(void);
|
||||||
cListObject *Get(int Index);
|
cListObject *Get(int Index);
|
||||||
int Count(void);
|
int Count(void);
|
||||||
@ -47,8 +58,7 @@ template<class T> class cList : public cListBase {
|
|||||||
public:
|
public:
|
||||||
T *Get(int Index) { return (T *)cListBase::Get(Index); }
|
T *Get(int Index) { return (T *)cListBase::Get(Index); }
|
||||||
T *First(void) { return (T *)objects; }
|
T *First(void) { return (T *)objects; }
|
||||||
|
T *Next(T *object) { return (T *)object->Next(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
int time_ms(void);
|
|
||||||
|
|
||||||
#endif //__TOOLS_H
|
#endif //__TOOLS_H
|
||||||
|
Loading…
Reference in New Issue
Block a user