summaryrefslogtreecommitdiff
path: root/library.py
diff options
context:
space:
mode:
Diffstat (limited to 'library.py')
-rwxr-xr-xlibrary.py192
1 files changed, 129 insertions, 63 deletions
diff --git a/library.py b/library.py
index 01924a2..272e9e5 100755
--- a/library.py
+++ b/library.py
@@ -1,99 +1,165 @@
#!/usr/bin/env python
-import configparser
-import gevent
-from gevent import monkey, queue
+"""This module implements a library for storing information on audio tracks."""
import logging
-import mutagen
import os
+from gevent import joinall, monkey, queue, sleep, spawn
+import mutagen
+import six
+from six.moves import configparser
+
from db.db_manager import DbManager
from models.track import Track
-file_store = queue.Queue()
-
logging.basicConfig(format="%(asctime)s %(message)s", level=logging.DEBUG)
+_LOGGER = logging.getLogger(__name__)
+
+if six.PY2:
+ def _u(string):
+ return unicode(string, encoding="utf_8")
+else:
+ def _u(string):
+ return string
+
+
+class MediaLibrary(object):
+ """Implements methods for storing and managing media in a library."""
+
+ def __init__(self, media_dir, database):
+ """Create a media library object.
+
+ Args:
+ media_dir (str): The path of the media directory
+ database (DatabaseManager): The media database
+
+ """
+ self.__media_dir = media_dir
+ self.__database = database
+
+ def store_track_task(self, file_queue):
+ """Store a track from the supplied queue.
+ Args:
+ file_queue (Queue[str]): A queue containing file paths.
-def store_track_task():
- while not file_store.empty():
- path = file_store.get()
- m = mutagen.File(path, easy=True)
- Track.store(path, m)
+ """
+ while not file_queue.empty():
+ path = file_queue.get()
+ metadata = mutagen.File(path, easy=True)
+ Track.store(_u(path), metadata, self.__database)
- gevent.sleep(0)
+ sleep(0)
+ def run(self, path=None):
+ """Store all tracks located in the supplied path.
-def run(path=None):
- db = DbManager()
- if path is not None:
- if os.path.isdir(path):
- store_dir(path)
+ Args:
+ path (str): The path to an audio file or directory containing audio
+ files.
+
+ """
+ if path is not None:
+ if os.path.isdir(path):
+ self.store_dir(path)
+ else:
+ self.store_file(path)
else:
- store_file(path)
- else:
- store_dir("/media/Music")
- db.export()
+ self.store_dir(self.__media_dir)
+
+ self.__database.export()
+
+ def store_file(self, path):
+ """Store an audio file.
+
+ Args:
+ path (str): The path to an audio file.
+
+ """
+ metadata = mutagen.File(path, easy=True)
+ if metadata:
+ if not Track.store(_u(path), metadata, self.__database):
+ _LOGGER.error("Problem saving %s", path)
+
+ def store_dir(self, path):
+ """Store all audio files in a directory.
+ Args:
+ path (str): The path to a directory.
-def store_file(path):
- logger = logging.getLogger("store_file")
- m = mutagen.File(path, easy=True)
- if m:
- if not Track.store(path, m):
- logger.error("Problem saving %s" % (path,))
+ """
+ _LOGGER.info("Scanning files")
+ file_queue = queue.Queue()
-def store_dir(path):
- logger = logging.getLogger("store_dir")
- logger.info("Scanning files")
+ allowed_extensions = [".mp3", ".ogg", ".flac", ".wav", ".aac", ".ape"]
+ for root, dummy, files in os.walk(path):
+ for name in files:
+ file_path = "".join([root, "/", name])
+ dummy, ext = os.path.splitext(file_path)
- allowed_extensions = [".mp3", ".ogg", ".flac", ".wav", ".aac", ".ape"]
- for root, dirs, files in os.walk(path):
- for name in files:
- file_path = "".join([root, "/", name])
- file, ext = os.path.splitext(file_path)
+ if ext.lower() in allowed_extensions:
+ file_queue.put(file_path)
- if ext.lower() in allowed_extensions:
- file_store.put(file_path)
+ _LOGGER.info("Storing tracks")
+ joinall([spawn(self.store_track_task, file_queue)] * 18)
+ _LOGGER.info("Done")
- logger.info("Storing tracks")
- gevent.joinall([gevent.spawn(store_track_task)] * 6)
- logger.info("Done")
+ def delete_file(self, path):
+ """Delete a file from the library.
+ Args:
+ path (str): The path for the file.
-def delete_file(path):
- track = Track.find_by_path(path)
+ """
+ track = Track.find_by_path(_u(path), self.__database)
- if track:
- track_album = track.album
- track_artists = track.artists
+ if track:
+ track_album = track.album
+ track_artists = track.artists
- track.delete()
+ track.delete()
- if track_album and len(track_album.tracks) == 0:
- track_album.delete()
+ if track_album and len(track_album.tracks) == 0:
+ track_album.delete()
- for artist in track_artists:
- if len(artist.tracks) == 0:
- artist.delete()
+ for artist in track_artists:
+ if len(artist.tracks) == 0:
+ artist.delete()
+ def update_file(self, path):
+ """Update a file in the library.
-def update_file(path):
- m = mutagen.File(path, easy=True)
- if m:
- track = Track.find_by_path(path)
- track.update(m)
+ Args:
+ path (str): The path for the file.
+ """
+ metadata = mutagen.File(path, easy=True)
+ if metadata:
+ track = Track.find_by_path(_u(path), self.__database)
+ track.update(metadata)
+
+ def update_track_filename(self, oldpath, newpath):
+ """Update a track's filename.
+
+ Args:
+ oldpath (str): The old path of the file.
+ newpath (str): The new path of the file.
+
+ """
+ track = Track.find_by_path(_u(oldpath), self.__database)
+ track.filename = _u(newpath)
+ track.save()
-def update_track_filename(oldpath, newpath):
- track = Track.find_by_path(oldpath)
- track.filename = newpath
- track.save()
if __name__ == "__main__":
monkey.patch_all(thread=False)
- config = configparser.ConfigParser()
- config.read("mach2.ini")
+ __CONFIG = configparser.ConfigParser()
+ __CONFIG.read("mach2.ini")
+
+ db = DbManager(__CONFIG.get("DEFAULT", "library"))
+ media_path = __CONFIG.get("DEFAULT", "media_dir")
+
+ media_library = MediaLibrary(media_path, db)
- run(config["DEFAULT"]["media_dir"])
+ media_library.run()