musick/mobject.py
2023-06-06 18:26:52 -04:00

158 lines
4.3 KiB
Python

from mutagen.id3 import ID3, APIC, TIT2, TPE1, TALB, Encoding, PictureType
from mutagen.flac import FLAC, Picture
from pathlib import Path
import io
class MObject:
_file_bytes : bytes
_file_io : io.BytesIO
def __init__(self, fb : bytes):
self._file_bytes = fb
self._file_io = io.BytesIO(fb)
return
def get_bytes(self) -> bytes:
return self._file_io.getbuffer()
def get_title(self) -> list[str]:
raise Exception("unimplemented")
def get_album(self) -> list[str]:
raise Exception("unimplemented")
def get_artist(self) -> list[str]:
raise Exception("unimplemented")
def get_cover(self) -> bytes:
raise Exception("unimplemented")
def set_artist(self, val : list[str]) -> None:
raise Exception("unimplemented")
def set_album(self, val : list[str]) -> None:
raise Exception("unimplemented")
def set_title(self, val : list[str]) -> None:
raise Exception("unimplemented")
def set_cover(self, val : bytes, png : bool = False) -> None:
raise Exception("unimplemented")
class MMP3Object(MObject):
_id3 : ID3
def __init__(self, file : bytes):
super().__init__(file)
self._id3 = ID3()
self._id3.load(self._file_io, translate = True)
return
def get_title(self) -> list[str]:
return self._id3.get("TIT2")
def set_title(self, val : list[str]) -> None:
self._id3.delall("TIT2")
self._id3.add(TIT2(text = val))
self._file_io.seek(0)
self._id3.save(self._file_io)
def get_album(self) -> list[str]:
return self._id3.get("TALB")
def set_album(self, val : list[str]) -> None:
self._id3.delall("TALB")
self._id3.add(TALB(text = val))
self._file_io.seek(0)
self._id3.save(self._file_io)
def get_artist(self) -> list[str]:
return self._id3.get("TPE1")
def set_artist(self, val : list[str]):
self._id3.delall("TPE1")
self._id3.add(TPE1(text = val))
self._file_io.seek(0)
self._id3.save(self._file_io)
def get_cover(self) -> bytes:
cover = self._id3.getall("APIC")
if (cover == None or len(cover) == 0):
return None
return cover[0].data
def set_cover(self, val : bytes, png : bool = False) -> None:
self._id3.delall("APIC")
self._id3.add(APIC(encoding = Encoding.UTF8, mime = "image/png" if png else "image/jpeg", type=PictureType.COVER_FRONT, desc=u"Cover", data = val))
self._file_io.seek(0)
self._id3.save(self._file_io)
class MFLACObject(MObject):
_flac : FLAC
def __init__(self, file : bytes):
super().__init__(file)
self._flac = FLAC(self._file_io)
return
def get_title(self) -> list[str]:
return self._flac.get("TITLE")
def set_title(self, val : list[str]) -> None:
self._flac["TITLE"] = val[0]
self._file_io.seek(0)
self._flac.save(self._file_io)
def get_album(self) -> list[str]:
return self._flac.get("ALBUM")
def set_album(self, val : list[str]) -> None:
self._flac["ALBUM"] = val[0]
self._file_io.seek(0)
self._flac.save(self._file_io)
def get_artist(self) -> list[str]:
return self._flac.get("ARTIST")
def set_artist(self, val : list[str]):
self._flac["ARTIST"] = val
self._file_io.seek(0)
self._flac.save(self._file_io)
def get_cover(self) -> bytes:
pics = self._flac.pictures
if len(pics) > 0:
return pics[0].data
else:
return None
def set_cover(self, val : bytes, png : bool = False) -> None:
self._flac.clear_pictures()
pic = Picture()
pic.type = PictureType.COVER_FRONT
pic.mime = "image/png" if png else "image/jpeg"
pic.desc = "Cover"
pic.data = val
self._flac.add_picture(pic)
self._file_io.seek(0)
self._flac.save(self._file_io)
def create_mobject(filepath : str) -> MObject:
fp = Path(filepath)
with open(fp, "rb") as f:
buf = f.read()
if (fp.suffix == ".mp3"):
return MMP3Object(buf)
if (fp.suffix == ".flac"):
return MFLACObject(buf)
return None