Author: duncan
Date: Fri Mar  7 16:38:06 2008
New Revision: 10476

Log:
Some fixes for music player daemon to shutdown gracefully
Some corrections for the 'Freevo' class and method spacings


Modified:
   branches/rel-1-7/freevo/src/audio/plugins/mpd_playlist.py
   branches/rel-1-7/freevo/src/audio/plugins/mpd_status.py
   branches/rel-1-7/freevo/src/audio/plugins/mpdclient2.py
   branches/rel-1/freevo/src/audio/plugins/album_tree.py
   branches/rel-1/freevo/src/audio/plugins/mpd_playlist.py
   branches/rel-1/freevo/src/audio/plugins/mpd_status.py
   branches/rel-1/freevo/src/audio/plugins/mpdclient2.py

Modified: branches/rel-1-7/freevo/src/audio/plugins/mpd_playlist.py
==============================================================================
--- branches/rel-1-7/freevo/src/audio/plugins/mpd_playlist.py   (original)
+++ branches/rel-1-7/freevo/src/audio/plugins/mpd_playlist.py   Fri Mar  7 
16:38:06 2008
@@ -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()

Modified: branches/rel-1-7/freevo/src/audio/plugins/mpd_status.py
==============================================================================
--- branches/rel-1-7/freevo/src/audio/plugins/mpd_status.py     (original)
+++ branches/rel-1-7/freevo/src/audio/plugins/mpd_status.py     Fri Mar  7 
16:38:06 2008
@@ -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:

Modified: branches/rel-1-7/freevo/src/audio/plugins/mpdclient2.py
==============================================================================
--- branches/rel-1-7/freevo/src/audio/plugins/mpdclient2.py     (original)
+++ branches/rel-1-7/freevo/src/audio/plugins/mpdclient2.py     Fri Mar  7 
16:38:06 2008
@@ -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
 
+    # 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

Modified: branches/rel-1/freevo/src/audio/plugins/album_tree.py
==============================================================================
--- branches/rel-1/freevo/src/audio/plugins/album_tree.py       (original)
+++ branches/rel-1/freevo/src/audio/plugins/album_tree.py       Fri Mar  7 
16:38:06 2008
@@ -42,6 +42,7 @@
 from audio import audioitem
 from gui import ProgressBox
 
+
 class treeSpec(object):
     """
     see: PluginInterface() below for freevo plugin doc.
@@ -59,6 +60,7 @@
         self.alt_grouping = alt_grouping
         self.cursor = cursor
 
+
     def get_query(self, data):
         """
         builds query
@@ -94,12 +96,15 @@
 
         return query
 
+
     def execute(self, data):
         self.cursor.execute(self.get_query(data))
         return list(self.cursor)
         #should return an iterator/generator instead of a list?
         #dont confuse others/need count for progress -->return list
 
+
+
 class PluginInterface(plugin.MainMenuPlugin):
     """
     Plugin to browse songs in a tree-like way.
@@ -188,6 +193,7 @@
         else:
             self.load_spec(config.AUDIO_ALBUM_TREE_SPEC)
 
+
     def shutdown(self):
         """
         shut down the sqlite database
@@ -195,6 +201,7 @@
         _debug_('shutdown', 2)
         db.close()
 
+
     def load_spec(self, spec_list):
         """
         load definitions from config
@@ -207,6 +214,7 @@
                 tree.alt_grouping = specdef['alt_grouping']
             self.album_tree_list.append(tree)
 
+
     def load_demo(self):
         """
         load predefined testing layout
@@ -241,15 +249,16 @@
     def items(self, parent):
         return [ self.show_item ]
 
+
     def actions(self):
         #todo: add random 10 etc..
         return []
 
+
     def onchoose_main(self, arg=None, menuw=None):
         """
         main menu
         """
-        #
         items = []
         for tree in self.album_tree_list:
             items.append(menu.MenuItem(tree.name, action=self.onchoose_node, 
arg=[tree, []]))
@@ -260,6 +269,7 @@
         menuw.pushmenu(myobjectmenu)
         menuw.refresh()
 
+
     def onchoose_node(self, arg=None, menuw=None):
         """
         browse through a tree specification
@@ -290,6 +300,7 @@
         menuw.pushmenu(myobjectmenu)
         menuw.refresh()
 
+
     def onchoose_last_node(self, tree, data, menuw):
         """
         last node in tree generates a playlist.

Modified: branches/rel-1/freevo/src/audio/plugins/mpd_playlist.py
==============================================================================
--- branches/rel-1/freevo/src/audio/plugins/mpd_playlist.py     (original)
+++ branches/rel-1/freevo/src/audio/plugins/mpd_playlist.py     Fri Mar  7 
16:38:06 2008
@@ -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()

Modified: branches/rel-1/freevo/src/audio/plugins/mpd_status.py
==============================================================================
--- branches/rel-1/freevo/src/audio/plugins/mpd_status.py       (original)
+++ branches/rel-1/freevo/src/audio/plugins/mpd_status.py       Fri Mar  7 
16:38:06 2008
@@ -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:

Modified: branches/rel-1/freevo/src/audio/plugins/mpdclient2.py
==============================================================================
--- branches/rel-1/freevo/src/audio/plugins/mpdclient2.py       (original)
+++ branches/rel-1/freevo/src/audio/plugins/mpdclient2.py       Fri Mar  7 
16:38:06 2008
@@ -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
 
+    # 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

-------------------------------------------------------------------------
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-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to