Run file import in separate thread

This commit is contained in:
Keith Edmunds 2022-04-19 15:25:15 +01:00
parent e2af6dd7ac
commit c7f7f25af0
3 changed files with 51 additions and 43 deletions

View File

@ -54,6 +54,7 @@ class Config(object):
NORMALISE_ON_IMPORT = True NORMALISE_ON_IMPORT = True
NOTE_TIME_FORMAT = "%H:%M:%S" NOTE_TIME_FORMAT = "%H:%M:%S"
ROOT = os.environ.get('ROOT') or "/home/kae/music" ROOT = os.environ.get('ROOT') or "/home/kae/music"
IMPORT_DESTINATION = os.path.join(ROOT, "Singles")
SCROLL_TOP_MARGIN = 3 SCROLL_TOP_MARGIN = 3
TESTMODE = True TESTMODE = True
TOD_TIME_FORMAT = "%H:%M:%S" TOD_TIME_FORMAT = "%H:%M:%S"

View File

@ -4,6 +4,7 @@ import argparse
import os.path import os.path
import psutil import psutil
import sys import sys
import threading
import urllib.parse import urllib.parse
import webbrowser import webbrowser
@ -24,6 +25,7 @@ from PyQt5.QtWidgets import (
QLineEdit, QLineEdit,
QListWidgetItem, QListWidgetItem,
QMainWindow, QMainWindow,
QMessageBox,
) )
import dbconfig import dbconfig
@ -420,14 +422,47 @@ class Window(QMainWindow, Ui_MainWindow):
dlg = QFileDialog() dlg = QFileDialog()
dlg.setFileMode(QFileDialog.ExistingFiles) dlg.setFileMode(QFileDialog.ExistingFiles)
dlg.setViewMode(QFileDialog.Detail) dlg.setViewMode(QFileDialog.Detail)
# TODO: remove hardcoded directory dlg.setDirectory(Config.IMPORT_DESTINATION)
dlg.setDirectory(os.path.join(Config.ROOT, "Singles"))
dlg.setNameFilter("Music files (*.flac *.mp3)") dlg.setNameFilter("Music files (*.flac *.mp3)")
if dlg.exec_(): if dlg.exec_():
with Session() as session: with Session() as session:
txt: str = ""
new_tracks = []
for fname in dlg.selectedFiles(): for fname in dlg.selectedFiles():
track = create_track_from_file(session, fname) tags = helpers.get_tags(fname)
new_tracks.append((fname, tags))
title = tags['title']
artist = tags['artist']
possible_matches = Tracks.search_titles(session, title)
if possible_matches:
txt += 'Similar to new track '
txt += f'"{title}" by "{artist}":\n'
for track in possible_matches:
txt += f' "{track.title}" by {track.artist}\n'
txt += "\n"
# Check whether to proceed if there were potential matches
if txt:
txt += "Proceed with import?"
result = QMessageBox.question(self,
"Possible duplicates",
txt,
QMessageBox.Ok,
QMessageBox.Cancel
)
if result == QMessageBox.Cancel:
return
# Import in separate thread
thread = threading.Thread(target=self._import_tracks,
args=(session, new_tracks))
thread.start()
def _import_tracks(self, session: Session, tracks: list):
"""Import passed files"""
for (fname, tags) in tracks:
track = create_track_from_file(session, fname, tags=tags)
# Add to playlist on screen # Add to playlist on screen
# If we don't specify "repaint=False", playlist will # If we don't specify "repaint=False", playlist will
# also be saved to database # also be saved to database

View File

@ -38,7 +38,6 @@ def main():
group.add_argument('-f', '--full-update', group.add_argument('-f', '--full-update',
action="store_true", dest="full_update", action="store_true", dest="full_update",
default=False, help="Update database") default=False, help="Update database")
group.add_argument('-i', '--import', dest="fname", help="Input file")
args = p.parse_args() args = p.parse_args()
# Run as required # Run as required
@ -50,18 +49,13 @@ def main():
DEBUG("Full update of database") DEBUG("Full update of database")
with Session() as session: with Session() as session:
full_update_db(session) full_update_db(session)
elif args.fname:
fname = os.path.realpath(args.fname)
with Session() as session:
create_track_from_file(session, fname, interactive=True)
else: else:
INFO("No action specified") INFO("No action specified")
DEBUG("Finished") DEBUG("Finished")
def create_track_from_file(session, path, normalise=None, interactive=False): def create_track_from_file(session, path, normalise=None, tags=None):
""" """
Create track in database from passed path, or update database entry Create track in database from passed path, or update database entry
if path already in database. if path already in database.
@ -69,34 +63,14 @@ def create_track_from_file(session, path, normalise=None, interactive=False):
Return track. Return track.
""" """
if interactive: if not tags:
msg = f"Importing {path}"
INFO(msg)
INFO("-" * len(msg))
INFO("Get track info...")
t = get_tags(path) t = get_tags(path)
title = t['title'] else:
artist = t['artist'] t = tags
if interactive:
INFO(f" Title: \"{title}\"")
INFO(f" Artist: \"{artist}\"")
# Check for duplicate
if interactive:
tracks = Tracks.search_titles(session, title)
if tracks:
print("Found the following possible matches:")
for track in tracks:
print(f'"{track.title}" by {track.artist}')
response = input("Continue [c] or abort [a]?")
if not response:
return
if response[0].lower() not in ['c', 'y']:
return
track = Tracks.get_or_create(session, path) track = Tracks.get_or_create(session, path)
track.title = title track.title = t['title']
track.artist = artist track.artist = t['artist']
if interactive:
INFO("Parse for start, fade and silence...")
audio = get_audio_segment(path) audio = get_audio_segment(path)
track.duration = len(audio) track.duration = len(audio)
track.start_gap = leading_silence(audio) track.start_gap = leading_silence(audio)
@ -108,8 +82,6 @@ def create_track_from_file(session, path, normalise=None, interactive=False):
session.commit() session.commit()
if normalise or normalise is None and Config.NORMALISE_ON_IMPORT: if normalise or normalise is None and Config.NORMALISE_ON_IMPORT:
if interactive:
INFO("Normalise...")
# Check type # Check type
ftype = os.path.splitext(path)[1][1:] ftype = os.path.splitext(path)[1][1:]
if ftype not in ['mp3', 'flac']: if ftype not in ['mp3', 'flac']: