MODULE TVChannels;
IMPORT
Files, XMLScanner, XMLParser, XML, XMLObjects, Dates, Strings, Clock;
CONST
ChannelFile* = "TVChannels.XML";
MaxAge = 180;
TYPE
TVChannel* = OBJECT
VAR
name*: ARRAY 33 OF CHAR;
freq*: LONGINT;
hasTeletext*: BOOLEAN;
cachingTime*: Dates.DateTime;
PROCEDURE &Init*;
BEGIN
hasTeletext := TRUE
END Init;
PROCEDURE HasRecentData*() : BOOLEAN;
VAR
dNow, tNow, dCache, tCache, hmNow, hmCache: LONGINT;
BEGIN
IF ~Dates.ValidDateTime(cachingTime) THEN
RETURN FALSE
END;
Clock.Get(tNow, dNow);
Dates.DateTimeToOberon(cachingTime, dCache, tCache);
IF dNow # dCache THEN
RETURN FALSE
END;
hmNow := tNow DIV 64;
hmCache := tCache DIV 64;
RETURN hmCache > (hmNow - MaxAge);
END HasRecentData;
END TVChannel;
ChannelArray = POINTER TO ARRAY OF TVChannel;
ChannelList* = OBJECT
VAR
list : ChannelArray;
count : LONGINT;
readLock : LONGINT;
PROCEDURE &New*;
BEGIN NEW(list, 8); readLock := 0
END New;
PROCEDURE GetCount*():LONGINT;
BEGIN
RETURN count
END GetCount;
PROCEDURE Grow;
VAR old: ChannelArray;
i : LONGINT;
BEGIN
old := list;
NEW(list, LEN(list)*2);
FOR i := 0 TO count-1 DO list[i] := old[i] END
END Grow;
PROCEDURE Add*(x : TVChannel);
BEGIN {EXCLUSIVE}
AWAIT(readLock = 0);
IF count = LEN(list) THEN Grow END;
list[count] := x;
INC(count)
END Add;
PROCEDURE IndexOf *(x: TVChannel) : LONGINT;
VAR i : LONGINT;
BEGIN
i := 0 ; WHILE i < count DO IF list[i] = x THEN RETURN i END; INC(i) END;
RETURN -1
END IndexOf;
PROCEDURE Remove*(x : TVChannel);
VAR i : LONGINT;
BEGIN {EXCLUSIVE}
AWAIT(readLock = 0);
i:=0; WHILE (i<count) & (list[i]#x) DO INC(i) END;
IF i<count THEN
WHILE (i<count-1) DO list[i]:=list[i+1]; INC(i) END;
DEC(count);
list[count]:=NIL
END
END Remove;
PROCEDURE Clear*;
VAR i : LONGINT;
BEGIN {EXCLUSIVE}
AWAIT(readLock = 0);
FOR i := 0 TO count - 1 DO list[i] := NIL END;
count := 0
END Clear;
PROCEDURE GetItem*(i:LONGINT) : TVChannel;
BEGIN
ASSERT((i >= 0) & (i < count), 101);
RETURN list[i]
END GetItem;
PROCEDURE Lock*;
BEGIN {EXCLUSIVE}
INC(readLock); ASSERT(readLock > 0)
END Lock;
PROCEDURE Unlock*;
BEGIN {EXCLUSIVE}
DEC(readLock); ASSERT(readLock >= 0)
END Unlock;
END ChannelList;
VAR
channels*: ChannelList;
PROCEDURE LoadChannelTable* (filename: ARRAY OF CHAR);
VAR
f: Files.File; reader: Files.Reader;
scanner: XMLScanner.Scanner; parser: XMLParser.Parser;
xmlChannels : XML.Document; enum: XMLObjects.Enumerator;
e : XML.Element; s : XML.String;
p : ANY;
ch : TVChannel;
BEGIN
IF channels = NIL THEN
NEW(channels)
END;
channels.Clear;
xmlChannels := NIL;
f := Files.Old (filename);
IF f # NIL THEN
NEW(reader, f, 0);
NEW(scanner, reader);
NEW(parser, scanner);
xmlChannels := parser.Parse();
IF xmlChannels # NIL THEN
e := xmlChannels.GetRoot();
enum := e.GetContents();
WHILE enum.HasMoreElements() DO
p := enum.GetNext();
IF p IS XML.Element THEN
e := p(XML.Element);
s := e.GetName();
IF (s # NIL) & (s^ = "Channel") THEN
NEW(ch);
s := e.GetAttributeValue ("name");
IF s # NIL THEN
COPY (s^, ch.name)
END;
s := e.GetAttributeValue ("freq");
IF s # NIL THEN
Strings.StrToInt (s^, ch.freq)
END;
s := e.GetAttributeValue ("teletext");
IF (s # NIL) & (s^ = "false") THEN
ch.hasTeletext := FALSE
END;
channels.Add (ch)
END
END
END
END
END
END LoadChannelTable;
BEGIN
NEW(channels);
LoadChannelTable(ChannelFile)
END TVChannels.