musicmuster/songdb.py
2021-03-14 18:22:20 +00:00

130 lines
3.4 KiB
Python
Executable File

#!/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"<Track(id={self.id}, title={self.title}, "
f"artist={self.artist}, path={self.path}>"
)
@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
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 = 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()