204 lines
5.2 KiB
Python
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
|