layouts, mutagen id3 tags, table drag & drop, double click to play
This commit is contained in:
parent
76c1aa554b
commit
a982a025fe
@ -4,7 +4,6 @@ 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 add_files_to_library
|
||||||
from utils import get_id3_tags
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
@ -57,9 +56,6 @@ 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"""
|
||||||
|
|||||||
8
main.py
8
main.py
@ -69,7 +69,7 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
|||||||
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.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(self.clear_database) # Clear database
|
||||||
## tableView
|
## tableView
|
||||||
# self.tableView.clicked.connect(self.set_clicked_cell_filepath)
|
# 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
|
||||||
@ -194,7 +194,11 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
def scan_libraries(self):
|
def scan_libraries(self):
|
||||||
scan_for_music()
|
scan_for_music()
|
||||||
# refresh datatable
|
self.tableView.fetch_library()
|
||||||
|
|
||||||
|
def clear_database(self):
|
||||||
|
initialize_library_database()
|
||||||
|
self.tableView.fetch_library()
|
||||||
|
|
||||||
def process_probe(self, buff):
|
def process_probe(self, buff):
|
||||||
buff.startTime()
|
buff.startTime()
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
from .safe_get import safe_get
|
||||||
from .get_id3_tags import get_id3_tags
|
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
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import DBA
|
import DBA
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
from utils import get_id3_tags
|
from utils import get_id3_tags
|
||||||
|
from utils import safe_get
|
||||||
|
|
||||||
config = ConfigParser()
|
config = ConfigParser()
|
||||||
config.read("config.ini")
|
config.read("config.ini")
|
||||||
@ -11,37 +12,47 @@ def add_files_to_library(files):
|
|||||||
`files` | list() | List of fully qualified paths to audio file(s)
|
`files` | list() | List of fully qualified paths to audio file(s)
|
||||||
Returns a count of records added
|
Returns a count of records added
|
||||||
"""
|
"""
|
||||||
print(f'utils | adding files to library: {files}')
|
print(f"utils | adding 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 file in files:
|
for filepath in files:
|
||||||
if any(file.lower().endswith(ext) for ext in extensions):
|
if any(filepath.lower().endswith(ext) for ext in extensions):
|
||||||
filename = file.split("/")[-1]
|
filename = filepath.split("/")[-1]
|
||||||
audio = get_id3_tags(file)
|
audio = get_id3_tags(filepath)
|
||||||
|
if "title" not in audio:
|
||||||
|
return
|
||||||
# Append data tuple to insert_data list
|
# Append data tuple to insert_data list
|
||||||
insert_data.append(
|
insert_data.append(
|
||||||
(
|
(
|
||||||
file,
|
filepath,
|
||||||
audio.title,
|
safe_get(audio, "title", [])[0],
|
||||||
audio.album,
|
safe_get(audio, "album", [])[0] if "album" in audio else None,
|
||||||
audio.artist,
|
safe_get(audio, "artist", [])[0] if "artist" in audio else None,
|
||||||
audio.genre,
|
",".join(safe_get(audio, "genre", []))
|
||||||
|
if "genre" in audio
|
||||||
|
else None,
|
||||||
filename.split(".")[-1],
|
filename.split(".")[-1],
|
||||||
audio.year,
|
safe_get(audio, "date", [])[0] if "date" in audio else None,
|
||||||
audio.bitrate,
|
safe_get(audio, "bitrate", [])[0] if "birate" in audio else None,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check if batch size is reached
|
# Check if batch size is reached
|
||||||
if len(insert_data) >= 1000:
|
if len(insert_data) >= 1000:
|
||||||
with DBA.DBAccess() as db:
|
with DBA.DBAccess() as db:
|
||||||
db.executemany('INSERT OR IGNORE INTO library (filepath, title, album, artist, genre, codec, album_date, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', insert_data)
|
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_data = [] # Reset the insert_data list
|
||||||
|
|
||||||
# Insert any remaining data
|
# Insert any remaining data
|
||||||
if insert_data:
|
if insert_data:
|
||||||
with DBA.DBAccess() as db:
|
with DBA.DBAccess() as db:
|
||||||
db.executemany('INSERT OR IGNORE INTO library (filepath, title, album, artist, genre, codec, album_date, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', insert_data)
|
db.executemany(
|
||||||
|
"INSERT OR IGNORE INTO library (filepath, title, album, artist, genre, codec, album_date, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
insert_data,
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -11,11 +11,8 @@ def get_id3_tags(file):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
audio = EasyID3(file)
|
audio = EasyID3(file)
|
||||||
|
print(f'ID3 Tags: {audio}')
|
||||||
return audio
|
return audio
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error: {e}")
|
print(f"Error: {e}")
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
filepath = '/home/billy/Music/songs/meanings/blah99/H.mp3'
|
|
||||||
id3_tags = get_id3_tags(filepath)
|
|
||||||
print(id3_tags)
|
|
||||||
3
utils/safe_get.py
Normal file
3
utils/safe_get.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Define a function to safely access dictionary keys
|
||||||
|
def safe_get(dictionary, key, default=None):
|
||||||
|
return dictionary.get(key, default)
|
||||||
@ -2,14 +2,15 @@ import os
|
|||||||
import DBA
|
import DBA
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
from utils import get_id3_tags
|
from utils import get_id3_tags
|
||||||
|
from utils import safe_get
|
||||||
|
|
||||||
config = ConfigParser()
|
config = ConfigParser()
|
||||||
config.read('config.ini')
|
config.read("config.ini")
|
||||||
|
|
||||||
|
|
||||||
def scan_for_music():
|
def scan_for_music():
|
||||||
root_dir = config.get('directories', 'library')
|
root_dir = config.get("directories", "library")
|
||||||
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 dirpath, dirnames, filenames in os.walk(root_dir):
|
for dirpath, dirnames, filenames in os.walk(root_dir):
|
||||||
@ -17,29 +18,39 @@ def scan_for_music():
|
|||||||
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 = get_id3_tags(filepath)
|
audio = get_id3_tags(filepath)
|
||||||
|
if "title" not in audio:
|
||||||
|
return
|
||||||
|
|
||||||
# Append data tuple to insert_data list
|
# Append data tuple to insert_data list
|
||||||
insert_data.append((
|
insert_data.append(
|
||||||
|
(
|
||||||
filepath,
|
filepath,
|
||||||
audio.title,
|
safe_get(audio, "title", [])[0],
|
||||||
audio.album,
|
safe_get(audio, "album", [])[0] if "album" in audio else None,
|
||||||
audio.artist,
|
safe_get(audio, "artist", [])[0] if "artist" in audio else None,
|
||||||
audio.genre,
|
",".join(safe_get(audio, "genre", [])) if "genre" in audio else None,
|
||||||
filename.split('.')[-1],
|
filename.split(".")[-1],
|
||||||
audio.year,
|
safe_get(audio, "date", [])[0] if "date" in audio else None,
|
||||||
audio.bitrate
|
safe_get(audio, "bitrate", [])[0] if "birate" in audio else None,
|
||||||
))
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Check if batch size is reached
|
# Check if batch size is reached
|
||||||
if len(insert_data) >= 1000:
|
if len(insert_data) >= 1000:
|
||||||
with DBA.DBAccess() as db:
|
with DBA.DBAccess() as db:
|
||||||
db.executemany('INSERT OR IGNORE INTO library (filepath, title, album, artist, genre, codec, album_date, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', insert_data)
|
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_data = [] # Reset the insert_data list
|
||||||
|
|
||||||
# Insert any remaining data
|
# Insert any remaining data
|
||||||
if insert_data:
|
if insert_data:
|
||||||
with DBA.DBAccess() as db:
|
with DBA.DBAccess() as db:
|
||||||
db.executemany('INSERT OR IGNORE INTO library (filepath, title, album, artist, genre, codec, album_date, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', insert_data)
|
db.executemany(
|
||||||
|
"INSERT OR IGNORE INTO library (filepath, title, album, artist, genre, codec, album_date, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
insert_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# id int unsigned auto_increment,
|
# id int unsigned auto_increment,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user