Browse Source

remove tmp files when they leave playlist

however, this doesn't work consistently across larigira restarts: you should expect that restarting larigira
will cause leftover files to remain.
refs #12
boyska 7 years ago
parent
commit
e35834a21d
2 changed files with 52 additions and 0 deletions
  1. 6 0
      larigira/mpc.py
  2. 46 0
      larigira/unused.py

+ 6 - 0
larigira/mpc.py

@@ -9,6 +9,7 @@ from mpd import MPDClient, ConnectionError, CommandError
 from .event import Monitor
 from .eventutils import ParentedLet, Timer
 from .audiogen import audiogenerate
+from .unused import UnusedCleaner
 
 
 def get_mpd_client(conf):
@@ -99,6 +100,7 @@ class Controller(gevent.Greenlet):
         self.conf = conf
         self.q = Queue()
         self.player = Player(self.conf)
+        self.tmpcleaner = UnusedCleaner(conf)
         if 'DB_URI' in self.conf:
             self.monitor = Monitor(self.q, self.conf)
             self.monitor.parent_greenlet = self
@@ -125,6 +127,7 @@ class Controller(gevent.Greenlet):
             if kind == 'timer' or (kind == 'mpc' and
                                    args[0] in ('player', 'playlist')):
                 gevent.Greenlet.spawn(self.player.check_playlist)
+                self.tmpcleaner.check_playlist()
             elif kind == 'mpc':
                 pass
             elif kind == 'uris_enqueue':
@@ -135,6 +138,9 @@ class Controller(gevent.Greenlet):
                 except Exception:
                     self.log.exception("Error while adding to queue; "
                                        "bad audiogen output?")
+                else:
+                    for fname in args[0]['uris']:
+                        self.tmpcleaner.watch(fname)
             elif (kind == 'signal' and args[0] == signal.SIGALRM) or \
                     kind == 'refresh':
                 # it's a tick!

+ 46 - 0
larigira/unused.py

@@ -0,0 +1,46 @@
+'''
+This component will look for files to be removed. There are some assumptions:
+    * Only files in $TMPDIR are removed. Please remember that larigira has its
+      own specific TMPDIR
+    * MPD URIs are parsed, and only file:/// is supported
+'''
+import os
+import logging
+import mpd
+
+
+class UnusedCleaner:
+    def __init__(self, conf):
+        self.conf = conf
+        self.waiting_removal_files = set()
+        self.log = logging.getLogger(self.__class__.__name__)
+
+    def _get_mpd(self):
+        mpd_client = mpd.MPDClient(use_unicode=True)
+        mpd_client.connect(self.conf['MPD_HOST'], self.conf['MPD_PORT'])
+        return mpd_client
+
+    def watch(self, uri):
+        '''
+        adds fpath to the list of "watched" file
+
+        as soon as it leaves the mpc playlist, it is removed
+        '''
+        if not uri.startswith('file:///'):
+            raise ValueError('not a file URI')
+        fpath = uri[len('file://'):]
+        if not os.path.exists(fpath):
+            self.log.warning('a path that does not exist is being monitored')
+        self.waiting_removal_files.add(fpath)
+
+    def check_playlist(self):
+        '''check playlist + internal watchlist to see what can be removed'''
+        mpd = self._get_mpd()
+        files_in_playlist = {song['file'] for song in mpd.playlistid()
+                             if song['file'].startswith('/')}
+        for fpath in self.waiting_removal_files - files_in_playlist:
+            # we can remove it!
+            self.log.debug('removing unused: {}'.format(fpath))
+            self.waiting_removal_files.remove(fpath)
+            if os.path.exists(fpath):
+                os.unlink(fpath)