Update of /cvsroot/freevo/freevo/WIP/Ruelle
In directory sc8-pr-cvs1:/tmp/cvs-serv5349
Added Files:
tvtime.py
Log Message:
first stage of new tvtime plugin
--- NEW FILE: tvtime.py ---
#if 0 /*
# -----------------------------------------------------------------------
# tvtime.py - Temporary implementation of a TV function using tvtime
# -----------------------------------------------------------------------
# $Id: tvtime.py,v 1.1 2003/09/10 14:19:08 mikeruelle Exp $
#
# Notes:
# Todo:
#
# -----------------------------------------------------------------------
# $Log: tvtime.py,v $
# Revision 1.1 2003/09/10 14:19:08 mikeruelle
# first stage of new tvtime plugin
#
# Revision 1.17 2003/09/03 17:54:38 dischi
# Put logfiles into LOGDIR not $FREEVO_STARTDIR because this variable
# doesn't exist anymore.
#
# Revision 1.16 2003/09/01 19:46:03 dischi
# add menuw to eventhandler, it may be needed
#
# Revision 1.15 2003/08/23 12:51:43 dischi
# removed some old CVS log messages
#
#
# -----------------------------------------------------------------------
# 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
#
# ----------------------------------------------------------------------- */
#endif
# 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 util # Various utilities
import osd # The OSD class, used to communicate with the OSD daemon
import rc # The RemoteControl class.
import childapp # Handle child applications
import tv.epg_xmltv as epg # The Electronic Program Guide
import event as em
import plugin
# Set to 1 for debug output
DEBUG = config.DEBUG or 3
TRUE = 1
FALSE = 0
# 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)
#check and create the stationlist.xml if it doesn't exist
self.createStationListXML()
# create the tvtime object and register it
plugin.register(TVTime(), plugin.TV)
def createStationListXML(self):
tvtimedir = os.path.join(os.environ['HOME'], '.tvtime')
if (os.path.isfile(os.path.join(tvtimedir, 'stationlist.xml'))):
print "found stationlist.xml"
# if exists check cache of mtime.
# if doesn't exist or is old
# write new stationlist
self.writeStationListXML()
# write new cache of mtimes.
else:
print "not found stationlist.xml"
self.writeStationListXML()
# write new cache of mtimes.
# find out how to use the autogen list of channels
# for custom freq ' band="Custom" channel="55.25MHz" '
def writeStationListXML(self):
norm='freevo'
tvnorm = config.CONF.tv
tvnorm.upper()
tvtimefile = os.path.join(os.environ['HOME'], '.tvtime', 'stationlist.xml')
fp = open(tvtimefile,'w')
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:
fp.write(' <station name="%s" active="1" position="%s" band="US Cable"
channel="%s"/>\n' % (cgi.escape(m[1]),c,m[2]))
c = c + 1
fp.write(' </list>\n')
fp.write('</stationlist>\n')
fp.close()
class TVTime:
__muted = 0
__igainvol = 0
def __init__(self):
self.thread = TVTime_Thread()
self.thread.setDaemon(1)
self.thread.start()
self.tuner_chidx = 0 # Current channel, index into config.TV_CHANNELS
self.app_mode = 'tv'
def TunerSetChannel(self, tuner_channel):
for pos in range(len(config.TV_CHANNELS)):
channel = config.TV_CHANNELS[pos]
if channel[2] == tuner_channel:
self.tuner_chidx = pos
return
print 'ERROR: Cannot find tuner channel "%s" in the TV channel listing' %
tuner_channel
self.tuner_chidx = 0
def TunerGetChannelInfo(self):
'''Get program info for the current channel'''
tuner_id = config.TV_CHANNELS[self.tuner_chidx][2]
chan_name = config.TV_CHANNELS[self.tuner_chidx][1]
chan_id = config.TV_CHANNELS[self.tuner_chidx][0]
channels = epg.get_guide().GetPrograms(start=time.time(),
stop=time.time(), chanids=[chan_id])
if channels and channels[0] and channels[0].programs:
start_s = time.strftime('%H:%M',
time.localtime(channels[0].programs[0].start))
stop_s = time.strftime('%H:%M',
time.localtime(channels[0].programs[0].stop))
ts = '(%s-%s)' % (start_s, stop_s)
prog_info = '%s %s' % (ts, channels[0].programs[0].title)
else:
prog_info = 'No info'
return tuner_id, chan_name, prog_info
def TunerGetChannel(self):
return config.TV_CHANNELS[self.tuner_chidx][2]
def TunerNextChannel(self):
self.tuner_chidx = (self.tuner_chidx+1) % len(config.TV_CHANNELS)
def TunerPrevChannel(self):
self.tuner_chidx = (self.tuner_chidx-1) % len(config.TV_CHANNELS)
def Play(self, mode, tuner_channel=None, channel_change=0):
if tuner_channel != None:
try:
self.TunerSetChannel(tuner_channel)
except ValueError:
pass
if mode == 'tv':
tuner_channel = self.TunerGetChannel()
w, h = config.TV_VIEW_SIZE
cf_norm, cf_input, cf_clist, cf_device = config.TV_SETTINGS.split()
s_norm = cf_norm.upper()
# XXX I'm just guessing for some of these, fix later...
clist_conv = { 'us-bcast' : 'us-broadcast',
'us-cable' : 'us-cable',
'us-cable-hrc' : 'us-cable',
'japan-bcast' : 'japan-broadcast',
'japan-cable' : 'japan-cable',
'europe-west' : 'europe',
'europe-east' : 'europe',
'italy' : 'europe',
'newzealand' : 'newzealand',
'australia' : 'australia',
'ireland' : 'europe',
'france' : 'france',
'china-bcast' : 'europe',
'southafrica' : 'europe',
'argentina' : 'europe',
'canada-cable' : 'us-cable'}
s_clist = clist_conv.get(cf_clist, 'us-cable')
if DEBUG:
print 'TVTIME, using chanlist "%s" for given choice "%s"' % (cf_clist,
s_clist)
# XXX cf_norm, cf_clist doesn't fully correspond to MPlayer!
# Most of these options are only available in tvtime ver >= 0.9.8
outputplugin = config.CONF.display
if config.CONF.display == 'x11':
outputplugin = 'Xv'
if config.CONF.display == 'mga':
outputplugin = 'mga'
if config.CONF.display == 'dfbmga':
outputplugin = 'directfb'
command = '%s -D %s -k -I %s -n %s -d %s -f %s -c %s' % (config.TVTIME_CMD,
outputplugin,
w,
s_norm,
cf_device,
'freevo',
self.tuner_chidx)
if osd.get_fullscreen() == 1:
command += ' -m'
else:
command += ' -M'
else:
print 'Mode "%s" is not implemented' % mode # XXX ui.message()
return
self.mode = mode
mixer = plugin.getbyname('MIXER')
# XXX 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.thread.mode = 'play'
self.thread.command = command
self.thread.mode_flag.set()
self.prev_app = rc.app()
rc.app(self)
if osd.focused_app():
osd.focused_app().hide()
# Suppress annoying audio clicks
time.sleep(0.4)
# XXX 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):
mixer = plugin.getbyname('MIXER')
if mixer:
mixer.setLineinVolume(0)
mixer.setMicVolume(0)
mixer.setIgainVolume(0) # Input on emu10k cards.
self.thread.mode = 'stop'
self.thread.mode_flag.set()
rc.app(self.prev_app)
if osd.focused_app():
osd.focused_app().show()
while self.thread.mode == 'stop':
time.sleep(0.05)
print 'stopped %s app' % self.mode
def eventhandler(self, event, menuw=None):
print '%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
# Go to the prev/next channel in the list
if event == em.TV_CHANNEL_UP:
self.TunerPrevChannel()
self.thread.app.setchannel('UP')
else:
self.TunerNextChannel()
self.thread.app.setchannel('DOWN')
return TRUE
elif event == em.TOGGLE_OSD:
self.thread.app.write('DISPLAY_INFO\n')
return TRUE
return FALSE
# ======================================================================
class TVTimeApp(childapp.ChildApp):
"""
class controlling the in and output from the tvtime process
"""
def __init__(self, app):
if config.MPLAYER_DEBUG:
fname_out = os.path.join(config.LOGDIR, 'tvtime_stdout.log')
fname_err = os.path.join(config.LOGDIR, 'tvtime_stderr.log')
try:
self.log_stdout = open(fname_out, 'a')
self.log_stderr = open(fname_err, 'a')
except IOError:
print
print (('ERROR: Cannot open "%s" and "%s" for ' +
'TVTime logging!') % (fname_out, fname_err))
print 'Please set MPLAYER_DEBUG=0 in local_conf.py, or '
print 'start Freevo from a directory that is writeable!'
print
else:
print 'TVTime logging to "%s" and "%s"' % (fname_out, fname_err)
childapp.ChildApp.__init__(self, app)
def kill(self):
# Use SIGINT instead of SIGKILL to make sure TVTime shuts
# down properly and releases all resources before it gets
# reaped by childapp.kill().wait()
self.write('quit\n')
childapp.ChildApp.kill(self, signal.SIGINT)
# XXX Krister testcode for proper X11 video
if DEBUG: print 'Killing tvtime'
if config.MPLAYER_DEBUG:
self.log_stdout.close()
self.log_stderr.close()
def stdout_cb(self, line):
# XXX FIXME to the new event handling
events = { 'n' : em.MIXER_VOLDOWN,
'm' : em.MIXER_VOLUP,
'c' : em.TV_CHANNEL_UP,
'v' : em.TV_CHANNEL_DOWN,
'Escape' : em.STOP,
# 'Up' : rc.UP,
# 'Down' : rc.DOWN,
# 'Left' : rc.LEFT,
# 'Right' : rc.RIGHT,
# ' ' : rc.SELECT,
# 'Enter' : rc.SELECT,
'F3' : em.MIXER_MUTE,
# 'e' : rc.ENTER,
# 'd' : rc.DISPLAY,
's' : em.STOP }
print 'TVTIME 1 KEY EVENT: "%s"' % str(list(line)) # XXX TEST
if line == 'F10':
print 'TVTIME screenshot!'
self.write('screenshot\n')
elif line == 'z':
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
if config.MPLAYER_DEBUG:
try:
self.log_stdout.write(line + '\n')
except ValueError:
pass # File closed
def stderr_cb(self, line):
if config.MPLAYER_DEBUG:
try:
self.log_stderr.write(line + '\n')
except ValueError:
pass # File closed
def setchannel(self, channelno):
cmd = 'CHANNEL_%s\n' % channelno
self.write(cmd)
self.write('enter\n')
# ======================================================================
class TVTime_Thread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.mode = 'idle'
self.mode_flag = threading.Event()
self.command = ''
self.app = None
self.fifo = None
self.audioinfo = None # Added to enable update of GUI
def run(self):
while 1:
if self.mode == 'idle':
self.mode_flag.wait()
self.mode_flag.clear()
elif self.mode == 'play':
# X11 cannot handle two fullscreen windows, so shut down the window.
if config.CONF.display == 'x11':
if DEBUG:
print "Stopping Display for tvtime/x11"
osd.stopdisplay()
if DEBUG:
print 'TVTime_Thread.run(): Started, cmd=%s' % self.command
self.app = TVTimeApp(self.command)
while self.mode == 'play' and self.app.isAlive():
if self.audioinfo:
if not self.audioinfo.pause:
self.audioinfo.draw()
time.sleep(0.1)
self.app.kill()
# Ok, we can use the OSD again.
if config.CONF.display == 'x11':
if DEBUG:
print "Display now back online"
osd.restartdisplay()
osd.update()
if self.mode == 'play':
if DEBUG: print 'posting play_end'
rc.post_event(em.PLAY_END)
self.mode = 'idle'
else:
self.mode = 'idle'
-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
Freevo-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog