implement wave, flac, m4a, aiff files
This commit is contained in:
parent
df9399403a
commit
890a6171c9
@ -648,9 +648,9 @@ class MusicTable(QTableView):
|
|||||||
"""
|
"""
|
||||||
# debug(f'add_files_to_library() files={files}')
|
# debug(f'add_files_to_library() files={files}')
|
||||||
worker = Worker(add_files_to_database, files, None)
|
worker = Worker(add_files_to_database, files, None)
|
||||||
_ = worker.signals.signal_progress.connect(self.qapp.handle_progress) # type: ignore
|
worker.signals.signal_progress.connect(self.qapp.handle_progress) # type: ignore
|
||||||
_ = worker.signals.signal_result.connect(self.on_add_files_to_database_finished)
|
worker.signals.signal_result.connect(self.on_add_files_to_database_finished)
|
||||||
_ = worker.signals.signal_finished.connect(self.load_music_table)
|
worker.signals.signal_finished.connect(self.load_music_table)
|
||||||
if self.qapp:
|
if self.qapp:
|
||||||
threadpool = self.qapp.threadpool # type: ignore
|
threadpool = self.qapp.threadpool # type: ignore
|
||||||
threadpool.start(worker)
|
threadpool.start(worker)
|
||||||
|
|||||||
2
main.py
2
main.py
@ -739,7 +739,7 @@ if __name__ == "__main__":
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Allow for dynamic imports of my custom classes and utilities
|
# Allow for dynamic imports of my custom classes and utilities
|
||||||
# ?
|
# such as `from utils import whatever`
|
||||||
project_root = os.path.abspath(os.path.dirname(__file__))
|
project_root = os.path.abspath(os.path.dirname(__file__))
|
||||||
sys.path.append(project_root)
|
sys.path.append(project_root)
|
||||||
# Start the app
|
# Start the app
|
||||||
|
|||||||
@ -13,11 +13,12 @@ def add_files_to_database(files: list[str], playlist_id: int | None = None, prog
|
|||||||
files: list() of fully qualified paths to audio file(s)
|
files: list() of fully qualified paths to audio file(s)
|
||||||
progress_callback: emit data for user feedback
|
progress_callback: emit data for user feedback
|
||||||
|
|
||||||
Returns a tuple where the first value is the success state
|
Returns:
|
||||||
and the second value is a list of failed to add items
|
tuple
|
||||||
```
|
- 1st value is the success state
|
||||||
(True, {"filename.mp3":"failed because i said so"})
|
- 2nd value is a list of failed to add items
|
||||||
```
|
|
||||||
|
(e.g., (True, {"filename.mp3":"failed because i said so"}))
|
||||||
"""
|
"""
|
||||||
debug('add_files_to_database()')
|
debug('add_files_to_database()')
|
||||||
# yea
|
# yea
|
||||||
@ -52,14 +53,17 @@ def add_files_to_database(files: list[str], playlist_id: int | None = None, prog
|
|||||||
# FIXME: can this be improved?
|
# FIXME: can this be improved?
|
||||||
# filename.basename or something like that
|
# filename.basename or something like that
|
||||||
filename = filepath.split("/")[-1]
|
filename = filepath.split("/")[-1]
|
||||||
|
print('getting tags')
|
||||||
tags, fail_reason = get_tags(filepath)
|
tags, fail_reason = get_tags(filepath)
|
||||||
if fail_reason:
|
if fail_reason:
|
||||||
# if we fail to get audio tags, skip to next song
|
# if we fail to get audio tags, skip to next song
|
||||||
failed_dict[filepath] = fail_reason
|
failed_dict[filepath] = fail_reason
|
||||||
continue
|
continue
|
||||||
|
print('remapping tags')
|
||||||
# remap tags from ID3 to database tags
|
# remap tags from ID3 to database tags
|
||||||
audio: dict[str, str | int | None] = id3_remap(tags)
|
audio: dict[str, str | int | None] = id3_remap(tags)
|
||||||
# Append data tuple to insert_data list
|
# Append data tuple to insert_data list
|
||||||
|
print('appending extra info')
|
||||||
insert_data.append(
|
insert_data.append(
|
||||||
(
|
(
|
||||||
filepath,
|
filepath,
|
||||||
@ -79,7 +83,10 @@ def add_files_to_database(files: list[str], playlist_id: int | None = None, prog
|
|||||||
debug(f"inserting a LOT of songs: {len(insert_data)}")
|
debug(f"inserting a LOT of songs: {len(insert_data)}")
|
||||||
with DBA.DBAccess() as db:
|
with DBA.DBAccess() as db:
|
||||||
db.executemany(
|
db.executemany(
|
||||||
"INSERT OR IGNORE INTO song (filepath, title, album, artist, track_number, genre, codec, album_date, bitrate, length_ms) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
|
"""
|
||||||
|
INSERT OR IGNORE INTO song
|
||||||
|
(filepath, title, album, artist, track_number, genre, codec, album_date, bitrate, length_ms)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);""",
|
||||||
insert_data,
|
insert_data,
|
||||||
)
|
)
|
||||||
insert_data = [] # Reset the insert_data list
|
insert_data = [] # Reset the insert_data list
|
||||||
@ -88,7 +95,9 @@ def add_files_to_database(files: list[str], playlist_id: int | None = None, prog
|
|||||||
# debug(f'inserting the rest of the songs | insert_data={insert_data}')
|
# debug(f'inserting the rest of the songs | insert_data={insert_data}')
|
||||||
with DBA.DBAccess() as db:
|
with DBA.DBAccess() as db:
|
||||||
db.executemany(
|
db.executemany(
|
||||||
"INSERT OR IGNORE INTO song (filepath, title, album, artist, track_number, genre, codec, album_date, bitrate, length_ms) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
|
"""INSERT OR IGNORE INTO song
|
||||||
|
(filepath, title, album, artist, track_number, genre, codec, album_date, bitrate, length_ms)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);""",
|
||||||
insert_data,
|
insert_data,
|
||||||
)
|
)
|
||||||
return True, failed_dict
|
return True, failed_dict
|
||||||
|
|||||||
@ -1,26 +1,100 @@
|
|||||||
from mutagen.id3 import ID3
|
from mutagen.id3 import ID3, APIC
|
||||||
|
from mutagen.flac import FLAC, Picture
|
||||||
|
from mutagen.mp4 import MP4
|
||||||
|
from mutagen.wave import WAVE
|
||||||
|
from mutagen.aiff import AIFF
|
||||||
from logging import debug, error
|
from logging import debug, error
|
||||||
|
|
||||||
|
|
||||||
|
# def get_album_art(file: str | None) -> bytes:
|
||||||
|
# """
|
||||||
|
# Get the album art for an audio file
|
||||||
|
# # Parameters
|
||||||
|
# `file` | str | Fully qualified path to file
|
||||||
|
# # Returns
|
||||||
|
# bytes for album art or placeholder artwork
|
||||||
|
# """
|
||||||
|
# default_image_path = "./assets/default_album_art.jpg"
|
||||||
|
# if file:
|
||||||
|
# try:
|
||||||
|
# audio = ID3(file)
|
||||||
|
# for tag in audio.getall("APIC"):
|
||||||
|
# if tag.type == 3: # 3 is the type for front cover
|
||||||
|
# return tag.data
|
||||||
|
# if audio.getall("APIC"):
|
||||||
|
# return audio.getall("APIC")[0].data
|
||||||
|
# except Exception as e:
|
||||||
|
# error(f"Error retrieving album art: {e}")
|
||||||
|
# return bytes()
|
||||||
|
# with open(default_image_path, "rb") as f:
|
||||||
|
# # debug("loading placeholder album art")
|
||||||
|
# return f.read()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_album_art(file: str | None) -> bytes:
|
def get_album_art(file: str | None) -> bytes:
|
||||||
"""Get the album art for an audio file
|
|
||||||
# Parameters
|
|
||||||
`file` | str | Fully qualified path to file
|
|
||||||
# Returns
|
|
||||||
bytes for album art or placeholder artwork
|
|
||||||
"""
|
"""
|
||||||
|
Get album art for MP3, FLAC, WAV, AIFF, M4A files.
|
||||||
|
Parameters:
|
||||||
|
- `file` | str | Fully qualified path to file
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
- bytes for album art or placeholder artwork
|
||||||
|
"""
|
||||||
|
|
||||||
default_image_path = "./assets/default_album_art.jpg"
|
default_image_path = "./assets/default_album_art.jpg"
|
||||||
if file:
|
def fallback():
|
||||||
try:
|
try:
|
||||||
|
with open(default_image_path, "rb") as f:
|
||||||
|
return f.read()
|
||||||
|
except Exception:
|
||||||
|
return b""
|
||||||
|
if not file:
|
||||||
|
return fallback()
|
||||||
|
|
||||||
|
try:
|
||||||
|
ext = file.lower().split(".")[-1]
|
||||||
|
# ---------------- MP3 ----------------
|
||||||
|
if ext == "mp3":
|
||||||
audio = ID3(file)
|
audio = ID3(file)
|
||||||
for tag in audio.getall("APIC"):
|
apics = audio.getall("APIC")
|
||||||
if tag.type == 3: # 3 is the type for front cover
|
if apics:
|
||||||
|
# prefer front cover (type 3)
|
||||||
|
for tag in apics:
|
||||||
|
if tag.type == 3:
|
||||||
return tag.data
|
return tag.data
|
||||||
if audio.getall("APIC"):
|
return apics[0].data
|
||||||
return audio.getall("APIC")[0].data
|
# ---------------- FLAC ----------------
|
||||||
|
elif ext == "flac":
|
||||||
|
audio = FLAC(file)
|
||||||
|
if audio.pictures:
|
||||||
|
# prefer front cover
|
||||||
|
for pic in audio.pictures:
|
||||||
|
if pic.type == 3:
|
||||||
|
return pic.data
|
||||||
|
return audio.pictures[0].data
|
||||||
|
# ---------------- M4A / MP4 ----------------
|
||||||
|
elif ext in ("m4a", "mp4"):
|
||||||
|
audio = MP4(file)
|
||||||
|
cov = audio.tags.get("covr")
|
||||||
|
if cov:
|
||||||
|
# covr is a list of MP4Cover objects
|
||||||
|
return bytes(cov[0])
|
||||||
|
# ---------------- WAV ----------------
|
||||||
|
elif ext == "wav":
|
||||||
|
return fallback()
|
||||||
|
# audio = WAVE(file)
|
||||||
|
# if hasattr(audio, "pictures") and audio.pictures:
|
||||||
|
# return audio.pictures[0].data
|
||||||
|
# ---------------- AIFF ----------------
|
||||||
|
elif ext in ("aiff", "aif"):
|
||||||
|
return fallback()
|
||||||
|
# audio = AIFF(file)
|
||||||
|
# if hasattr(audio, "pictures") and audio.pictures:
|
||||||
|
# return audio.pictures[0].data
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error(f"Error retrieving album art: {e}")
|
error(f"Error retrieving album art: {e}")
|
||||||
return bytes()
|
|
||||||
with open(default_image_path, "rb") as f:
|
return fallback()
|
||||||
# debug("loading placeholder album art")
|
|
||||||
return f.read()
|
|
||||||
|
|||||||
@ -3,11 +3,93 @@ from logging import debug, error
|
|||||||
from mutagen.id3 import ID3
|
from mutagen.id3 import ID3
|
||||||
from mutagen.mp3 import MP3
|
from mutagen.mp3 import MP3
|
||||||
from mutagen.flac import FLAC
|
from mutagen.flac import FLAC
|
||||||
|
from mutagen.wave import WAVE
|
||||||
|
from mutagen.aiff import AIFF
|
||||||
|
from mutagen.mp4 import MP4
|
||||||
from mutagen.id3._frames import TIT2
|
from mutagen.id3._frames import TIT2
|
||||||
from mutagen.id3._util import ID3NoHeaderError
|
from mutagen.id3._util import ID3NoHeaderError
|
||||||
|
|
||||||
from utils import handle_date_tag
|
from utils import handle_date_tag
|
||||||
|
|
||||||
|
def get_flac_tags(filename: str) -> tuple[FLAC, str]:
|
||||||
|
try:
|
||||||
|
audio = FLAC(filename)
|
||||||
|
except Exception:
|
||||||
|
audio = FLAC()
|
||||||
|
try:
|
||||||
|
if os.path.exists(filename):
|
||||||
|
audio.save(os.path.abspath(filename))
|
||||||
|
title = os.path.splitext(os.path.basename(filename))[0]
|
||||||
|
if audio.tags is None:
|
||||||
|
audio.add_tags()
|
||||||
|
if "title" not in audio:
|
||||||
|
audio["title"] = [title]
|
||||||
|
audio.save()
|
||||||
|
return audio, ""
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return FLAC(), f"Could not assign FLAC tag: {e}"
|
||||||
|
|
||||||
|
def get_m4a_tags(filename: str) -> tuple[MP4, str]:
|
||||||
|
try:
|
||||||
|
audio = MP4(filename)
|
||||||
|
except Exception:
|
||||||
|
audio = MP4()
|
||||||
|
try:
|
||||||
|
if os.path.exists(filename):
|
||||||
|
audio.save(os.path.abspath(filename))
|
||||||
|
title = os.path.splitext(os.path.basename(filename))[0]
|
||||||
|
if audio.tags is None:
|
||||||
|
audio.add_tags()
|
||||||
|
tags = audio.tags
|
||||||
|
if "©nam" not in tags:
|
||||||
|
tags["©nam"] = [title]
|
||||||
|
audio.save()
|
||||||
|
return audio, ""
|
||||||
|
except Exception as e:
|
||||||
|
return MP4(), f"Could not assign M4A tag: {e}"
|
||||||
|
|
||||||
|
def get_aiff_tags(filename: str) -> tuple[AIFF, str]:
|
||||||
|
try:
|
||||||
|
audio = AIFF(filename)
|
||||||
|
except Exception:
|
||||||
|
audio = AIFF()
|
||||||
|
try:
|
||||||
|
if os.path.exists(filename):
|
||||||
|
audio.save(os.path.abspath(filename))
|
||||||
|
title = os.path.splitext(os.path.basename(filename))[0]
|
||||||
|
if audio.tags is None:
|
||||||
|
audio.add_tags()
|
||||||
|
if "TIT2" not in audio:
|
||||||
|
audio["TIT2"] = TIT2(encoding=3, text=[title])
|
||||||
|
audio.save()
|
||||||
|
return audio, ""
|
||||||
|
except Exception as e:
|
||||||
|
return AIFF(), f"Could not assign AIFF tag: {e}"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_wav_tags(filename: str) -> tuple[WAVE, str]:
|
||||||
|
"""Get or create basic WAV tags (RIFF INFO)"""
|
||||||
|
try:
|
||||||
|
audio = WAVE(filename)
|
||||||
|
except Exception:
|
||||||
|
audio = WAVE()
|
||||||
|
try:
|
||||||
|
if os.path.exists(filename):
|
||||||
|
audio = WAVE(filename)
|
||||||
|
title = os.path.splitext(os.path.basename(filename))[0]
|
||||||
|
# IMPORTANT: ensure tag container exists
|
||||||
|
if audio.tags is None:
|
||||||
|
audio.add_tags()
|
||||||
|
# RIFF INFO lives in audio.tags.info in many Mutagen versions
|
||||||
|
if not hasattr(audio.tags, "info") or audio.tags.info is None:
|
||||||
|
audio.add_tags()
|
||||||
|
audio.tags["INAM"] = title
|
||||||
|
audio.save(filename)
|
||||||
|
return audio, ""
|
||||||
|
except Exception as e:
|
||||||
|
return WAVE(), f"Could not assign WAV tag to file: {e}"
|
||||||
|
|
||||||
def get_mp3_tags(filename: str) -> tuple[MP3 | ID3 | FLAC, str]:
|
def get_mp3_tags(filename: str) -> tuple[MP3 | ID3 | FLAC, str]:
|
||||||
"""Get ID3 tags for mp3 file"""
|
"""Get ID3 tags for mp3 file"""
|
||||||
@ -16,11 +98,9 @@ def get_mp3_tags(filename: str) -> tuple[MP3 | ID3 | FLAC, str]:
|
|||||||
audio = MP3(filename)
|
audio = MP3(filename)
|
||||||
except ID3NoHeaderError:
|
except ID3NoHeaderError:
|
||||||
audio = MP3()
|
audio = MP3()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if os.path.exists(filename):
|
if os.path.exists(filename):
|
||||||
audio.save(os.path.abspath(filename))
|
audio.save(os.path.abspath(filename))
|
||||||
|
|
||||||
title = os.path.splitext(os.path.basename(filename))[0]
|
title = os.path.splitext(os.path.basename(filename))[0]
|
||||||
if "TIT2" not in list(audio.keys()):
|
if "TIT2" not in list(audio.keys()):
|
||||||
# if title tag doesnt exist, create it - filename
|
# if title tag doesnt exist, create it - filename
|
||||||
@ -29,23 +109,21 @@ def get_mp3_tags(filename: str) -> tuple[MP3 | ID3 | FLAC, str]:
|
|||||||
# Save the updated tags
|
# Save the updated tags
|
||||||
audio.save()
|
audio.save()
|
||||||
return audio, ""
|
return audio, ""
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return MP3(), f"Could not assign ID3 tag to file: {e}"
|
return MP3(), f"Could not assign ID3 tag to file: {e}"
|
||||||
|
|
||||||
|
|
||||||
def id3_remap(audio: MP3 | ID3 | FLAC) -> dict[str, str | int | None]:
|
def id3_remap(audio: MP3 | ID3 | FLAC | WAVE | AIFF | MP4) -> dict[str, str | int | None]:
|
||||||
"""
|
"""
|
||||||
Turns the ID3 dict of an audio file into a normal dict that I, the human, can use.
|
Turns the ID3 dict of an audio file into a normal dict that I, the human, can use.
|
||||||
Add extra fields too :D yahooo
|
Add extra fields too :D yahooo
|
||||||
"""
|
"""
|
||||||
# FIXME: implement other filetypes here too
|
# TODO: implement other filetypes here too
|
||||||
remap = {}
|
remap = {}
|
||||||
|
# .mp3
|
||||||
if isinstance(audio, MP3):
|
if isinstance(audio, MP3):
|
||||||
# so ugly
|
|
||||||
uslt_tags = [tag for tag in audio.keys() if tag.startswith("USLT::")]
|
uslt_tags = [tag for tag in audio.keys() if tag.startswith("USLT::")]
|
||||||
lyrics = next((audio[tag].text for tag in uslt_tags), "")
|
lyrics = next((audio[tag].text for tag in uslt_tags), "")
|
||||||
# so ugly
|
|
||||||
remap = {
|
remap = {
|
||||||
"title": audio.get("TIT2"),
|
"title": audio.get("TIT2"),
|
||||||
"artist": audio.get("TPE1"),
|
"artist": audio.get("TPE1"),
|
||||||
@ -64,10 +142,96 @@ def id3_remap(audio: MP3 | ID3 | FLAC) -> dict[str, str | int | None]:
|
|||||||
continue
|
continue
|
||||||
if not isinstance(v, str) and not isinstance(v, int):
|
if not isinstance(v, str) and not isinstance(v, int):
|
||||||
remap[k] = v.text[0]
|
remap[k] = v.text[0]
|
||||||
|
# .wav
|
||||||
|
if isinstance(audio, WAVE):
|
||||||
|
print('is wave file')
|
||||||
|
remap = {
|
||||||
|
"title": audio.get("INAM"),
|
||||||
|
"artist": audio.get("IART"),
|
||||||
|
"album": audio.get("IPRD"),
|
||||||
|
"track_number": audio.get("ITRK"),
|
||||||
|
"genre": audio.get("IGNR"),
|
||||||
|
"date": audio.get("ICRD"),
|
||||||
|
"comment": audio.get("ICMT"),
|
||||||
|
"bitrate": getattr(audio.info, "bitrate", None),
|
||||||
|
"length": int(round(audio.info.length, 0)),
|
||||||
|
"lyrics": audio.get("USLT") or "",
|
||||||
|
}
|
||||||
|
for k, v in remap.items():
|
||||||
|
print(f'k: {k}, v: {v}')
|
||||||
|
if v is None:
|
||||||
|
continue
|
||||||
|
# WAV tags are often mutagen.id3.TextFrame-like or lists/bytes
|
||||||
|
if not isinstance(v, str) and not isinstance(v, int):
|
||||||
|
try:
|
||||||
|
# RIFF INFO tags are often simple strings but sometimes wrapped
|
||||||
|
remap[k] = v.text[0] if hasattr(v, "text") else str(v)
|
||||||
|
except Exception:
|
||||||
|
remap[k] = str(v)
|
||||||
|
if isinstance(audio, AIFF):
|
||||||
|
tags = audio.tags or {}
|
||||||
|
remap = {
|
||||||
|
"title": audio.get("TIT2"),
|
||||||
|
"artist": audio.get("TPE1"),
|
||||||
|
"album": audio.get("TALB"),
|
||||||
|
"track_number": audio.get("TRCK"),
|
||||||
|
"genre": audio.get("TCON"),
|
||||||
|
"date": audio.get("TDRC"),
|
||||||
|
"lyrics": audio.get("USLT::eng") if "USLT::eng" in tags else "",
|
||||||
|
"bitrate": getattr(audio.info, "bitrate", None),
|
||||||
|
"length": int(round(audio.info.length, 0)),
|
||||||
|
}
|
||||||
|
for k, v in remap.items():
|
||||||
|
if v is None:
|
||||||
|
continue
|
||||||
|
if not isinstance(v, (str, int)):
|
||||||
|
remap[k] = v.text[0] if hasattr(v, "text") else str(v)
|
||||||
|
|
||||||
|
if isinstance(audio, MP4):
|
||||||
|
tags = audio.tags or {}
|
||||||
|
|
||||||
|
remap = {
|
||||||
|
"title": audio.get("©nam"),
|
||||||
|
"artist": audio.get("©ART"),
|
||||||
|
"album": audio.get("©alb"),
|
||||||
|
"track_number": audio.get("trkn"),
|
||||||
|
"genre": audio.get("©gen"),
|
||||||
|
"date": audio.get("©day"),
|
||||||
|
"lyrics": audio.get("©lyr"),
|
||||||
|
"length": int(round(audio.info.length, 0)) if audio.info else 0,
|
||||||
|
"bitrate": getattr(audio.info, "bitrate", None),
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v in remap.items():
|
||||||
|
if v is None:
|
||||||
|
continue
|
||||||
|
if not isinstance(v, (str, int)):
|
||||||
|
remap[k] = str(v)
|
||||||
|
|
||||||
|
if isinstance(audio, FLAC):
|
||||||
|
tags = audio.tags or {}
|
||||||
|
|
||||||
|
remap = {
|
||||||
|
"title": audio.get("title"),
|
||||||
|
"artist": audio.get("artist"),
|
||||||
|
"album": audio.get("album"),
|
||||||
|
"track_number": audio.get("tracknumber"),
|
||||||
|
"genre": audio.get("genre"),
|
||||||
|
"date": audio.get("date"),
|
||||||
|
"lyrics": audio.get("lyrics"),
|
||||||
|
"bitrate": getattr(audio.info, "bitrate", None),
|
||||||
|
"length": int(round(audio.info.length, 0)),
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v in remap.items():
|
||||||
|
if v is None:
|
||||||
|
continue
|
||||||
|
if not isinstance(v, (str, int)):
|
||||||
|
remap[k] = str(v)
|
||||||
return remap
|
return remap
|
||||||
|
|
||||||
|
|
||||||
def get_tags(filename: str) -> tuple[MP3 | ID3 | FLAC, str]:
|
def get_tags(filename: str) -> tuple[MP3 | ID3 | WAVE | FLAC | AIFF | MP4, str]:
|
||||||
"""
|
"""
|
||||||
Get the "ID3" tags for an audio file
|
Get the "ID3" tags for an audio file
|
||||||
Returns a tuple of:
|
Returns a tuple of:
|
||||||
@ -77,7 +241,7 @@ def get_tags(filename: str) -> tuple[MP3 | ID3 | FLAC, str]:
|
|||||||
Args
|
Args
|
||||||
- filename
|
- filename
|
||||||
Returns
|
Returns
|
||||||
- tuple(ID3/dict, fail_reason)
|
- tuple(MP3/WAVE/FLAC/ID3/dict, fail_reason)
|
||||||
|
|
||||||
ID3 dict looks like this:
|
ID3 dict looks like this:
|
||||||
{
|
{
|
||||||
@ -86,12 +250,33 @@ def get_tags(filename: str) -> tuple[MP3 | ID3 | FLAC, str]:
|
|||||||
...
|
...
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
# FIXME: this is where i implement other filetypes
|
|
||||||
if filename.lower().endswith(".mp3"):
|
if filename.lower().endswith(".mp3"):
|
||||||
try:
|
try:
|
||||||
tags, details = get_mp3_tags(filename)
|
tags, details = get_mp3_tags(filename)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
tags, details = ID3(), str(e)
|
tags, details = ID3(), str(e)
|
||||||
|
elif filename.lower().endswith(".wav"):
|
||||||
|
try:
|
||||||
|
tags, details = get_wav_tags(filename)
|
||||||
|
except Exception as e:
|
||||||
|
tags, details = WAVE(), str(e)
|
||||||
|
elif filename.lower().endswith(".flac"):
|
||||||
|
try:
|
||||||
|
tags, details = get_flac_tags(filename)
|
||||||
|
except Exception as e:
|
||||||
|
tags, details = FLAC(), str(e)
|
||||||
|
elif filename.lower().endswith(".aiff"):
|
||||||
|
try:
|
||||||
|
tags, details = get_aiff_tags(filename)
|
||||||
|
except Exception as e:
|
||||||
|
tags, details = AIFF(), str(e)
|
||||||
|
elif filename.lower().endswith(".m4a"):
|
||||||
|
try:
|
||||||
|
tags, details = get_m4a_tags(filename)
|
||||||
|
except Exception as e:
|
||||||
|
tags, details = MP4(), str(e)
|
||||||
else:
|
else:
|
||||||
tags, details = ID3(), "non mp3 file"
|
tags, details = ID3(), "Unsupported filetype"
|
||||||
return tags, details
|
return tags, details
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user