engine-sync/engine_sync/track.py

204 lines
5.2 KiB
Python

import math
from pathlib import Path
from mutagen.mp3 import MP3
from mutagen.flac import FLAC
from datetime import datetime
from dateutil.parser import parse as dateparse
class Track:
def __init__(
self,
file: Path,
bitrate: int = None,
file_size: int = None,
creation_date: int = None,
modification_date: int = None,
length: int = None,
title: str = None,
artists: list[str] = None,
album: str = None,
genre: str = None,
bpm: int = None,
release_date: datetime = None,
label: str = None,
cover: bytes = None,
filetype: str = None,
explicit: bool = False,
engine_id: int = None,
):
self.file = file
self.bitrate = bitrate
self.file_size = file_size
self.creation_date = creation_date
self.modification_date = modification_date
self.length = length
self.title = title
self.artists = artists
self.album = album
self.genre = genre
self.bpm = bpm
self.release_date = release_date
self.label = label
self.cover = cover
self.filetype = filetype
self.explicit = explicit
self.engine_id = engine_id
def fill_empty(self):
if self.title is None:
self.title = ""
if self.artists is None:
self.artists = [""]
if self.album is None:
self.album = ""
if self.genre is None:
self.genre = ""
if self.release_date is None:
self.release_date = datetime.now()
if self.label is None:
self.label = ""
if self.explicit is None:
self.explicit = False
def load_from_metadata(self):
"""
Try to fill up non-defined fields from file metadata.
"""
if self.file.suffix == ".flac":
self.load_from_metadata_flac()
def load_from_metadata_flac(self):
"""
Try to fill up non-defined fields from file metadata.
Loads the fields from a FLAC file.
"""
tags = FLAC(self.file)
if self.bitrate is None:
self.bitrate = int(tags.info.bitrate / 1000)
if self.file_size is None:
self.file_size = self.file.stat().st_size
if self.creation_date is None:
self.creation_date = int(self.file.stat().st_ctime)
if self.modification_date is None:
self.modification_date = int(self.file.stat().st_mtime)
if self.length is None:
self.length = int(math.ceil(tags.info.length))
if self.title is None:
try:
self.title = tags["title"][0]
except KeyError:
pass
if self.artists is None:
try:
self.artists = tags["artist"]
except KeyError:
pass
if self.album is None:
try:
self.album = tags["album"][0]
except KeyError:
pass
if self.genre is None:
try:
self.genre = tags["genre"][0]
except KeyError:
pass
if self.bpm is None:
try:
self.bpm = int(tags["bpm"][0])
except KeyError:
pass
if self.release_date is None:
try:
self.release_date = dateparse(tags["date"][0])
except KeyError:
pass
if self.label is None:
try:
self.label = tags["publisher"][0]
except KeyError:
pass
if self.cover is None:
pictures = tags.pictures
if pictures is not None and len(pictures) > 0:
self.cover = tags.pictures[0].data
if self.explicit is None:
try:
self.explicit = bool(tags["itunesadvisory"])
except KeyError:
self.explicit = False
def __str__(self) -> str:
st = (
"'"
+ self.title
+ "' by "
+ ", ".join(self.artists)
+ " in album '"
+ self.album
+ "', released "
+ str(self.release_date.date())
)
if self.label is not None:
st += " by " + self.label + ". "
else:
st += ". "
st += "Song is "
if self.bpm is not None:
st += "at " + str(self.bpm) + " BPM, "
st += "Explicit " + str(self.explicit)
if self.genre is not None:
st += ", Genre " + self.genre
st += (
", Runtime "
+ str(self.length)
+ ", Bitrate "
+ str(self.bitrate)
+ ", File size "
+ str(self.file_size)
+ ", Created "
+ str(self.creation_date)
+ ", Last modified "
+ str(self.modification_date)
)
if self.engine_id is not None:
st += ", Engine ID " + str(self.engine_id)
if self.cover is None:
st += ", No cover."
else:
st += ", Cover attached."
return st