ui updates, move print to logging debug/error/info, other stuff that i forgor?
This commit is contained in:
parent
eff515cd32
commit
2efe108f8c
19
README.md
19
README.md
@ -4,23 +4,31 @@ PyQt5 music player for Linux inspired by MusicBee & iTunes
|
||||
|
||||
## Installation:
|
||||
clone the repo
|
||||
```
|
||||
```bash
|
||||
git clone https://github.com/billypom/musicpom
|
||||
```
|
||||
|
||||
install system packages
|
||||
```
|
||||
```bash
|
||||
sudo apt install ffmpeg, python3-pyqt5
|
||||
```
|
||||
|
||||
create environment
|
||||
```
|
||||
```bash
|
||||
cd musicpom
|
||||
virtualenv venv
|
||||
cd ..
|
||||
cd musicpom
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
run the program
|
||||
|
||||
create ui.py from ui.ui
|
||||
```bash
|
||||
pyuic5 ui.ui -o ui.py
|
||||
```
|
||||
|
||||
run
|
||||
```bash
|
||||
python3 main.py
|
||||
```
|
||||
|
||||
@ -28,12 +36,13 @@ python3 main.py
|
||||
|
||||
- [x] right-click menu
|
||||
- [x] editable lyrics window
|
||||
- [x] batch metadata changer (red text on fields that have differing info)
|
||||
- [x] batch metadata changer (red highlight fields that have differing info)
|
||||
- [x] playlists
|
||||
- [ ] delete songs from library (del key || right-click delete)
|
||||
- [ ] .wav, .ogg, .flac convertor
|
||||
- [ ] FIXME: dbaccess is instantiated for every track being reorganized
|
||||
- [ ] automatic "radio" based on artist or genre
|
||||
- [ ] search bar, full text search on song, artist, album
|
||||
- [ ] when table is focused, start typing to match against the primary sort column
|
||||
- [ ] "installer" - put files in /opt? script to install and uninstall
|
||||
- [ ] .deb package?
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import os
|
||||
import tempfile
|
||||
from logging import debug
|
||||
from PyQt5.QtWidgets import (
|
||||
QGraphicsPixmapItem,
|
||||
QGraphicsScene,
|
||||
@ -56,7 +57,7 @@ class AlbumArtGraphicsView(QGraphicsView):
|
||||
if urls:
|
||||
first_url = urls[0].toLocalFile()
|
||||
if first_url.lower().endswith((".png", ".jpg", ".jpeg")):
|
||||
print(f"dropped {first_url}")
|
||||
debug(f"dropped {first_url}")
|
||||
self.albumArtDropped.emit(
|
||||
first_url
|
||||
) # emit signal that album art was dropped
|
||||
|
||||
@ -8,6 +8,7 @@ from PyQt5.QtWidgets import (
|
||||
from PyQt5.QtGui import QFont
|
||||
from components.ErrorDialog import ErrorDialog
|
||||
from utils import set_id3_tag
|
||||
from logging import debug
|
||||
|
||||
|
||||
class LyricsWindow(QDialog):
|
||||
@ -37,7 +38,7 @@ class LyricsWindow(QDialog):
|
||||
value=self.input_field.toPlainText(),
|
||||
)
|
||||
if success:
|
||||
print("lyrical success! yay")
|
||||
debug("lyrical success! yay")
|
||||
else:
|
||||
error_dialog = ErrorDialog("Could not save lyrics :( sad")
|
||||
error_dialog.exec()
|
||||
|
||||
@ -15,6 +15,7 @@ from utils.get_id3_tags import get_id3_tags
|
||||
from utils.set_id3_tag import set_id3_tag
|
||||
from utils.update_song_in_database import update_song_in_database
|
||||
from utils.id3_tag_mapping import id3_tag_mapping
|
||||
from logging import debug
|
||||
# import re
|
||||
|
||||
|
||||
@ -74,8 +75,8 @@ class MetadataWindow(QDialog):
|
||||
tag_sets[tag].append(song_data[tag].text[0])
|
||||
except KeyError:
|
||||
pass
|
||||
print("tag sets:")
|
||||
print(tag_sets)
|
||||
debug("tag sets:")
|
||||
debug(tag_sets)
|
||||
|
||||
# UI Creation
|
||||
current_layout = QHBoxLayout()
|
||||
|
||||
@ -43,7 +43,7 @@ from utils.get_id3_tags import get_id3_tags
|
||||
from utils.get_album_art import get_album_art
|
||||
from utils import set_id3_tag
|
||||
from subprocess import Popen
|
||||
import logging
|
||||
from logging import debug, error
|
||||
import configparser
|
||||
import os
|
||||
import shutil
|
||||
@ -146,7 +146,7 @@ class MusicTable(QTableView):
|
||||
# in order to sort the data more effectively & have more control over UI refreshes.
|
||||
|
||||
# Disconnect these signals to prevent unnecessary loads
|
||||
logging.info("sort_table_by_multiple_columns()")
|
||||
debug("sort_table_by_multiple_columns()")
|
||||
self.disconnect_data_changed()
|
||||
self.disconnect_layout_changed()
|
||||
sort_orders = []
|
||||
@ -168,7 +168,7 @@ class MusicTable(QTableView):
|
||||
# `len(config_sort_orders)` number of SELECTs
|
||||
for i in reversed(range(len(sort_orders))):
|
||||
if sort_orders[i] is not None:
|
||||
logging.info(f"sorting column {i} by {sort_orders[i]}")
|
||||
debug(f"sorting column {i} by {sort_orders[i]}")
|
||||
self.sortByColumn(i, sort_orders[i])
|
||||
|
||||
self.connect_data_changed()
|
||||
@ -298,7 +298,7 @@ class MusicTable(QTableView):
|
||||
try:
|
||||
self.model2.removeRow(index)
|
||||
except Exception as e:
|
||||
logging.info(f" delete_songs() failed | {e}")
|
||||
debug(f" delete_songs() failed | {e}")
|
||||
self.connect_data_changed()
|
||||
|
||||
def open_directory(self):
|
||||
@ -343,7 +343,7 @@ class MusicTable(QTableView):
|
||||
else:
|
||||
raise RuntimeError("No USLT tags found in song metadata")
|
||||
except Exception as e:
|
||||
logging.error(f"show_lyrics_menu() | could not retrieve lyrics | {e}")
|
||||
error(f"show_lyrics_menu() | could not retrieve lyrics | {e}")
|
||||
lyrics = ""
|
||||
lyrics_window = LyricsWindow(selected_song_filepath, lyrics)
|
||||
lyrics_window.exec_()
|
||||
@ -370,7 +370,7 @@ class MusicTable(QTableView):
|
||||
if e is None:
|
||||
return
|
||||
data = e.mimeData()
|
||||
logging.info(f"dropEvent data: {data}")
|
||||
debug(f"dropEvent data: {data}")
|
||||
if data and data.hasUrls():
|
||||
directories = []
|
||||
files = []
|
||||
@ -384,8 +384,8 @@ class MusicTable(QTableView):
|
||||
# append 1 file
|
||||
files.append(path)
|
||||
e.accept()
|
||||
print(f"directories: {directories}")
|
||||
print(f"files: {files}")
|
||||
debug(f"directories: {directories}")
|
||||
debug(f"files: {files}")
|
||||
if directories:
|
||||
worker = Worker(self.get_audio_files_recursively, directories)
|
||||
worker.signals.signal_progress.connect(self.handle_progress)
|
||||
@ -444,7 +444,7 @@ class MusicTable(QTableView):
|
||||
|
||||
def on_cell_data_changed(self, topLeft: QModelIndex, bottomRight: QModelIndex):
|
||||
"""Handles updating ID3 tags when data changes in a cell"""
|
||||
logging.info("on_cell_data_changed")
|
||||
debug("on_cell_data_changed")
|
||||
if isinstance(self.model2, QStandardItemModel):
|
||||
# get the ID of the row that was edited
|
||||
id_index = self.model2.index(topLeft.row(), 0) # ID is column 0, always
|
||||
@ -458,7 +458,7 @@ class MusicTable(QTableView):
|
||||
# update the ID3 information
|
||||
user_input_data = topLeft.data()
|
||||
edited_column_name = self.database_columns[topLeft.column()]
|
||||
logging.info(f"edited column name: {edited_column_name}")
|
||||
debug(f"edited column name: {edited_column_name}")
|
||||
response = set_id3_tag(filepath, edited_column_name, user_input_data)
|
||||
if response:
|
||||
# Update the library with new metadata
|
||||
@ -518,9 +518,9 @@ class MusicTable(QTableView):
|
||||
"UPDATE song SET filepath = ? WHERE filepath = ?",
|
||||
(new_path, filepath),
|
||||
)
|
||||
logging.info(f"reorganize_files() | Moved: {filepath} -> {new_path}")
|
||||
debug(f"reorganize_files() | Moved: {filepath} -> {new_path}")
|
||||
except Exception as e:
|
||||
logging.warning(
|
||||
error(
|
||||
f"reorganize_files() | Error moving file: {filepath} | {e}"
|
||||
)
|
||||
# Draw the rest of the owl
|
||||
@ -539,7 +539,7 @@ class MusicTable(QTableView):
|
||||
- Drag & Drop song(s) on tableView
|
||||
- File > Open > List of song(s)
|
||||
"""
|
||||
logging.info(f"add files, files: {files}")
|
||||
debug(f"add files, files: {files}")
|
||||
worker = Worker(add_files_to_library, files)
|
||||
worker.signals.signal_progress.connect(self.qapp.handle_progress)
|
||||
worker.signals.signal_finished.connect(self.load_music_table)
|
||||
@ -547,7 +547,7 @@ class MusicTable(QTableView):
|
||||
threadpool = self.qapp.threadpool
|
||||
threadpool.start(worker)
|
||||
else:
|
||||
logging.warning("Application window could not be found")
|
||||
error("Application window could not be found")
|
||||
|
||||
def load_music_table(self, *playlist_id):
|
||||
"""
|
||||
@ -566,7 +566,7 @@ class MusicTable(QTableView):
|
||||
# Fetch playlist data
|
||||
selected_playlist_id = playlist_id[0]
|
||||
try:
|
||||
logging.info(
|
||||
debug(
|
||||
f"load_music_table() | selected_playlist_id: {selected_playlist_id}"
|
||||
)
|
||||
with DBA.DBAccess() as db:
|
||||
@ -575,7 +575,7 @@ class MusicTable(QTableView):
|
||||
(selected_playlist_id,),
|
||||
)
|
||||
except Exception as e:
|
||||
logging.warning(f"load_music_table() | Unhandled exception: {e}")
|
||||
error(f"load_music_table() | Unhandled exception: {e}")
|
||||
return
|
||||
else: # Load the library
|
||||
# Fetch playlist data
|
||||
@ -586,7 +586,7 @@ class MusicTable(QTableView):
|
||||
(),
|
||||
)
|
||||
except Exception as e:
|
||||
logging.warning(f"load_music_table() | Unhandled exception: {e}")
|
||||
error(f"load_music_table() | Unhandled exception: {e}")
|
||||
return
|
||||
# Populate the model
|
||||
for row_data in data:
|
||||
@ -612,7 +612,7 @@ class MusicTable(QTableView):
|
||||
|
||||
def restore_scroll_position(self) -> None:
|
||||
"""Restores the scroll position"""
|
||||
logging.info("restore_scroll_position")
|
||||
debug("restore_scroll_position")
|
||||
# QTimer.singleShot(
|
||||
# 100,
|
||||
# lambda: self.verticalScrollBar().setValue(self.vertical_scroll_position),
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
from PyQt5.QtWidgets import QListWidget, QTreeWidget, QTreeWidgetItem
|
||||
from PyQt5.QtCore import pyqtSignal
|
||||
import DBA
|
||||
from logging import debug
|
||||
|
||||
|
||||
class PlaylistWidgetItem(QTreeWidgetItem):
|
||||
@ -36,7 +37,7 @@ class PlaylistsPane(QTreeWidget):
|
||||
|
||||
def playlist_clicked(self, item):
|
||||
if isinstance(item, PlaylistWidgetItem):
|
||||
print(f"ID: {item.id}, name: {item.text(0)}")
|
||||
debug(f"ID: {item.id}, name: {item.text(0)}")
|
||||
self.playlist_db_id_choice = item.id
|
||||
self.playlistChoiceSignal.emit(int(item.id))
|
||||
elif item.text(0).lower() == "all songs":
|
||||
|
||||
1
create_ui.sh
Executable file
1
create_ui.sh
Executable file
@ -0,0 +1 @@
|
||||
pyuic5 ui.ui -o ui.py
|
||||
6
main.py
6
main.py
@ -10,6 +10,7 @@ from mutagen.id3._frames import APIC
|
||||
from configparser import ConfigParser
|
||||
import traceback
|
||||
import DBA
|
||||
from logging import debug
|
||||
from ui import Ui_MainWindow
|
||||
from PyQt5.QtWidgets import (
|
||||
QFileDialog,
|
||||
@ -290,7 +291,6 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||
"""Start playback of `tableView.current_song_filepath` & moves playback slider"""
|
||||
# get metadata
|
||||
self.current_song_metadata = self.tableView.get_current_song_metadata()
|
||||
print(f'current_song_metadata: {self.current_song_metadata}')
|
||||
# read the file
|
||||
url = QUrl.fromLocalFile(self.tableView.get_current_song_filepath())
|
||||
# load the audio content
|
||||
@ -369,7 +369,7 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||
# delete APIC data
|
||||
try:
|
||||
audio = ID3(file)
|
||||
print(audio)
|
||||
debug(audio)
|
||||
if "APIC:" in audio:
|
||||
del audio["APIC:"]
|
||||
logging.info("Deleting album art")
|
||||
@ -426,12 +426,14 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
||||
try:
|
||||
self.current_volume = self.volumeSlider.value()
|
||||
self.player.setVolume(self.current_volume)
|
||||
self.volumeLabel = str(self.current_volume)
|
||||
except Exception as e:
|
||||
logging.error(f"main.py volume_changed() | Changing volume error: {e}")
|
||||
|
||||
def speed_changed(self, rate: int) -> None:
|
||||
"""Handles playback speed changes"""
|
||||
self.player.setPlaybackRate(rate / 50)
|
||||
self.speedLabel.setText(str(round(rate/50, 2)))
|
||||
|
||||
def on_play_clicked(self) -> None:
|
||||
"""Updates the Play & Pause buttons when clicked"""
|
||||
|
||||
@ -1,34 +1,37 @@
|
||||
import sys
|
||||
from mutagen.id3 import ID3, APIC
|
||||
from mutagen.id3 import ID3
|
||||
# i just added the below line - APIC was originally in the above
|
||||
# but pyright yelled at me...
|
||||
from mutagen.id3._frames import APIC
|
||||
import os
|
||||
import logging
|
||||
from logging import debug
|
||||
|
||||
|
||||
def print_id3_tags(file_path):
|
||||
"""Prints all ID3 tags for a given audio file."""
|
||||
"""Prints all ID3 tags for a given audio file to debug out."""
|
||||
try:
|
||||
audio = ID3(file_path)
|
||||
except Exception as e:
|
||||
print(f"Error reading ID3 tags: {e}")
|
||||
debug(f"Error reading ID3 tags: {e}")
|
||||
return
|
||||
|
||||
for tag in audio.keys():
|
||||
# Special handling for APIC frames (attached pictures)
|
||||
if isinstance(audio[tag], APIC):
|
||||
print(
|
||||
debug(
|
||||
f"{tag}: Picture, MIME type: {audio[tag].mime}, Description: {audio[tag].desc}"
|
||||
)
|
||||
else:
|
||||
print(f"{tag}: {audio[tag].pprint()}")
|
||||
debug(f"{tag}: {audio[tag].pprint()}")
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python show_id3_tags.py /path/to/audio/file")
|
||||
debug("Usage: python show_id3_tags.py /path/to/audio/file")
|
||||
sys.exit(1)
|
||||
file_path = sys.argv[1]
|
||||
if not os.path.exists(file_path):
|
||||
print("File does not exist.")
|
||||
debug("File does not exist.")
|
||||
sys.exit(1)
|
||||
print_id3_tags(file_path)
|
||||
|
||||
|
||||
79
ui.py
79
ui.py
@ -81,15 +81,51 @@ class Ui_MainWindow(object):
|
||||
self.playbackSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.playbackSlider.setObjectName("playbackSlider")
|
||||
self.horizontalLayout.addWidget(self.playbackSlider)
|
||||
self.timeHorizontalLayout2 = QtWidgets.QHBoxLayout()
|
||||
self.timeHorizontalLayout2.setObjectName("timeHorizontalLayout2")
|
||||
self.startTimeLabel = QtWidgets.QLabel(self.centralwidget)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Monospace")
|
||||
font.setItalic(False)
|
||||
self.startTimeLabel.setFont(font)
|
||||
self.startTimeLabel.setObjectName("startTimeLabel")
|
||||
self.horizontalLayout.addWidget(self.startTimeLabel)
|
||||
self.timeHorizontalLayout2.addWidget(self.startTimeLabel)
|
||||
self.slashLabel = QtWidgets.QLabel(self.centralwidget)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Monospace")
|
||||
font.setItalic(False)
|
||||
self.slashLabel.setFont(font)
|
||||
self.slashLabel.setObjectName("slashLabel")
|
||||
self.horizontalLayout.addWidget(self.slashLabel)
|
||||
self.timeHorizontalLayout2.addWidget(self.slashLabel)
|
||||
self.endTimeLabel = QtWidgets.QLabel(self.centralwidget)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Monospace")
|
||||
font.setBold(True)
|
||||
font.setItalic(False)
|
||||
font.setWeight(75)
|
||||
self.endTimeLabel.setFont(font)
|
||||
self.endTimeLabel.setObjectName("endTimeLabel")
|
||||
self.horizontalLayout.addWidget(self.endTimeLabel)
|
||||
self.timeHorizontalLayout2.addWidget(self.endTimeLabel)
|
||||
self.horizontalLayout.addLayout(self.timeHorizontalLayout2)
|
||||
self.speedSlider = QtWidgets.QSlider(self.centralwidget)
|
||||
self.speedSlider.setMinimum(0)
|
||||
self.speedSlider.setMaximum(100)
|
||||
self.speedSlider.setSingleStep(1)
|
||||
self.speedSlider.setProperty("value", 50)
|
||||
self.speedSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.speedSlider.setInvertedAppearance(False)
|
||||
self.speedSlider.setTickPosition(QtWidgets.QSlider.TicksAbove)
|
||||
self.speedSlider.setObjectName("speedSlider")
|
||||
self.horizontalLayout.addWidget(self.speedSlider)
|
||||
self.speedLabel = QtWidgets.QLabel(self.centralwidget)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Monospace")
|
||||
self.speedLabel.setFont(font)
|
||||
self.speedLabel.setObjectName("speedLabel")
|
||||
self.horizontalLayout.addWidget(self.speedLabel)
|
||||
self.horizontalLayout.setStretch(0, 4)
|
||||
self.horizontalLayout.setStretch(2, 4)
|
||||
self.horizontalLayout.setStretch(3, 1)
|
||||
self.vLayoutPlaybackVisuals.addLayout(self.horizontalLayout)
|
||||
self.PlotWidget = PlotWidget(self.centralwidget)
|
||||
self.PlotWidget.setObjectName("PlotWidget")
|
||||
@ -127,6 +163,8 @@ class Ui_MainWindow(object):
|
||||
self.hLayoutControls = QtWidgets.QHBoxLayout()
|
||||
self.hLayoutControls.setSpacing(6)
|
||||
self.hLayoutControls.setObjectName("hLayoutControls")
|
||||
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.hLayoutControls.addItem(spacerItem)
|
||||
self.previousButton = QtWidgets.QPushButton(self.centralwidget)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(28)
|
||||
@ -145,6 +183,13 @@ class Ui_MainWindow(object):
|
||||
self.nextButton.setFont(font)
|
||||
self.nextButton.setObjectName("nextButton")
|
||||
self.hLayoutControls.addWidget(self.nextButton)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.hLayoutControls.addItem(spacerItem1)
|
||||
self.hLayoutControls.setStretch(0, 1)
|
||||
self.hLayoutControls.setStretch(1, 2)
|
||||
self.hLayoutControls.setStretch(2, 2)
|
||||
self.hLayoutControls.setStretch(3, 2)
|
||||
self.hLayoutControls.setStretch(4, 1)
|
||||
self.verticalLayout_3.addLayout(self.hLayoutControls)
|
||||
self.hLayoutControls2 = QtWidgets.QHBoxLayout()
|
||||
self.hLayoutControls2.setSpacing(6)
|
||||
@ -153,22 +198,21 @@ class Ui_MainWindow(object):
|
||||
self.volumeSlider.setMaximum(100)
|
||||
self.volumeSlider.setProperty("value", 50)
|
||||
self.volumeSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.volumeSlider.setTickPosition(QtWidgets.QSlider.TicksAbove)
|
||||
self.volumeSlider.setObjectName("volumeSlider")
|
||||
self.hLayoutControls2.addWidget(self.volumeSlider)
|
||||
self.volumeLabel = QtWidgets.QLabel(self.centralwidget)
|
||||
self.volumeLabel.setObjectName("volumeLabel")
|
||||
self.hLayoutControls2.addWidget(self.volumeLabel)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.hLayoutControls2.addItem(spacerItem2)
|
||||
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.pushButton.setObjectName("pushButton")
|
||||
self.hLayoutControls2.addWidget(self.pushButton)
|
||||
self.hLayoutControls2.setStretch(0, 1)
|
||||
self.hLayoutControls2.setStretch(2, 4)
|
||||
self.hLayoutControls2.setStretch(3, 1)
|
||||
self.verticalLayout_3.addLayout(self.hLayoutControls2)
|
||||
self.hLayoutControls3 = QtWidgets.QHBoxLayout()
|
||||
self.hLayoutControls3.setObjectName("hLayoutControls3")
|
||||
self.speedSlider = QtWidgets.QSlider(self.centralwidget)
|
||||
self.speedSlider.setMinimum(0)
|
||||
self.speedSlider.setMaximum(100)
|
||||
self.speedSlider.setSingleStep(1)
|
||||
self.speedSlider.setProperty("value", 50)
|
||||
self.speedSlider.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.speedSlider.setInvertedAppearance(False)
|
||||
self.speedSlider.setTickPosition(QtWidgets.QSlider.NoTicks)
|
||||
self.speedSlider.setObjectName("speedSlider")
|
||||
self.hLayoutControls3.addWidget(self.speedSlider)
|
||||
self.verticalLayout_3.addLayout(self.hLayoutControls3)
|
||||
self.verticalLayout_3.setStretch(0, 20)
|
||||
MainWindow.setCentralWidget(self.centralwidget)
|
||||
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
||||
@ -227,9 +271,12 @@ class Ui_MainWindow(object):
|
||||
self.startTimeLabel.setText(_translate("MainWindow", "00:00"))
|
||||
self.slashLabel.setText(_translate("MainWindow", "/"))
|
||||
self.endTimeLabel.setText(_translate("MainWindow", "00:00"))
|
||||
self.speedLabel.setText(_translate("MainWindow", "1.00"))
|
||||
self.previousButton.setText(_translate("MainWindow", "⏮️"))
|
||||
self.playButton.setText(_translate("MainWindow", "▶️"))
|
||||
self.nextButton.setText(_translate("MainWindow", "⏭️"))
|
||||
self.volumeLabel.setText(_translate("MainWindow", "50"))
|
||||
self.pushButton.setText(_translate("MainWindow", "nothing"))
|
||||
self.menuFile.setTitle(_translate("MainWindow", "File"))
|
||||
self.menuEdit.setTitle(_translate("MainWindow", "Edit"))
|
||||
self.menuView.setTitle(_translate("MainWindow", "View"))
|
||||
|
||||
158
ui.ui
158
ui.ui
@ -17,7 +17,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="20,0,0,0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="20,0,0">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,2">
|
||||
<property name="spacing">
|
||||
@ -126,7 +126,7 @@
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="vLayoutPlaybackVisuals">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="4,0,4,1">
|
||||
<item>
|
||||
<widget class="QSlider" name="playbackSlider">
|
||||
<property name="orientation">
|
||||
@ -135,23 +135,84 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="startTimeLabel">
|
||||
<property name="text">
|
||||
<string>00:00</string>
|
||||
<layout class="QHBoxLayout" name="timeHorizontalLayout2">
|
||||
<item>
|
||||
<widget class="QLabel" name="startTimeLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
<italic>false</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>00:00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="slashLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
<italic>false</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>/</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="endTimeLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
<weight>75</weight>
|
||||
<italic>false</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>00:00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="speedSlider">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksAbove</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="slashLabel">
|
||||
<property name="text">
|
||||
<string>/</string>
|
||||
<widget class="QLabel" name="speedLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="endTimeLabel">
|
||||
<property name="text">
|
||||
<string>00:00</string>
|
||||
<string>1.00</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -217,10 +278,23 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="hLayoutControls">
|
||||
<layout class="QHBoxLayout" name="hLayoutControls" stretch="1,2,2,2,1">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="previousButton">
|
||||
<property name="font">
|
||||
@ -257,10 +331,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="hLayoutControls2">
|
||||
<layout class="QHBoxLayout" name="hLayoutControls2" stretch="1,0,4,1">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
@ -275,34 +362,35 @@
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksAbove</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="hLayoutControls3">
|
||||
<item>
|
||||
<widget class="QSlider" name="speedSlider">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>50</number>
|
||||
<widget class="QLabel" name="volumeLabel">
|
||||
<property name="text">
|
||||
<string>50</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::NoTicks</enum>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>nothing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import DBA
|
||||
from logging import debug
|
||||
|
||||
|
||||
def delete_and_create_library_database():
|
||||
@ -6,6 +7,6 @@ def delete_and_create_library_database():
|
||||
with open("utils/delete_and_create_library.sql", "r") as file:
|
||||
lines = file.read()
|
||||
for statement in lines.split(";"):
|
||||
print(f"executing [{statement}]")
|
||||
debug(f"executing [{statement}]")
|
||||
with DBA.DBAccess() as db:
|
||||
db.execute(statement, ())
|
||||
|
||||
@ -7,6 +7,7 @@ from PyQt5 import QtCore
|
||||
from pydub import AudioSegment
|
||||
import numpy as np
|
||||
from scipy.ndimage.filters import gaussian_filter1d
|
||||
from logging import info
|
||||
|
||||
|
||||
class FFTAnalyser(QtCore.QThread):
|
||||
@ -57,7 +58,7 @@ class FFTAnalyser(QtCore.QThread):
|
||||
freq = np.fft.fftfreq(fourier.size, d=0.05)
|
||||
amps = 2 / v_sample.size * np.abs(fourier)
|
||||
data = np.array([freq, amps]).T
|
||||
# print(data)
|
||||
# info(data)
|
||||
|
||||
point_range = 1 / self.resolution
|
||||
point_samples = []
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
from mutagen.id3 import ID3
|
||||
import logging
|
||||
from logging import debug, error
|
||||
|
||||
|
||||
def get_album_art(file: str) -> bytes:
|
||||
@ -18,7 +18,7 @@ def get_album_art(file: str) -> bytes:
|
||||
if audio.getall("APIC"):
|
||||
return audio.getall("APIC")[0].data
|
||||
except Exception as e:
|
||||
print(f"Error retrieving album art: {e}")
|
||||
error(f"Error retrieving album art: {e}")
|
||||
with open(default_image_path, "rb") as f:
|
||||
logging.info("loading placeholder album art")
|
||||
debug("loading placeholder album art")
|
||||
return f.read()
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import DBA
|
||||
from logging import debug
|
||||
|
||||
|
||||
def initialize_db():
|
||||
@ -6,6 +7,6 @@ def initialize_db():
|
||||
with open("utils/init.sql", "r") as file:
|
||||
lines = file.read()
|
||||
for statement in lines.split(";"):
|
||||
print(f"executing [{statement}]")
|
||||
debug(f"executing [{statement}]")
|
||||
with DBA.DBAccess() as db:
|
||||
db.execute(statement, ())
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user