Update of /cvsroot/freevo/freevo/WIP/RobShortt/lib/vdrpylib
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16673

Added Files:
        README.vdrpylib __init__.py channel.py event.py mark.py 
        recording.py svdrp.py timer.py vdr.py 
Log Message:
This is vdrpylib, taken from http://sourceforge.net/projects/vdrpylib/ which 
looks very much like a dead project.  I have started on the bugfixes and
updates for Python 2.3.  This looks like a good library for interfacing with
VDR and we could add to it.


--- NEW FILE: vdr.py ---
#####################################################################
# Copyright 2002 Stefan Goetz
#####################################################################
# This file is part of vdrpylib.
# 
# vdrpylib is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# vdrpylib is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with vdrpylib; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#####################################################################

import cStringIO
import os.path
import re

import channel
import event
import recording
import svdrp
import timer

class VDR:
        """This class represents a VDR instance and all its associated
        data.
        
        It is a container for channel objects and runtime-related data.
        It offers functions to retrieve channel and EPG data from the
        VDR files or via SVDRP.
        
        The channels variable is a dictionary containing integer objects
        with the service ID of a channel as key and Channel objects as
        values.
        
        The recordings variable is a list containing Recording objects.
        The recordings are sorted by their start time.
        
        The timers variable is a list containing Timer objects. The
        timers are sorted according to their index.

        The host variable is a string containing the name of the host
        running VDR.
        
        The port variable is an integer containing the port at which the
        SVDR protocol is available on host.

        The vdrfile variable is a string containing the path to the VDR
        executable.

        The videopath variable is a string containing the path to the VDR
        recordings (specify /video<n> with the lowest <n> in your system
        if you have multiple directories containing recordings).

        The following variables specify path names for VDR data files.
        They default to the VDR default file names. Their paths are
        derived from the videopath variable.
        
        The cafile variable is a string containing the name of VDR's 
        ca.conf file.

        The channelsfile variable is a string containing the name of
        VDR's channels.conf file.

        The epgfile variable is a string containing the path to VDR's 
        epg.data file.

        The setupfile variable is a string containing the path to VDR's 
        setup.conf file.

        The svdrpfile variable is a string containing the path to VDR's 
        svdrphosts.conf file.

        The timerfile variable is a string containing the path to VDR's 
        timers.conf file.
        """

        def __init__(self,
                host = 'localhost',
                port = svdrp.SVDRP_PORT,
                vdrfile = '/usr/local/bin/vdr',
                videopath = '/video',
                cafile = 'ca.conf',
                channelsfile = 'channels.conf',
                epgfile = 'epg.data',
                setupfile = 'setup.conf',
                svdrpfile = 'svdrphosts.conf',
                timerfile = 'timers.conf'):
                
                self.svdrp = None
                self.channels = {}
                self.recordings = []
                self.timers = []

                self.host = host
                self.port = port
                
                self.vdrfile = vdrfile

                # determine all existing video paths
                self.videopath = videopath
                self.vpaths = self.getvpaths(self.videopath)

                # in the case of multiple video paths find where the
                # following files are located:
                self.cafile = self.findinvpaths(cafile)
                self.channelsfile = self.findinvpaths(channelsfile)
                self.epgfile = self.findinvpaths(epgfile)
                self.setupfile = self.findinvpaths(setupfile)
                self.svdrpfile = self.findinvpaths(svdrpfile)
                self.timerfile = self.findinvpaths(timerfile)


        def getvpaths(self, path):
                """Returns the available video paths (possibly) containing
                recordings in the system.
                """
                pat = re.compile('([^0-9]*)([0-9]+)')
                result = pat.match(self.videopath)
                if result is None:
                        return [path]
                else:
                        paths = []
                        basepath = result.groups(1)
                        curnr = int(result.groups(2))
                        if basepath == None:
                                basepath = ''
                        curpath = basepath + str(curnr)
                        while os.isdir(curpath):
                                paths.append(curpath)
                                curnr = curnr + 1
                                curpath = basepath + str(curnr)
                        return paths
        
        
        def findinvpaths(self, filename):
                """Tries to locate and verify the existence of a file in any
                of the vpaths.
                
                The filename variable is expected to be a string containing
                name of the file to be located.
                
                The return value is a string containing the full path of the
                file to be located. If no file with the specified name exists
                in any of the vpaths, None is returned.
                """
                for vpath in self.vpaths:
                        path = os.path.join(vpath, filename)
                        if os.path.isfile(path):
                                return path
                return None


        def getsvdrp(self):
                """Returns an SVDRP object to the VDR instance represented by
                this VDR object.
                
                The connection is made to the remote endpoint identified by
                the host and port variables. If host or port are None, no
                connection can established and this function returns None.
                """
                if self.svdrp is None and self.host and self.port:
                        self.svdrp = svdrp.SVDRP(self.host, self.port)
                return self.svdrp


        def close(self):
                """Closes the SVDRP connection to the VDR instance
                represented by this VDR object.
                """
                if self.svdrp is not None:
                        self.svdrp.close()
                        self.svdrp = None


        def getchannel(self, id):
                """Returns a channel by index, SID, or name.
                
                The id argument can be an integer which is either
                interpreted as an index of an channel if less than 1000 or as
                the     service ID of a channel if greater or equal than 1000.
                The     argument may also be a string containing the name of a
                channel. The specified string does not have to be a complete
                name as it is matched from the start of the name. If the
                string matches the start of multiple channel names, it is
                unspecified which channel is returned. The matching is
                performed case insensitively.
                
                The return value is a Channel object representing the
                channel found, or None if no channel could be identified from
                the first parameter
                """
                try:
                        x = int(id)
                        if x < 1000:
                                # assume that this is a channel's index
                                for ch in self.channels.values():
                                        if x in ch.indexes:
                                                return ch
                        else:
                                # assume that this is a channel's service ID
                                if self.channels.has_key(x):
                                        return self.channels[x]
                except:
                        # a string, well, must be a channel's name then
                        id = id.lower()
                        id_len = len(id)
                        for ch in self.channels.values():
                                if ch.name.lower()[0:id_len] == id:
                                        return ch
                
                return None


        def retrievechannels(self):
                """Retrieves the list of channels from VDR via SVDRP and adds
                them to the list of channels of this VDR object.
                
                The remote endpoint of the SVDRP connection used is
                identified by the host and port variables of this object.
                
                The return value is the list of Channel objects retrieved
                from VDR. If an error occurres the function returns None and
                the channel list of this VDR object is not modified.
                """
                if self.getsvdrp() is None:
                        return None
                chans = self.svdrp.lstc()
                
                if chans is not None:
                        self.channels = chans
                
                return chans
        
        
        def readchannels(self):
                """Reads a list of channels from VDR's channels.conf file and
                adds them to this VDR object.
                
                This function reads the file named by the channelfile
                variable.
                
                The return value is the list of Channel objects read from the
                file.
                """
                fh = open(self.channelsfile, 'r')
                counter = 0
                chans = {}
                line = fh.readline()
                while line:
                        line = line.strip()
                        if len(line) > 0 and line[0] != ':':
                                counter = counter + 1
                                c = channel.Channel(line, counter)
                                if chans.has_key(c.sid):
                                        chans[c.sid].indexes.append(counter)
                                else:
                                        chans[c.sid] = c
                        line = fh.readline()
                
                self.channels = chans
                return chans


        def parseepg(self, fh):
                """Parses EPG data in the format of VDR's epg.data file and
                adds it to this VDR object.
                
                This function can also handle data with SVDRP line headers.
                
                The fh arguments is the file handle to read the data from.
                
                The return value is an integer containing the number of EPG
                events parsed.
                """
                channel = None
                ev = None
                counter = 0

                line = fh.readline()
                while line:
                        line = line.strip()

                        # special handling of data coming in via SVDRP
                        if line[0:4] == '215-':
                                line = line[4:]
                        if line[0:4] == '250 ':
                                line = fh.readline()
                                continue

                        if line[0] == 'C':
                                # channel start
                                tokens = line.split(None, 2)
                                ch_sid = int(tokens[1])

                                if self.channels.has_key(ch_sid):
                                        channel = self.channels[ch_sid]
                                else:
                                        channel = channel.Channel()
                                        channel.sid = ch_sid
                                        channel.name = tokens[2]
                        elif line[0] == 'E':
                                # event start
                                ev = event.Event()
                                ev.parseheader(line[2:])
                                ev.source = 'vdr'
                                ev.channel = channel
                        elif line[0] == 'T':
                                # title
                                ev.title = line[2:]
                        elif line[0] == 'S':
                                # subtitle
                                ev.subtitle = line[2:]
                        elif line[0] == 'D':
                                # description
                                ev.desc = line[2:]
                        elif line[0] == 'e':
                                # event end
                                channel.addevent(ev)
                                ev = None
                                counter = counter + 1
                        elif line[0] == 'c':
                                # channel end
                                self.channels[channel.sid] = channel
                                channel = None
                        else:
                                # unknown line identifier
                                print 'Unable to parse line ' + line
                                break
                        line = fh.readline()
                fh.close()
                return counter


        def retrieveepg(self):
                """Retrieves EPG data via SVDRP from VDR and adds it to this
                VDR object.
                
                The remote endpoint of the SVDRP connection used is
                identified by the host and port variables of this object.
                
                The return value is an integer containing the number of EPG
                events retrieved or None if an error occurred or no
                connection could be established.
                """
                counter = 0
                if self.getsvdrp() is None:
                        return None
                result = self.svdrp.write_cmd('lste')
                fh = cstringio.cStringIO(result)
                return parseepg(fh)


        def readepg(self):
                """Reads EPG data from VDR's epg.data file and adds it to
                this VDR object.
                
                This function reads the file named by the epgfile variable.
                
                The return value is an integer containing the number of EPG
                events read.
                """
                fh = open(self.epgfile, 'r')
                return self.parseepg(fh)


        def updateepg(self, channels):
                """Transmit EPG data of this object to VDR.
                
                The channels argument is a list of Channel objects containing
                the Event objects to be added to VDR's EPG list.
                
                The return value is true if all EPG events were transmitted
                successfully, false else.
                """
                if self.getsvdrp() is None:
                        return None
                return self.svdrp.pute(channels)


        def retrieverecordings(self):
                """Retrieves all available information about recordings from
                VDR via SVDRP and adds such Recording objects to this VDR
                object.
                
                The remote endpoint of the SVDRP connection used is
                identified by the host and port variables of this object.
                
                The return value is a list containing Recording objects or
                None if an error occurred or no connection could be
                established.
                """
                if self.getsvdrp() is None:
                        return None
                result = self.svdrp.lstr()
                if result is not None:
                        self.recordings = result
                return result
        
        
        def readrecordings(self):
                """Scans the  recordings directories for all available
                information about recordings and adds such Recording objects
                to this VDR     object.
                
                The videopath variable of this object identifies the path(s)
                to be scanned.
                
                The return value is a list containing Recording objects or
                None if an error occurred.
                """
                self.recordings = []
                
                # what to do with every directory
                def visit(arg, dirname, names):
                        if dirname[-4:] == '.rec':
                                r = recording.Recording(dirname)
                                arg.append(r)
                
                # recursively search all video paths
                for curpath in self.vpaths:
                        os.path.walk(curpath, visit, self.recordings)
                
                # sort recordings by start time and set correct index
                self.recordings.sort()
                counter = 1
                for rec in self.recordings:
                        rec.index = counter
                        counter = counter + 1
                
                return self.recordings


        def retrievetimers(self):
                """Retrieves all available information about timers from
                VDR via SVDRP and adds such Timers objects to this VDR
                object.
                
                The remote endpoint of the SVDRP connection used is
                identified by the host and port variables of this object.
                
                The return value is a list containing Timer objects or
                None if an error occurred or no connection could be
                established.
                """
                if self.getsvdrp() is None:
                        return None
                result = self.svdrp.lstt()
                if result is not None:
                        self.timers = result
                return result
                

        def readtimers(self):
                """Reads VDR's timer file and adds the found Timer objects
                to this VDR     object.
                
                The timerfile variable of this object identifies the file
                to be read.
                
                The return value is a list containing Timer objects or
                None if an error occurred.
                """
                self.timers = []
                
                try:
                        index = 1
                        fh = open(self.timerfile, 'r')
                        line = fh.readline()
                        while line:
                                t = timer.Timer(line.strip(), index)
                                if t.name is None:
                                        print 'Could not parse line ' + str(index) + ' 
in file ' + self.timerfile + ': ' + line.strip()
                                self.timers.append(t)
                                line = fh.readline()
                                index = index + 1
                        fh.close()
                except IOError:
                        return None
                
                return self.timers






--- NEW FILE: __init__.py ---
#####################################################################
# Copyright 2002 Stefan Goetz
#####################################################################
# This file is part of vdrpylib.
# 
# vdrpylib is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# vdrpylib is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with vdrpylib; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#####################################################################


--- NEW FILE: timer.py ---
#####################################################################
# Copyright 2002 Stefan Goetz
#####################################################################
# This file is part of vdrpylib.
# 
# vdrpylib is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# vdrpylib is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with vdrpylib; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#####################################################################

#####################################################################
# Todo:
#####################################################################
# Find a nice way to represent the channel as an object


#####################################################################
# imports
#####################################################################
import re
import string
from types import *


#####################################################################
# module wide variables
#####################################################################
# a regex describing the format of a timer specification string
_pat = re.compile('((?P<index>\d+) 
)?(?P<id>\d+):(?P<channel>\d+):(?P<day>\d{0,2}|.{7}):(?P<start>\d+):(?P<stop>\d+):(?P<prio>\d+):(?P<lifetime>\d+):(?P<name>[^:]*):(?P<summary>.*)')


#####################################################################
# module wide functions
#####################################################################
def parsetime(t):
        """Converts a string containing a start or stop time in VDR's
        standard format ('hhmm') to the number of seconds since
        midnight.
        """
        return int(t[0:2]) * 3600 + int(t[2:4]) * 60


def strtime(t):
        """Converts the numeric start and stop time into a string
        with VDR's standard format ('hhmm').
        """
        return string.zfill(str(int(t / 3600)), 2) + string.zfill(str(int(t / 60) % 
60), 2)


def parserecurrence(s):
        """Converts the given string from VDR's representation of
        recurring timers to a list with 7 elements evaluating to true
        or false.
        """
        recurrence = [ 0 ] * 7
        for counter in range(0, 7):
                recurrence[counter] = (not (s[counter] == '-'))
        return recurrence


def strrecurrence(r):
        """Converts the internal recurrence representation into a string
        with VDR's format.
        """
        s = ''
        for x in r:
                if x:
                        s = s + 'X'
                else:
                        s = s + '-'
        return s


#####################################################################
# class definitions
#####################################################################
class Timer:
        """This class represents a VDR timer.
        
        The index variable is an integer containing the index of this
        timer into the total list of timers of a VDR instance.
        
        The name variable is a string containing the name of this timer
        also serving as the name for the corresponding recording.
        
        The summary variable is a string containing the name of this
        timer also serving as the name for the corresponding recording.
        
        The channel variable is an instance of class Channel containing
        the channel this timer should record on.
        
        The start variable is an integer containing the number of seconds
        after midnight specifying the start time of the timer.
        
        The stop variable is an integer containing the number of seconds
        after midnight specifying the stop time of the timer.
        
        The day variable is an integer. If the recurrence variable is
        None, it contains the day of month on which the recording is to
        take place. If the recurrence variable is not None, day specifies
        the day of month on which the recurring recording is to take
        place the first time.
        
        The recurrence variable is a 7-element list containing values
        evaluating either to true or false. Each element represents a
        week day, element 0 being Monday through element 6 being Sunday.
        Their values indicate whether the recording shall take place at
        the corresponding week day. If the recurrence variable is not
        None, day specifies the day of month on which the recurring
        recording is to take place the first time.
        If the recurrence variable is None, this is a one-shot timer.
        
        The prio variable is an integer containing the priority of this
        timer. Values may range between 1 and 99.

        The lifetime variable is an integer containing the lifetime of
        this timer in days. Values may range between 1 and 99.
        
        The active variable is an integer evaluating to true if this
        timer is active and evaluating to false otherwise.
        """

        def __init__(self, s = None, index = None, vdr = None):
                """Creates a new Timer object.
                
                The optional s argument is expected to be a string containing
                a timer specification as can be found in VDR's timers.conf
                file or as returned by the LSTT SVDRP command.
                
                The optional index argument is expected to be an integer
                containing the index of this timer into the global list of
                timers of a VDR instance. The index of a timer can only be
                derived from its specification string (i.e. the s argument)
                when it it's in the SVDRP format. When reading VDR's
                timers.conf file the timer indexes are encoded implicitely in
                the line number and have thus to be passed explicitely to
                this constructor.
                
                The optional vdr argument is expected to an instance of class
                VDR. When specified, this class can offer more advanced
                abstractions than without it in which case it merely serves
                as a data container.
                """
                self.index = index
                self.name = None
                self.summary = None
                self.channel = None
                self.start = None
                self.stop = None
                self.day = None
                self.recurrence = None
                self.prio = None
                self.lifetime = None
                self.active = None
                self.vdr = vdr
                
                if s is not None:
                        self.parse(s)
        
        
        def parse(self, s):
                """Parses a timer definition and updates the data of this
                object accordingly.
                
                The s argument is expected to be a string containing
                a timer specification as can be found in VDR's timers.conf
                file or as returned by the LSTT SVDRP command. Note that only
                the SVDRP version allows to derive the index of a timer from
                the specification string.
                
                The return value evaluates to true if the string s could be
                parsed successfully.
                """
                if s is not None and isinstance(s, StringType) and len(s) > 5:
                        s = s.strip()
                        if s[0:3] == '250':
                                s = s[4:]
                        res = _pat.match(s)
                        if res is not None:
                                if res.group('index') is not None:
                                        self.index = int(res.group('index'))
                                self.active = int(res.group('id'))
                                self.channel = int(res.group('channel'))
                                d = res.group('day')
                                if len(d) == 7:
                                        self.day = None
                                        self.recurrence = parserecurrence(d)
                                else:
                                        self.day = int(d)
                                        self.recurrence = None
                                self.start = parsetime(res.group('start'))
                                self.stop = parsetime(res.group('stop'))
                                self.prio = int(res.group('prio'))
                                self.lifetime = int(res.group('lifetime'))
                                self.name = res.group('name')
                                if self.name is None:
                                        self.name = ''
                                self.summary = res.group('summary')
                                if self.summary is None:
                                        self.summary = ''
                                return 1
                return 0
        
        
        def __cmp__(self, other):
                """Compares two Timer objects by their indexes.
                """
                return cmp(self.index, other.index)


        def __str__(self):
                """Returns a string representation of this object in the
                format of VDR's timers.conf file.
                """
                day = ''
                if self.recurrence is not None:
                        day = strrecurrence(self.recurrence)
                else:
                        day = str(self.day)
                return string.join(map(str, [self.active, self.channel, day, 
strtime(self.start), strtime(self.stop), self.prio, self.lifetime, self.name, 
self.summary]), ':')


        def getchannel(self):
                """Returns the channel this timer refers to.
                
                In contrast to the numeric channel variable, this function
                returns a channel object if the vdr variable is not None.
                
                The return value is a instance of class Channel or None if
                this timer refers to no or an invalid channel or the vdr
                variable is None.
                """
                if self.vdr and self.vdr.channels and self.channel:
                        return self.vdr.getchannel(self.channel)
                return None
                        

--- NEW FILE: svdrp.py ---
#####################################################################
# Copyright 2002 Stefan Goetz
#####################################################################
# This file is part of vdrpylib.
# 
# vdrpylib is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# vdrpylib is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with vdrpylib; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#####################################################################

# import modules
import re
import string
import telnetlib
import time
from types import *

import channel
import recording
import timer

# SVDRP constants
SVDRP_PORT=2001
SVDRP_CMD_CHAN = 'chan'
SVDRP_CMD_CLRE = 'clre'
SVDRP_CMD_DELC = 'delc'
SVDRP_CMD_DELR = 'delr'
SVDRP_CMD_DELT = 'delt'
SVDRP_CMD_GRAB = 'grab'
SVDRP_CMD_HELP = 'help'
SVDRP_CMD_HITK = 'hitk'
SVDRP_CMD_LSTC = 'lstc'
SVDRP_CMD_LSTE = 'lste'
SVDRP_CMD_LSTR = 'lstr'
SVDRP_CMD_LSTT = 'lstt'
SVDRP_CMD_MESG = 'mesg'
SVDRP_CMD_MODC = 'modc'
SVDRP_CMD_MODT = 'modt'
SVDRP_CMD_MOVC = 'movc'
SVDRP_CMD_MOVT = 'movt'
SVDRP_CMD_NEWC = 'newc'
SVDRP_CMD_NEWT = 'newt'
SVDRP_CMD_NEXT = 'next'
SVDRP_CMD_PUTE = 'pute'
SVDRP_CMD_SCAN = 'scan'
SVDRP_CMD_STAT = 'stat'
SVDRP_CMD_UPDT = 'updt'
SVDRP_CMD_VOLU = 'volu'
SVDRP_CMD_QUIT = 'quit'


class SVDRP(telnetlib.Telnet):
        """A wrapper for VDR's SVDRP interface.
        
        An SVDRP object represents a telnet session to a VDR instance.
        SVDRP functionality is wrapped either at a text or at an object
        level where appropriate.
        
        Since the SVDRP class is derived from the telnetlib.Telnet class,
        the plain telnet interface may also be used to drive the
        protocol manually.
        """
        def __init__(self, host = None, port = SVDRP_PORT):
                self.host = host
                self.port = port

                if host is None:
                        telnetlib.Telnet.__init__(self)
                else:
                        telnetlib.Telnet.__init__(self, self.host, self.port)
                        # consume all output
                        result = ''
                        while not result:
                                result = self.read_very_eager()

        
        def open(self, host = None, port = SVDRP_PORT):
                """Connect to a host.
 
                The optional port argument is the port number to connect to.
                It defaults to the standard SVDRP port (2001).

                Don't try to reopen an already connected instance.
                """
                if host:
                    telnetlib.Telnet.open(self, host, port)
                elif self.host:
                    telnetlib.Telnet.open(self, self.host, self.port)


        def close(self):
                self.write_cmd('quit')
                telnetlib.Telnet.close(self)


        def read_reply(self):
                """Read a SVDRP-style reply.
                
                Reads input until a reply to an SVDRP command is found.
                
                The function returns a string containing the complete reply.
                
                The     reply is expected to be delimited by a line starting with
                a 3-digit number followed by a blank, followed by arbitrary
                text and a terminating newline.
                """
                pat = re.compile('^\d\d\d .*\n', re.M)
                reply = ''
                buffer = self.read_very_eager()
                while not pat.search(buffer):
                        reply = reply + buffer
                        time.sleep(0.2)
                        buffer = self.read_very_eager()
                reply = reply + buffer
                return reply


        def write_cmd(self, cmd):
                """Send text to the server and return its reply.
                
                The cmd argument contains the string written to the
                underlying telnet object. It is made sure that the string
                ends in a newline character so that it is recognized as a
                command by VDR.
                
                The function returns a string containing VDR's reply.
                """
                if len(cmd) == 0:
                        return ''
                if cmd[-1] != '\n':
                        cmd = cmd + '\n'
                self.read_very_eager()
                self.write(cmd)
                return self.read_reply()

        
        def hitk(self, key):
                """Hit the given remote control key.
                
                The key argument is expected to be a string containing one
                of the key names understood by VDR.
                
                The return value is 0 if the command failed and 1 otherwise.
                """
                result = self.write_cmd('hitk ' + str(key) + '\n')
                if result[0:3] == '250':
                        return 1
                else:
                        print 'hitk returned: ' + result
                        return 0
        

        def chan(self, chan, vdr = None):
                """Switch the current channel.
                
                The channel argument can be a Channel object or a string
                containing a channel name or index or being '+' or '-' for
                switching to the next or previous channel.
                
                The vdr argument is a VDR object from which fully qualified
                Channel object can be retrieved.
                
                The return value is a Channel object representing the
                current channel if a VDR object was supplied, else it is the
                string returned by VDR or None if the command failed.
                """
                if isinstance(chan, channel.Channel):
                        result = self.write_cmd('chan ' + channel.name + '\n')
                elif isinstance(chan, StringType) or isinstance(chan, IntType):
                        result = self.write_cmd('chan %s\n' % chan)
                if result[0:3] == '250':
                        if vdr:
                                return vdr.getchannel(result.split(None, 2)[1])
                        else:
                                return result[3:]
                else:
                        print 'chan returned: ' + result
                        return None
        

        def lstc(self, id = None):
                """List channel details.
                
                If the id argument is an integer the channel with that
                index is listed. If the argument is a string all channels
                containing that string as part of their name are listed.
                If the argument is None, all channels are listed.
                
                The return value is a list of Channel objects representing
                the listed channels. If the command failed, None is returned.
                """
                if id is None:
                        result = self.write_cmd('lstc\n')
                else:
                        result = self.write_cmd('lstc ' + str(id) + '\n')
                
                # check first line of output
                if result[0:3] != '250':
                        print 'lstc returned: ' + result
                        return None
                
                if id is None:
                        # return recording summary
                        return result[4:]
                else:
                        # create Channel objects from output
                        channels = {}
                        counter = 1
                        for line in result.split('\n'):
                                if len(line) > 5:
                                        tokens = line.strip()[4:].split(None, 1)
                                        if len(tokens) > 1:
                                                c = channel.Channel(tokens[-1], 
counter)
                                                channels[c.sid] = c
                                                counter = counter + 1

                        return channels


        def pute(self, channels):
                """Put data into the EPG list.
                
                The channels argument is a list of Channel objects containing
                the Event objects to be the EPG list.
                
                The return value is true if all EPG events were transmitted
                successfully, false else.
                """
                result = self.write_cmd('pute\n')
                if result[0:3] != '354':
                        print 'pute returned: ' + result
                        return 0

                for ch in channels:
                        self.write(ch.getepgstr())
                self.write('.\n')

                result = self.read_reply()
                if result[0:3] != '250':
                        print 'pute returned: ' + result
                        return 0
                
                return 1


        def lstr(self, index = None):
                """List VDR recordings.
                
                The optional index argument is expected to be an integer
                containing an index into the global list of recordings.
                
                If no index argument is given, the return value is a list of
                Recording objects. If an index is given, a string containing
                the summary for that recording is returned.
                If an error occurs, None is returned.
                """
                result = ''
                if index is None:
                        result = self.write_cmd('lstr\n')
                else:
                        result = self.write_cmd('lstr ' + str(index) + '\n')
                        if result[0:3] == '550':
                                return ''
                        elif result[0:3] == '250':
                                return result.strip()[4:]

                # check first line of output
                if result[0:3] != '250':
                        print 'lstr returned: ' + result
                        return None
                
                # create Recording objects from output
                recs = []
                for line in result.split('\n'):
                        if len(line) > 5 and line[:3] == '250':
                                r = recording.Recording(line)
                                r.setsource(self)
                                recs.append(r)
                
                return recs


        def lstt(self, index = None):
                """List VDR timers.
                
                The optional index argument is expected to be an integer
                containing an index into the global list of timers.
                
                If no index argument is given, the return value is a list of
                Timer objects. If an index is given, a Timer object
                representing the timer with the specified index is
                returned. If an error occurs, None is returned.
                """
                result = ''
                if index is None:
                        result = self.write_cmd('lstt\n')
                else:
                        result = self.write_cmd('lstt ' + str(index) + '\n')

                # check first line of output
                if result[0:3] != '250':
                        print 'lstt returned: ' + result
                        return None
                
                # create Recording objects from output
                timers = []
                for line in result.split('\n'):
                        if len(line) > 5 and line[:3] == '250':
                                t = timer.Timer(line)
                                timers.append(t)
                
                return timers


                



--- NEW FILE: event.py ---
#####################################################################
# Copyright 2002 Stefan Goetz
#####################################################################
# This file is part of vdrpylib.
# 
# vdrpylib is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# vdrpylib is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with vdrpylib; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#####################################################################

class Event:
        """Represents an event in the EPG data, i.e. a program.
        """

        def __init__(self):
                """Constructs an Event object with all fields set to None.
                """
                self.channel = None
                self.id = None
                self.start = None
                self.dur = None
                self.tableID = None
                self.title = None
                self.subtitle = None
                self.desc = None
                self.source = None
                

        def __str__(self):
                """Returns a string representation for this event in the
                format of VDR's epg.data file.
                """
                s = 'E ' + str(self.id) + ' ' + str(self.start) + ' ' + str(self.dur)
                if self.tableID is not None and self.tableID != 0:
                        s = s + ' ' + self.tableID
                s = s + '\n'
                if self.title is not None:
                        s = s + 'T ' + self.title + '\n'
                if self.subtitle is not None:
                        s = s + 'S ' + self.subtitle + '\n'
                if self.desc is not None:
                        s = s + 'D ' + self.desc + '\n'
                s = s + 'e\n'
                return s
        
        
        def __cmp__(self, other):
                """Compares this event against another by their start times.
                """
                return cmp(self.start, other.start)
        

        def parseheader(self, str):
                """Parses a string containing an event specification in the
                format of VDR's epg.data file.
                
                The first argument is the specification string to parse.
                
                Returns true if the specification string could be parsed
                successfully, false else.
                """
                tokens = str.split()
                if len(tokens) < 3 or len(tokens) > 4:
                        return 0
                self.id = int(tokens[0])
                self.start = int(tokens[1])
                self.dur = int(tokens[2])
                if len(tokens) == 4:
                        self.tableID = tokens[3]
                return 1

--- NEW FILE: recording.py ---
#####################################################################
# Copyright 2002 Stefan Goetz
#####################################################################
# This file is part of vdrpylib.
# 
# vdrpylib is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# vdrpylib is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with vdrpylib; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#####################################################################

import os.path
import re
import string
import struct
import time
from types import *

import svdrp


class Recording:
        """This class represents a VDR recording.
        
        Data about a recording can either be obtained via SVDRP or by
        disk access (which gives more accurate information).
        
        Note that when setting an SVDRP object as a recording's source,
        this SVDRP object is implicitely accessed in some of the getXXX()
        functions. Further accesses go to cache but the SVDRP connection
        may not be closed until after the first access to those getXXX()
        functions.
        """

        def __init__(self, source = None, index = None):
                """Creates a new Recording object.
                
                The optional source argument is expected to be an SVDRP object or a
                string containing a recording description in the format as
                returned by the SVDRP LSTR command or a string containing
                the path to a recording.
                
                The index is expected to be an integer containing the index
                of this recording into the total list of recordings of a VDR
                instance (base 1). If the source argument is a recording
                description the index is derived from that description rather
                than from the index argument which may thus be ommitted.
                
                With SVDRP connections it is more efficient to run the LSTR
                command once and create a Recording object per line than
                creating multiple Recording object with an SVDRP object and
                varying indexes as this requires as many executions of the
                LSTR command.
                """
                self.source = source
                self.index = index
                self.name = None
                self.summary = None
                self.start = None
                self.prio = None
                self.lifetime = None
                self.marks = None
                self.resume = None
                
                if source is not None:
                        self.init(source, index)
        
        
        def init(self, source, index = None):
                """Initialize the data associated with this recording object
                from the given source.
                
                The source argument is expected to be an SVDRP object or a
                string containing a recording description in the format as
                returned by the SVDRP LSTR command or a string containing
                the path to a recording.
                
                The index is expected to be an integer containing the index
                of this recording into the total list of recordings of a VDR
                instance (base 1). If the source argument is a recording
                description the index is derived from that description rather
                than from the index argument which may thus be ommitted.
                
                With SVDRP connections it is more efficient to run the LSTR
                command once and create a Recording object per line than
                creating multiple Recording object with an SVDRP object and
                varying indexes as this requires as many executions of the
                LSTR command.
                """
                if isinstance(source, svdrp.SVDRP) and index is not None:
                        pat = re.compile('250[ -]' + str(index) + ' ')
                        result = source.write_cmd('LSTR\n')
                        if result[0:3] != '250':
                                print 'lstr returned: ' + result
                        for line in result.split('\n'):
                                line = line.strip()
                                if pat.match(line):
                                        self.init(line)
                                        
                elif isinstance(source, StringType) and len(source) > 5 and source[:3] 
== '250':
                        tokens = source.strip()[4:].split(None, 3)
                        if len(tokens) == 4:
                                self.index = int(tokens[0])
                                if len(tokens[1].split('.')) == 2:
                                        tokens[1] = tokens[1] + '.' + 
time.strftime('%Y')
                                self.start = int(time.mktime(time.strptime(tokens[1] + 
' ' + tokens[2].replace('*', ''), '%d.%m.%Y %H:%M')))
                                self.name = tokens[3]
                                if tokens[2].find('*'):
                                        self.resume = 0
                                else:
                                        self.resume = -1
                
                elif isinstance(source, StringType) and os.path.isdir(source):
                        pat = 
re.compile('(/video\d*/)?(.*)/(\d{4}-\d\d-\d\d\.\d\d\.\d\d)\.(\d\d)\.(\d\d)\.rec/?')
                        result = pat.match(source)
                        if result is None:
                                raise TypeError, 'path of recording has unknown format'
                        self.index = index
                        self.name = result.group(2)
                        self.start = int(time.mktime(time.strptime(result.group(3), 
'%Y-%m-%d.%H.%M')))
                        self.prio = int(result.group(4))
                        self.lifetime = int(result.group(5))
                
                else:
                        raise TypeError, 'argument source has invalid type'
        
        
        def getsource(self):
                """Returns the data source of this recording object.
                
                The return value is either a SVDRP object or a string
                containing the path to this recording.
                """
                return self.source
        
        
        def setsource(self, source):
                """Sets a data source for this recording object.
                
                The source argument is expected to be either a SVDRP object
                or a string containing the path to a recording.
                """
                if isinstance(source, svdrp.SVDRP) or \
                        (isinstance(source, StringType) and \
                        os.path.isdir(source)):
                        self.source = source
                else:
                        raise TypeError, 'argument source has invalid type'
        
        
        def getindex(self):
                """Returns the index of this recording.
                
                The return value is an integer representing the index of this
                recording into the complete list of recordings of a VDR
                instance.
                """
                return self.index
        
        
        def getname(self):
                """Returns the name of this recording.
                
                The return value is a string containing the name of this
                recording.
                """
                return self.name
        
        
        def getsummary(self):
                """Returns the summary of this recording.
                
                Depending on the source given at construction time, the
                summary for this recording is retrieved via SVDRP or from
                the summary.vdr file.
                
                The return value is a string containing the summary of this
                recording.
                """
                if self.summary is None:
                        if isinstance(self.source, svdrp.SVDRP):
                                self.summary = self.source.lstr(self.index)
                        elif isinstance(self.source, StringType) and 
os.path.isdir(self.source):
                                fh = open(os.path.join(self.source, 'summary.vdr'), 
'r')
                                self.summary = fh.read()
                                fh.close()
                return self.summary
        
        
        def getstart(self):
                """Returns the start time of this recording.
                
                The return value is an integer containing the time when the
                recording started as seconds since the epoch.
                """
                return self.start
        
        
        def getprio(self):
                """Return the priority of this recording.
                
                The return value is an integer containing the priority of
                this recording (which is derived from the corresponding
                timer).
                """
                return self.prio
        
        
        def getlifetime(self):
                """Returns the lifetime of this recording.
                
                The return value is an integer containing the number of days
                since start this recording is guaranteed to not be deleted by
                VDR.
                """
                return self.lifetime
        
        
        def getmarks(self):
                """Returns the editing marks of this recording.
                
                The return value is a list of Mark objects representing the
                editing marks of this recording.
                """
                if self.marks is None:
                        if isinstance(self.source, StringType) and \
                                os.path.isdir(self.source) and \
                                os.path.isfile(os.path.join(self.source, 'marks.vdr')):
                                
                                self.marks = []
                                fh = open(os.path.join(self.source, 'marks.vdr'), 'r')
                                line = fh.readline()
                                while line:
                                        mk = mark.Mark(line.strip())
                                        self.marks.append(mk)
                                        line = fh.readline()
                                fh.close()
                                
                return self.marks
        
        
        def getresume(self):
                """Returns the resume offset for this recording.
                
                The return value is an integer containing the resume offset
                of this recording.
                
                If the recording does not have a resume offset, the return
                value is -1. If the recording has an unknown resume offset
                (may occur when retrieving recording data via SVDRP), the
                return value is 0.
                """
                if self.resume is None:
                        dfn = None
                        if isinstance(self.source, StringType) and \
                                os.path.isdir(self.source):
                                if os.path.isfile(os.path.join(self.source, 
'resume.vdr')):
                                        fh = open(os.path.join(self.source, 
'resume.vdr'), 'r')
                                        nr = fh.read()
                                        fh.close()
                                        self.resume = struct.unpack('l', nr)[0]
                                else:
                                        self.resume = -1
                        elif isinstance(self.source, StringType) and len(self.source) 
> 5 and self.source[:3] == '250':
                                dfn = self.source
                        elif isinstance(self.source, svdrp.SVDRP):
                                dfn = self.source.lstr(self.index)
                        
                        if dfn is not None:
                                tokens = dfn.strip()[4:].split(None, 3)
                                if len(tokens) == 4:
                                        if tokens[2].find('*'):
                                                self.resume = 0
                                        else:
                                                self.resume = -1
                return self.resume
        
        
        def isnew(self):
                """Returns whether this recording is unwatched, i.e. whether
                it does not have a resume offset.
                """
                return self.getresume() == -1


        def __cmp__(self, other):
                """Compares two Recording objects by their start times.
                """
                return cmp(self.start, other.start)









--- NEW FILE: mark.py ---
#####################################################################
# Copyright 2002 Stefan Goetz
#####################################################################
# This file is part of vdrpylib.
# 
# vdrpylib is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# vdrpylib is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with vdrpylib; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#####################################################################

import re

class Mark:
        """This class represents an editing mark of a VDR recording.

        The seconds variable is an integer representing the offset of
        this mark into the recording in seconds.
        
        The frames variable is an integer representing the offset of
        this mark into the recording relative to the position 
        indicated by the seconds variable. With 25 fps recordings the
        value of this variable ranges between 0 and 24.
        
        The comment variable is a string containing the comment of this
        mark. If there is no comment associated with this mark, this
        variable is None.
        """
        _pat = re.compile('(\d\d):(\d\d):(\d\d)(\.(\d+))?( (.*))?')

        def __init__(self, str = None):
                """Construct a new Mark object.
                
                The optional str argument is a string containing the
                specification of an editing mark in the format of VDR's
                marks.vdr file.
                """
                self.seconds = 0
                self.frames = 0
                self.comment = None
                
                if str is not None:
                        self.parse(str)


        def parse(self, str):
                """Parse a string for editing mark data and update this
                object's data accordingly.
                
                The str argument is a string containing the
                specification of an editing mark in the format of VDR's
                marks.vdr file.
                """
                res = _pat.match(str)
                self.seconds = int(res.group(1)) * 3600 + int(res.group(2)) * 60 + 
int(res.group(3))
                if result.group(4) is None:
                        self.frames = 0
                else:
                        self.frames = int(result.group(5))
                self.comment = result.group(7)
        
        
        def __str__(self):
                """Returns a string representation of this mark in the format
                of VDR's marks.vdr file.
                """
                s = str(self.seconds / 3600) + ':' + str((self.seconds / 60) % 60) + 
':' + str(self.seconds % 60)
                if self.frames != 0:
                        s = s + '.' + str(self.frames)
                if self.comment is not None:
                        s = s + ' ' + self.comment
                return s



                

--- NEW FILE: README.vdrpylib ---
VDR Python Library ('vdrpylib')
-------------------------------

This is a programming library written in Python (http://python.org/) for the
Video Disk Recorder (VDR) project (http://www.cadsoft.de/people/kls/vdr/).

Please see the INSTALL file for details on how to install this program on your
computer.

For further information please refer to http://sourceforge.net/projects/vdrpylib/

The author can be contacted at [EMAIL PROTECTED]


Applications
------------

Also part of this package are the following applications based on vdrpylib:

- Extended Electronic Program Guide ('expg')

Please see the README files in the coresponding sub-directories for additional
information


Library Concepts and Overview
-----------------------------

The idea of this library is to represent the data available from an
instance of VDR as a class hierarchy. It shall relieve the programmer
of the burden to directly interact with VDR's interfaces like
configuration files or SVDRP. Instead a programmer can examine and
manipulate timers, recordings, etc. at the class level.

Class Hierarchy:

The central class of the library is the VDR class serving both as the
main data container and as a control interface to VDR. It collects
objects of these types:
- Channel
- Timer
- Recording

The Channel class collects objects of these types:
- Event (EPG events)

The Timer class only contains singular members.

The Recording class collects objects of these types:
- Mark (editing mark)

Class Dependencies:

The library tries to encapsulate all data entities in classes. Many
of those entities are associated with each other, e.g. timers and EPG
events are associated with channels.
VDR represents such associations in a very simple form (often an
index into a global list of the associated object). Thus, vdrpylib
needs to retrieve all available objects from VDR (channels in this
example) in order to provide a class view of such associations (so
that a timer object actually provides a channel object and not only
the integer index).
Of course this is rather expensive and may be unwanted if all the
programmer needs is a single object type (e.g. she may want to simply
parse the timers file).
Thus, vdrpylib uses the VDR class as a central data container which
allows classes to establish references to each other. If an object
like Timer is supplied with a VDR object, it can represent channels
as the objects it finds in the VDR object. If the Timer is not passed
an instance of class VDR, it merely serves itself as a container for
timer data.

--- NEW FILE: channel.py ---
#####################################################################
# Copyright 2002 Stefan Goetz
#####################################################################
# This file is part of vdrpylib.
# 
# vdrpylib is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# vdrpylib is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with vdrpylib; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#####################################################################

import string

class Channel:
        """This class represents a program channel.
        
        It is intended to a container for the technical channel data as
        as for EPG Event objects.
        
        VDR may place a single physical channel at several locations in
        its global list of channels. This class does not represent a slot
        in the global list of channels but a physical channel. Physical
        channels are assumed to be uniquely identifiable by their SID.
        
        The indexes variable is a list containing the indexes of this
        channel in the global list of channels of a VDR instance.
        
        The name variable is a string containing the name of this
        channel.
        
        The freq variable is an integer containing the frequency of this
        channel in Hz.
        
        The pol variable is a string of length one containing the
        polariazation of this channel. 'h' stands for horizontal, 'v' for
        vertical polarization.
        
        The diseqc variable is an integer containing the DiSEqC code for
        this channel.
        
        The srate variable is an integer containing the symbol rate of
        this channel.
        
        The vpid variable is an integer containing the video PID of this
        channel.
        
        The apids variable is a list of integers containing the audio
        PIDs of this channel.
        
        The dpis variable is a list of integers containing the dolby
        digital (AC3) PIDs of this channel.
        
        The tpid variable is an integer containing the teletext PID of
        this channel.
        
        The ca variable is an integer defining how the channel can be
        accessed over the available DVB cards.
        
        The sid variable is an integer containing the service ID of this
        channel.
        
        The events variable is a list of Event objects sorted by start
        time. The list should not be manipulated directly but only
        through the XXXevent() functions of this class.
        """
        def __init__(self, line = None, index = None):
                self.indexes = []
                self.name = None
                self.freq = None
                self.pol = None
                self.diseqc = None
                self.srate = None
                self.vpid = None
                self.apids = []
                self.dpids = []
                self.tpid = None
                self.ca = None
                self.sid = None
                self.events = []
                if line is not None:
                        self.parse(line)
                if index is not None:
                        self.indexes.append(index)
                
        def __str__(self):
                """Creates a string representation of this channel object
                in the format of VDR's channels.conf file.
                """
                apids = string.join([string.join(map(str, self.apids), ','), 
string.join(map(str, self.dpids), ',')], ';')
                return string.join(map(str, [self.name, self.freq, self.pol, 
self.diseqc, self.srate, self.vpid, apids, self.tpid, self.ca, self.sid]), ':')

        
        def parse(self, string):
                """Parses a standard channel specification as can be found in
                VDR's channels.conf file.
                
                All fields of this channel object are set according to the 
                specification string given in the first argument.
                """
                tokens = string.strip().split(':')
                self.name = tokens[0]
                self.freq = int(tokens[1])
                self.pol = tokens[2]
                self.diseqc = int(tokens[3])
                self.srate = int(tokens[4])
                self.vpid = int(tokens[5])
                apids = tokens[6]
                self.tpid = int(tokens[7])
                self.ca = int(tokens[8])
                self.sid = int(tokens[9])
                tokens = apids.split(';')
                self.apids = map(int, tokens[0].split(','))
                if len(tokens) == 2:
                        self.dpids = map(int, tokens[1].split(','))
                
        def addevent(self, ev):
                """Add an EPG event to the list of events for this channel.
                
                If the event has no ID one is assigned.
                
                The first argument shall be an Event object representing
                the event to be added. The start time of the event to add
                must be later than the end of any other event of this
                channel.
                
                The return value is the ID of the event if it satisfied the
                given restrictions and was added, else None is returned.
                """
                if len(self.events) == 0 or self.events[-1].start + 
self.events[-1].dur <= ev.start:
                        self.events.append(ev)
                        if ev.id is None:
                                if len(self.events) > 1:
                                        ev.id = (self.events[-2].id + 1) % 65536
                                else:
                                        ev.id = 0
                        return ev.id
                else:
                        return None
        
        
        def getepgstr(self):
                """Creates a string representation of this channel object
                in the format of VDR's epgdata file including all contained
                EPG events.
                """
                s = 'C ' + str(self.sid)
                if self.name is not None:
                        s = s + ' ' + self.name
                s = s + '\n'
                for ev in self.events:
                        s = s + str(ev)
                s = s + 'c\n'
                return s



-------------------------------------------------------
This SF.Net email is sponsored by BEA Weblogic Workshop
FREE Java Enterprise J2EE developer tools!
Get your free copy of BEA WebLogic Workshop 8.1 today.
http://ads.osdn.com/?ad_id=4721&alloc_id=10040&op=click
_______________________________________________
Freevo-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to