file>open files dialog and lyrics testing
This commit is contained in:
parent
767ce3fa9c
commit
a78b5c1a51
49
components/LyricsWindow.py
Normal file
49
components/LyricsWindow.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
from PyQt5.QtWidgets import (
|
||||||
|
QDialog,
|
||||||
|
QPlainTextEdit,
|
||||||
|
QVBoxLayout,
|
||||||
|
QLabel,
|
||||||
|
QPushButton,
|
||||||
|
)
|
||||||
|
from PyQt5.QtGui import QFont
|
||||||
|
from utils import set_id3_tag
|
||||||
|
|
||||||
|
|
||||||
|
class LyricsWindow(QDialog):
|
||||||
|
def __init__(self, song_filepath, lyrics):
|
||||||
|
super(LyricsWindow, self).__init__()
|
||||||
|
self.setWindowTitle("Lyrics")
|
||||||
|
self.lyrics = lyrics
|
||||||
|
self.song_filepath = song_filepath
|
||||||
|
self.input_field = ""
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
# label = QLabel("Lyrics")
|
||||||
|
# layout.addWidget(label)
|
||||||
|
|
||||||
|
# Labels & input fields
|
||||||
|
self.input_fields = {}
|
||||||
|
lyrics_label = QLabel("Lyrics")
|
||||||
|
lyrics_label.setFont(QFont("Sans", weight=QFont.Bold)) # bold category
|
||||||
|
lyrics_label.setStyleSheet("text-transform:uppercase;") # uppercase category
|
||||||
|
layout.addWidget(lyrics_label)
|
||||||
|
self.input_field = QPlainTextEdit(self.lyrics)
|
||||||
|
layout.addWidget(self.input_field)
|
||||||
|
|
||||||
|
# Save button
|
||||||
|
save_button = QPushButton("Save")
|
||||||
|
save_button.clicked.connect(self.save)
|
||||||
|
layout.addWidget(save_button)
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
"""Saves the current lyrics text to the USLT/lyrics ID3 tag"""
|
||||||
|
success = set_id3_tag(
|
||||||
|
filepath=self.song_filepath,
|
||||||
|
tag_name="lyrics",
|
||||||
|
value=self.input_field.toPlainText(),
|
||||||
|
)
|
||||||
|
if success:
|
||||||
|
print("success! yay")
|
||||||
|
else:
|
||||||
|
print("NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN")
|
||||||
|
self.close()
|
||||||
@ -1,6 +1,7 @@
|
|||||||
from mutagen.easyid3 import EasyID3
|
from mutagen.easyid3 import EasyID3
|
||||||
import DBA
|
import DBA
|
||||||
from PyQt5.QtGui import (
|
from PyQt5.QtGui import (
|
||||||
|
QDragMoveEvent,
|
||||||
QStandardItem,
|
QStandardItem,
|
||||||
QStandardItemModel,
|
QStandardItemModel,
|
||||||
QKeySequence,
|
QKeySequence,
|
||||||
@ -16,6 +17,7 @@ from PyQt5.QtWidgets import (
|
|||||||
QAbstractItemView,
|
QAbstractItemView,
|
||||||
)
|
)
|
||||||
from PyQt5.QtCore import QModelIndex, Qt, pyqtSignal, QTimer
|
from PyQt5.QtCore import QModelIndex, Qt, pyqtSignal, QTimer
|
||||||
|
from components.LyricsWindow import LyricsWindow
|
||||||
from utils import add_files_to_library
|
from utils import add_files_to_library
|
||||||
from utils import update_song_in_library
|
from utils import update_song_in_library
|
||||||
from utils import get_id3_tags
|
from utils import get_id3_tags
|
||||||
@ -107,45 +109,79 @@ class MusicTable(QTableView):
|
|||||||
QMessageBox.Yes,
|
QMessageBox.Yes,
|
||||||
)
|
)
|
||||||
if reply:
|
if reply:
|
||||||
# selected_rows = self.get_selected_rows()
|
|
||||||
selected_filepaths = self.get_selected_songs_filepaths()
|
selected_filepaths = self.get_selected_songs_filepaths()
|
||||||
# for index in selected_rows:
|
selected_indices = self.get_selected_rows()
|
||||||
# self.model().removeRow(index)
|
|
||||||
for file in selected_filepaths:
|
for file in selected_filepaths:
|
||||||
with DBA.DBAccess() as db:
|
with DBA.DBAccess() as db:
|
||||||
db.execute("DELETE FROM library WHERE filepath = ?", (file,))
|
db.execute("DELETE FROM library WHERE filepath = ?", (file,))
|
||||||
|
for index in selected_indices:
|
||||||
|
self.model.removeRow(index)
|
||||||
|
|
||||||
def open_directory(self):
|
def open_directory(self):
|
||||||
|
"""Opens the currently selected song in the system file manager"""
|
||||||
|
if self.get_selected_song_filepath() is None:
|
||||||
|
QMessageBox.warning(
|
||||||
|
self,
|
||||||
|
"File does not exist",
|
||||||
|
"No file is selected, or the file does not exist",
|
||||||
|
QMessageBox.Ok,
|
||||||
|
QMessageBox.Ok,
|
||||||
|
)
|
||||||
|
return
|
||||||
filepath = self.get_selected_song_filepath().split("/")
|
filepath = self.get_selected_song_filepath().split("/")
|
||||||
filepath.pop()
|
filepath.pop()
|
||||||
path = "/".join(filepath)
|
path = "/".join(filepath)
|
||||||
Popen(["xdg-open", path])
|
Popen(["xdg-open", path])
|
||||||
|
|
||||||
def show_lyrics_menu(self):
|
def show_lyrics_menu(self):
|
||||||
|
"""Shows the lyrics for the currently selected song"""
|
||||||
|
selected_song_filepath = self.get_selected_song_filepath()
|
||||||
|
if selected_song_filepath is None:
|
||||||
|
return
|
||||||
|
current_song = self.get_selected_song_metadata()
|
||||||
|
print(f"MusicTable.py | show_lyrics_menu | current song: {current_song}")
|
||||||
|
try:
|
||||||
|
lyrics = current_song["lyrics"]
|
||||||
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
try:
|
||||||
|
lyrics = current_song["USLT"]
|
||||||
|
except Exception:
|
||||||
|
lyrics = ""
|
||||||
|
lyrics_window = LyricsWindow(selected_song_filepath, lyrics)
|
||||||
|
lyrics_window.exec_()
|
||||||
|
|
||||||
def dragEnterEvent(self, event: QDragEnterEvent):
|
def dragEnterEvent(self, e: QDragEnterEvent | None):
|
||||||
if event.mimeData().hasUrls():
|
if e is None:
|
||||||
event.accept()
|
return
|
||||||
|
data = e.mimeData()
|
||||||
|
if data and data.hasUrls():
|
||||||
|
e.accept()
|
||||||
else:
|
else:
|
||||||
event.ignore()
|
e.ignore()
|
||||||
|
|
||||||
def dragMoveEvent(self, event: QDragEnterEvent):
|
def dragMoveEvent(self, e: QDragMoveEvent | None):
|
||||||
if event.mimeData().hasUrls():
|
if e is None:
|
||||||
event.accept()
|
return
|
||||||
|
data = e.mimeData()
|
||||||
|
if data and data.hasUrls():
|
||||||
|
e.accept()
|
||||||
else:
|
else:
|
||||||
event.ignore()
|
e.ignore()
|
||||||
|
|
||||||
def dropEvent(self, event: QDropEvent):
|
def dropEvent(self, e: QDropEvent | None):
|
||||||
if event.mimeData().hasUrls():
|
if e is None:
|
||||||
|
return
|
||||||
|
data = e.mimeData()
|
||||||
|
if data and data.hasUrls():
|
||||||
files = []
|
files = []
|
||||||
for url in event.mimeData().urls():
|
for url in data.urls():
|
||||||
if url.isLocalFile():
|
if url.isLocalFile():
|
||||||
files.append(url.path())
|
files.append(url.path())
|
||||||
self.add_files(files)
|
self.add_files(files)
|
||||||
event.accept()
|
e.accept()
|
||||||
else:
|
else:
|
||||||
event.ignore()
|
e.ignore()
|
||||||
|
|
||||||
def setup_keyboard_shortcuts(self):
|
def setup_keyboard_shortcuts(self):
|
||||||
"""Setup shortcuts here"""
|
"""Setup shortcuts here"""
|
||||||
|
|||||||
@ -1,23 +1,25 @@
|
|||||||
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QLabel, QLineEdit, QPushButton
|
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QLabel, QLineEdit, QPushButton
|
||||||
from PyQt5.QtGui import QFont
|
from PyQt5.QtGui import QFont
|
||||||
import configparser
|
|
||||||
|
|
||||||
class PreferencesWindow(QDialog):
|
class PreferencesWindow(QDialog):
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
super(PreferencesWindow, self).__init__()
|
super(PreferencesWindow, self).__init__()
|
||||||
self.setWindowTitle('Preferences')
|
self.setWindowTitle("Preferences")
|
||||||
self.config = config
|
self.config = config
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
label = QLabel('Preferences Window')
|
label = QLabel("Preferences Window")
|
||||||
layout.addWidget(label)
|
layout.addWidget(label)
|
||||||
|
|
||||||
# Labels & input fields
|
# Labels & input fields
|
||||||
self.input_fields = {}
|
self.input_fields = {}
|
||||||
for category in self.config.sections():
|
for category in self.config.sections():
|
||||||
category_label = QLabel(f'{category}')
|
category_label = QLabel(f"{category}")
|
||||||
category_label.setFont(QFont('', weight=QFont.Bold)) # bold category
|
category_label.setFont(QFont("", weight=QFont.Bold)) # bold category
|
||||||
category_label.setStyleSheet("text-transform:uppercase;") # uppercase category
|
category_label.setStyleSheet(
|
||||||
|
"text-transform:uppercase;"
|
||||||
|
) # uppercase category
|
||||||
layout.addWidget(category_label)
|
layout.addWidget(category_label)
|
||||||
for key in self.config[category]:
|
for key in self.config[category]:
|
||||||
label = QLabel(key)
|
label = QLabel(key)
|
||||||
@ -27,7 +29,7 @@ class PreferencesWindow(QDialog):
|
|||||||
self.input_fields[key] = input_field
|
self.input_fields[key] = input_field
|
||||||
|
|
||||||
# Save button
|
# Save button
|
||||||
save_button = QPushButton('Save')
|
save_button = QPushButton("Save")
|
||||||
save_button.clicked.connect(self.save_preferences)
|
save_button.clicked.connect(self.save_preferences)
|
||||||
layout.addWidget(save_button)
|
layout.addWidget(save_button)
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
@ -40,8 +42,7 @@ class PreferencesWindow(QDialog):
|
|||||||
self.config[category][key] = self.input_fields[key].text()
|
self.config[category][key] = self.input_fields[key].text()
|
||||||
|
|
||||||
# Write the config file
|
# Write the config file
|
||||||
with open('config.ini', 'w') as configfile:
|
with open("config.ini", "w") as configfile:
|
||||||
self.config.write(configfile)
|
self.config.write(configfile)
|
||||||
|
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
|||||||
@ -3,3 +3,4 @@ from .AlbumArtGraphicsView import AlbumArtGraphicsView
|
|||||||
from .AudioVisualizer import AudioVisualizer
|
from .AudioVisualizer import AudioVisualizer
|
||||||
from .PreferencesWindow import PreferencesWindow
|
from .PreferencesWindow import PreferencesWindow
|
||||||
from .ErrorDialog import ErrorDialog
|
from .ErrorDialog import ErrorDialog
|
||||||
|
from .LyricsWindow import LyricsWindow
|
||||||
|
|||||||
41
main.py
41
main.py
@ -10,19 +10,20 @@ from configparser import ConfigParser
|
|||||||
import DBA
|
import DBA
|
||||||
from ui import Ui_MainWindow
|
from ui import Ui_MainWindow
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
|
QFileDialog,
|
||||||
QMainWindow,
|
QMainWindow,
|
||||||
QApplication,
|
QApplication,
|
||||||
QGraphicsScene,
|
QGraphicsScene,
|
||||||
QHeaderView,
|
QHeaderView,
|
||||||
QGraphicsPixmapItem,
|
QGraphicsPixmapItem,
|
||||||
|
QMessageBox,
|
||||||
)
|
)
|
||||||
from PyQt5.QtCore import QUrl, QTimer, QEvent, Qt, QModelIndex
|
from PyQt5.QtCore import QUrl, QTimer, QEvent, Qt, QModelIndex
|
||||||
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent, QAudioProbe
|
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent, QAudioProbe
|
||||||
from PyQt5.QtGui import QPixmap, QStandardItemModel
|
from PyQt5.QtGui import QPixmap, QStandardItemModel
|
||||||
from utils import scan_for_music
|
from utils import scan_for_music
|
||||||
from utils import delete_and_create_library_database
|
from utils import delete_and_create_library_database
|
||||||
from components import AudioVisualizer
|
from components import PreferencesWindow, AudioVisualizer
|
||||||
from components import PreferencesWindow
|
|
||||||
|
|
||||||
# Create ui.py file from Qt Designer
|
# Create ui.py file from Qt Designer
|
||||||
# pyuic5 ui.ui -o ui.py
|
# pyuic5 ui.ui -o ui.py
|
||||||
@ -89,14 +90,19 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
|||||||
self.on_previous_clicked
|
self.on_previous_clicked
|
||||||
) # Click to previous song
|
) # Click to previous song
|
||||||
self.nextButton.clicked.connect(self.on_next_clicked) # Click to next song
|
self.nextButton.clicked.connect(self.on_next_clicked) # Click to next song
|
||||||
|
# FILE MENU
|
||||||
|
self.actionOpenFiles.triggered.connect(self.open_files) # Open files window
|
||||||
|
# EDIT MENU
|
||||||
|
# VIEW MENU
|
||||||
self.actionPreferences.triggered.connect(
|
self.actionPreferences.triggered.connect(
|
||||||
self.actionPreferencesClicked
|
self.open_preferences
|
||||||
) # Open preferences menu
|
) # Open preferences menu
|
||||||
|
# QUICK ACTIONS MENU
|
||||||
self.actionScanLibraries.triggered.connect(self.scan_libraries) # Scan library
|
self.actionScanLibraries.triggered.connect(self.scan_libraries) # Scan library
|
||||||
self.actionClearDatabase.triggered.connect(
|
self.actionClearDatabase.triggered.connect(
|
||||||
self.clear_database
|
self.clear_database
|
||||||
) # Clear database
|
) # Clear database
|
||||||
## tableView
|
## tableView triggers
|
||||||
self.tableView.doubleClicked.connect(
|
self.tableView.doubleClicked.connect(
|
||||||
self.play_audio_file
|
self.play_audio_file
|
||||||
) # Listens for the double click event, then plays the song
|
) # Listens for the double click event, then plays the song
|
||||||
@ -322,15 +328,40 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
|||||||
def on_next_clicked(self) -> None:
|
def on_next_clicked(self) -> None:
|
||||||
print("next")
|
print("next")
|
||||||
|
|
||||||
def actionPreferencesClicked(self) -> None:
|
def open_files(self) -> None:
|
||||||
|
"""Opens the open files window"""
|
||||||
|
open_files_window = QFileDialog(
|
||||||
|
self, "Open file(s)", ".", "Audio files (*.mp3)"
|
||||||
|
)
|
||||||
|
# QFileDialog.FileMode enum { AnyFile, ExistingFile, Directory, ExistingFiles }
|
||||||
|
open_files_window.setFileMode(QFileDialog.ExistingFiles)
|
||||||
|
open_files_window.exec_()
|
||||||
|
filenames = open_files_window.selectedFiles()
|
||||||
|
print("file names chosen")
|
||||||
|
print(filenames)
|
||||||
|
self.tableView.add_files(filenames)
|
||||||
|
|
||||||
|
def open_preferences(self) -> None:
|
||||||
|
"""Opens the preferences window"""
|
||||||
preferences_window = PreferencesWindow(self.config)
|
preferences_window = PreferencesWindow(self.config)
|
||||||
preferences_window.exec_() # Display the preferences window modally
|
preferences_window.exec_() # Display the preferences window modally
|
||||||
|
|
||||||
def scan_libraries(self) -> None:
|
def scan_libraries(self) -> None:
|
||||||
|
"""Scans for new files in the configured library folder
|
||||||
|
Refreshes the datagridview"""
|
||||||
scan_for_music()
|
scan_for_music()
|
||||||
self.tableView.fetch_library()
|
self.tableView.fetch_library()
|
||||||
|
|
||||||
def clear_database(self) -> None:
|
def clear_database(self) -> None:
|
||||||
|
"""Clears all songs from the database"""
|
||||||
|
reply = QMessageBox.question(
|
||||||
|
self,
|
||||||
|
"Confirmation",
|
||||||
|
"Clear all songs from database?",
|
||||||
|
QMessageBox.Yes | QMessageBox.No,
|
||||||
|
QMessageBox.Yes,
|
||||||
|
)
|
||||||
|
if reply:
|
||||||
delete_and_create_library_database()
|
delete_and_create_library_database()
|
||||||
self.tableView.fetch_library()
|
self.tableView.fetch_library()
|
||||||
|
|
||||||
|
|||||||
6
ui.py
6
ui.py
@ -154,7 +154,7 @@ class Ui_MainWindow(object):
|
|||||||
self.verticalLayout_3.setStretch(3, 1)
|
self.verticalLayout_3.setStretch(3, 1)
|
||||||
MainWindow.setCentralWidget(self.centralwidget)
|
MainWindow.setCentralWidget(self.centralwidget)
|
||||||
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
||||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 1152, 41))
|
self.menubar.setGeometry(QtCore.QRect(0, 0, 1152, 21))
|
||||||
self.menubar.setObjectName("menubar")
|
self.menubar.setObjectName("menubar")
|
||||||
self.menuFile = QtWidgets.QMenu(self.menubar)
|
self.menuFile = QtWidgets.QMenu(self.menubar)
|
||||||
self.menuFile.setObjectName("menuFile")
|
self.menuFile.setObjectName("menuFile")
|
||||||
@ -174,6 +174,9 @@ class Ui_MainWindow(object):
|
|||||||
self.actionScanLibraries.setObjectName("actionScanLibraries")
|
self.actionScanLibraries.setObjectName("actionScanLibraries")
|
||||||
self.actionClearDatabase = QtWidgets.QAction(MainWindow)
|
self.actionClearDatabase = QtWidgets.QAction(MainWindow)
|
||||||
self.actionClearDatabase.setObjectName("actionClearDatabase")
|
self.actionClearDatabase.setObjectName("actionClearDatabase")
|
||||||
|
self.actionOpenFiles = QtWidgets.QAction(MainWindow)
|
||||||
|
self.actionOpenFiles.setObjectName("actionOpenFiles")
|
||||||
|
self.menuFile.addAction(self.actionOpenFiles)
|
||||||
self.menuEdit.addAction(self.actionPreferences)
|
self.menuEdit.addAction(self.actionPreferences)
|
||||||
self.menuQuick_Actions.addAction(self.actionScanLibraries)
|
self.menuQuick_Actions.addAction(self.actionScanLibraries)
|
||||||
self.menuQuick_Actions.addAction(self.actionClearDatabase)
|
self.menuQuick_Actions.addAction(self.actionClearDatabase)
|
||||||
@ -205,5 +208,6 @@ class Ui_MainWindow(object):
|
|||||||
self.actionPreferences.setStatusTip(_translate("MainWindow", "Open preferences"))
|
self.actionPreferences.setStatusTip(_translate("MainWindow", "Open preferences"))
|
||||||
self.actionScanLibraries.setText(_translate("MainWindow", "Scan libraries"))
|
self.actionScanLibraries.setText(_translate("MainWindow", "Scan libraries"))
|
||||||
self.actionClearDatabase.setText(_translate("MainWindow", "Clear Database"))
|
self.actionClearDatabase.setText(_translate("MainWindow", "Clear Database"))
|
||||||
|
self.actionOpenFiles.setText(_translate("MainWindow", "Open file(s)"))
|
||||||
from components import AlbumArtGraphicsView, MusicTable
|
from components import AlbumArtGraphicsView, MusicTable
|
||||||
from pyqtgraph import PlotWidget
|
from pyqtgraph import PlotWidget
|
||||||
|
|||||||
8
ui.ui
8
ui.ui
@ -274,13 +274,14 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1152</width>
|
<width>1152</width>
|
||||||
<height>41</height>
|
<height>21</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menuFile">
|
<widget class="QMenu" name="menuFile">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>File</string>
|
<string>File</string>
|
||||||
</property>
|
</property>
|
||||||
|
<addaction name="actionOpenFiles"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuEdit">
|
<widget class="QMenu" name="menuEdit">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -324,6 +325,11 @@
|
|||||||
<string>Clear Database</string>
|
<string>Clear Database</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionOpenFiles">
|
||||||
|
<property name="text">
|
||||||
|
<string>Open file(s)</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
|||||||
@ -14,15 +14,15 @@ def add_files_to_library(files):
|
|||||||
"""
|
"""
|
||||||
if not files:
|
if not files:
|
||||||
return []
|
return []
|
||||||
print(f"utils/add_files_to_library: {files}")
|
# print(f"utils/add_files_to_library: {files}")
|
||||||
extensions = config.get("settings", "extensions").split(",")
|
extensions = config.get("settings", "extensions").split(",")
|
||||||
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):
|
||||||
filename = filepath.split("/")[-1]
|
filename = filepath.split("/")[-1]
|
||||||
audio = get_id3_tags(filepath)
|
audio = get_id3_tags(filepath)
|
||||||
print('add_files_to_library audio:')
|
# print("add_files_to_library audio:")
|
||||||
print(audio)
|
# print(audio)
|
||||||
# Skip if no title is found (but should never happen
|
# Skip if no title is found (but should never happen
|
||||||
if "title" not in audio:
|
if "title" not in audio:
|
||||||
continue
|
continue
|
||||||
|
|||||||
2
utils/create_blank_mp3.sh
Normal file
2
utils/create_blank_mp3.sh
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
ffmpeg -f lavfi -i anullsrc=r=44100:cl=mono -t 5 -q:a 9 -acodec libmp3lame out.mp3
|
||||||
@ -20,24 +20,25 @@ def get_id3_tags(file):
|
|||||||
is_easy_id3 = False
|
is_easy_id3 = False
|
||||||
audio = {}
|
audio = {}
|
||||||
|
|
||||||
print('get_id3_tags audio:')
|
# print('get_id3_tags audio:')
|
||||||
print(audio)
|
# print(audio)
|
||||||
|
|
||||||
# Check if all tags are empty
|
# Check if all tags are empty
|
||||||
tags_are_empty = all(not values for values in audio.values())
|
tags_are_empty = all(not values for values in audio.values())
|
||||||
if tags_are_empty:
|
if tags_are_empty:
|
||||||
# split on / to get just the filename
|
# split on / to get just the filename
|
||||||
# os.path.splitext to get name without extension
|
# os.path.splitext to get name without extension
|
||||||
audio['title'] = [os.path.splitext(file.split('/')[-1])[0]]
|
audio["title"] = [os.path.splitext(file.split("/")[-1])[0]]
|
||||||
|
|
||||||
if audio['title'] is None: # I guess a song could have other tags
|
if audio["title"] is None: # I guess a song could have other tags
|
||||||
# without a title, so i make sure to have title
|
# without a title, so i make sure to have title
|
||||||
audio['title'] = [os.path.splitext(file.split('/')[-1])[0]]
|
audio["title"] = [os.path.splitext(file.split("/")[-1])[0]]
|
||||||
|
|
||||||
if is_easy_id3: # i can ignore this error because of this check
|
if is_easy_id3: # i can ignore this error because of this check
|
||||||
audio.save() # type: ignore
|
audio.save() # type: ignore
|
||||||
return audio
|
return audio
|
||||||
|
|
||||||
|
|
||||||
# import sys
|
# import sys
|
||||||
# my_file = sys.argv[1]
|
# my_file = sys.argv[1]
|
||||||
# data = get_id3_tags(my_file)
|
# data = get_id3_tags(my_file)
|
||||||
|
|||||||
@ -84,12 +84,12 @@ def set_id3_tag(filepath: str, tag_name: str, value: str):
|
|||||||
Args:
|
Args:
|
||||||
filepath: path to the mp3 file
|
filepath: path to the mp3 file
|
||||||
tag_name: common name of the ID3 tag
|
tag_name: common name of the ID3 tag
|
||||||
value: valut to set for the tag
|
value: value to set for the tag
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True / False"""
|
True / False"""
|
||||||
print(
|
print(
|
||||||
f"set_id3_tag(): filepath: {filepath} | tag_name: {tag_name} | value: {value}"
|
f"set_id3_tag.py | filepath: {filepath} | tag_name: {tag_name} | value: {value}"
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -105,11 +105,16 @@ def set_id3_tag(filepath: str, tag_name: str, value: str):
|
|||||||
if tdat_tag:
|
if tdat_tag:
|
||||||
# update TDAT if we have it
|
# update TDAT if we have it
|
||||||
audio_file.tags.add(tdat_tag)
|
audio_file.tags.add(tdat_tag)
|
||||||
|
elif tag_name == "lyrics":
|
||||||
|
print("lyrics..........")
|
||||||
|
audio_file.tags.add(USLT(encoding=3, lang="eng", desc="desc", text=value))
|
||||||
elif tag_name in id3_tag_mapping: # Tag accounted for
|
elif tag_name in id3_tag_mapping: # Tag accounted for
|
||||||
tag_class = id3_tag_mapping[tag_name]
|
tag_class = id3_tag_mapping[tag_name]
|
||||||
|
print(f"set_id3_tag.py | tag_class: {tag_class}")
|
||||||
# if issubclass(tag_class, EasyID3) or issubclass(tag_class, ID3): # Type safety
|
# if issubclass(tag_class, EasyID3) or issubclass(tag_class, ID3): # Type safety
|
||||||
if issubclass(tag_class, Frame):
|
if issubclass(tag_class, Frame):
|
||||||
audio_file.tags.add(tag_class(encoding=3, text=value)) # Add the tag
|
audio_file.tags.add(tag_class(encoding=3, text=value)) # Add the tag
|
||||||
|
print(f"AAAAAAAAAAAAAA")
|
||||||
else:
|
else:
|
||||||
# dialog = ErrorDialog(f'ID3 tag not supported.\nTag: {tag_name}\nTag class: {tag_class}\nValue:{value}')
|
# dialog = ErrorDialog(f'ID3 tag not supported.\nTag: {tag_name}\nTag class: {tag_class}\nValue:{value}')
|
||||||
# dialog.exec_()
|
# dialog.exec_()
|
||||||
@ -122,9 +127,9 @@ def set_id3_tag(filepath: str, tag_name: str, value: str):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
audio_file.save()
|
audio_file.save()
|
||||||
print("ID3 tags updated:")
|
print("set_id3_tag.py | ID3 tags updated:")
|
||||||
print(get_id3_tags(filepath))
|
print(get_id3_tags(filepath))
|
||||||
print("-----")
|
print("set_id3_tag.py | -----")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user