2024-02-28 19:11:45 +00:00
|
|
|
from mutagen.id3 import ID3, APIC, TIT2, TPE1, TPE2, TALB, Encoding, PictureType
|
2023-06-05 07:26:36 +00:00
|
|
|
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()
|
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def get_title(self) -> list[str]:
|
2023-06-05 07:26:36 +00:00
|
|
|
raise Exception("unimplemented")
|
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def get_album(self) -> list[str]:
|
2023-06-05 07:26:36 +00:00
|
|
|
raise Exception("unimplemented")
|
|
|
|
|
2024-02-28 19:11:45 +00:00
|
|
|
def get_album_artist(self) -> list[str]:
|
|
|
|
raise Exception("unimplemented")
|
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def get_artist(self) -> list[str]:
|
2023-06-05 07:26:36 +00:00
|
|
|
raise Exception("unimplemented")
|
|
|
|
|
|
|
|
def get_cover(self) -> bytes:
|
|
|
|
raise Exception("unimplemented")
|
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def set_artist(self, val : list[str]) -> None:
|
2023-06-05 07:26:36 +00:00
|
|
|
raise Exception("unimplemented")
|
|
|
|
|
2024-02-28 19:11:45 +00:00
|
|
|
def set_album_artist(self, val : list[str]) -> None:
|
|
|
|
raise Exception("unimplemented")
|
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def set_album(self, val : list[str]) -> None:
|
2023-06-05 07:26:36 +00:00
|
|
|
raise Exception("unimplemented")
|
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def set_title(self, val : list[str]) -> None:
|
2023-06-05 07:26:36 +00:00
|
|
|
raise Exception("unimplemented")
|
2023-06-06 22:26:52 +00:00
|
|
|
|
2023-06-05 07:26:36 +00:00
|
|
|
def set_cover(self, val : bytes, png : bool = False) -> None:
|
|
|
|
raise Exception("unimplemented")
|
|
|
|
|
|
|
|
class MMP3Object(MObject):
|
|
|
|
_id3 : ID3
|
|
|
|
def __init__(self, file : bytes):
|
2023-06-05 10:57:58 +00:00
|
|
|
super().__init__(file)
|
2023-06-05 07:26:36 +00:00
|
|
|
|
|
|
|
self._id3 = ID3()
|
|
|
|
self._id3.load(self._file_io, translate = True)
|
|
|
|
return
|
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def get_title(self) -> list[str]:
|
|
|
|
return self._id3.get("TIT2")
|
2023-06-05 07:26:36 +00:00
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def set_title(self, val : list[str]) -> None:
|
2023-06-05 07:26:36 +00:00
|
|
|
self._id3.delall("TIT2")
|
|
|
|
self._id3.add(TIT2(text = val))
|
2023-06-05 10:57:58 +00:00
|
|
|
|
|
|
|
self._file_io.seek(0)
|
|
|
|
self._id3.save(self._file_io)
|
2023-06-05 07:26:36 +00:00
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def get_album(self) -> list[str]:
|
|
|
|
return self._id3.get("TALB")
|
2023-06-05 07:26:36 +00:00
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def set_album(self, val : list[str]) -> None:
|
2023-06-05 07:26:36 +00:00
|
|
|
self._id3.delall("TALB")
|
|
|
|
self._id3.add(TALB(text = val))
|
2023-06-05 10:57:58 +00:00
|
|
|
|
|
|
|
self._file_io.seek(0)
|
|
|
|
self._id3.save(self._file_io)
|
2023-06-05 07:26:36 +00:00
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def get_artist(self) -> list[str]:
|
|
|
|
return self._id3.get("TPE1")
|
2023-06-05 07:26:36 +00:00
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def set_artist(self, val : list[str]):
|
2023-06-05 07:26:36 +00:00
|
|
|
self._id3.delall("TPE1")
|
|
|
|
self._id3.add(TPE1(text = val))
|
2023-06-05 10:57:58 +00:00
|
|
|
|
|
|
|
self._file_io.seek(0)
|
|
|
|
self._id3.save(self._file_io)
|
2024-02-28 19:11:45 +00:00
|
|
|
|
|
|
|
def get_album_artist(self) -> list[str]:
|
|
|
|
return self._id3.get("TPE2")
|
|
|
|
|
|
|
|
def set_album_artist(self, val : list[str]) -> None:
|
|
|
|
self._id3.delall("TPE2")
|
|
|
|
self._id3.add(TPE2(text = val))
|
|
|
|
|
|
|
|
self._file_io.seek(0)
|
|
|
|
self._id3.save(self._file_io)
|
2023-06-05 07:26:36 +00:00
|
|
|
|
|
|
|
def get_cover(self) -> bytes:
|
2023-06-05 10:57:58 +00:00
|
|
|
cover = self._id3.getall("APIC")
|
|
|
|
if (cover == None or len(cover) == 0):
|
|
|
|
return None
|
|
|
|
return cover[0].data
|
2023-06-05 07:26:36 +00:00
|
|
|
|
|
|
|
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))
|
2023-06-05 10:57:58 +00:00
|
|
|
|
|
|
|
self._file_io.seek(0)
|
|
|
|
self._id3.save(self._file_io)
|
2023-06-05 07:26:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
class MFLACObject(MObject):
|
|
|
|
_flac : FLAC
|
|
|
|
def __init__(self, file : bytes):
|
2023-06-05 10:57:58 +00:00
|
|
|
super().__init__(file)
|
2023-06-05 07:26:36 +00:00
|
|
|
|
|
|
|
self._flac = FLAC(self._file_io)
|
|
|
|
return
|
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def get_title(self) -> list[str]:
|
|
|
|
return self._flac.get("TITLE")
|
2023-06-05 07:26:36 +00:00
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def set_title(self, val : list[str]) -> None:
|
|
|
|
self._flac["TITLE"] = val[0]
|
2023-06-05 10:57:58 +00:00
|
|
|
|
|
|
|
self._file_io.seek(0)
|
|
|
|
self._flac.save(self._file_io)
|
2023-06-05 07:26:36 +00:00
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def get_album(self) -> list[str]:
|
|
|
|
return self._flac.get("ALBUM")
|
2023-06-05 07:26:36 +00:00
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def set_album(self, val : list[str]) -> None:
|
|
|
|
self._flac["ALBUM"] = val[0]
|
2023-06-05 10:57:58 +00:00
|
|
|
|
|
|
|
self._file_io.seek(0)
|
|
|
|
self._flac.save(self._file_io)
|
2023-06-05 07:26:36 +00:00
|
|
|
|
2024-02-28 19:11:45 +00:00
|
|
|
def get_album_artist(self) -> list[str]:
|
2024-03-11 18:53:24 +00:00
|
|
|
return self._flac.get("ALBUMARTIST")
|
2024-02-28 19:11:45 +00:00
|
|
|
|
|
|
|
def set_album_artist(self, val : list[str]) -> None:
|
2024-03-11 18:53:24 +00:00
|
|
|
self._flac["ALBUMARTIST"] = val
|
|
|
|
|
|
|
|
self._file_io.seek(0)
|
|
|
|
self._flac.save(self._file_io)
|
2024-02-28 19:11:45 +00:00
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def get_artist(self) -> list[str]:
|
|
|
|
return self._flac.get("ARTIST")
|
2023-06-05 07:26:36 +00:00
|
|
|
|
2023-06-06 22:26:52 +00:00
|
|
|
def set_artist(self, val : list[str]):
|
2023-06-05 07:26:36 +00:00
|
|
|
self._flac["ARTIST"] = val
|
2023-06-05 10:57:58 +00:00
|
|
|
|
|
|
|
self._file_io.seek(0)
|
|
|
|
self._flac.save(self._file_io)
|
2023-06-05 07:26:36 +00:00
|
|
|
|
|
|
|
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)
|
2023-06-05 10:57:58 +00:00
|
|
|
|
|
|
|
self._file_io.seek(0)
|
|
|
|
self._flac.save(self._file_io)
|
2023-06-05 07:26:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
def create_mobject(filepath : str) -> MObject:
|
|
|
|
fp = Path(filepath)
|
|
|
|
with open(fp, "rb") as f:
|
|
|
|
buf = f.read()
|
2023-06-05 10:57:58 +00:00
|
|
|
if (fp.suffix == ".mp3"):
|
2023-06-05 07:26:36 +00:00
|
|
|
return MMP3Object(buf)
|
2023-06-05 10:57:58 +00:00
|
|
|
if (fp.suffix == ".flac"):
|
2023-06-05 07:26:36 +00:00
|
|
|
return MFLACObject(buf)
|
|
|
|
return None
|