Author: duncan
Date: Wed Dec 20 22:19:37 2006
New Revision: 8752

Added:
   branches/rel-1/freevo/src/plugins/vfd.py
Modified:
   branches/rel-1/freevo/ChangeLog

Log:
[ 1619761 ] Shuttle VFD plug-in
Plug-in added


Modified: branches/rel-1/freevo/ChangeLog
==============================================================================
--- branches/rel-1/freevo/ChangeLog     (original)
+++ branches/rel-1/freevo/ChangeLog     Wed Dec 20 22:19:37 2006
@@ -26,6 +26,7 @@
  * New home automation plug-in, allows controlling device in the home! 
(F#1605293)
  * New Linux event device support (F#1579124)
  * New RSS server, for getting podcasts, etc. (F#1580407)
+ * New Shuttle VFD plug-in (F#1619761)
  * New XM online plugin (F#1580412)
  * New webserver library, allows playing/viewing on local and host machines 
(F#1592806)
  * Updated cdbackup plug-in to accept CD_RIP_CASE and CD_RIP_REPLACE_SPACE 
(F#1616046)

Added: branches/rel-1/freevo/src/plugins/vfd.py
==============================================================================
--- (empty file)
+++ branches/rel-1/freevo/src/plugins/vfd.py    Wed Dec 20 22:19:37 2006
@@ -0,0 +1,840 @@
+# -*- coding: iso-8859-1 -*-
+# -----------------------------------------------------------------------
+# vfd.py - use PyVFD to display menus and players
+# -----------------------------------------------------------------------
+# $Id: vfd.py $
+#
+# Notes:
+#    To activate, put the following line in local_conf.py:
+#       plugin.activate('vfd')
+# Todo:        
+#    1) Use Threads. pyusb is too blocking!
+#    2) See if it's possible to scroll the display
+# -----------------------------------------------------------------------
+# $Log$
+# -----------------------------------------------------------------------
+# 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
+#
+# ----------------------------------------------------------------------- */
+
+
+from menu import MenuItem
+import copy
+import time
+import plugin
+from event import *
+from struct import *
+import config
+import util
+from util.tv_util import get_chan_displayname
+import sys
+import os
+
+try:
+    import pyusb
+except:
+    print String(_("ERROR")+": "+_("You need pyusb (http://pyusb.berlios.de/) 
to run \"vfd\" plugin."))
+
+dbglvl=1
+
+# Configuration: (Should move to freevo_conf.py?)
+sep_str = " | " # use as separator between two strings. Like: "Length: 
123<sep_str>Plot: ..."
+sep_str_mscroll = "   " # if string > width of vfd add this 
+
+# Animaton-Sequence used in audio playback
+# Some displays (like the CrytstalFontz) do display the \ as a /
+animation_audioplayer_chars = ['-','\\','|','/']
+
+# Bitmapped codes for icons
+Clock =       0x10000000 
+Radio =       0x08000000
+Music =       0x04000000
+CD_DVD =      0x02000000
+Television =  0x01000000
+Camera =      0x00100000
+Rewind =      0x00080000
+Record =      0x00040000
+Play =        0x00020000
+Pause =       0x00010000
+Stop =        0x00001000
+FastForward = 0x00000800
+Reverse =     0x00000400
+Repeat =      0x00000200
+Mute =        0x00000100
+
+def rjust( s, n ):
+    return s[ : n ].rjust( n )
+
+# menu_info: information to be shown when in menu
+# Structure:
+#
+# menu_info = {
+#     <TYPE> : [ ( <ATTRIBUTE>, <FORMAT_STRING> ), ... ],
+#    }
+# <ATTRIBUTE> is some valid attribute to item.getattr()
+menu_info = {
+    "main" : [ ],
+    "audio" : [ ( "length", _( "Length" ) + ": %s" ),
+                ( "artist", _( "Artist" ) + ": %s" ),
+                ( "album", _( "Album" )   + ": %s" ),
+                ( "year", _( "Year" )     + ": %s" ) ],
+    "audiocd" : [ ( "len(tracks)", _( "Tracks" ) + ": %s" ),
+                  ( "artist", _( "Artist" ) + ": %s" ),
+                  ( "album", _( "Album" )   + ": %s" ),
+                  ( "year", _( "Year" )     + ": %s" ) ],
+    "video" : [ ( "length", _( "Length" )   + ": %s" ),
+                ( "geometry", _( "Resolution" ) + ": %s" ),
+                ( "aspect", _( "Aspect" ) + ": %s" ),
+                ( "tagline", _( "Tagline" ) + ": %s" ),
+                ( "plot", _( "Plot" ) + ": %s" ) ],
+    "dir" : [ ( "plot", _( "Plot" ) + ": %s" ),
+              ( "tagline", _( "Tagline" ) + ": %s" ) ],
+    "image" : [ ( "geometry", _( "Geometry" ) + ": %s" ),
+                ( "date", _( "Date" ) + ": %s" ),
+                ( "description", _( "Description" ) + ": %s" ) ],
+    "playlist" : [ ( "len(playlist)", _( "%s items" ) ) ],
+    "mame" : [ ( "description", _( "Description" ) + ": %s" ) ],
+    "unknow" : [ ]
+    }
+# menu_strinfo: will be passed to time.strinfo() and added to the end of info 
(after menu_info)
+menu_strinfo = {
+    "main" : "%H:%M - %a, %d-%b", # I like time in main menu
+    "audio" : None,
+    "audiocd" : None,
+    "video" : None,
+    "image" : None,
+    "dir" : None,
+    "playlist" : None,
+    "mame" : None,
+    "unknow" : None
+    }
+
+
+# layouts: dict of layouts (screens and widgets)
+# Structure:
+#
+# layouts = { <#_OF_LINES_IN_DISPLAY> :
+#             { <#_OF_CHARS_IN_LINES> :
+#                { <SCREEN_NAME> :
+#                  <WIDGET_NAME> : ( <WIDGET_TYPE>,
+#                                    <WIDGET_PARAMETERS>,
+#                                    <PARAMETERS_VALUES> ),
+#                  ...
+#                  <MORE_WIDGETS>
+#                  ...
+#                },
+#                ...
+#                <MORE_SCREENS>
+#                ...
+#              }
+#           }
+# Note:
+#    <PARAMETERS_VALUES>: will be used like this:
+#       <WIDGET_PARAMETERS> % eval( <PARAMETERS_VALUES> )
+#    There should be at least these screens:
+#       welcome: will be the shown during the startup
+#          menu: will be used in menu mode
+#        player: will be used in player mode
+#            tv: will be used in tv mode
+# Values should match the ones supported by VFDd (man VFDd)
+layouts = { 1 : # 1 line display
+            { 20 : # 20 chars per line
+              # Welcome screen
+              { "welcome":
+                { "title"    : ( "title",
+                                 "Freevo",
+                                 None ),
+                  "calendar" : ( "scroller",
+                                 "" + _( "Today is %s." ) + "%s",
+                                 "( time.strftime('%A, %d-%B'), 
self.get_sepstrmscroll(time.strftime('%A, %d-%B')) )" ),
+                  "clock"    : ( "string",
+                                 "%s",
+                                 "( time.strftime('%T') )" )
+                  },
+
+                 "menu"    :
+                 { "title_v"  : ( "scroller",
+                                  "%s%s",
+                                  "( menu.heading, 
self.get_sepstrmscroll(menu.heading) )" ),
+                   "item_v"   : ( "scroller",
+                                  "%s%s",
+                                  "( title, self.get_sepstrmscroll(title) )" )
+                   },
+
+                 "audio_player":
+                 { "music_v"   : ( "scroller",
+                                   "%s%s",
+                                   "( title, self.get_sepstrmscroll(title) )" 
),
+                  "time_v1"   : ( "string",
+                                  "'% 2d:%02d/'",
+                                  "( int(player.length / 60), 
int(player.length % 60) )" ),
+                  "time_v2"   : ( "string",
+                                  "'% 2d:%02d'",
+                                  "( int(player.elapsed / 60), 
int(player.elapsed % 60) )" ),
+                  "time_v3"   : ( "string",
+                                  "'( %2d%%)'",
+                                  "( int(player.elapsed * 100 / player.length) 
)" ),
+                  # animation at the begining of the time line
+                  "animation_v": ( "string", "'%s'",
+                                   "animation_audioplayer_chars[player.elapsed 
% len(animation_audioplayer_chars)]")
+                   },
+
+                 "radio_player":
+                 { "radio_v"   : ( "scroller",
+                                   "%s%s",
+                                   "( title, self.get_sepstrmscroll(title) )" 
),
+                  "time_v1"   : ( "string",
+                                  "'% 2d:%02d/'",
+                                  "( int(player.length / 60), 
int(player.length % 60) )" ),
+                  "time_v2"   : ( "string",
+                                  "'% 2d:%02d'",
+                                  "( int(player.elapsed / 60), 
int(player.elapsed % 60) )" ),
+                  "time_v3"   : ( "string",
+                                  "'( %2d%%)'",
+                                  "( int(player.elapsed * 100 / player.length) 
)" ),
+                  # animation at the begining of the time line
+                  "animation_v": ( "string", "'%s'",
+                                   "animation_audioplayer_chars[player.elapsed 
% len(animation_audioplayer_chars)]")
+                   },
+
+                "video_player"  :
+                { "video_v"   : ( "scroller",
+                                  "%s%s",
+                                "( title, self.get_sepstrmscroll(title) )" ),
+                  "time_v1"   : ( "string",
+                                  "'%s /'",
+                                  "( length )" ),
+                  "time_v2"   : ( "string",
+                                  "'%s'",
+                                  "( elapsed )" ),
+                  # animation at the begining of the time line
+                  "animation_v": ( "string", "'%s'",
+                                   "animation_audioplayer_chars[player.elapsed 
% len(animation_audioplayer_chars)]")
+                  },
+
+
+                 "tv":
+                 { "chan_v"   : ( "scroller",
+                                  "%s%s",
+                                  "( get_chan_displayname(tv.channel_id), 
self.get_sepstrmscroll( get_chan_displayname(tv.channel_id)) )" ),
+                   "prog_v"   : ( "scroller",
+                                  "%s%s",
+                                  "( tv.title, 
self.get_sepstrmscroll(tv.title) )" )
+                   }
+                } # screens
+              } # chars per line
+            } # lines per display
+
+# poll_widgets: widgets that should be refreshed during the pool
+# Structure:
+#
+# poll_widgets = { <#_OF_LINES_IN_DISPLAY> :
+#                  { <SCREEN_NAME> : ( <WIDGET_NAME>, ... ) },
+#                  ...
+#                }
+poll_widgets = { 1 : {
+    20 : { "welcome" : [ "clock" ] },    
+    },
+                 }
+
+def get_info( item, list ):
+    info = ""
+
+    for l in list:
+
+        v = item.getattr( l[ 0 ] )
+        if v:
+            if info:
+                info += sep_str
+            info += l[ 1 ] % v
+
+    return info
+
+
+class PluginInterface( plugin.DaemonPlugin ):
+    """
+    Display context info on Shuttle's VFD (Versatile Front-panel Display)
+
+    Requirements:
+       * pyusb: installed (http://pyusb.berlios.de/) with name patch as
+                the default module is called usb and conflicts with freevo's
+                usb plugin.
+       * pyusb-0.3.3-name.patch (http://www.linuxowl.com/patches/)
+
+    Updates available from http://www.linuxowl.com/software.
+
+    To activate this plugin, just put the following line at the end of your
+    local_conf.py file:
+
+    plugin.activate( 'vfd' )
+
+    """
+    __author__           = 'Duncan Webb'
+    __author_email__     = '[EMAIL PROTECTED]'
+    __maintainer__       = __author__
+    __maintainer_email__ = __author_email__
+    __version__          = '$Revision: 20060727 $'
+
+    def send( self, data ):
+        "Send a piece of data to specified VFD device, retrying if necessary"
+        attempts = 3
+        while attempts > 0:
+            try:
+                _debug_(_("Sending data %r attempt=%d"%(data,4-attempts)), 
dbglvl+1)
+                time.sleep(self.sleepLength)
+                r=self.vfd.controlMsg(0x21,   # Message to Class Interface
+                               0x09,
+                               data,
+                               0x0200,
+                               0x0001) # Endpoint 1
+                return
+            except Exception,e:
+                attempts -= 1
+                _debug_( _( "WARNING" ) + ": " + _( "%r 
attempt=%d"%(data,4-attempts)), 1)
+
+        raise e
+
+    def msg( self, msgtype, *msgdata ):
+        assert msgtype >= 0 and msgtype <= 0xf
+        assert len(msgdata) <= 7
+
+        retval = chr((msgtype<<4)+len(msgdata))
+        if len(msgdata) == 1 and type(msgdata[0]) == str:
+            retval += msgdata[0]+"\x00"*(7-len(msgdata[0]))
+        else:
+            retval += "".join([type(x) == int and chr(x) or x for x in 
msgdata])
+            retval += "\x00"*(7-len(msgdata))
+        _debug_('retval=%r, msgtype=%s, len(msgdata)=%s, msgdata=%s' % \
+            (retval, msgtype, len(msgdata), msgdata), dbglvl+1)
+        return retval
+
+    def clear( self ):
+        "Clear the display"
+        self.last_message = None
+        self.last_bitmask = None
+        self.send(self.msg(1,1))
+
+    def reset( self ):
+        "Reset the cursor position"
+        self.send(self.msg(1,2))
+
+    def split( self, s, length, maxlength ):
+        "Split a string into chunks, but no longer than maxlength"
+        if len(s) > maxlength:
+            _debug_('Truncating \"%s\" longer than %d characters' % 
(s,maxlength), dbglvl+1)
+            s = s[:maxlength]
+        s = s.center(maxlength)
+        out = []
+        for x in range(0,len(s),length):
+            out.append(s[x:x+length])
+        return out
+
+    def message( self, msgstring, cls=0 ):
+        "Update the display with a string, specifying if it should be cleared 
first"
+
+        try:
+            msgstring = msgstring.encode('latin1')
+        except UnicodeError:
+            # Strange for some reason the name changes on play
+            _debug_('%s' % [x for x in msgstring])
+            #_debug_('%d' % [x for x in msgstring])
+            #_debug_('%s' % [type(x) for x in msgstring])
+
+        if self.last_message == msgstring:
+            return
+
+        _debug_('message \"%s\"->\"%s\" cls=%s' % (self.last_message, 
msgstring, cls), dbglvl)
+        self.last_message = msgstring
+
+        msgparts = self.split(msgstring, 7, self.maxStringLength)
+        _debug_('msgparts=%s' % (msgparts), dbglvl+1)
+
+        if cls:
+            self.clear()
+        else:
+            self.reset()
+
+        for part in msgparts:
+            self.send(self.msg(9,*part))
+
+    def icons( self ):
+        "Update icons to be shown"
+        _debug_('device=%x media=%x recording=%x running=%x muted=%x 
volume=%x' % \
+            (self.device, self.media, self.recording, self.running, 
self.muted, self.volume), dbglvl+1)
+        self.bitmask = self.device | self.media | self.recording | 
self.running | self.muted | self.volume
+        if self.bitmask == self.last_bitmask:
+            return
+        _debug_('last_bitmask=\"%r\"->bitmask=\"%r\"' % (self.last_bitmask, 
self.bitmask), dbglvl+1)
+        self.last_bitmask = self.bitmask
+        self.send(self.msg(7,pack('I', self.bitmask)))
+
+    def set_device( self, device=None ):
+        if device != None:
+            self.device = device
+        _debug_('device=%s, self.device=%s' % (device, self.device), dbglvl+1)
+
+    def set_media( self, media=None ):
+        if media != None:
+            self.media = media
+        _debug_('media=%s, self.media=%s' % (media, self.media), dbglvl)
+
+    def set_running( self, running=None ):
+        if running != None:
+            self.running = running
+        _debug_('running=%s, self.running=%s' % (running, self.running), 
dbglvl+1)
+
+    def set_recording( self, recording=None ):
+        if recording != None:
+            self.recording = recording
+        else:
+            self.recording = (os.path.exists(self.tvlockfile) and Record) or 0
+        _debug_('recording=%s, self.recording=%s' % (recording, 
self.recording), dbglvl+1)
+
+    def set_mixer( self, muted=None, volume=None ):
+        if self.mixer == None:
+            return
+
+        if muted == None:
+            muted = self.mixer.getMuted()
+        self.muted = (muted and Mute) or 0
+
+        if volume == None:
+            volume = self.mixer.getVolume()
+        self.volume = int(((volume + 8.0) * 11.0) / 99.0) # 99 / 11 - 1 = 8
+
+        _debug_('muted=%s, self.muted=%s, volume=%s, self.volume=%s' % (muted, 
self.muted, volume, self.volume), dbglvl)
+
+    def widget_set( self, screen, widget, value ):
+        #if widget != 'clock' and widget != 'time_v1' and widget != 'time_v2' 
and widget != 'time_v3' and widget != 'animation_v':
+        if widget != 'clock' and widget != 'time_v2' and widget != 'time_v3' 
and widget != 'animation_v':
+            _debug_('screen=%s, widget=%s, value=%s' % ( screen, widget, value 
), dbglvl)
+        if screen == "welcome":
+            pass
+        elif screen == "menu":
+            if widget == "title_v":
+                if value == "Freevo Main Menu":
+                    self.set_device(0)
+                elif value == "TV Main Menu":
+                    self.set_device(Television)
+                elif value == "Movie Main Menu":
+                    self.set_device(CD_DVD)
+                elif value == "Audio Main Menu":
+                    self.set_device(Music)
+                elif value == "Radio Stations":
+                    self.set_device(Radio)
+                elif value == "Image Main Menu":
+                    self.set_device(Camera)
+                elif value == "Headlines Sites":
+                    self.set_device(0)
+                elif value == "Weather":
+                    self.set_device(0)
+            self.set_running(0)
+        elif screen == "radio_player":
+            self.set_device(Radio)
+        elif screen == "audio_player":
+            self.set_device(Music)
+        elif screen == "video_player":
+            self.set_device(CD_DVD)
+        elif screen == "tv":
+            self.set_device(Television)
+        else:
+            _debug_('ERROR: unknown screen screen=%s, widget=%s, value=%s' % ( 
screen, widget, value ), 0)
+
+        if widget == "title":
+            pass
+        elif widget == "title_v":
+            pass
+        elif widget == "item_v":
+            self.message(value)
+        elif widget == "radio_v":
+            self.message(value)
+        elif widget == "music_v":
+            self.message(value)
+        elif widget == "video_v":
+            self.message(value)
+        elif widget == "chan_v":
+            self.message(value)
+        elif widget == "prog_v":
+            pass
+        elif widget == "time_v1":
+            pass
+        elif widget == "time_v2":
+            pass
+        elif widget == "time_v3":
+            self.set_running(Play) #work around for audio
+        elif widget == "animation_v":
+            pass
+        elif widget == "clock":
+            pass
+        elif widget == "calendar":
+            pass
+        else:
+            _debug_('ERROR: unknown widget screen=%s, widget=%s, value=%s' % ( 
screen, widget, value ), 0)
+        self.icons()
+
+    def __init__( self ):
+        """
+        init the vfd
+        """
+        plugin.DaemonPlugin.__init__(self)
+
+        self.disable = 0
+        self.playitem = None
+        self.event_listener = 1
+        self.vendorID = 4872    # Shuttle Inc
+        self.productID = 0003   # VFD Module
+        self.maxStringLength = 20
+        self.sleepLength = 0.015
+        self.vfd = None
+        for bus in pyusb.busses():
+            for dev in bus.devices:
+                if dev.idVendor == self.vendorID and dev.idProduct == 
self.productID:
+                    self.vfd = dev.open()
+                    _debug_('Found VFD on bus %s at device %s' % 
(bus.dirname,dev.filename), dbglvl)
+
+        if self.vfd == None:
+            _debug_(String(_( "ERROR" )) + ":" + String(_( "Cannot find VFD 
device" )), 0)
+            self.disable = 1
+            self.reason = "Cannot find VFD device"
+            return
+        self.clear()
+
+        self.mixer = plugin.getbyname('MIXER')
+        if self.mixer == None:
+            _debug_(String(_( "ERROR" )) + ":" + String(_( "Cannot find MIXER" 
)), 0)
+            self.disable = 1
+            self.reason = "Cannot find MIXER"
+            return
+
+        self.tvlockfile = config.FREEVO_CACHEDIR + '/record'
+
+        self.set_device(0)
+        self.set_media(0)
+        self.set_running(0)
+        self.set_recording(0)
+        self.set_mixer(0)
+        self.icons()
+
+        self.poll_interval = 10
+        self.poll_menu_only = 0
+        self.height = 1
+        self.width  = 20
+        self.last_message = None
+        self.last_bitmask = 0
+        self.generate_screens()
+
+        plugin.register( self, "vfd" )
+
+
+        # Show welcome screen:
+        for w in self.screens[ "welcome" ]:
+            type, param, val = self.screens[ "welcome" ][ w ]            
+            if val: param = param % eval( val )
+
+            self.widget_set( "welcome", w, param )
+
+        self.last_screen = "welcome"
+
+        self.lsv = { } # will hold last screen value (lsv)
+
+    def close( self ):
+        """
+        to be called before the plugin exists.
+        """
+        self.message( "bye" )
+
+    def draw( self, ( type, object ), osd ):
+        """
+        'Draw' the information on the VFD display.
+        """
+        if self.disable: return
+
+        #_debug_('draw(self, (%s,%s), %s)' % (type, object, osd))
+
+        # Check if audio is detached
+        # When in detached mode, do not draw the player screen
+        if plugin.getbyname('audio.detachbar'):
+            if type == 'player' and plugin.getbyname('audio.detachbar').status 
!= 0:
+                return
+
+        if type == 'player':
+            sname = "%s_%s" % ( object.type, type )
+        else:
+            sname = type
+
+        if not self.screens.has_key( sname ):
+            sname = 'menu'
+
+        _debug_('sname=%s, last_screen=%s' % (sname, self.last_screen), 
dbglvl+1)
+        if sname != self.last_screen:
+            # recreate screen
+            # This is used to handle cases where the previous screen was dirty
+            # ie: played music with info and now play music without, the 
previous
+            #     info will still be there
+            self.generate_screen( sname )
+            self.lsv = { } # reset last changed values
+
+        if type == 'menu':   
+            menu  = object.menustack[ -1 ]
+            title = menu.selected.name
+            if isinstance( menu.selected, MenuItem ):
+                title = _( title )
+            typeinfo = menu.selected.type
+            info = ""
+
+            if menu.selected.getattr( 'type' ):
+                typeinfo = menu.selected.getattr( 'type' )
+
+            # get info:
+            if menu.selected.type and menu_info.has_key( menu.selected.type ):
+                info = get_info( menu.selected, menu_info[ menu.selected.type 
] )
+                if menu_strinfo.has_key( menu.selected.type ) and 
menu_strinfo[ menu.selected.type ]:
+                    if info:
+                        info += sep_str
+                    info += time.strftime( menu_strinfo[ menu.selected.type ] )
+
+            # specific things related with item type
+            if menu.selected.type == 'audio':
+                title = String(menu.selected.getattr( 'title' ))
+                if not title:
+                    title = String(menu.selected.getattr( 'name' ))
+                if menu.selected.getattr( 'trackno' ):
+                    title = "%s - %s" % ( String(menu.selected.getattr( 
'trackno' )), title )
+
+        elif type == 'player':
+            player = object
+            title  = player.getattr( 'title' )
+            if not title:
+                title = String(player.getattr( 'name' ))
+
+            if player.type == 'radio':
+                if player.getattr( 'trackno' ):
+                    title = "%s - %s" % ( String(player.getattr( 'trackno' )), 
title )
+
+            elif player.type == 'audio':
+                if player.getattr( 'trackno' ):
+                    title = "%s - %s" % ( String(player.getattr( 'trackno' )), 
title )
+
+            elif player.type == 'video':
+                length = player.getattr( 'length' )
+                elapsed = player.elapsed
+                if elapsed / 3600:
+                    elapsed ='%d:%02d:%02d' % ( elapsed / 3600, ( elapsed % 
3600 ) / 60,
+                                                elapsed % 60)
+                else:
+                    elapsed = '%d:%02d' % ( elapsed / 60, elapsed % 60)
+                try:
+                    percentage = float( player.elapsed / 
player.info.video[0].length )
+                except:
+                    percentage = None
+
+
+        elif type == 'tv':
+            tv = copy.copy( object.selected )
+
+            if tv.start == 0:
+                tv.start = " 0:00"
+                tv.stop  = "23:59" # could also be: '????'
+            else:
+                tv.start = time.localtime( tv.start )
+                tv.stop  = time.localtime( tv.stop )
+
+                tv.start = "% 2d:%02d" % ( tv.start[ 3 ], tv.start[ 4 ] )
+                tv.stop  = "% 2d:%02d" % ( tv.stop[ 3 ], tv.stop[ 4 ] )
+
+
+        s = self.screens[ sname ]
+        for w in s:
+            t, param, val = s[ w ]
+            try:
+                if val: param = param % eval( val )
+            except:
+                param = None
+
+            k = '%s %s' % ( sname, w )
+            try:
+                if String(self.lsv[ k ]) == String(param):
+                    continue # nothing changed in this widget
+            except KeyError:
+                pass
+
+            self.lsv[ k ] = param
+            if param:
+                self.widget_set( sname, w, param )
+
+        if self.last_screen != sname:
+            self.last_screen = sname
+
+
+    def poll( self ):
+        if self.disable: return
+
+        if self.playitem:
+            self.draw( ( 'player', self.playitem ), None )
+
+        try:
+            screens = poll_widgets[ self.lines ][ self.columns ]
+        except:
+            return
+
+        for s in screens:
+            widgets = screens[ s ]
+
+            for w in widgets:
+                type, param, val = self.screens[ s ][ w ]
+
+                if val: param = param % eval( val )
+                self.widget_set( s, w, param )
+
+        self.set_recording()
+        self.icons()
+
+
+    def generate_screens( self ):
+        screens = None
+        l = self.height
+        c = self.width
+        # Find a screen
+        # find a display with 'l' lines
+        while not screens:
+            try:                
+                screens = layouts[ l ]
+            except KeyError:
+                _debug_( _( "WARNING" ) + ": " + _( "Could not find screens 
for %d lines VFD!" ) % l, dbglvl)
+                l -= 1
+                if l < 1:
+                    _debug_(String(_( "ERROR" )) + ": " + String(_( "No 
screens found for this VFD (%dx%d)!" )) % \
+                        ( self.height, self.width ), 0)
+                    self.disable = 1
+                    return
+        # find a display with 'l' line and 'c' columns
+        while not screens:
+            try:
+                screens = layouts[ l ][ c ]
+            except KeyError:
+                _debug_( _( "WARNING" ) + ": " + _( "Could not find screens 
for %d lines and %d columns VFD!" ) % \
+                    ( l, c ), 1)
+                c -= 1
+                if c < 1:
+                    _debug_(String(_( "ERROR" )) + ": " + String(_( "No 
screens found for this VFD (%dx%d)!" )) % \
+                        ( self.height, self.width ), 0)
+                    self.disable = 1
+                    return
+
+
+        self.lines = l
+        self.columns = c
+        try:
+            self.screens = screens = layouts[ l ][ c ]
+        except KeyError:
+            _debug_(String(_( "ERROR" )) + ": " + String(_( "No screens found 
for this VFD (%dx%d)!" )) % \
+                ( self.height, self.width ), 0)
+            self.disable = 1
+            return
+
+        for s in screens:
+            self.generate_screen( s )
+
+
+    def generate_screen( self, s ):
+        if not self.screens.has_key( s ):
+            s = 'menu'
+        widgets = self.screens[ s ]
+
+        for w in widgets:
+            type, param, val = self.screens[ s ][ w ]
+            _debug_('self.screens[ %s ][ %s ]=%s' % (s,w,self.screens[ s ][ w 
]), dbglvl+1)
+
+
+    def eventhandler( self, event, menuw=None ):
+        update_bits = 0
+        _debug_('eventhandler(self, %s, %s) %s arg=%s' % (event, menuw, self, 
event.arg), dbglvl)
+
+        if event == 'MIXER_MUTE':
+            # it seems that the exent is received before the mixer has been 
set!
+            self.set_mixer(self.mixer.getMuted() == 0)
+            update_bits = 1
+        elif event == 'MIXER_VOLDOWN' or event == 'MIXER_VOLUP':
+            self.set_mixer(0)
+            update_bits = 1
+        elif event == 'PLAY' or event == 'PLAY_START':
+            self.set_running(Play)
+            self.playitem = event.arg
+            update_bits = 1
+        elif event == 'PLAY_END' or event == 'USER_END' or event == 'STOP':
+            self.set_running(0)
+            self.playitem = None
+            update_bits = 1
+        elif event == 'PAUSE':
+            # two pauses resume play but leaves Pause!
+            self.set_running(Pause)
+            update_bits = 1
+        elif event == 'SEEK':
+            self.set_running((event.arg < 0 and Rewind) or FastForward)
+            update_bits = 1
+        elif event == 'PLUGIN_EVENT IDENTIFY_MEDIA':
+            media = event.arg[0]
+            self.set_media((hasattr(media.item, 'type') and Clock) or 0)
+            update_bits = 1
+        elif event == 'VIDEO_START':
+            self.set_running(Play)
+            update_bits = 1
+        elif event == 'VIDEO_END':
+            self.set_running(Stop)
+            update_bits = 1
+        elif event == 'BUTTON':
+            pass
+        elif event == 'VIDEO_SEND_MPLAYER_CMD':
+            pass
+        elif event == 'OSD_MESSAGE':
+            pass
+        elif event == 'MENU_UP':
+            pass
+        elif event == 'MENU_DOWN':
+            pass
+        elif event == 'MENU_PAGEUP':
+            pass
+        elif event == 'MENU_PAGEDOWN':
+            pass
+        elif event == 'MENU_SELECT':
+            pass
+        elif event == 'MENU_SUBMENU':
+            pass
+        elif event == 'MENU_BACK_ONE_MENU':
+            pass
+        elif event == 'MENU_GOTO_MAINMENU':
+            pass
+        else:
+            #_debug_('eventhandler(self, %s, %s) %s arg=%s' % (event, menuw, 
self, event.arg), dbglvl)
+            _debug_('\"%s\" not handled' % (event))
+
+        if update_bits:
+            self.icons()
+
+        return 0
+
+    def get_sepstrmscroll( self, mscrolldata ):
+        """
+        used for marquee scroller; returns seperator if info is wider then lcd
+        """
+        if len(mscrolldata) > self.width:
+            return sep_str_mscroll
+        else:
+            return ''
+

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to