Elizabeth Dodd wrote:
On Fri, 21 Dec 2007, Duncan Webb wrote:
Elizabeth Dodd wrote:
On Fri, 21 Dec 2007, Duncan Webb wrote:
Elizabeth Dodd wrote:
On Thu, 20 Dec 2007, Elizabeth Dodd wrote:
In Freevo 1.7-4 the mpd plugin crashes looking for OSD_OVERSCAN_LEFT
and OSD_OVERSCAN_RIGHT

so my will-code-for-food assistant has sorted this out for me

We haven't looked at svn to see if this is OK or not in svn
<redface>
don't trust the "paste as attachment" in kmail
</redface>

not a real diff, but close enough

mpd.py 204 <<<<<<
          # set the multiplier to be used in all screen drawing
-         self.xmult = float(osd.width  - config.OSD_OVERSCAN_LEFT -
OSD_OVERSCAN_RIGHT) / 800
-         self.ymult = float(osd.height - config.OSD_OVERSCAN_TOP -
OSD_OVERSCAN_BOTTOM) / 600
+         self.xmult = float(osd.width  - config.OSD_OVERSCAN_LEFT -
config.OSD_OVERSCAN_RIGHT) / 800
+         self.ymult = float(osd.height - config.OSD_OVERSCAN_TOP -
config.OSD_OVERSCAN_BOTTOM) / 600


now it has the line wrap problem I was trying to be smart and avoid
Thanks for this, silly bug.
The whole system isn't actually operational yet; there may be more little
bugs and sometime over the silly season the report will be ready for the
wiki. There may be more bugs to find yet.
I like people to use the tracker to report bugs, this way there is a
history and they will be reported in the ChangeLog and you can attach a
unified diff to the report. If you're not sure what I'm talking about
see:
http://doc.freevo.org/Contributing?action=show#head-9ec333e919eefa9afe3b19d
417596d388a209b6d

To submit a new one, follow this link:
https://sourceforge.net/tracker/?func=add&group_id=46652&atid=446895

Duncan



Replacement MPD plugin has been coded (for about 2 weeks food).
It is on the tracker as graham put it there last night.


Can you test the attached patch, it changes the thread handling. This is based on the page http://www.thescripts.com/forum/thread45247.html

I patch has been applied to svn, so hopefully it is working. The reason is that kaa is a bit picky about threads not terminating.

Thanks
Duncan
Index: src/audio/plugins/mpdclient2.py
===================================================================
--- src/audio/plugins/mpdclient2.py	(revision 10462)
+++ src/audio/plugins/mpdclient2.py	(working copy)
@@ -11,7 +11,7 @@
 
 import socket
 from time import sleep
-import thread
+from threading import Thread, Event, Lock
 
 # a line is either:
 #
@@ -22,6 +22,7 @@
 class socket_talker(object):
 
     def __init__(self, host, port):
+        _debug_('socket_talker.__init__(host, port)', 2)
         self.host = host
         self.port = port
         self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -31,9 +32,10 @@
         self.ack = ''
         self.done = True
 
+
     # this SUCKS
-
     def get_line(self):
+        _debug_('get_line()', 2)
         if not self.current_line:
             self.current_line = self.file.readline().rstrip("\n")
         if not self.current_line:
@@ -42,7 +44,9 @@
             self.done = True
         return self.current_line
 
+
     def putline(self, line):
+        _debug_('putline(line)', 2)
         self.file.write("%s\n" % line)
         try:
             self.file.flush()
@@ -50,7 +54,9 @@
             pass
         self.done = False
 
+
     def get_pair(self):
+        _debug_('get_pair()', 2)
         line = self.get_line()
         self.ack = ''
 
@@ -152,21 +158,25 @@
 }
 
 def is_command(cmd):
+    _debug_('is_command(cmd)', 2)
     return cmd in [ k[0] for k in commands.keys() ]
 
 def escape(text):
+    _debug_('escape(text)', 2)
     # join/split is faster than replace
     text = '\\\\'.join(text.split('\\')) # \ -> \\
     text = '\\"'.join(text.split('"')) # " -> \"
     return text
 
 def get_command(cmd, args):
+    _debug_('get_command(cmd, args)', 2)
     try:
         return commands[(cmd, len(args))]
     except KeyError:
         raise RuntimeError("no such command: %s (%d args)" % (cmd, len(args)))
 
 def send_command(talker, cmd, args):
+    _debug_('send_command(talker, cmd, args)', 2)
     args = list(args[:])
     for i, arg in enumerate(args):
         if not isinstance(arg, int):
@@ -175,15 +185,21 @@
     talker.putline(format % tuple([cmd] + list(args)))
 
 class sender_n_fetcher(object):
+    """ """
     def __init__(self, sender, fetcher):
+        _debug_('sender_n_fetcher.__init__(sender, fetcher)', 2)
         self.sender = sender
         self.fetcher = fetcher
         self.iterate = False
 
+
     def __getattr__(self, cmd):
+        _debug_('sender_n_fetcher.__getattr__(cmd)', 2)
         return lambda *args: self.send_n_fetch(cmd, args)
 
+
     def send_n_fetch(self, cmd, args):
+        _debug_('send_n_fetch(cmd, args)', 2)
         getattr(self.sender, cmd)(*args)
         junk, howmany, type, keywords = get_command(cmd, args)
 
@@ -202,9 +218,11 @@
             self.fetcher.clear()
             return result
 
+
         # stupid hack because you apparently can't return non-None and yield
         # within the same function
         def yield_then_clear(it):
+            _debug_('yield_then_clear(it)', 2)
             for x in it:
                 yield x
             self.fetcher.clear()
@@ -212,23 +230,36 @@
 
 
 class command_sender(object):
+    """ """
     def __init__(self, talker):
+        _debug_('command_sender.__init__(talker)', 2)
         self.talker = talker
+
+
     def __getattr__(self, cmd):
+        _debug_('command_sender.__getattr__(cmd)', 2)
         return lambda *args: send_command(self.talker, cmd, args)
 
+
+
 class response_fetcher(object):
+    """ """
     def __init__(self, talker):
+        _debug_('response_fetcher.__init__(talker)', 2)
         self.talker = talker
         self.converters = {}
 
+
     def clear(self):
+        _debug_('clear()', 2)
         while not self.talker.done:
             self.talker.current_line = ''
             self.talker.get_line()
         self.talker.current_line = ''
 
+
     def one_object(self, keywords, type):
+        _debug_('one_object(keywords, type)', 2)
         # if type isn't empty, then the object's type is set to it.  otherwise
         # the type is set to the key of the first key/val pair.
 
@@ -261,7 +292,9 @@
 
         return entity
 
+
     def all_objects(self, keywords, type):
+        _debug_('all_objects(keywords, type)', 2)
         while 1:
             obj = self.one_object(keywords, type)
             if not obj:
@@ -270,14 +303,23 @@
             if self.talker.done:
                 raise StopIteration
 
+
     def convert(self, cmd, key, val):
+        _debug_('convert(cmd, key, val)', 2)
         # if there's a converter, convert it, otherwise return it the same
         return self.converters.get(cmd, {}).get(key, lambda x: x)(val)
 
+
+
 class dictobj(dict):
+    """ """
     def __getattr__(self, attr):
+        _debug_('dictobj.__getattr__(attr)', 2)
         return self[attr]
+
+
     def __repr__(self):
+        _debug_('dictobj.__repr__()', 2)
         # <mpdclient2.dictobj at 0x12345678 ..
         #   {
         #     key: val,
@@ -288,8 +330,12 @@
                 ',\n    '.join([ '%s: %s' % (k, v) for k, v in self.items() ]) +
                 '\n  }>')
 
+
+
 class mpd_connection(object):
+    """ """
     def __init__(self, host, port):
+        _debug_('mpd_connection.__init__(host, port)', 2)
         self.talker = socket_talker(host, port)
         self.send = command_sender(self.talker)
         self.fetch = response_fetcher(self.talker)
@@ -297,25 +343,31 @@
 
         self._hello()
 
+
     def _hello(self):
+        _debug_('_hello()', 2)
         line = self.talker.get_line()
         if not line.startswith("OK MPD "):
             raise RuntimeError("this ain't mpd")
         self.mpd_version = line[len("OK MPD "):].strip()
         self.talker.current_line = ''
 
+
     # conn.foo() is equivalent to conn.do.foo(), but nicer
     def __getattr__(self, attr):
+        _debug_('mpd_connection.__getattr__(attr)', 2)
         if is_command(attr):
             return getattr(self.do, attr)
         raise AttributeError(attr)
 
 def parse_host(host):
+    _debug_('parse_host(host)', 2)
     if '@' in host:
         return host.split('@', 1)
     return '', host
 
 def connect(**kw):
+    _debug_('connect(**kw)', 2)
     import os
 
     port = int(os.environ.get('MPD_PORT', 6600))
@@ -339,41 +391,71 @@
 
 
 #
-# # Thread safe extenstion added by Graham Billiau <[EMAIL PROTECTED]>
+# Thread safe extenstion added by Graham Billiau <[EMAIL PROTECTED]>
 #
-
-# TODO:
-#   sometimes this hangs, probably a problem with the locking
-
-def MPD_Ping_Thread(conn):
+class MPD_Ping_Thread(Thread):
     """This should be run as a thread
     It constantly loops, sending keepalive packets to the mpd server
     it exits cleanly after the connection is closed"""
-    while True:
-        sleep(10)
-        try:
-            if not conn:
-                return
-            conn.ping()
-        except socket.error:
-            return
+    def __init__(self, conn):
+        _debug_('__init__(conn=%r)' % (conn,), 2)
+        self.conn = conn
+        self._stopevent = Event()
+        self._sleepperiod = 10.0
+        Thread.__init__(self, name="MPD_Ping_Thread")
 
+
+    def join(self, timeout=None):
+        _debug_('join(timeout=None)', 2)
+        """
+        Stop the thread
+        """
+        self._stopevent.set()
+        Thread.join(self, timeout)
+
+
+    def run(self):
+        _debug_('run()', 2)
+        while not self._stopevent.isSet():
+            try:
+                self.conn.ping()
+            except socket.error:
+                break
+            self._stopevent.wait(self._sleepperiod)
+
+
+
 class Thread_MPD_Connection:
     """This is a wrapper around the mpdclient2 library to make it thread safe"""
-    #conn
-    def __init__ (self, host, port, keepalive=False, pword = None):
+    def __init__(self, host, port, keepalive=False, pword=None):
         """create the connection and locks,
-        if keepalive is True the connection will not time out and must be explcitly closed"""
+        if keepalive is True the connection will not time out and must be explcitly closed
+        """
+        _debug_('Thread_MPD_Connection.__init__(host=%r, port=%r, keepalive=%r, pword=%r)' %
+            (host, port, keepalive, pword), 1)
         self.conn = mpd_connection(host, port)
-        if (pword is not None):
+        if pword is not None:
             self.conn.password(pword)
-        self.lock = thread.allocate_lock()
-        if (keepalive == True):
-            thread.start_new_thread(MPD_Ping_Thread, (self, ))
+        self.lock = Lock()
+        if keepalive:
+            self.ping_thread = MPD_Ping_Thread(self)
+            if self.ping_thread:
+                self.ping_thread.start()
 
+
+    def join(self):
+        """ stop the ping thread """
+        _debug_('Thread_MPD_Connection.join()', 2)
+        if self.ping_thread:
+            self.ping_thread.join()
+
+
     def __getattr__(self, attr):
         """pass the request on to the connection object, while ensuring no conflicts"""
+        _debug_('__getattr__(attr)', 2)
         self.lock.acquire()
-        funct = self.conn.__getattr__(attr)
-        self.lock.release()
+        try:
+            funct = self.conn.__getattr__(attr)
+        finally:
+            self.lock.release()
         return funct
Index: src/audio/plugins/mpd_playlist.py
===================================================================
--- src/audio/plugins/mpd_playlist.py	(revision 10462)
+++ src/audio/plugins/mpd_playlist.py	(working copy)
@@ -100,6 +100,7 @@
 
     def shutdown(self):
         """close the connection to the mpd server"""
+        self.conn.join()
         try:
             # this always throws EOFError, even though there isn't really an error
             self.conn.close()
Index: src/audio/plugins/mpd_status.py
===================================================================
--- src/audio/plugins/mpd_status.py	(revision 10462)
+++ src/audio/plugins/mpd_status.py	(working copy)
@@ -72,7 +72,6 @@
     __maintainer_email__ = __author_email__
     __version__          = '2'
 
-
     def __init__(self):
         """Initilise the plugin"""
         if not config.MPD_MUSIC_BASE_PATH:
@@ -115,6 +114,7 @@
 
     def shutdown(self):
         """close the connection to the MPD server"""
+        self.conn.join()
         try:
             self.conn.close()
         except EOFError:
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Freevo-users mailing list
Freevo-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/freevo-users

Reply via email to