Author: duncan
Date: Wed Dec 19 15:18:39 2007
New Revision: 10219

Log:
[ 1821809 ] idlebar.weather plugin fix
Update, but not the supplied patch, has been applied
The update uses a thread to update the weather data


Added:
   branches/rel-1-7/freevo/share/icons/weather/na.png   (contents, props 
changed)
   branches/rel-1/freevo/share/icons/weather/na.png   (contents, props changed)
Modified:
   branches/rel-1-7/freevo/ChangeLog
   branches/rel-1-7/freevo/src/plugins/idlebar/weather.py
   branches/rel-1/freevo/ChangeLog
   branches/rel-1/freevo/src/plugins/idlebar/weather.py

Modified: branches/rel-1-7/freevo/ChangeLog
==============================================================================
--- branches/rel-1-7/freevo/ChangeLog   (original)
+++ branches/rel-1-7/freevo/ChangeLog   Wed Dec 19 15:18:39 2007
@@ -25,6 +25,7 @@
  * New somafm web radio fxd file and images added (F#1845786)
  * New six channel mixer and idlebar plug-in (F#1833749)
  * Updated French translation (F#1832751)
+ * Updated idlebar weather plug-in not to block the main loop (F#1821809)
  * Updated mediainfo to stop caching of hidden directories (F#1849569)
  * Updated mplayer to allow the volume events to passed over and shown 
(F#1834486)
  * Updated webserver media library (F#1835346)

Added: branches/rel-1-7/freevo/share/icons/weather/na.png
==============================================================================
Binary file. No diff available.

Modified: branches/rel-1-7/freevo/src/plugins/idlebar/weather.py
==============================================================================
--- branches/rel-1-7/freevo/src/plugins/idlebar/weather.py      (original)
+++ branches/rel-1-7/freevo/src/plugins/idlebar/weather.py      Wed Dec 19 
15:18:39 2007
@@ -30,6 +30,7 @@
 import os
 import time
 import string
+from threading import Thread, Condition
 
 # freevo modules
 from plugins.idlebar import IdleBarPlugin
@@ -37,6 +38,68 @@
 import util.pymetar as pymetar
 
 
+class WeatherFetcher(Thread):
+    """
+    Class to fetch the weather in a thread
+    """
+    def __init__(self, condition, metarcode, tempunits, cachefile):
+        """ Initialise the thread """
+        Thread.__init__(self)
+        _debug_('WeatherFetcher.__init__(condition=%r, metarcode=%r, 
tempunits=%r, cachefile=%r)' % (condition, metarcode, tempunits, cachefile), 2)
+        self.condition = condition
+        self.metarcode = metarcode
+        self.tempunits = tempunits
+        self.cachefile = cachefile
+        self.stopping = False
+
+    def run(self):
+        _debug_('WeatherFetcher.run()', 2)
+        self.condition.acquire()
+        _debug_('WeatherFetcher condition.acquired', 2)
+        try:
+            while not self.stopping:
+                _debug_('WeatherFetcher condition.waiting', 2)
+                self.condition.wait()
+                _debug_('WeatherFetcher condition.waited', 2)
+                if self.stopping:
+                    break
+                #_debug_('ReportFetcher(%r)' % (self.metarcode,), 2)
+                try:
+                    rf = pymetar.ReportFetcher(self.metarcode)
+                    rep = rf.FetchReport()
+                    rp=pymetar.ReportParser()
+                    pr=rp.ParseReport(rep)
+                    if (pr.getTemperatureCelsius()):
+                        if self.tempunits == 'F':
+                            temperature = '%2d' % pr.getTemperatureFahrenheit()
+                        elif self.tempunits == 'K':
+                            ktemp = pr.getTemperatureCelsius() + 273
+                            temperature = '%3d' % ktemp
+                        else:
+                            temperature = '%2d' % pr.getTemperatureCelsius()
+                    else:
+                        temperature = '?'  # Make it a string to match above.
+                    if pr.getPixmap():
+                        icon = pr.getPixmap() + '.png'
+                    else:
+                        icon = 'na.png'
+                    try:
+                        cachefile = open(self.cachefile, 'w+')
+                        cachefile.write(temperature + '\n')
+                        cachefile.write(icon + '\n')
+                        cachefile.close()
+                        _debug_('WeatherFetcher cache written', 2)
+                    except IOError, why:
+                        _debug_('Failed to create %r: %s' % (self.cachefile, 
why), 2)
+
+                except Exception, why:
+                    _debug_(why, 2)
+        finally:
+            self.condition.release()
+            _debug_('WeatherFetcher condition.released', 2)
+
+
+
 class PluginInterface(IdleBarPlugin):
     """
     Shows the current weather.
@@ -49,6 +112,9 @@
     """
 
     def __init__(self, zone='CYYZ', units='C'):
+        """
+        """
+        _debug_('PluginInterface.__init__(zone=%r, units=%r)' % (zone, units), 
2)
         if not config.USE_NETWORK:
             self.reason = 'USE_NETWORK not enabled'
             return
@@ -57,78 +123,75 @@
         self.TEMPUNITS = units
         self.METARCODE = zone
         self.WEATHERCACHE = config.FREEVO_CACHEDIR + '/weather'
-        print
-        print 'WARNING: the idlebar.weather plugin downloads new weather'
-        print 'information inside the main loop. This bug makes all menu'
-        print 'actions _very_ slow. Consider not using this plugin for higher'
-        print 'speed.'
-        print
+        self.cachetime = 0
+        self.condition = Condition()
+        self.fetcher = WeatherFetcher(self.condition, self.METARCODE, 
self.TEMPUNITS, self.WEATHERCACHE)
+        self.fetcher.start()
+
+
+    def config(self):
+        return [
+            ('IDLEBAR_WEATHER_REFRESH', 3600, 'The time to refresh the weather 
cache'),
+        ]
+
+
+    def shutdown(self):
+        _debug_('shutdown()', 2)
+        self.condition.acquire()
+        _debug_('checkweather condition.acquired', 2)
+        try:
+            self.condition.notifyAll()
+        finally:
+            self.condition.release()
+        self.fetcher.stopping = True
+        self.fetcher.join()
 
 
     def checkweather(self):
-        # We don't want to do this every 30 seconds, so we need
-        # to cache the date somewhere.
-        #
-        # First check the age of the cache.
-        #
-        if (os.path.isfile(self.WEATHERCACHE) == 0 or \
-            (abs(time.time() - os.path.getmtime(self.WEATHERCACHE)) > 3600)):
+        """
+        We don't want to do this every 30 seconds, so we need
+        to cache the date somewhere.
+        """
+        _debug_('checkweather()', 2)
+        self.condition.acquire()
+        _debug_('checkweather condition.acquired', 2)
+        try:
             try:
-                rf=pymetar.ReportFetcher(self.METARCODE)
-                rep=rf.FetchReport()
-                rp=pymetar.ReportParser()
-                pr=rp.ParseReport(rep)
-                if (pr.getTemperatureCelsius()):
-                    if self.TEMPUNITS == 'F':
-                        temperature = '%2d' % pr.getTemperatureFahrenheit()
-                    elif self.TEMPUNITS == 'K':
-                        ktemp = pr.getTemperatureCelsius() + 273
-                        temperature = '%3d' % ktemp
-                    else:
-                        temperature = '%2d' % pr.getTemperatureCelsius()
+                if os.path.isfile(self.WEATHERCACHE):
+                    cachetime = os.path.getmtime(self.WEATHERCACHE)
                 else:
-                    temperature = '?'  # Make it a string to match above.
-                if pr.getPixmap():
-                    icon = pr.getPixmap() + '.png'
-                else:
-                    icon = 'sun.png'
-                cachefile = open(self.WEATHERCACHE,'w+')
-                cachefile.write(temperature + '\n')
-                cachefile.write(icon + '\n')
-                cachefile.close()
-            except:
-                try:
-                    # HTTP Problems, use cache. Wait till next try.
+                    cachetime = 0
+                # Tell the thread to run once
+                if time.time() - cachetime > config.IDLEBAR_WEATHER_REFRESH:
+                    self.condition.notify()
+                    _debug_('checkweather condition.notified', 2)
+
+                # First time around or when there is no network there may be 
no weather cache file
+                _debug_('cachetime=%r diff=%s' % (cachetime, cachetime - 
self.cachetime), 2)
+                if cachetime:
                     cachefile = open(self.WEATHERCACHE,'r')
                     newlist = map(string.rstrip, cachefile.readlines())
                     temperature,icon = newlist
                     cachefile.close()
-                except IOError:
-                    _debug_('error reading cache. Using fake weather.', 
DWARNING)
-                    try:
-                        cachefile = open(self.WEATHERCACHE,'w+')
-                        cachefile.write('?' + '\n')
-                        cachefile.write('sun.png' + '\n')
-                        cachefile.close()
-                    except IOError:
-                        _debug_('You have no permission to write %s' % 
self.WEATHERCACHE, DERROR)
-                    return '0', 'sun.png'
-
+                    self.cachetime = cachetime
+                    _debug_('checkweather returning %r' % ((temperature, 
icon),), 2)
+                    return temperature, icon
+                else:
+                    _debug_('checkweather returning %r' % (('?', 'na.png'),), 
2)
+                return '?', 'na.png'
+            except Exception, why:
+                _debug_(why, 2)
+        finally:
+            self.condition.release()
+            _debug_('checkweather condition.released', 2)
 
-        else:
-            cachefile = open(self.WEATHERCACHE,'r')
-            newlist = map(string.rstrip, cachefile.readlines())
-            temperature,icon = newlist
-            cachefile.close()
-        return temperature, icon
 
     def draw(self, (type, object), x, osd):
+        _debug_('draw((type=%r, object=%r), x=%r, osd=%r)' % (type, object, x, 
osd), 2)
         temp,icon = self.checkweather()
         font  = osd.get_font('small0')
-        osd.draw_image(os.path.join(config.ICON_DIR, 'weather/' + icon),
-                        (x, osd.y + 15, -1, -1))
+        osd.draw_image(os.path.join(config.ICON_DIR, 'weather/' + icon), (x, 
osd.y + 15, -1, -1))
         temp = u'%s\xb0' % temp
         width = font.stringsize(temp)
-        osd.write_text(temp, font, None, x + 15, osd.y + 55 - font.h, width, 
font.h,
-                       'left', 'top')
+        osd.write_text(temp, font, None, x + 15, osd.y + 55 - font.h, width, 
font.h, 'left', 'top')
         return width + 15

Modified: branches/rel-1/freevo/ChangeLog
==============================================================================
--- branches/rel-1/freevo/ChangeLog     (original)
+++ branches/rel-1/freevo/ChangeLog     Wed Dec 19 15:18:39 2007
@@ -32,6 +32,7 @@
  * New somafm web radio fxd file and images added (F#1845786)
  * New six channel mixer and idlebar plug-in (F#1833749)
  * Updated French translation (F#1832751)
+ * Updated idlebar weather plug-in not to block the main loop (F#1821809)
  * Updated mediainfo to stop caching of hidden directories (F#1849569)
  * Updated mplayer to allow the volume events to passed over and shown 
(F#1834486)
  * Updated webserver media library (F#1835346)

Added: branches/rel-1/freevo/share/icons/weather/na.png
==============================================================================
Binary file. No diff available.

Modified: branches/rel-1/freevo/src/plugins/idlebar/weather.py
==============================================================================
--- branches/rel-1/freevo/src/plugins/idlebar/weather.py        (original)
+++ branches/rel-1/freevo/src/plugins/idlebar/weather.py        Wed Dec 19 
15:18:39 2007
@@ -30,6 +30,7 @@
 import os
 import time
 import string
+from threading import Thread, Condition
 
 # freevo modules
 from plugins.idlebar import IdleBarPlugin
@@ -37,6 +38,68 @@
 import util.pymetar as pymetar
 
 
+class WeatherFetcher(Thread):
+    """
+    Class to fetch the weather in a thread
+    """
+    def __init__(self, condition, metarcode, tempunits, cachefile):
+        """ Initialise the thread """
+        Thread.__init__(self)
+        _debug_('WeatherFetcher.__init__(condition=%r, metarcode=%r, 
tempunits=%r, cachefile=%r)' % (condition, metarcode, tempunits, cachefile), 2)
+        self.condition = condition
+        self.metarcode = metarcode
+        self.tempunits = tempunits
+        self.cachefile = cachefile
+        self.stopping = False
+
+    def run(self):
+        _debug_('WeatherFetcher.run()', 2)
+        self.condition.acquire()
+        _debug_('WeatherFetcher condition.acquired', 2)
+        try:
+            while not self.stopping:
+                _debug_('WeatherFetcher condition.waiting', 2)
+                self.condition.wait()
+                _debug_('WeatherFetcher condition.waited', 2)
+                if self.stopping:
+                    break
+                #_debug_('ReportFetcher(%r)' % (self.metarcode,), 2)
+                try:
+                    rf = pymetar.ReportFetcher(self.metarcode)
+                    rep = rf.FetchReport()
+                    rp=pymetar.ReportParser()
+                    pr=rp.ParseReport(rep)
+                    if (pr.getTemperatureCelsius()):
+                        if self.tempunits == 'F':
+                            temperature = '%2d' % pr.getTemperatureFahrenheit()
+                        elif self.tempunits == 'K':
+                            ktemp = pr.getTemperatureCelsius() + 273
+                            temperature = '%3d' % ktemp
+                        else:
+                            temperature = '%2d' % pr.getTemperatureCelsius()
+                    else:
+                        temperature = '?'  # Make it a string to match above.
+                    if pr.getPixmap():
+                        icon = pr.getPixmap() + '.png'
+                    else:
+                        icon = 'na.png'
+                    try:
+                        cachefile = open(self.cachefile, 'w+')
+                        cachefile.write(temperature + '\n')
+                        cachefile.write(icon + '\n')
+                        cachefile.close()
+                        _debug_('WeatherFetcher cache written', 2)
+                    except IOError, why:
+                        _debug_('Failed to create %r: %s' % (self.cachefile, 
why), 2)
+
+                except Exception, why:
+                    _debug_(why, 2)
+        finally:
+            self.condition.release()
+            _debug_('WeatherFetcher condition.released', 2)
+
+
+
 class PluginInterface(IdleBarPlugin):
     """
     Shows the current weather.
@@ -49,6 +112,9 @@
     """
 
     def __init__(self, zone='CYYZ', units='C'):
+        """
+        """
+        _debug_('PluginInterface.__init__(zone=%r, units=%r)' % (zone, units), 
2)
         if not config.USE_NETWORK:
             self.reason = 'USE_NETWORK not enabled'
             return
@@ -57,78 +123,75 @@
         self.TEMPUNITS = units
         self.METARCODE = zone
         self.WEATHERCACHE = config.FREEVO_CACHEDIR + '/weather'
-        print
-        print 'WARNING: the idlebar.weather plugin downloads new weather'
-        print 'information inside the main loop. This bug makes all menu'
-        print 'actions _very_ slow. Consider not using this plugin for higher'
-        print 'speed.'
-        print
+        self.cachetime = 0
+        self.condition = Condition()
+        self.fetcher = WeatherFetcher(self.condition, self.METARCODE, 
self.TEMPUNITS, self.WEATHERCACHE)
+        self.fetcher.start()
+
+
+    def config(self):
+        return [
+            ('IDLEBAR_WEATHER_REFRESH', 3600, 'The time to refresh the weather 
cache'),
+        ]
+
+
+    def shutdown(self):
+        _debug_('shutdown()', 2)
+        self.condition.acquire()
+        _debug_('checkweather condition.acquired', 2)
+        try:
+            self.condition.notifyAll()
+        finally:
+            self.condition.release()
+        self.fetcher.stopping = True
+        self.fetcher.join()
 
 
     def checkweather(self):
-        # We don't want to do this every 30 seconds, so we need
-        # to cache the date somewhere.
-        #
-        # First check the age of the cache.
-        #
-        if (os.path.isfile(self.WEATHERCACHE) == 0 or \
-            (abs(time.time() - os.path.getmtime(self.WEATHERCACHE)) > 3600)):
+        """
+        We don't want to do this every 30 seconds, so we need
+        to cache the date somewhere.
+        """
+        _debug_('checkweather()', 2)
+        self.condition.acquire()
+        _debug_('checkweather condition.acquired', 2)
+        try:
             try:
-                rf=pymetar.ReportFetcher(self.METARCODE)
-                rep=rf.FetchReport()
-                rp=pymetar.ReportParser()
-                pr=rp.ParseReport(rep)
-                if (pr.getTemperatureCelsius()):
-                    if self.TEMPUNITS == 'F':
-                        temperature = '%2d' % pr.getTemperatureFahrenheit()
-                    elif self.TEMPUNITS == 'K':
-                        ktemp = pr.getTemperatureCelsius() + 273
-                        temperature = '%3d' % ktemp
-                    else:
-                        temperature = '%2d' % pr.getTemperatureCelsius()
+                if os.path.isfile(self.WEATHERCACHE):
+                    cachetime = os.path.getmtime(self.WEATHERCACHE)
                 else:
-                    temperature = '?'  # Make it a string to match above.
-                if pr.getPixmap():
-                    icon = pr.getPixmap() + '.png'
-                else:
-                    icon = 'sun.png'
-                cachefile = open(self.WEATHERCACHE,'w+')
-                cachefile.write(temperature + '\n')
-                cachefile.write(icon + '\n')
-                cachefile.close()
-            except:
-                try:
-                    # HTTP Problems, use cache. Wait till next try.
+                    cachetime = 0
+                # Tell the thread to run once
+                if time.time() - cachetime > config.IDLEBAR_WEATHER_REFRESH:
+                    self.condition.notify()
+                    _debug_('checkweather condition.notified', 2)
+
+                # First time around or when there is no network there may be 
no weather cache file
+                _debug_('cachetime=%r diff=%s' % (cachetime, cachetime - 
self.cachetime), 2)
+                if cachetime:
                     cachefile = open(self.WEATHERCACHE,'r')
                     newlist = map(string.rstrip, cachefile.readlines())
                     temperature,icon = newlist
                     cachefile.close()
-                except IOError:
-                    _debug_('error reading cache. Using fake weather.', 
DWARNING)
-                    try:
-                        cachefile = open(self.WEATHERCACHE,'w+')
-                        cachefile.write('?' + '\n')
-                        cachefile.write('sun.png' + '\n')
-                        cachefile.close()
-                    except IOError:
-                        _debug_('You have no permission to write %s' % 
self.WEATHERCACHE, DERROR)
-                    return '0', 'sun.png'
-
+                    self.cachetime = cachetime
+                    _debug_('checkweather returning %r' % ((temperature, 
icon),), 2)
+                    return temperature, icon
+                else:
+                    _debug_('checkweather returning %r' % (('?', 'na.png'),), 
2)
+                return '?', 'na.png'
+            except Exception, why:
+                _debug_(why, 2)
+        finally:
+            self.condition.release()
+            _debug_('checkweather condition.released', 2)
 
-        else:
-            cachefile = open(self.WEATHERCACHE,'r')
-            newlist = map(string.rstrip, cachefile.readlines())
-            temperature,icon = newlist
-            cachefile.close()
-        return temperature, icon
 
     def draw(self, (type, object), x, osd):
+        _debug_('draw((type=%r, object=%r), x=%r, osd=%r)' % (type, object, x, 
osd), 2)
         temp,icon = self.checkweather()
         font  = osd.get_font('small0')
-        osd.draw_image(os.path.join(config.ICON_DIR, 'weather/' + icon),
-                        (x, osd.y + 15, -1, -1))
+        osd.draw_image(os.path.join(config.ICON_DIR, 'weather/' + icon), (x, 
osd.y + 15, -1, -1))
         temp = u'%s\xb0' % temp
         width = font.stringsize(temp)
-        osd.write_text(temp, font, None, x + 15, osd.y + 55 - font.h, width, 
font.h,
-                       'left', 'top')
+        osd.write_text(temp, font, None, x + 15, osd.y + 55 - font.h, width, 
font.h, 'left', 'top')
         return width + 15

-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services
for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to