layouts, mutagen id3 tags, table drag & drop, double click to play
This commit is contained in:
parent
b85cd47844
commit
76c1aa554b
@ -1,10 +1,17 @@
|
|||||||
from PyQt5 import QtWidgets, QtGui, QtCore
|
from PyQt5 import QtWidgets
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from .fft_analyser import FFTAnalyser
|
from utils import FFTAnalyser
|
||||||
|
|
||||||
class AudioVisualizer(QtWidgets.QWidget):
|
class AudioVisualizer(QtWidgets.QWidget):
|
||||||
|
"""_Audio Visualizer component_
|
||||||
|
|
||||||
|
Args:
|
||||||
|
QtWidgets (_type_): _description_
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
_type_: _description_
|
||||||
|
"""
|
||||||
def __init__(self, media_player):
|
def __init__(self, media_player):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.media_player = media_player
|
self.media_player = media_player
|
||||||
@ -1,16 +1,17 @@
|
|||||||
import DBA
|
import DBA
|
||||||
from PyQt5.QtGui import QStandardItem, QStandardItemModel
|
from PyQt5.QtGui import QStandardItem, QStandardItemModel
|
||||||
from PyQt5.QtWidgets import QTableView, QApplication
|
from PyQt5.QtWidgets import QTableView
|
||||||
from PyQt5.QtCore import QTimer
|
from PyQt5.QtCore import QTimer
|
||||||
from tinytag import TinyTag
|
from tinytag import TinyTag
|
||||||
|
from utils import add_files_to_library
|
||||||
|
from utils import get_id3_tags
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
class MusicTable(QTableView):
|
class MusicTable(QTableView):
|
||||||
def __init__(self, parent=None, qapp=None):
|
def __init__(self, parent=None, qapp=None):
|
||||||
QTableView.__init__(self, parent)
|
QTableView.__init__(self, parent)
|
||||||
self.headers = ['title', 'artist', 'album', 'genre', 'codec', 'year', 'path']
|
self.headers = ['title', 'artist', 'album', 'genre', 'codec', 'year', 'path']
|
||||||
self.model = QStandardItemModel()
|
|
||||||
self.model.setHorizontalHeaderLabels(self.headers)
|
|
||||||
self.songChanged = None
|
self.songChanged = None
|
||||||
self.selected_song_filepath = None
|
self.selected_song_filepath = None
|
||||||
self.current_song_filepath = None
|
self.current_song_filepath = None
|
||||||
@ -56,6 +57,9 @@ class MusicTable(QTableView):
|
|||||||
"""Sets the filepath of the currently selected song"""
|
"""Sets the filepath of the currently selected song"""
|
||||||
self.selected_song_filepath = self.currentIndex().siblingAtColumn(self.headers.index('path')).data()
|
self.selected_song_filepath = self.currentIndex().siblingAtColumn(self.headers.index('path')).data()
|
||||||
print(f'Selected song: {self.selected_song_filepath}')
|
print(f'Selected song: {self.selected_song_filepath}')
|
||||||
|
print('TAGS:')
|
||||||
|
print(get_id3_tags(self.selected_song_filepath))
|
||||||
|
print('END TAGS')
|
||||||
|
|
||||||
def set_current_song_filepath(self):
|
def set_current_song_filepath(self):
|
||||||
"""Sets the filepath of the currently playing/chosen song"""
|
"""Sets the filepath of the currently playing/chosen song"""
|
||||||
@ -80,6 +84,9 @@ class MusicTable(QTableView):
|
|||||||
|
|
||||||
|
|
||||||
def fetch_library(self):
|
def fetch_library(self):
|
||||||
|
"""Initialize the tableview model"""
|
||||||
|
self.model = QStandardItemModel()
|
||||||
|
self.model.setHorizontalHeaderLabels(self.headers)
|
||||||
# Fetch library data
|
# Fetch library data
|
||||||
with DBA.DBAccess() as db:
|
with DBA.DBAccess() as db:
|
||||||
data = db.query('SELECT title, artist, album, genre, codec, album_date, filepath FROM library;', ())
|
data = db.query('SELECT title, artist, album, genre, codec, album_date, filepath FROM library;', ())
|
||||||
@ -89,6 +96,20 @@ class MusicTable(QTableView):
|
|||||||
self.model.appendRow(items)
|
self.model.appendRow(items)
|
||||||
# Set the model to the tableView (we are the tableview)
|
# Set the model to the tableView (we are the tableview)
|
||||||
self.setModel(self.model)
|
self.setModel(self.model)
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def add_files(self, files):
|
||||||
|
"""When song(s) added to the library, update the tableview model
|
||||||
|
- Drag & Drop song(s) on tableView
|
||||||
|
- File > Open > List of song(s)
|
||||||
|
"""
|
||||||
|
print(f'tableView - adding files: {files}')
|
||||||
|
response = add_files_to_library(files)
|
||||||
|
if response:
|
||||||
|
self.fetch_library()
|
||||||
|
else:
|
||||||
|
logging.warning('MusicTable.add_files | failed to add files to library')
|
||||||
|
|
||||||
|
|
||||||
def load_qapp(self, qapp):
|
def load_qapp(self, qapp):
|
||||||
self.qapp = qapp
|
self.qapp = qapp
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
from .MusicTable import MusicTable
|
from .MusicTable import MusicTable
|
||||||
|
from .AudioVisualizer import AudioVisualizer
|
||||||
52
main.py
52
main.py
@ -2,15 +2,16 @@ import DBA
|
|||||||
from ui import Ui_MainWindow
|
from ui import Ui_MainWindow
|
||||||
from PyQt5.QtWidgets import QMainWindow, QApplication
|
from PyQt5.QtWidgets import QMainWindow, QApplication
|
||||||
import qdarktheme
|
import qdarktheme
|
||||||
from PyQt5.QtCore import QUrl, QTimer, QFile, QTextStream
|
from PyQt5.QtCore import QUrl, QTimer, QEvent
|
||||||
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent, QAudioProbe
|
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent, QAudioProbe
|
||||||
from PyQt5.QtGui import QStandardItem, QStandardItemModel
|
|
||||||
from utils import scan_for_music
|
from utils import scan_for_music
|
||||||
from utils import initialize_library_database
|
from utils import initialize_library_database
|
||||||
from utils import AudioVisualizer
|
from components import AudioVisualizer
|
||||||
from pyqtgraph import mkBrush
|
from pyqtgraph import mkBrush
|
||||||
from components import MusicTable
|
import configparser
|
||||||
|
|
||||||
|
# Create ui.py file from Qt Designer
|
||||||
|
# pyuic5 ui.ui -o ui.py
|
||||||
|
|
||||||
class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||||
def __init__(self, qapp):
|
def __init__(self, qapp):
|
||||||
@ -23,6 +24,8 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
|||||||
self.qapp = qapp
|
self.qapp = qapp
|
||||||
print(f'ApplicationWindow self.qapp: {self.qapp}')
|
print(f'ApplicationWindow self.qapp: {self.qapp}')
|
||||||
self.tableView.load_qapp(self.qapp)
|
self.tableView.load_qapp(self.qapp)
|
||||||
|
self.config = configparser.ConfigParser()
|
||||||
|
self.config.read('config.ini')
|
||||||
|
|
||||||
global stopped
|
global stopped
|
||||||
stopped = False
|
stopped = False
|
||||||
@ -64,12 +67,51 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
|||||||
# self.pauseButton.clicked.connect(self.on_pause_clicked)
|
# self.pauseButton.clicked.connect(self.on_pause_clicked)
|
||||||
self.previousButton.clicked.connect(self.on_previous_clicked) # Click to previous song
|
self.previousButton.clicked.connect(self.on_previous_clicked) # 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
|
||||||
# self.tableView.clicked.connect(self.set_clicked_cell_filepath)
|
|
||||||
self.actionPreferences.triggered.connect(self.actionPreferencesClicked) # Open preferences menu
|
self.actionPreferences.triggered.connect(self.actionPreferencesClicked) # Open preferences menu
|
||||||
self.actionScanLibraries.triggered.connect(self.scan_libraries) # Scan library
|
self.actionScanLibraries.triggered.connect(self.scan_libraries) # Scan library
|
||||||
self.actionClearDatabase.triggered.connect(initialize_library_database) # Clear database
|
self.actionClearDatabase.triggered.connect(initialize_library_database) # Clear database
|
||||||
|
## tableView
|
||||||
|
# self.tableView.clicked.connect(self.set_clicked_cell_filepath)
|
||||||
self.tableView.doubleClicked.connect(self.play_audio_file) # Double click to play song
|
self.tableView.doubleClicked.connect(self.play_audio_file) # Double click to play song
|
||||||
|
self.tableView.viewport().installEventFilter(self) # for drag & drop functionality
|
||||||
|
# self.tableView.model.layoutChanged()
|
||||||
|
### set column widths
|
||||||
|
table_view_column_widths = str(self.config['table']['column_widths']).split(',')
|
||||||
|
for i in range(self.tableView.model.columnCount()):
|
||||||
|
self.tableView.setColumnWidth(i, int(table_view_column_widths[i]))
|
||||||
|
|
||||||
|
def eventFilter(self, source, event):
|
||||||
|
"""Handles events"""
|
||||||
|
# tableView (drag & drop)
|
||||||
|
if (source is self.tableView.viewport() and
|
||||||
|
(event.type() == QEvent.DragEnter or
|
||||||
|
event.type() == QEvent.DragMove or
|
||||||
|
event.type() == QEvent.Drop) and
|
||||||
|
event.mimeData().hasUrls()):
|
||||||
|
files = []
|
||||||
|
if event.type() == QEvent.Drop:
|
||||||
|
for url in event.mimeData().urls():
|
||||||
|
if url.isLocalFile():
|
||||||
|
files.append(url.path())
|
||||||
|
self.tableView.add_files(files)
|
||||||
|
event.accept()
|
||||||
|
return True
|
||||||
|
return super().eventFilter(source, event)
|
||||||
|
|
||||||
|
def closeEvent(self, event):
|
||||||
|
"""Save settings when closing the application"""
|
||||||
|
# MusicTable/tableView column widths
|
||||||
|
list_of_column_widths = []
|
||||||
|
for i in range(self.tableView.model.columnCount()):
|
||||||
|
list_of_column_widths.append(str(self.tableView.columnWidth(i)))
|
||||||
|
column_widths_as_string = ','.join(list_of_column_widths)
|
||||||
|
self.config['table']['column_widths'] = column_widths_as_string
|
||||||
|
|
||||||
|
|
||||||
|
# Save the config
|
||||||
|
with open('config.ini', 'w') as configfile:
|
||||||
|
self.config.write(configfile)
|
||||||
|
super().closeEvent(event)
|
||||||
|
|
||||||
def play_audio_file(self):
|
def play_audio_file(self):
|
||||||
"""Start playback of selected track & moves playback slider"""
|
"""Start playback of selected track & moves playback slider"""
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
tinytag
|
mutagen
|
||||||
matplotlib
|
matplotlib
|
||||||
pyqt5
|
pyqt5
|
||||||
pydub
|
pydub
|
||||||
|
|||||||
@ -10,3 +10,7 @@ reorganize_destination = /where/to/reorganize/to
|
|||||||
[settings]
|
[settings]
|
||||||
# Which file types are scanned
|
# Which file types are scanned
|
||||||
extensions = mp3,wav,ogg,flac
|
extensions = mp3,wav,ogg,flac
|
||||||
|
|
||||||
|
[table]
|
||||||
|
# Music table column widths
|
||||||
|
column_widths = 181,116,222,76,74,72,287
|
||||||
158
ui.py
158
ui.py
@ -18,32 +18,13 @@ class Ui_MainWindow(object):
|
|||||||
MainWindow.setStatusTip("")
|
MainWindow.setStatusTip("")
|
||||||
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
||||||
self.centralwidget.setObjectName("centralwidget")
|
self.centralwidget.setObjectName("centralwidget")
|
||||||
self.frame = QtWidgets.QFrame(self.centralwidget)
|
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.centralwidget)
|
||||||
self.frame.setGeometry(QtCore.QRect(0, 160, 1061, 461))
|
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
|
self.frame_6 = QtWidgets.QFrame(self.centralwidget)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
self.frame_6.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
||||||
sizePolicy.setVerticalStretch(0)
|
self.frame_6.setFrameShadow(QtWidgets.QFrame.Raised)
|
||||||
sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth())
|
self.frame_6.setObjectName("frame_6")
|
||||||
self.frame.setSizePolicy(sizePolicy)
|
self.frame_2 = QtWidgets.QFrame(self.frame_6)
|
||||||
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
|
||||||
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
|
|
||||||
self.frame.setObjectName("frame")
|
|
||||||
self.tableView = MusicTable(self.frame)
|
|
||||||
self.tableView.setGeometry(QtCore.QRect(0, 0, 1061, 461))
|
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
|
||||||
sizePolicy.setHorizontalStretch(0)
|
|
||||||
sizePolicy.setVerticalStretch(0)
|
|
||||||
sizePolicy.setHeightForWidth(self.tableView.sizePolicy().hasHeightForWidth())
|
|
||||||
self.tableView.setSizePolicy(sizePolicy)
|
|
||||||
self.tableView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
|
||||||
self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
|
|
||||||
self.tableView.setEditTriggers(QtWidgets.QAbstractItemView.AnyKeyPressed|QtWidgets.QAbstractItemView.EditKeyPressed)
|
|
||||||
self.tableView.setAlternatingRowColors(True)
|
|
||||||
self.tableView.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
|
||||||
self.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
|
||||||
self.tableView.setObjectName("tableView")
|
|
||||||
self.tableView.verticalHeader().setVisible(False)
|
|
||||||
self.frame_2 = QtWidgets.QFrame(self.centralwidget)
|
|
||||||
self.frame_2.setGeometry(QtCore.QRect(0, 0, 161, 161))
|
self.frame_2.setGeometry(QtCore.QRect(0, 0, 161, 161))
|
||||||
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
||||||
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
|
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
|
||||||
@ -51,26 +32,7 @@ class Ui_MainWindow(object):
|
|||||||
self.albumGraphicsView = QtWidgets.QGraphicsView(self.frame_2)
|
self.albumGraphicsView = QtWidgets.QGraphicsView(self.frame_2)
|
||||||
self.albumGraphicsView.setGeometry(QtCore.QRect(0, 0, 161, 161))
|
self.albumGraphicsView.setGeometry(QtCore.QRect(0, 0, 161, 161))
|
||||||
self.albumGraphicsView.setObjectName("albumGraphicsView")
|
self.albumGraphicsView.setObjectName("albumGraphicsView")
|
||||||
self.horizontalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
|
self.frame_4 = QtWidgets.QFrame(self.frame_6)
|
||||||
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(540, 0, 521, 41))
|
|
||||||
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
|
|
||||||
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
|
|
||||||
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
|
|
||||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
|
||||||
self.playbackSlider = QtWidgets.QSlider(self.horizontalLayoutWidget)
|
|
||||||
self.playbackSlider.setOrientation(QtCore.Qt.Horizontal)
|
|
||||||
self.playbackSlider.setObjectName("playbackSlider")
|
|
||||||
self.horizontalLayout.addWidget(self.playbackSlider)
|
|
||||||
self.startTimeLabel = QtWidgets.QLabel(self.horizontalLayoutWidget)
|
|
||||||
self.startTimeLabel.setObjectName("startTimeLabel")
|
|
||||||
self.horizontalLayout.addWidget(self.startTimeLabel)
|
|
||||||
self.slashLabel = QtWidgets.QLabel(self.horizontalLayoutWidget)
|
|
||||||
self.slashLabel.setObjectName("slashLabel")
|
|
||||||
self.horizontalLayout.addWidget(self.slashLabel)
|
|
||||||
self.endTimeLabel = QtWidgets.QLabel(self.horizontalLayoutWidget)
|
|
||||||
self.endTimeLabel.setObjectName("endTimeLabel")
|
|
||||||
self.horizontalLayout.addWidget(self.endTimeLabel)
|
|
||||||
self.frame_4 = QtWidgets.QFrame(self.centralwidget)
|
|
||||||
self.frame_4.setGeometry(QtCore.QRect(540, 40, 521, 121))
|
self.frame_4.setGeometry(QtCore.QRect(540, 40, 521, 121))
|
||||||
self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
self.frame_4.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
||||||
self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised)
|
self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised)
|
||||||
@ -78,18 +40,7 @@ class Ui_MainWindow(object):
|
|||||||
self.PlotWidget = PlotWidget(self.frame_4)
|
self.PlotWidget = PlotWidget(self.frame_4)
|
||||||
self.PlotWidget.setGeometry(QtCore.QRect(0, 0, 521, 121))
|
self.PlotWidget.setGeometry(QtCore.QRect(0, 0, 521, 121))
|
||||||
self.PlotWidget.setObjectName("PlotWidget")
|
self.PlotWidget.setObjectName("PlotWidget")
|
||||||
self.frame_3 = QtWidgets.QFrame(self.centralwidget)
|
self.frame_5 = QtWidgets.QFrame(self.frame_6)
|
||||||
self.frame_3.setGeometry(QtCore.QRect(0, 680, 1061, 61))
|
|
||||||
self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
|
||||||
self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)
|
|
||||||
self.frame_3.setObjectName("frame_3")
|
|
||||||
self.volumeSlider = QtWidgets.QSlider(self.frame_3)
|
|
||||||
self.volumeSlider.setGeometry(QtCore.QRect(10, 10, 181, 31))
|
|
||||||
self.volumeSlider.setMaximum(100)
|
|
||||||
self.volumeSlider.setProperty("value", 50)
|
|
||||||
self.volumeSlider.setOrientation(QtCore.Qt.Horizontal)
|
|
||||||
self.volumeSlider.setObjectName("volumeSlider")
|
|
||||||
self.frame_5 = QtWidgets.QFrame(self.centralwidget)
|
|
||||||
self.frame_5.setGeometry(QtCore.QRect(160, 0, 381, 161))
|
self.frame_5.setGeometry(QtCore.QRect(160, 0, 381, 161))
|
||||||
self.frame_5.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
self.frame_5.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
||||||
self.frame_5.setFrameShadow(QtWidgets.QFrame.Raised)
|
self.frame_5.setFrameShadow(QtWidgets.QFrame.Raised)
|
||||||
@ -123,30 +74,99 @@ class Ui_MainWindow(object):
|
|||||||
self.albumLabel.setFont(font)
|
self.albumLabel.setFont(font)
|
||||||
self.albumLabel.setObjectName("albumLabel")
|
self.albumLabel.setObjectName("albumLabel")
|
||||||
self.verticalLayout.addWidget(self.albumLabel)
|
self.verticalLayout.addWidget(self.albumLabel)
|
||||||
self.horizontalLayoutWidget_2 = QtWidgets.QWidget(self.centralwidget)
|
self.horizontalLayoutWidget = QtWidgets.QWidget(self.frame_6)
|
||||||
self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(0, 620, 1061, 60))
|
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(540, 0, 521, 41))
|
||||||
self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2")
|
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
|
||||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2)
|
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
|
||||||
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
|
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||||
|
self.playbackSlider = QtWidgets.QSlider(self.horizontalLayoutWidget)
|
||||||
|
self.playbackSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||||
|
self.playbackSlider.setObjectName("playbackSlider")
|
||||||
|
self.horizontalLayout.addWidget(self.playbackSlider)
|
||||||
|
self.startTimeLabel = QtWidgets.QLabel(self.horizontalLayoutWidget)
|
||||||
|
self.startTimeLabel.setObjectName("startTimeLabel")
|
||||||
|
self.horizontalLayout.addWidget(self.startTimeLabel)
|
||||||
|
self.slashLabel = QtWidgets.QLabel(self.horizontalLayoutWidget)
|
||||||
|
self.slashLabel.setObjectName("slashLabel")
|
||||||
|
self.horizontalLayout.addWidget(self.slashLabel)
|
||||||
|
self.endTimeLabel = QtWidgets.QLabel(self.horizontalLayoutWidget)
|
||||||
|
self.endTimeLabel.setObjectName("endTimeLabel")
|
||||||
|
self.horizontalLayout.addWidget(self.endTimeLabel)
|
||||||
|
self.verticalLayout_3.addWidget(self.frame_6)
|
||||||
|
self.frame = QtWidgets.QFrame(self.centralwidget)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth())
|
||||||
|
self.frame.setSizePolicy(sizePolicy)
|
||||||
|
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
||||||
|
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
|
||||||
|
self.frame.setObjectName("frame")
|
||||||
|
self.verticalLayoutWidget_2 = QtWidgets.QWidget(self.frame)
|
||||||
|
self.verticalLayoutWidget_2.setGeometry(QtCore.QRect(0, 0, 1061, 461))
|
||||||
|
self.verticalLayoutWidget_2.setObjectName("verticalLayoutWidget_2")
|
||||||
|
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_2)
|
||||||
|
self.verticalLayout_2.setSizeConstraint(QtWidgets.QLayout.SetNoConstraint)
|
||||||
|
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||||
|
self.tableView = MusicTable(self.verticalLayoutWidget_2)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
|
||||||
|
sizePolicy.setHorizontalStretch(1)
|
||||||
|
sizePolicy.setVerticalStretch(1)
|
||||||
|
sizePolicy.setHeightForWidth(self.tableView.sizePolicy().hasHeightForWidth())
|
||||||
|
self.tableView.setSizePolicy(sizePolicy)
|
||||||
|
self.tableView.setMaximumSize(QtCore.QSize(32000, 32000))
|
||||||
|
self.tableView.setAcceptDrops(True)
|
||||||
|
self.tableView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
|
self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
|
||||||
|
self.tableView.setEditTriggers(QtWidgets.QAbstractItemView.AnyKeyPressed|QtWidgets.QAbstractItemView.EditKeyPressed)
|
||||||
|
self.tableView.setAlternatingRowColors(True)
|
||||||
|
self.tableView.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||||
|
self.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||||
|
self.tableView.setSortingEnabled(True)
|
||||||
|
self.tableView.setObjectName("tableView")
|
||||||
|
self.tableView.horizontalHeader().setCascadingSectionResizes(True)
|
||||||
|
self.tableView.horizontalHeader().setStretchLastSection(True)
|
||||||
|
self.tableView.verticalHeader().setVisible(False)
|
||||||
|
self.verticalLayout_2.addWidget(self.tableView)
|
||||||
|
self.verticalLayout_3.addWidget(self.frame)
|
||||||
|
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||||
self.previousButton = QtWidgets.QPushButton(self.horizontalLayoutWidget_2)
|
self.previousButton = QtWidgets.QPushButton(self.centralwidget)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(28)
|
font.setPointSize(28)
|
||||||
self.previousButton.setFont(font)
|
self.previousButton.setFont(font)
|
||||||
self.previousButton.setObjectName("previousButton")
|
self.previousButton.setObjectName("previousButton")
|
||||||
self.horizontalLayout_2.addWidget(self.previousButton)
|
self.horizontalLayout_2.addWidget(self.previousButton)
|
||||||
self.playButton = QtWidgets.QPushButton(self.horizontalLayoutWidget_2)
|
self.playButton = QtWidgets.QPushButton(self.centralwidget)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(28)
|
font.setPointSize(28)
|
||||||
self.playButton.setFont(font)
|
self.playButton.setFont(font)
|
||||||
self.playButton.setObjectName("playButton")
|
self.playButton.setObjectName("playButton")
|
||||||
self.horizontalLayout_2.addWidget(self.playButton)
|
self.horizontalLayout_2.addWidget(self.playButton)
|
||||||
self.nextButton = QtWidgets.QPushButton(self.horizontalLayoutWidget_2)
|
self.nextButton = QtWidgets.QPushButton(self.centralwidget)
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setPointSize(28)
|
font.setPointSize(28)
|
||||||
self.nextButton.setFont(font)
|
self.nextButton.setFont(font)
|
||||||
self.nextButton.setObjectName("nextButton")
|
self.nextButton.setObjectName("nextButton")
|
||||||
self.horizontalLayout_2.addWidget(self.nextButton)
|
self.horizontalLayout_2.addWidget(self.nextButton)
|
||||||
|
self.verticalLayout_3.addLayout(self.horizontalLayout_2)
|
||||||
|
self.frame_3 = QtWidgets.QFrame(self.centralwidget)
|
||||||
|
self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
||||||
|
self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)
|
||||||
|
self.frame_3.setObjectName("frame_3")
|
||||||
|
self.volumeSlider = QtWidgets.QSlider(self.frame_3)
|
||||||
|
self.volumeSlider.setGeometry(QtCore.QRect(10, 10, 181, 31))
|
||||||
|
self.volumeSlider.setMaximum(100)
|
||||||
|
self.volumeSlider.setProperty("value", 50)
|
||||||
|
self.volumeSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||||
|
self.volumeSlider.setObjectName("volumeSlider")
|
||||||
|
self.verticalLayout_3.addWidget(self.frame_3)
|
||||||
|
self.verticalLayout_3.setStretch(0, 3)
|
||||||
|
self.verticalLayout_3.setStretch(1, 8)
|
||||||
|
self.verticalLayout_3.setStretch(2, 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, 1062, 24))
|
self.menubar.setGeometry(QtCore.QRect(0, 0, 1062, 24))
|
||||||
@ -183,12 +203,12 @@ class Ui_MainWindow(object):
|
|||||||
def retranslateUi(self, MainWindow):
|
def retranslateUi(self, MainWindow):
|
||||||
_translate = QtCore.QCoreApplication.translate
|
_translate = QtCore.QCoreApplication.translate
|
||||||
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
|
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
|
||||||
self.startTimeLabel.setText(_translate("MainWindow", "00:00"))
|
|
||||||
self.slashLabel.setText(_translate("MainWindow", "/"))
|
|
||||||
self.endTimeLabel.setText(_translate("MainWindow", "00:00"))
|
|
||||||
self.artistLabel.setText(_translate("MainWindow", "artist"))
|
self.artistLabel.setText(_translate("MainWindow", "artist"))
|
||||||
self.titleLabel.setText(_translate("MainWindow", "song title"))
|
self.titleLabel.setText(_translate("MainWindow", "song title"))
|
||||||
self.albumLabel.setText(_translate("MainWindow", "album"))
|
self.albumLabel.setText(_translate("MainWindow", "album"))
|
||||||
|
self.startTimeLabel.setText(_translate("MainWindow", "00:00"))
|
||||||
|
self.slashLabel.setText(_translate("MainWindow", "/"))
|
||||||
|
self.endTimeLabel.setText(_translate("MainWindow", "00:00"))
|
||||||
self.previousButton.setText(_translate("MainWindow", "⏮️"))
|
self.previousButton.setText(_translate("MainWindow", "⏮️"))
|
||||||
self.playButton.setText(_translate("MainWindow", "▶️"))
|
self.playButton.setText(_translate("MainWindow", "▶️"))
|
||||||
self.nextButton.setText(_translate("MainWindow", "⏭️"))
|
self.nextButton.setText(_translate("MainWindow", "⏭️"))
|
||||||
|
|||||||
281
ui.ui
281
ui.ui
@ -17,65 +17,15 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget">
|
<widget class="QWidget" name="centralwidget">
|
||||||
<widget class="QFrame" name="frame">
|
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="3,8,1,1">
|
||||||
<property name="geometry">
|
<item>
|
||||||
<rect>
|
<widget class="QFrame" name="frame_6">
|
||||||
<x>0</x>
|
|
||||||
<y>160</y>
|
|
||||||
<width>1061</width>
|
|
||||||
<height>461</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Ignored" vsizetype="Ignored">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="frameShape">
|
<property name="frameShape">
|
||||||
<enum>QFrame::StyledPanel</enum>
|
<enum>QFrame::StyledPanel</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="frameShadow">
|
<property name="frameShadow">
|
||||||
<enum>QFrame::Raised</enum>
|
<enum>QFrame::Raised</enum>
|
||||||
</property>
|
</property>
|
||||||
<widget class="MusicTable" name="tableView">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>1061</width>
|
|
||||||
<height>461</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="horizontalScrollBarPolicy">
|
|
||||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeAdjustPolicy">
|
|
||||||
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
|
||||||
</property>
|
|
||||||
<property name="editTriggers">
|
|
||||||
<set>QAbstractItemView::AnyKeyPressed|QAbstractItemView::EditKeyPressed</set>
|
|
||||||
</property>
|
|
||||||
<property name="alternatingRowColors">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="selectionMode">
|
|
||||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
|
||||||
</property>
|
|
||||||
<property name="selectionBehavior">
|
|
||||||
<enum>QAbstractItemView::SelectRows</enum>
|
|
||||||
</property>
|
|
||||||
<attribute name="verticalHeaderVisible">
|
|
||||||
<bool>false</bool>
|
|
||||||
</attribute>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
<widget class="QFrame" name="frame_2">
|
<widget class="QFrame" name="frame_2">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
@ -102,46 +52,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="horizontalLayoutWidget">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>540</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>521</width>
|
|
||||||
<height>41</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QSlider" name="playbackSlider">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="startTimeLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>00:00</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="slashLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>/</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="endTimeLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>00:00</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QFrame" name="frame_4">
|
<widget class="QFrame" name="frame_4">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
@ -168,41 +78,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QFrame" name="frame_3">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>680</y>
|
|
||||||
<width>1061</width>
|
|
||||||
<height>61</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="frameShape">
|
|
||||||
<enum>QFrame::StyledPanel</enum>
|
|
||||||
</property>
|
|
||||||
<property name="frameShadow">
|
|
||||||
<enum>QFrame::Raised</enum>
|
|
||||||
</property>
|
|
||||||
<widget class="QSlider" name="volumeSlider">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>10</x>
|
|
||||||
<y>10</y>
|
|
||||||
<width>181</width>
|
|
||||||
<height>31</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>100</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>50</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
<widget class="QFrame" name="frame_5">
|
<widget class="QFrame" name="frame_5">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
@ -272,15 +147,129 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="horizontalLayoutWidget_2">
|
<widget class="QWidget" name="horizontalLayoutWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>540</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>521</width>
|
||||||
|
<height>41</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="playbackSlider">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="startTimeLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>00:00</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="slashLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>/</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="endTimeLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>00:00</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="verticalLayoutWidget_2">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>620</y>
|
<y>0</y>
|
||||||
<width>1061</width>
|
<width>1061</width>
|
||||||
<height>60</height>
|
<height>461</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetNoConstraint</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="MusicTable" name="tableView">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||||
|
<horstretch>1</horstretch>
|
||||||
|
<verstretch>1</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>32000</width>
|
||||||
|
<height>32000</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="acceptDrops">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="horizontalScrollBarPolicy">
|
||||||
|
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||||
|
</property>
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::AnyKeyPressed|QAbstractItemView::EditKeyPressed</set>
|
||||||
|
</property>
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||||
|
</property>
|
||||||
|
<property name="selectionBehavior">
|
||||||
|
<enum>QAbstractItemView::SelectRows</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="horizontalHeaderCascadingSectionResizes">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="horizontalHeaderStretchLastSection">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="verticalHeaderVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="previousButton">
|
<widget class="QPushButton" name="previousButton">
|
||||||
@ -319,8 +308,38 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame_3">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QSlider" name="volumeSlider">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>181</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>50</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
<widget class="QMenuBar" name="menubar">
|
<widget class="QMenuBar" name="menubar">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
|
from .get_id3_tags import get_id3_tags
|
||||||
from .initialize_library_database import initialize_library_database
|
from .initialize_library_database import initialize_library_database
|
||||||
from .scan_for_music import scan_for_music
|
from .scan_for_music import scan_for_music
|
||||||
from .audio_visualizer import AudioVisualizer
|
|
||||||
from .fft_analyser import FFTAnalyser
|
from .fft_analyser import FFTAnalyser
|
||||||
|
from .add_files_to_library import add_files_to_library
|
||||||
58
utils/add_files_to_library.py
Normal file
58
utils/add_files_to_library.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import DBA
|
||||||
|
from configparser import ConfigParser
|
||||||
|
from utils import get_id3_tags
|
||||||
|
|
||||||
|
config = ConfigParser()
|
||||||
|
config.read("config.ini")
|
||||||
|
|
||||||
|
|
||||||
|
def add_files_to_library(files):
|
||||||
|
"""Adds audio file(s) to the sqllite db
|
||||||
|
`files` | list() | List of fully qualified paths to audio file(s)
|
||||||
|
Returns a count of records added
|
||||||
|
"""
|
||||||
|
print(f'utils | adding files to library: {files}')
|
||||||
|
extensions = config.get('settings', 'extensions').split(',')
|
||||||
|
insert_data = [] # To store data for batch insert
|
||||||
|
for file in files:
|
||||||
|
if any(file.lower().endswith(ext) for ext in extensions):
|
||||||
|
filename = file.split("/")[-1]
|
||||||
|
audio = get_id3_tags(file)
|
||||||
|
# Append data tuple to insert_data list
|
||||||
|
insert_data.append(
|
||||||
|
(
|
||||||
|
file,
|
||||||
|
audio.title,
|
||||||
|
audio.album,
|
||||||
|
audio.artist,
|
||||||
|
audio.genre,
|
||||||
|
filename.split(".")[-1],
|
||||||
|
audio.year,
|
||||||
|
audio.bitrate,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if batch size is reached
|
||||||
|
if len(insert_data) >= 1000:
|
||||||
|
with DBA.DBAccess() as db:
|
||||||
|
db.executemany('INSERT OR IGNORE INTO library (filepath, title, album, artist, genre, codec, album_date, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', insert_data)
|
||||||
|
insert_data = [] # Reset the insert_data list
|
||||||
|
|
||||||
|
# Insert any remaining data
|
||||||
|
if insert_data:
|
||||||
|
with DBA.DBAccess() as db:
|
||||||
|
db.executemany('INSERT OR IGNORE INTO library (filepath, title, album, artist, genre, codec, album_date, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', insert_data)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
# id int unsigned auto_increment,
|
||||||
|
# title varchar(255),
|
||||||
|
# album varchar(255),
|
||||||
|
# artist varchar(255),
|
||||||
|
# genre varchar(255),
|
||||||
|
# codec varchar(15),
|
||||||
|
# album_date date,
|
||||||
|
# bitrate int unsigned,
|
||||||
|
# date_added TIMESTAMP default CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
# scan_for_music(config.get('directories', 'library1'))
|
||||||
@ -5,6 +5,11 @@ from pydub import AudioSegment
|
|||||||
|
|
||||||
|
|
||||||
def create_waveform_from_file(file):
|
def create_waveform_from_file(file):
|
||||||
|
"""_summary_
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file (_type_): _description_
|
||||||
|
"""
|
||||||
# Read the MP3 file
|
# Read the MP3 file
|
||||||
audio = AudioSegment.from_file(file)
|
audio = AudioSegment.from_file(file)
|
||||||
# Convert to mono and get frame rate and number of channels
|
# Convert to mono and get frame rate and number of channels
|
||||||
@ -43,7 +48,7 @@ def create_waveform_from_file(file):
|
|||||||
# Graph goes to ends of pic
|
# Graph goes to ends of pic
|
||||||
plt.xlim(0, len(waveform))
|
plt.xlim(0, len(waveform))
|
||||||
# Save pic
|
# Save pic
|
||||||
plt.savefig('now_playing_waveform.png', dpi=64, bbox_inches='tight', pad_inches=0)
|
plt.savefig('assets/now_playing_waveform.png', dpi=64, bbox_inches='tight', pad_inches=0)
|
||||||
# Show me tho
|
# Show me tho
|
||||||
# plt.show()
|
# plt.show()
|
||||||
|
|
||||||
|
|||||||
21
utils/get_id3_tags.py
Normal file
21
utils/get_id3_tags.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from mutagen.easyid3 import EasyID3
|
||||||
|
from mutagen import File
|
||||||
|
|
||||||
|
def get_id3_tags(file):
|
||||||
|
"""Get the ID3 tags for an audio file
|
||||||
|
# Parameters
|
||||||
|
`file` | str | Fully qualified path to file
|
||||||
|
|
||||||
|
# Returns
|
||||||
|
dict of all id3 tags
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
audio = EasyID3(file)
|
||||||
|
return audio
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
filepath = '/home/billy/Music/songs/meanings/blah99/H.mp3'
|
||||||
|
id3_tags = get_id3_tags(filepath)
|
||||||
|
print(id3_tags)
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import DBA
|
import DBA
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
from tinytag import TinyTag
|
from utils import get_id3_tags
|
||||||
|
|
||||||
config = ConfigParser()
|
config = ConfigParser()
|
||||||
config.read('config.ini')
|
config.read('config.ini')
|
||||||
@ -16,7 +16,7 @@ def scan_for_music():
|
|||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
if any(filename.lower().endswith(ext) for ext in extensions):
|
if any(filename.lower().endswith(ext) for ext in extensions):
|
||||||
filepath = os.path.join(dirpath, filename)
|
filepath = os.path.join(dirpath, filename)
|
||||||
audio = TinyTag.get(filepath)
|
audio = get_id3_tags(filepath)
|
||||||
|
|
||||||
# Append data tuple to insert_data list
|
# Append data tuple to insert_data list
|
||||||
insert_data.append((
|
insert_data.append((
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user