F V wrote:
Thank you for your help....but i can't donwload the attachment: tvtime.py
Can you send it to me by mail ?
Can i use it instead of " my tvtime.py " ? How ?

thanks

<snip>
Hi,

I've attached it again to this email. You might be able to just replace your tvtime.py but as I mentioned my version is quite old, from freevo-1.5.1 maybe so depending on what version you are running there could be issues. Back up your tvtime.py and try out this one. To use it I guess you'll have to at least change the line 'if config.CHANLIST =="ireland":' That will have to match whatever you have in your /etc/freevo/freevo.conf file from what I remember.

John
# -*- coding: iso-8859-1 -*-
# -----------------------------------------------------------------------
# tvtime.py - implementation of a TV function using tvtime
# -----------------------------------------------------------------------
# $Id: tvtime.py,v 1.38 2004/07/10 12:33:42 dischi Exp $
#
# Notes:
# Todo:        
#
# -----------------------------------------------------------------------
# $Log: tvtime.py,v $
# Revision 1.38  2004/07/10 12:33:42  dischi
# header cleanup
#
# Revision 1.37  2004/07/08 12:44:40  rshortt
# Add directfb as a display option.
#
# Revision 1.36  2004/06/06 17:15:10  mikeruelle
# removed some old bad code. mplayer debug has been superceded by childapp 
debug.
# the kill method is just plain bad.
#
# Revision 1.35  2004/05/29 23:01:03  mikeruelle
# make better use of freevo channels. getting better video group support slowly
#
# -----------------------------------------------------------------------
# Freevo - A Home Theater PC framework
# Copyright (C) 2002 Krister Lagerstrom, et al. 
# Please see the file freevo/Docs/CREDITS for a complete list of authors.
#
# This program 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.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MER-
# CHANTABILITY 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 this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ----------------------------------------------------------------------- */


# Configuration file. Determines where to look for AVI/MP3 files, etc
import config

import time, os
import string
import threading
import signal
import cgi
import re
import popen2
from xml.dom.ext.reader import Sax2
from xml.dom.ext import PrettyPrint
from cStringIO import StringIO

import util    # Various utilities
import osd
import rc      # The RemoteControl class.
import childapp # Handle child applications
import tv.epg_xmltv as epg # The Electronic Program Guide
import event as em
from tv.channels import FreevoChannels

import plugin

# Set to 1 for debug output
DEBUG = config.DEBUG

# Create the OSD object
osd = osd.get_singleton()

class PluginInterface(plugin.Plugin):
    """
    Plugin to watch tv with tvtime.
    """
    def __init__(self):
        plugin.Plugin.__init__(self)

        # get config locations and mod times so we can check if we need
        # to regen xml config files (because they changed)
        self.mylocalconf = self.findLocalConf()
        self.myfconfig = os.environ['FREEVO_CONFIG']
        self.tvtimecache = os.path.join(config.FREEVO_CACHEDIR, 'tvtimecache')
        self.mylocalconf_t = os.path.getmtime(self.mylocalconf)
        self.myfconfig_t = os.path.getmtime(self.myfconfig)

        self.xmltv_supported = self.isXmltvSupported()

        #check/create the stationlist.xml and tvtime.xml
        self.createTVTimeConfig()

        # create the tvtime object and register it
        plugin.register(TVTime(), plugin.TV)

    def isXmltvSupported(self):
        helpcmd = '%s --help' %  config.TVTIME_CMD
        has_xmltv=False
        child = popen2.Popen3( helpcmd, 1, 100)
        data = child.childerr.readline() # Just need the first line
        if data:
            data = re.search( "^(tvtime: )?Running tvtime 
(?P<major>\d+).(?P<minor>\d+).(?P<version>\d+).", data )
            if data:
                _debug_("major is: %s" % data.group( "major" ))
                _debug_("minor is: %s" % data.group( "minor" ))
                _debug_("version is: %s" % data.group( "version" ))
                major = int(data.group( "major" ))
                minor = int(data.group( "minor" ))
                ver = int(data.group( "version" ))
                if major > 0:
                    has_xmltv=True
                elif major == 0 and minor == 9 and ver >= 10:
                    has_xmltv=True
        child.wait()
        return has_xmltv

    def findLocalConf(self):
        cfgfilepath = [ '.', os.path.expanduser('~/.freevo'), '/etc/freevo' ]
        mylocalconf = ''
        for dir in cfgfilepath:
            mylocalconf = os.path.join(dir,'local_conf.py')
            if os.path.isfile(mylocalconf):
                break
        return mylocalconf

    def createTVTimeConfig(self):
        tvtimedir = os.path.join(os.environ['HOME'], '.tvtime')
        if not os.path.isdir(tvtimedir):
            os.mkdir(tvtimedir)
        if self.needNewConfigs():
            self.writeStationListXML()
            self.writeTvtimeXML()
            self.writeMtimeCache()

    def needNewConfigs(self):
        tvtimedir = os.path.join(os.environ['HOME'], '.tvtime')
        if not os.path.isfile(os.path.join(tvtimedir, 'stationlist.xml')):
            return 1

        if not os.path.isfile(os.path.join(tvtimedir, 'tvtime.xml')):
            return 1

        if not os.path.isfile(self.tvtimecache):
            _debug_('no cache file')
            return 1

        (cachelconf, cachelconf_t, cachefconf_t) = self.readMtimeCache()

        cachelconf = cachelconf.rstrip()
        cachelconf_t = cachelconf_t.rstrip()
        cachefconf_t = cachefconf_t.rstrip()

        if not (cachelconf == self.mylocalconf): 
            _debug_('local_conf changed places')
            return 1

        if (long(self.mylocalconf_t) > long(cachelconf_t)):
            _debug_('local_conf modified')
            return 1

        if (long(self.myfconfig_t) > long(cachefconf_t)):
            _debug_('fconfig modified')
            return 1

        return 0

    def readMtimeCache(self):
        return file(self.tvtimecache, 'rb').readlines()

    def writeMtimeCache(self):
        fp = open(self.tvtimecache, 'wb')
        fp.write(self.mylocalconf)
        fp.write('\n')
        fp.write(str(self.mylocalconf_t))
        fp.write('\n')
        fp.write(str(self.myfconfig_t))
        fp.write('\n')
        fp.close()

    def writeTvtimeXML(self):
        tvtimexml = os.path.join(os.environ['HOME'], '.tvtime', 'tvtime.xml')
        configcmd = os.path.join(os.path.dirname(config.TVTIME_CMD), 
"tvtime-configure")
        #cf_norm, cf_input, cf_clist, cf_device = config.TV_SETTINGS.split()
        fc = FreevoChannels()
        vg = fc.getVideoGroup(config.TV_CHANNELS[0][2])
        cf_norm = vg.tuner_norm
        cf_input = vg.input_num
        cf_device = vg.vdev
        s_norm = cf_norm.upper()
        daoptions = ''
        if os.path.isfile(tvtimexml):
            daoptions = ' -F ' + tvtimexml
        if self.xmltv_supported:
            daoptions += ' -d %s -n %s -t %s' % (cf_device, s_norm, 
config.XMLTV_FILE)
        else:
            daoptions += ' -d %s -n %s' % (cf_device, s_norm)
        if hasattr(config, "TV_TVTIME_SETUP_OPTS") and 
config.TV_TVTIME_SETUP_OPTS:
            daoptions += ' %s' % config.TV_TVTIME_SETUP_OPTS
        os.system(configcmd+daoptions)

    def writeStationListXML(self):
        self.createChannelsLookupTables()
        norm='freevo'
        tvnorm = config.CONF.tv
        tvnorm = tvnorm.upper()
        tvtimefile = os.path.join(os.environ['HOME'], '.tvtime', 
'stationlist.xml')
        if os.path.isfile(tvtimefile):
            self.mergeStationListXML(tvtimefile, tvnorm, norm)
        else:
            self.writeNewStationListXML(tvtimefile, tvnorm, norm)

    def mergeStationListXML(self, tvtimefile, tvnorm, norm):
        _debug_("merging stationlist.xml")
        try:
            os.rename(tvtimefile,tvtimefile+'.bak')
        except OSError:
            return

        reader = Sax2.Reader()
        doc = reader.fromStream(tvtimefile+'.bak')
        mystations = doc.getElementsByTagName('station')
        gotlist = 0
        freevonode = None
        for station in mystations:
            myparent = station.parentNode
            if myparent.getAttribute('norm') == tvnorm and 
myparent.getAttribute('frequencies') == 'freevo':
                myparent.removeChild(station)
                freevonode = myparent
                gotlist=1
        if not gotlist:
            child = doc.createElement('list')
            freevonode = child
            child.setAttribute('norm', tvnorm)
            child.setAttribute('frequencies', 'freevo')
            doc.documentElement.appendChild(child)
        #put in the new children
        c = 0
        for m in config.TV_CHANNELS:
            mychan = m[2]
            print 'from mychan'
            myband = self.lookupChannelBand(mychan)
            if myband == "Custom":
                print 'from custom'
                mychan = config.FREQUENCY_TABLE.get(mychan)
                mychan = float(mychan)
                mychan = mychan / 1000.0
                mychan = "%.2fMHz" % mychan
            if config.CHANLIST =="ireland":
                print 'from ireland'
                self.fc = FreevoChannels()
#               tuner_channel = self.fc.getChannel()
                tuner_channel = mychan
                freq_khz = self.fc.chanSet(tuner_channel, app='mplayer')
                mychan = "%1.2fMhz" % (freq_khz / 1000)
                myband = "Custom"
            if (hasattr(config, 'TV_PAD_CHAN_NUMBERS') and 
config.TV_PAD_CHAN_NUMBERS and re.search('^\d+$', mychan)):
                for i in range(c,int(mychan)):
                    fchild =  doc.createElement('station')
                    fchild.setAttribute('channel',str(i))
                    fchild.setAttribute('band',myband)
                    fchild.setAttribute('name',str(i))
                    fchild.setAttribute('active','0')
                    fchild.setAttribute('position',str(i))
                    freevonode.appendChild(fchild)
                    c = c + 1
            fchild =  doc.createElement('station')
            fchild.setAttribute('channel',mychan)
            fchild.setAttribute('band',myband)
            fchild.setAttribute('name',cgi.escape(m[1]))
            fchild.setAttribute('active','1')
            fchild.setAttribute('position',str(c))
            if self.xmltv_supported:
                fchild.setAttribute('xmltvid',m[0])
            freevonode.appendChild(fchild)
            c = c + 1
        # YUCK:
        # PrettyPrint the results to stationlistxml unfortuneately it
        # adds a bunch of stuff in comments at the end of the file
        # that causes the document not to load if we merge again later
        # so I print to a string buffer and then remove the offending
        # comments by truncating the output.
        strIO = StringIO()
        PrettyPrint(doc, strIO)
        mystr = strIO.getvalue()
        myindex = mystr.find('</stationlist>')
        mystr = mystr[:myindex+15]
        # how can 4suite be so stupid and still survive?
        mystr = mystr.replace('<!DOCTYPE stationlist PUBLIC 
"http://tvtime.sourceforge.net/DTD/stationlist1.dtd"; "-//tvtime//DTD 
stationlist 1.0//EN">','<!DOCTYPE stationlist PUBLIC "-//tvtime//DTD 
stationlist 1.0//EN" "http://tvtime.sourceforge.net/DTD/stationlist1.dtd";>')
        fp = open(tvtimefile,'wb')
        fp.write(mystr)
        fp.close()


    def writeNewStationListXML(self, tvtimefile, tvnorm, norm):
        _debug_("writing new stationlist.xml")
        fp = open(tvtimefile,'wb')
        fp.write('<?xml version="1.0"?>\n')
        fp.write('<!DOCTYPE stationlist PUBLIC "-//tvtime//DTD stationlist 
1.0//EN" "http://tvtime.sourceforge.net/DTD/stationlist1.dtd";>\n')
        fp.write('<stationlist xmlns="http://tvtime.sourceforge.net/DTD/";>\n')
        fp.write('  <list norm="%s" frequencies="%s">\n' % (tvnorm, norm))

        c = 0
        for m in config.TV_CHANNELS:
            mychan = str(m[2])
            myband = self.lookupChannelBand(mychan)
            if myband == "Custom":
                mychan = config.FREQUENCY_TABLE.get(mychan)
                mychan = float(mychan)
                mychan = mychan / 1000.0
                mychan = "%.2fMHz" % mychan
            if (hasattr(config, 'TV_PAD_CHAN_NUMBERS') and 
config.TV_PAD_CHAN_NUMBERS and re.search('^\d+$', mychan)):
                for i in range(c,int(mychan)):
                    fp.write('    <station name="%s" active="0" position="%s" 
band="%s" channel="%s"/>\n' % (i,i,myband,i))
                    c = c + 1
            if self.xmltv_supported:
                fp.write('    <station name="%s" xmltvid="%s" active="1" 
position="%s" band="%s" channel="%s"/>\n' % (cgi.escape(m[1]), m[0], c, myband, 
mychan))
            else:
                fp.write('    <station name="%s" active="1" position="%s" 
band="%s" channel="%s"/>\n' % (cgi.escape(m[1]),c,myband,mychan))
            c = c + 1

        fp.write('  </list>\n')
        fp.write('</stationlist>\n')
        fp.close()

    def lookupChannelBand(self, channel):
        # check if we have custom
       
        #Aubin's auto detection code works only for numeric channels and
        #forces them to int.
        channel = str(channel)
       
        if config.FREQUENCY_TABLE.has_key(channel):
            _debug_("have a custom")
            return "Custom"
        elif (re.search('^\d+$', channel)):
            _debug_("have number")
            if self.chanlists.has_key(config.CONF.chanlist):
                _debug_("found chanlist in our list")
                return self.chanlists[config.CONF.chanlist]
        elif self.chans2band.has_key(channel):
            _debug_("We know this channels band.")
            return self.chans2band[channel]
        _debug_("defaulting to USCABLE")
        return "US Cable"

    def createChannelsLookupTables(self):
        chanlisttmp = [ ('us-bcast', 'US Broadcast'), ('us-cable', 'US Cable'), 
('us-cable-hrc', 'US Cable'), ('japan-cable', 'Japan Cable'), ('japan-bcast', 
'Japan Broadcast'), ('china-bcast', 'China Broadcast') ]
        self.chanlists = dict(chanlisttmp)
        chans_list = [('T' + str(x), 'US Two-Way') for x in range(7, 15)]
        chans_list += [('A' + str(x), 'China Broadcast') for x in range(1, 8)]
        chans_list += [('B' + str(x), 'China Broadcast') for x in range(1, 32)]
        chans_list += [('C' + str(x), 'China Broadcast') for x in range(1, 6)]
        chans_list += [('E' + str(x), 'VHF E2-E12') for x in range(1, 13)]
        chans_list += [('S' + str(x), 'VHF S1-S41') for x in range(1, 42)]
        chans_list += [('Z+1', 'VHF Misc'), ('Z+2', 'VHF Misc')]
        chans_list += [(chr(x), 'VHF Misc') for x in range(88, 91)]
        chans_list += [('K%0.2i' % x, 'VHF France') for x in range(1, 11)]
        chans_list += [('H%0.2i' % x, 'VHF France') for x in range(1, 20)]
        chans_list += [('K' + chr(x), 'VHF France') for x in range(66, 82)]
        chans_list += [('SR' + str(x), 'VHF Russia') for x in range(1, 20)]
        chans_list += [('R' + str(x), 'VHF Russia') for x in range(1, 13)]
        chans_list += [('AS5A', 'VHF Australia'), ('AS9A', 'VHF Australia')]
        chans_list += [('AS' + str(x), 'VHF Australia') for x in range(1, 13)]
        chans_list += [('H1', 'VHF Italy'), ('H2', 'VHF Italy')]
        chans_list += [(chr(x), 'VHF Italy') for x in range(65, 73)]
        chans_list += [('I' + str(x), 'VHF Ireland') for x in range(1, 10)]
        chans_list += [('U' + str(x), 'UHF') for x in range(21, 70)]
        chans_list += [('AU' + str(x), 'UHF Australia') for x in range(28, 70)]
        chans_list += [('O' + str(x), 'Australia Optus') for x in range(1, 58)]
        self.chans2band=dict(chans_list)


class TVTime:

    __muted    = 0
    __igainvol = 0
    
    def __init__(self):
        self.app_mode = 'tv'
        self.fc = FreevoChannels()
        self.current_vg = None

    def TunerSetChannel(self, tuner_channel):
        for pos in range(len(config.TV_CHANNELS)):
            channel = config.TV_CHANNELS[pos]
            if channel[2] == tuner_channel:
                return pos
        print 'ERROR: Cannot find tuner channel "%s" in the TV channel listing' 
% tuner_channel
        return 0

    def TunerGetChannelInfo(self):
        return self.fc.getChannelInfo()

    def TunerGetChannel(self):
        return self.fc.getChannel()

    def Play(self, mode, tuner_channel=None, channel_change=0):

        if not tuner_channel:
            tuner_channel = self.fc.getChannel()
        vg = self.current_vg = self.fc.getVideoGroup(tuner_channel)

        if not vg.group_type == 'normal':
            print 'Tvtime only supports normal. "%s" is not implemented' % 
vg.group_type
            return

        if mode == 'tv' or mode == 'vcr':
            
            w, h = config.TV_VIEW_SIZE
            cf_norm = vg.tuner_norm
            cf_input = vg.input_num
            cf_device = vg.vdev

            s_norm = cf_norm.upper()

            outputplugin = config.CONF.display
            if config.CONF.display == 'x11':
                outputplugin = 'Xv'
            elif config.CONF.display == 'mga':
                outputplugin = 'mga'
            elif config.CONF.display in ( 'directfb', 'dfbmga' ):
                outputplugin = 'directfb'

            if mode == 'vcr':
                cf_input = '1'
                if hasattr(config, "TV_VCR_INPUT_NUM") and 
config.TV_VCR_INPUT_NUM:
                    cf_input = config.TV_VCR_INPUT_NUM

            self.fc.chan_index = self.TunerSetChannel(tuner_channel)

            if hasattr(config, 'TV_PAD_CHAN_NUMBERS') and 
config.TV_PAD_CHAN_NUMBERS:
                mychan = tuner_channel
            else:
                mychan = self.fc.chan_index

            _debug_('starting channel is %s' % mychan)

            command = '%s -D %s -k -I %s -n %s -d %s -f %s -c %s -i %s' % 
(config.TVTIME_CMD,
                                                                   outputplugin,
                                                                   w,
                                                                   s_norm,
                                                                   cf_device,
                                                                   'freevo',
                                                                   mychan,
                                                                   cf_input)

            if osd.get_fullscreen() == 1:
                command += ' -m'
            else:
                command += ' -M'


        else:
            print 'Mode "%s" is not implemented' % mode  # BUG ui.message()
            return

        self.mode = mode

        mixer = plugin.getbyname('MIXER')

        # BUG Mixer manipulation code.
        # TV is on line in
        # VCR is mic in
        # btaudio (different dsp device) will be added later
        if mixer and config.MAJOR_AUDIO_CTRL == 'VOL':
            mixer_vol = mixer.getMainVolume()
            mixer.setMainVolume(0)
        elif mixer and config.MAJOR_AUDIO_CTRL == 'PCM':
            mixer_vol = mixer.getPcmVolume()
            mixer.setPcmVolume(0)

        # Start up the TV task
        self.app=TVTimeApp(command)        

        self.prev_app = rc.app() # ???
        rc.app(self)

        # Suppress annoying audio clicks
        time.sleep(0.4)
        # BUG Hm.. This is hardcoded and very unflexible.
        if mixer and mode == 'vcr':
            mixer.setMicVolume(config.VCR_IN_VOLUME)
        elif mixer:
            mixer.setLineinVolume(config.TV_IN_VOLUME)
            mixer.setIgainVolume(config.TV_IN_VOLUME)
            
        if mixer and config.MAJOR_AUDIO_CTRL == 'VOL':
            mixer.setMainVolume(mixer_vol)
        elif mixer and config.MAJOR_AUDIO_CTRL == 'PCM':
            mixer.setPcmVolume(mixer_vol)

        if DEBUG: print '%s: started %s app' % (time.time(), self.mode)
        
        
    def Stop(self, channel_change=0):
        mixer = plugin.getbyname('MIXER')
        if mixer and not channel_change:
            mixer.setLineinVolume(0)
            mixer.setMicVolume(0)
            mixer.setIgainVolume(0) # Input on emu10k cards.

        self.app.stop('quit\n')
        rc.app(self.prev_app)

    def eventhandler(self, event, menuw=None):
        _debug_('%s: %s app got %s event' % (time.time(), self.mode, event))
        if event == em.STOP or event == em.PLAY_END:
            self.Stop()
            rc.post_event(em.PLAY_END)
            return True
        
        elif event == em.TV_CHANNEL_UP or event == em.TV_CHANNEL_DOWN:
            if self.mode == 'vcr':
                return
             
            if event == em.TV_CHANNEL_UP:
                nextchan = self.fc.getNextChannel()
            elif event == em.TV_CHANNEL_DOWN:
                nextchan = self.fc.getPrevChannel()
            nextvg = self.fc.getVideoGroup(nextchan)
            _debug_("nextchan is %s" % nextchan)

            # XXX hazardous to your health. don't use tvtime with anything
            # other than one normal video_group.
            # we lose track of the channel index at some points and
            # chaos ensues
            #if self.current_vg != nextvg:
            #    self.Stop(channel_change=1)
            #    self.Play('tv', nextchan)
            #    return TRUE

            self.fc.chanSet(nextchan, app=self.app)
            #self.current_vg = self.fc.getVideoGroup(self.fc.getChannel())

            # Go to the prev/next channel in the list
            if event == em.TV_CHANNEL_UP:
                self.app.write('CHANNEL_UP\n')
            else:
                self.app.write('CHANNEL_DOWN\n')

            return True
            
        elif event == em.TOGGLE_OSD:
            self.app.write('DISPLAY_INFO\n')
            return True
        
        elif event == em.OSD_MESSAGE:
            # XXX this doesn't work
            #self.app.write('display_message %s\n' % event.arg)
            #this does
            os.system('tvtime-command display_message \'%s\'' % event.arg)
            return True
       
        elif event in em.INPUT_ALL_NUMBERS:
            self.app.write('CHANNEL_%s\n' % event.arg)
            
        elif event == em.BUTTON:
            if event.arg == 'PREV_CH':
                self.app.write('CHANNEL_PREV\n')
                return True
                

        return False
        
            

# ======================================================================
class TVTimeApp(childapp.ChildApp2):
    """
    class controlling the in and output from the tvtime process
    """

    def __init__(self, (app)):
        childapp.ChildApp2.__init__(self, app, stop_osd=1)

    def stdout_cb(self, line):
        if not len(line) > 0: return
        # XXX Needed because tvtime grabs focus unless used with freevo -fs
        events = { 'n' : em.MIXER_VOLDOWN,
                   'm' : em.MIXER_VOLUP,
                   'c' : em.TV_CHANNEL_UP,
                   'v' : em.TV_CHANNEL_DOWN,
                   'Escape' : em.STOP,
                   'd' : em.TOGGLE_OSD,
                   '_' : em.Event(em.BUTTON, arg='PREV_CHAN'),
                   '0' : em.INPUT_0,
                   '1' : em.INPUT_1,
                   '2' : em.INPUT_2,
                   '3' : em.INPUT_3,
                   '4' : em.INPUT_4,
                   '5' : em.INPUT_5,
                   '6' : em.INPUT_6,
                   '7' : em.INPUT_7,
                   '8' : em.INPUT_8,
                   '9' : em.INPUT_9,
                   'F3' : em.MIXER_MUTE,
                   's' : em.STOP }

        if DEBUG: print 'TVTIME 1 KEY EVENT: "%s"' % str(list(line))
        if line == 'F10':
            if DEBUG: print 'TVTIME screenshot!'
            self.write('screenshot\n')
        elif line == 'z':
            if DEBUG: print 'TVTIME fullscreen toggle!'
            self.write('toggle_fullscreen\n')
            osd.toggle_fullscreen()
        else:
            event = events.get(line, None)
            if event is not None:
                rc.post_event(event)
                if DEBUG: print 'posted translated tvtime event "%s"' % event
            else:
                if DEBUG: print 'tvtime cmd "%s" not found!' % line
   
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Freevo-users mailing list
Freevo-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/freevo-users

Reply via email to