importing an mp3 file with no ID3 tags

This commit is contained in:
billypom on debian 2024-05-28 20:09:01 -04:00
parent 036852c307
commit b789542a51
5 changed files with 54 additions and 26 deletions

8
DBA.py
View File

@ -1,14 +1,18 @@
import sqlite3 import sqlite3
import logging
from configparser import ConfigParser from configparser import ConfigParser
class DBAccess: class DBAccess:
def __init__(self, db_name=None): def __init__(self, db_name=None):
logging.info('Instantiating DBAccess')
config = ConfigParser() config = ConfigParser()
config.read('config.ini') config.read('config.ini')
if db_name is None: if db_name is None:
db_name = config.get('db', 'database') db_name = config.get('db', 'database')
self._conn = sqlite3.connect(db_name) self._conn: sqlite3.Connection = sqlite3.connect(db_name)
self._cursor = self._conn.cursor() logging.info(f'DBAccess | self._conn = [\n{type(self._conn)}\n{self._conn}\n]')
self._cursor: sqlite3.Cursor = self._conn.cursor()
logging.info(f'DBAccess | self._cursor = [\n{type(self._cursor)}\n{self._cursor}\n]')
def __enter__(self): def __enter__(self):
return self return self

View File

@ -1,11 +1,10 @@
# MusicPom # MusicPom
iTunes-like music player built with PyQt5. PyQt5 music player inspired by MusicBee & iTunes
I am longing for a linux version of MusicBee, so I created this app for myself that will have all the features I want.
## Todo: ## Todo:
- [ ] Delete songs from library - [ ] Delete songs from library (del key || right-click delete)
- [x] Right-click menu
- [ ] .wav, .ogg, .flac convertor
- [ ] Editable lyrics textbox - [ ] Editable lyrics textbox
- [ ] .wav, .ogg, .flac conversions

View File

@ -7,7 +7,7 @@ from PyQt5.QtGui import (
QDragEnterEvent, QDragEnterEvent,
QDropEvent, QDropEvent,
) )
from PyQt5.QtWidgets import QTableView, QShortcut, QMessageBox, QAbstractItemView from PyQt5.QtWidgets import QAction, QMenu, QTableView, QShortcut, QMessageBox, QAbstractItemView
from PyQt5.QtCore import QModelIndex, Qt, pyqtSignal, QTimer from PyQt5.QtCore import QModelIndex, Qt, pyqtSignal, QTimer
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
@ -56,8 +56,8 @@ class MusicTable(QTableView):
self.database_columns = str(self.config["table"]["columns"]).split(",") self.database_columns = str(self.config["table"]["columns"]).split(",")
self.vertical_scroll_position = 0 self.vertical_scroll_position = 0
self.songChanged = None self.songChanged = None
self.selected_song_filepath = None self.selected_song_filepath = ''
self.current_song_filepath = None self.current_song_filepath = ''
# self.tableView.resizeColumnsToContents() # self.tableView.resizeColumnsToContents()
self.clicked.connect(self.set_selected_song_filepath) self.clicked.connect(self.set_selected_song_filepath)
# doubleClicked is a built in event for QTableView - we listen for this event and run set_current_song_filepath # doubleClicked is a built in event for QTableView - we listen for this event and run set_current_song_filepath
@ -68,6 +68,19 @@ class MusicTable(QTableView):
self.model.dataChanged.connect(self.on_cell_data_changed) # editing cells self.model.dataChanged.connect(self.on_cell_data_changed) # editing cells
self.model.layoutChanged.connect(self.restore_scroll_position) self.model.layoutChanged.connect(self.restore_scroll_position)
def contextMenuEvent(self, event):
"""Show a context menu when you right-click a row"""
menu = QMenu(self)
delete_action = QAction("Delete", self)
delete_action.triggered.connect(self.delete_selected_rows)
menu.addAction(delete_action)
menu.exec_(event.globalPos())
def delete_selected_rows(self):
selected_rows = self.selectionModel().selectedRows()
for index in selected_rows:
self.model().removeRow(index.row())
def dragEnterEvent(self, event: QDragEnterEvent): def dragEnterEvent(self, event: QDragEnterEvent):
if event.mimeData().hasUrls(): if event.mimeData().hasUrls():
event.accept() event.accept()
@ -255,7 +268,7 @@ class MusicTable(QTableView):
"""Returns the selected songs filepath""" """Returns the selected songs filepath"""
return self.selected_song_filepath return self.selected_song_filepath
def get_selected_song_metadata(self) -> dict: def get_selected_song_metadata(self) -> EasyID3 | dict:
"""Returns the selected song's ID3 tags""" """Returns the selected song's ID3 tags"""
return get_id3_tags(self.selected_song_filepath) return get_id3_tags(self.selected_song_filepath)
@ -263,11 +276,11 @@ class MusicTable(QTableView):
"""Returns the currently playing song filepath""" """Returns the currently playing song filepath"""
return self.current_song_filepath return self.current_song_filepath
def get_current_song_metadata(self) -> dict: def get_current_song_metadata(self) -> EasyID3 | dict:
"""Returns the currently playing song's ID3 tags""" """Returns the currently playing song's ID3 tags"""
return get_id3_tags(self.current_song_filepath) return get_id3_tags(self.current_song_filepath)
def get_current_song_album_art(self) -> None: def get_current_song_album_art(self) -> bytes:
"""Returns the APIC data (album art lol) for the currently playing song""" """Returns the APIC data (album art lol) for the currently playing song"""
return get_album_art(self.current_song_filepath) return get_album_art(self.current_song_filepath)

View File

@ -21,6 +21,8 @@ def add_files_to_library(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(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

View File

@ -11,22 +11,32 @@ def get_id3_tags(file):
dict of all id3 tags dict of all id3 tags
if all tags are empty, at minimum fill in the 'title' if all tags are empty, at minimum fill in the 'title'
""" """
is_easy_id3 = False
try: try:
is_easy_id3 = True
audio = EasyID3(file) audio = EasyID3(file)
# Check if all tags are empty
tags_are_empty = all(not values for values in audio.values())
if tags_are_empty:
# split on / to get just the filename
# os.path.splitext to get name without extension
audio['title'] = [os.path.splitext(file.split('/')[-1])[0]]
if audio['title'] is None: # I guess a song could have other tags
# without a title, so i make sure to have title
audio['title'] = [os.path.splitext(file.split('/')[-1])[0]]
audio.save()
return audio
except Exception as e: except Exception as e:
print(f"Error: {e}") is_easy_id3 = False
return {} audio = {}
print('get_id3_tags audio:')
print(audio)
# Check if all tags are empty
tags_are_empty = all(not values for values in audio.values())
if tags_are_empty:
# split on / to get just the filename
# os.path.splitext to get name without extension
audio['title'] = [os.path.splitext(file.split('/')[-1])[0]]
if audio['title'] is None: # I guess a song could have other tags
# without a title, so i make sure to have title
audio['title'] = [os.path.splitext(file.split('/')[-1])[0]]
if is_easy_id3: # i can ignore this error because of this check
audio.save() # type: ignore
return audio
# import sys # import sys
# my_file = sys.argv[1] # my_file = sys.argv[1]