add files to lib return value debug
This commit is contained in:
parent
47ec08ec15
commit
40d78066c6
@ -8,12 +8,11 @@ from logging import debug
|
|||||||
|
|
||||||
|
|
||||||
class DebugWindow(QDialog):
|
class DebugWindow(QDialog):
|
||||||
def __init__(self, song_filepath: str, text: str):
|
def __init__(self, text: str):
|
||||||
super(DebugWindow, self).__init__()
|
super(DebugWindow, self).__init__()
|
||||||
self.setWindowTitle("debug")
|
self.setWindowTitle("debug")
|
||||||
self.setMinimumSize(400, 400)
|
self.setMinimumSize(400, 400)
|
||||||
self.text: str = text
|
self.text: str = text
|
||||||
self.song_filepath: str = song_filepath
|
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
# Labels & input fields
|
# Labels & input fields
|
||||||
|
|||||||
@ -124,7 +124,7 @@ class MusicTable(QTableView):
|
|||||||
self.selected_song_filepath = ""
|
self.selected_song_filepath = ""
|
||||||
self.current_song_filepath = ""
|
self.current_song_filepath = ""
|
||||||
self.current_song_db_id = None
|
self.current_song_db_id = None
|
||||||
self.current_song_qmodelindex = None
|
self.current_song_qmodelindex: QModelIndex
|
||||||
|
|
||||||
# Properties
|
# Properties
|
||||||
self.setAcceptDrops(True)
|
self.setAcceptDrops(True)
|
||||||
@ -265,7 +265,7 @@ class MusicTable(QTableView):
|
|||||||
if directories:
|
if directories:
|
||||||
worker = Worker(self.get_audio_files_recursively, directories)
|
worker = Worker(self.get_audio_files_recursively, directories)
|
||||||
worker.signals.signal_progress.connect(self.handle_progress)
|
worker.signals.signal_progress.connect(self.handle_progress)
|
||||||
worker.signals.signal_result.connect(self.on_recursive_search_finished)
|
worker.signals.signal_result.connect(self.on_get_audio_files_recursively_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
|
threadpool = self.qapp.threadpool
|
||||||
@ -399,49 +399,29 @@ class MusicTable(QTableView):
|
|||||||
update_song_in_database(song_id, edited_column_name, user_input_data)
|
update_song_in_database(song_id, edited_column_name, user_input_data)
|
||||||
return
|
return
|
||||||
|
|
||||||
def on_recursive_search_finished(self, result):
|
|
||||||
"""file search completion handler"""
|
|
||||||
if result:
|
|
||||||
self.add_files_to_library(result)
|
|
||||||
|
|
||||||
def handle_progress(self, data):
|
def handle_progress(self, data):
|
||||||
"""Emits data to main"""
|
"""Emits data to main"""
|
||||||
self.handleProgressSignal.emit(data)
|
self.handleProgressSignal.emit(data)
|
||||||
|
|
||||||
# ____________________
|
def on_get_audio_files_recursively_finished(self, result):
|
||||||
# | |
|
"""file search completion handler"""
|
||||||
# | |
|
if result:
|
||||||
# | Connection Mgmt |
|
self.add_files_to_library(result)
|
||||||
# | |
|
|
||||||
# |____________________|
|
|
||||||
|
|
||||||
def disconnect_data_changed(self):
|
def on_add_files_to_database_finished(self, *args):
|
||||||
"""Disconnects the dataChanged signal from QTableView.model"""
|
"""
|
||||||
try:
|
Shows failed to import files and reasons
|
||||||
self.model2.dataChanged.disconnect()
|
Runs after worker process signal_finished for add_files_to_database()
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def connect_data_changed(self):
|
Args:
|
||||||
"""Connects the dataChanged signal from QTableView.model"""
|
- args: ((return_data),)
|
||||||
try:
|
- data returned from the original worker process function are returned here
|
||||||
self.model2.dataChanged.connect(self.on_cell_data_changed)
|
as the first item in a tuple
|
||||||
except Exception:
|
"""
|
||||||
pass
|
# TODO: make this prettier, show a table in a window instead of raw text probably
|
||||||
|
_, details = args[0][:2]
|
||||||
def disconnect_layout_changed(self):
|
window = DebugWindow(details)
|
||||||
"""Disconnects the layoutChanged signal from QTableView.model"""
|
window.exec_()
|
||||||
try:
|
|
||||||
self.model2.layoutChanged.disconnect()
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def connect_layout_changed(self):
|
|
||||||
"""Connects the layoutChanged signal from QTableView.model"""
|
|
||||||
try:
|
|
||||||
self.model2.layoutChanged.connect(self.restore_scroll_position)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# ____________________
|
# ____________________
|
||||||
# | |
|
# | |
|
||||||
@ -458,6 +438,7 @@ class MusicTable(QTableView):
|
|||||||
"""
|
"""
|
||||||
worker = Worker(add_files_to_database, files)
|
worker = Worker(add_files_to_database, files)
|
||||||
worker.signals.signal_progress.connect(self.qapp.handle_progress)
|
worker.signals.signal_progress.connect(self.qapp.handle_progress)
|
||||||
|
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
|
threadpool = self.qapp.threadpool
|
||||||
@ -539,12 +520,9 @@ class MusicTable(QTableView):
|
|||||||
|
|
||||||
def show_id3_tags_debug_menu(self):
|
def show_id3_tags_debug_menu(self):
|
||||||
"""Shows ID3 tags for a specific .mp3 file"""
|
"""Shows ID3 tags for a specific .mp3 file"""
|
||||||
selected_song_filepath = self.get_selected_song_filepath()
|
if self.get_selected_song_filepath() is not None:
|
||||||
if selected_song_filepath is None:
|
window = DebugWindow(str(self.get_selected_song_metadata()))
|
||||||
return
|
window.exec_()
|
||||||
current_song = self.get_selected_song_metadata()
|
|
||||||
lyrics_window = DebugWindow(selected_song_filepath, str(current_song))
|
|
||||||
lyrics_window.exec_()
|
|
||||||
|
|
||||||
def show_lyrics_menu(self):
|
def show_lyrics_menu(self):
|
||||||
"""Shows the lyrics for the currently selected song"""
|
"""Shows the lyrics for the currently selected song"""
|
||||||
@ -601,6 +579,8 @@ class MusicTable(QTableView):
|
|||||||
debug("reorganizing files")
|
debug("reorganizing files")
|
||||||
# FIXME: batch update, instead of doing 1 file at a time
|
# FIXME: batch update, instead of doing 1 file at a time
|
||||||
# DBAccess is being instantiated for every file, boo
|
# DBAccess is being instantiated for every file, boo
|
||||||
|
# NOTE:
|
||||||
|
# is that even possible with move file function?
|
||||||
|
|
||||||
# Get target directory
|
# Get target directory
|
||||||
target_dir = str(self.config["directories"]["reorganize_destination"])
|
target_dir = str(self.config["directories"]["reorganize_destination"])
|
||||||
@ -618,10 +598,8 @@ class MusicTable(QTableView):
|
|||||||
if progress_callback:
|
if progress_callback:
|
||||||
progress_callback.emit(f"Organizing: {filepath}")
|
progress_callback.emit(f"Organizing: {filepath}")
|
||||||
# Create the directories if they dont exist
|
# Create the directories if they dont exist
|
||||||
debug("make dirs")
|
|
||||||
os.makedirs(os.path.dirname(new_path), exist_ok=True)
|
os.makedirs(os.path.dirname(new_path), exist_ok=True)
|
||||||
# Move the file to the new directory
|
# Move the file to the new directory
|
||||||
debug(f"{filepath} > {new_path}")
|
|
||||||
shutil.move(filepath, new_path)
|
shutil.move(filepath, new_path)
|
||||||
# Update the db
|
# Update the db
|
||||||
with DBA.DBAccess() as db:
|
with DBA.DBAccess() as db:
|
||||||
@ -629,7 +607,7 @@ class MusicTable(QTableView):
|
|||||||
"UPDATE song SET filepath = ? WHERE filepath = ?",
|
"UPDATE song SET filepath = ? WHERE filepath = ?",
|
||||||
(new_path, filepath),
|
(new_path, filepath),
|
||||||
)
|
)
|
||||||
debug(f"reorganize_files() | Moved: {filepath} -> {new_path}")
|
# debug(f"reorganize_files() | Moved: {filepath} -> {new_path}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error(f"reorganize_files() | Error moving file: {filepath} | {e}")
|
error(f"reorganize_files() | Error moving file: {filepath} | {e}")
|
||||||
# Draw the rest of the owl
|
# Draw the rest of the owl
|
||||||
@ -757,7 +735,7 @@ class MusicTable(QTableView):
|
|||||||
|
|
||||||
def restore_scroll_position(self) -> None:
|
def restore_scroll_position(self) -> None:
|
||||||
"""Restores the scroll position"""
|
"""Restores the scroll position"""
|
||||||
debug("restore_scroll_position")
|
debug("restore_scroll_position (inactive)")
|
||||||
# QTimer.singleShot(
|
# QTimer.singleShot(
|
||||||
# 100,
|
# 100,
|
||||||
# lambda: self.verticalScrollBar().setValue(self.vertical_scroll_position),
|
# lambda: self.verticalScrollBar().setValue(self.vertical_scroll_position),
|
||||||
@ -845,6 +823,40 @@ class MusicTable(QTableView):
|
|||||||
"""Necessary for using members and methods of main application window"""
|
"""Necessary for using members and methods of main application window"""
|
||||||
self.qapp = qapp
|
self.qapp = qapp
|
||||||
|
|
||||||
|
# ____________________
|
||||||
|
# | |
|
||||||
|
# | |
|
||||||
|
# | Connection Mgmt |
|
||||||
|
# | |
|
||||||
|
# |____________________|
|
||||||
|
|
||||||
|
def disconnect_data_changed(self):
|
||||||
|
"""Disconnects the dataChanged signal from QTableView.model"""
|
||||||
|
try:
|
||||||
|
self.model2.dataChanged.disconnect()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def connect_data_changed(self):
|
||||||
|
"""Connects the dataChanged signal from QTableView.model"""
|
||||||
|
try:
|
||||||
|
self.model2.dataChanged.connect(self.on_cell_data_changed)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def disconnect_layout_changed(self):
|
||||||
|
"""Disconnects the layoutChanged signal from QTableView.model"""
|
||||||
|
try:
|
||||||
|
self.model2.layoutChanged.disconnect()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def connect_layout_changed(self):
|
||||||
|
"""Connects the layoutChanged signal from QTableView.model"""
|
||||||
|
try:
|
||||||
|
self.model2.layoutChanged.connect(self.restore_scroll_position)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# QT Roles
|
# QT Roles
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
from PyQt5.QtWidgets import QMessageBox
|
from PyQt5.QtWidgets import QMessageBox
|
||||||
|
from mutagen.id3 import ID3
|
||||||
import DBA
|
import DBA
|
||||||
from logging import debug
|
from logging import debug
|
||||||
from utils import get_id3_tags, convert_id3_timestamp_to_datetime
|
from utils import get_id3_tags, convert_id3_timestamp_to_datetime
|
||||||
@ -21,25 +22,21 @@ def add_files_to_database(files, progress_callback=None):
|
|||||||
Path(user_config_dir(appname="musicpom", appauthor="billypom")) / "config.ini"
|
Path(user_config_dir(appname="musicpom", appauthor="billypom")) / "config.ini"
|
||||||
)
|
)
|
||||||
config.read(cfg_file)
|
config.read(cfg_file)
|
||||||
|
|
||||||
if not files:
|
if not files:
|
||||||
return False
|
return False, {'Failure': 'All operations failed in add_files_to_database()'}
|
||||||
extensions = config.get("settings", "extensions").split(",")
|
extensions = config.get("settings", "extensions").split(",")
|
||||||
|
failed_dict = {}
|
||||||
insert_data = [] # To store data for batch insert
|
insert_data = [] # To store data for batch insert
|
||||||
for filepath in files:
|
for filepath in files:
|
||||||
if any(filepath.lower().endswith(ext) for ext in extensions):
|
if any(filepath.lower().endswith(ext) for ext in extensions):
|
||||||
if progress_callback:
|
if progress_callback:
|
||||||
progress_callback.emit(filepath)
|
progress_callback.emit(filepath)
|
||||||
filename = filepath.split("/")[-1]
|
filename = filepath.split("/")[-1]
|
||||||
audio = get_id3_tags(filepath)
|
|
||||||
if not audio:
|
audio, details = get_id3_tags(filepath)
|
||||||
QMessageBox.error(
|
if not isinstance(audio, ID3):
|
||||||
"Error",
|
failed_dict[filepath] = details
|
||||||
f"Could not retrieve ID3 tags for {filepath}",
|
continue
|
||||||
QMessageBox.Ok,
|
|
||||||
QMessageBox.Ok,
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
title = audio["TIT2"].text[0]
|
title = audio["TIT2"].text[0]
|
||||||
@ -105,7 +102,7 @@ def add_files_to_database(files, progress_callback=None):
|
|||||||
"INSERT OR IGNORE INTO song (filepath, title, album, artist, track_number, genre, codec, album_date, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
"INSERT OR IGNORE INTO song (filepath, title, album, artist, track_number, genre, codec, album_date, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
insert_data,
|
insert_data,
|
||||||
)
|
)
|
||||||
return True
|
return True, failed_dict
|
||||||
|
|
||||||
|
|
||||||
# id int unsigned auto_increment,
|
# id int unsigned auto_increment,
|
||||||
|
|||||||
@ -5,38 +5,39 @@ from mutagen.id3._frames import TIT2
|
|||||||
from mutagen.id3._util import ID3NoHeaderError
|
from mutagen.id3._util import ID3NoHeaderError
|
||||||
|
|
||||||
|
|
||||||
def get_id3_tags(filename: str):
|
def get_id3_tags(filename: str) -> tuple[object, str]:
|
||||||
"""Get the ID3 tags for an audio file"""
|
"""Get the ID3 tags for an audio file"""
|
||||||
# debug(filename)
|
# debug(filename)
|
||||||
|
|
||||||
if filename.endswith(".flac"):
|
if filename.endswith(".mp3"):
|
||||||
return
|
try:
|
||||||
|
# Open the MP3 file and read its content
|
||||||
|
audio = ID3(filename)
|
||||||
|
except ID3NoHeaderError:
|
||||||
|
audio = ID3()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Open the MP3 file and read its content
|
if os.path.exists(filename):
|
||||||
audio = ID3(filename)
|
audio.save(os.path.abspath(filename))
|
||||||
except ID3NoHeaderError:
|
|
||||||
audio = ID3()
|
|
||||||
|
|
||||||
try:
|
# NOTE: If 'TIT2' tag is not set, we add it with a default value
|
||||||
if os.path.exists(filename):
|
# title = filename without extension
|
||||||
audio.save(os.path.abspath(filename))
|
|
||||||
|
|
||||||
# NOTE: If 'TIT2' tag is not set, we add it with a default value
|
title = os.path.splitext(os.path.basename(filename))[0]
|
||||||
# title = filename without extension
|
list_of_id3_tags = list(audio.keys())
|
||||||
|
if "TIT2" in list_of_id3_tags:
|
||||||
title = os.path.splitext(os.path.basename(filename))[0]
|
audio.save()
|
||||||
list_of_id3_tags = list(audio.keys())
|
return audio, ""
|
||||||
if "TIT2" in list_of_id3_tags:
|
else:
|
||||||
|
tit2_tag = TIT2(encoding=3, text=[title])
|
||||||
|
audio["TIT2"] = tit2_tag
|
||||||
|
# Save the updated tags
|
||||||
audio.save()
|
audio.save()
|
||||||
return audio
|
return audio, ""
|
||||||
else:
|
|
||||||
tit2_tag = TIT2(encoding=3, text=[title])
|
except Exception as e:
|
||||||
audio["TIT2"] = tit2_tag
|
error(f"Could not assign file ID3 tag: {e}")
|
||||||
# Save the updated tags
|
return None, f"Could not assign ID3 tag to file: {e}"
|
||||||
audio.save()
|
return None, "non mp3 file"
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
error(f"Could not assign file ID3 tag: {e}")
|
|
||||||
|
|
||||||
return audio
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user