#!/usr/bin/python3 import argparse import hashlib import logging import os import sqlalchemy import pytiger.logging.config from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Float, DateTime, Integer, String from sqlalchemy.orm.exc import NoResultFound from sqlalchemy.orm import sessionmaker from tinytag import TinyTag # "Constants" ROOT = "/home/kae/music" DISPLAY_SQL = False MYSQL_CONNECT = "mysql+mysqldb://songdb:songdb@localhost/songdb" # Instantiate logging pytiger.logging.config.basic_config(stderr=False, level=logging.INFO) log = logging.getLogger(__name__) log.info("Starting") # Declare mapping Base = declarative_base() # Database classes class Tracks(Base): __tablename__ = 'tracks' id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(256), index=True) artist = Column(String(256), index=True) length = Column(Integer, index=True) path = Column(String(2048), index=False, nullable=False) mtime = Column(Float, index=True) lastplayed = Column(DateTime, index=True, default=None) def __repr__(self): return ( f"" ) @classmethod def get_or_create(cls, session, path): try: track = session.query(cls).filter(cls.path == path).one() except NoResultFound: track = Tracks() track.path = path session.add(track) return track @staticmethod def search_titles(text): return Tracks.query.filter( Tracks.title.ilike(text) ).all() def main(): "Main loop" # Set up database connection log.info("Connect to database") engine = sqlalchemy.create_engine(f"{MYSQL_CONNECT}?charset=utf8", encoding='utf-8', echo=DISPLAY_SQL) Base.metadata.create_all(engine) # Create a Session Session = sessionmaker(bind=engine) session = Session() # Parse command line p = argparse.ArgumentParser() p.add_argument('-u', '--update', action="store_true", dest="update", default=True, help="Update database") args = p.parse_args() # Run as required if args.update: log.info("Updating database") update_db(session) log.info("Finished") def update_db(session): """ Repopulate database TODO: remove missing files """ count = 0 for root, dirs, files in os.walk(ROOT): for f in files: count += 1 path = os.path.join(root, f) ext = os.path.splitext(f)[1] if ext in [".flac", ".mp3"]: track = Tracks.get_or_create(session, os.path.relpath(path, ROOT)) tag = TinyTag.get(path) track.title = tag.title track.artist = tag.artist track.length = int(tag.duration * 1000) track.mtime = os.path.getmtime(path) elif ext not in [".jpg"]: print(f"Unrecognised file type: {path}") session.commit() print(f"{count} files processed") def md5(path): "https://stackoverflow.com/questions/3431825/" "generating-an-md5-checksum-of-a-file" hash_md5 = hashlib.md5() with open(path, "rb") as f: for chunk in iter(lambda: f.read(4096), b""): hash_md5.update(chunk) return hash_md5.hexdigest() if __name__ == '__main__': main()