Separate out model

This commit is contained in:
Keith Edmunds 2021-03-21 19:55:33 +00:00
parent dab05c079a
commit a6b089a5ae
4 changed files with 160 additions and 154 deletions

99
app.py
View File

@ -1,17 +1,12 @@
#!/usr/bin/python3
import sys
import vlc
from datetime import datetime, timedelta
from pydub import AudioSegment
from PyQt5.QtCore import QEvent, Qt
from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow, QMessageBox
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow
from PyQt5.QtWidgets import QTableWidgetItem, QFileDialog, QListWidgetItem
from PyQt5.uic import loadUi
from threading import Timer
from time import sleep
from timeloop import Timeloop
from tinytag import TinyTag
from main_window_ui import Ui_MainWindow
@ -19,11 +14,6 @@ from dlg_search_database_ui import Ui_Dialog
from songdb import Tracks
import sqlalchemy
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
class RepeatedTimer:
def __init__(self, interval, function, *args, **kwargs):
@ -81,7 +71,7 @@ class Track:
return AudioSegment.from_mp3(path)
elif path.endswith('.flac'):
return AudioSegment.from_file(path, "flac")
except:
except AttributeError:
return None
def leading_silence(self, audio_segment, silence_threshold=-50.0,
@ -232,92 +222,11 @@ class DbDialog(QDialog):
self.ui.listWidget.addItem(t)
def listdclick(self, entry):
import ipdb; ipdb.set_trace()
print(f"clicked entry id={entry.data(Qt.UserRole)}")
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec())
# tl = Timeloop()
#
#
#
# # @tl.job(interval=timedelta(seconds=1))
# def update_progress(player, talk_at, silent_at):
# elapsed_time = player.get_time()
# total_time = player.get_length()
# remaining_time = total_time - elapsed_time
# talk_time = remaining_time - (total_time - talk_at)
# silent_time = remaining_time - (total_time - silent_at)
# end_time = (datetime.now() + timedelta(
# milliseconds=remaining_time)).strftime("%H:%M:%S")
# print(
# f"\t{ms_to_mmss(elapsed_time)}/"
# f"{ms_to_mmss(total_time)}\t\t"
# f"Talk in: {ms_to_mmss(talk_time)} "
# f"Silent in: {ms_to_mmss(silent_time)} "
# f"Ends at: {end_time} [{ms_to_mmss(remaining_time)}]"
# , end="\r")
#
#
# # Print name of current song, print name of next song. Play current when
# # return pressed, Pri--current-song-output-lengthnt remaining time every
# # second. When it ends, print name of new current and next song.
#
#
# def test():
# track = "wibg.mp3"
# segment = AudioSegment.from_mp3(trm.ack)
# print(f"Track: {track}")
# print(f"Leading silence: {ms_to_mmss(leading_silence(segment),
# decimals=1)}")
# talk_at = significant_fade(segment)
# silent_at = trailing_silence(segment)
# print(f"Talkover fade: {ms_to_mmss(talk_at)}")
# print(f"Track silent from: {ms_to_mmss(silent_at)}")
# p = vlc.MediaPlayer("wibg.mp3")
# _ = input("")
# p.play()
# print()
# rt = RepeatedTimer(0.5, update_progress, p, talk_at, silent_at)
# sleep(1)
# while p.is_playing():
# sleep(1)
# rt.stop() # better in a try/finally block to make sure the program ends!
# print("End")
#def kae2(self, index):
# print(f"table header click, index={index}")
#def kae(self, a, b, c):
# self.data.append(f"a={a}, b={b}, c={c}")
#def mousePressEvent(self, QMouseEvent):
# print("mouse press")
#def mouseReleaseEvent(self, QMouseEvent):
# print("mouse release")
# # QMessageBox.about(
# # self,
# # "About Sample Editor",
# # "\n".join(self.data)
# # )
#def eventFilter(self, obj, event):
# # you could be doing different groups of actions
# # for different types of widgets and either filtering
# # the event or not.
# # Here we just check if its one of the layout widgets
# # if self.layout.indexOf(obj) != -1:
# # print(f"event received: {event.type()}")
# if event.type() == QEvent.MouseButtonPress:
# print("Widget click")
# # if I returned True right here, the event
# # would be filtered and not reach the obj,
# # meaning that I decided to handle it myself
# # regardless, just do the default
# return super().eventFilter(obj, event)

70
model.py Normal file
View File

@ -0,0 +1,70 @@
#!/usr/bin/python3
import logging
import sqlalchemy
import pytiger.logging.config
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Float, DateTime, Integer, String
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.orm import sessionmaker
# "Constants"
DISPLAY_SQL = False
MYSQL_CONNECT = "mysql+mysqldb://songdb:songdb@localhost/songdb"
# Instantiate logging
pytiger.logging.config.basic_config(stderr=False, level=logging.INFO)
log = logging.getLogger(__name__)
log.info("Starting")
# Create session at the global level as per
# https://docs.sqlalchemy.org/en/13/orm/session_basics.html
# Set up database connection
log.info("Connect to database")
engine = sqlalchemy.create_engine(f"{MYSQL_CONNECT}?charset=utf8",
encoding='utf-8',
echo=DISPLAY_SQL)
Base = declarative_base()
Base.metadata.create_all(engine)
# Create a Session
Session = sessionmaker(bind=engine)
session = Session()
# Database classes
class Tracks(Base):
__tablename__ = 'tracks'
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(256), index=True)
artist = Column(String(256), index=True)
length = Column(Integer, index=True)
path = Column(String(2048), index=False, nullable=False)
mtime = Column(Float, index=True)
lastplayed = Column(DateTime, index=True, default=None)
def __repr__(self):
return (
f"<Track(id={self.id}, title={self.title}, "
f"artist={self.artist}, path={self.path}>"
)
@classmethod
def get_or_create(cls, path):
try:
track = session.query(cls).filter(cls.path == path).one()
except NoResultFound:
track = Tracks()
track.path = path
session.add(track)
return track
@staticmethod
def search_titles(text):
return session.query(Tracks).filter(
Tracks.title.ilike(f"%{text}%")
).all()

View File

@ -4,76 +4,21 @@ import argparse
import hashlib
import logging
import os
import sqlalchemy
import pytiger.logging.config
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Float, DateTime, Integer, String
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.orm import sessionmaker
from tinytag import TinyTag
from model import Tracks, session
# "Constants"
ROOT = "/home/kae/music"
DISPLAY_SQL = False
MYSQL_CONNECT = "mysql+mysqldb://songdb:songdb@localhost/songdb"
# Instantiate logging
pytiger.logging.config.basic_config(stderr=False, level=logging.INFO)
log = logging.getLogger(__name__)
log.info("Starting")
# Create session at the global level as per
# https://docs.sqlalchemy.org/en/13/orm/session_basics.html
# Set up database connection
log.info("Connect to database")
engine = sqlalchemy.create_engine(f"{MYSQL_CONNECT}?charset=utf8",
encoding='utf-8',
echo=DISPLAY_SQL)
Base = declarative_base()
Base.metadata.create_all(engine)
# Create a Session
Session = sessionmaker(bind=engine)
session = Session()
# Database classes
class Tracks(Base):
__tablename__ = 'tracks'
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(256), index=True)
artist = Column(String(256), index=True)
length = Column(Integer, index=True)
path = Column(String(2048), index=False, nullable=False)
mtime = Column(Float, index=True)
lastplayed = Column(DateTime, index=True, default=None)
def __repr__(self):
return (
f"<Track(id={self.id}, title={self.title}, "
f"artist={self.artist}, path={self.path}>"
)
@classmethod
def get_or_create(cls, path):
try:
track = session.query(cls).filter(cls.path == path).one()
except NoResultFound:
track = Tracks()
track.path = path
session.add(track)
return track
@staticmethod
def search_titles(text):
return session.query(Tracks).filter(
Tracks.title.ilike(f"%{text}%")
).all()
def main():
"Main loop"
@ -117,11 +62,12 @@ def update_db():
print(f"Unrecognised file type: {path}")
session.commit()
print(f"{count} files processed")
def md5(path):
"https://stackoverflow.com/questions/3431825/"
"https://stackoverflow.nl9om/questions/3431825/"
"generating-an-md5-checksum-of-a-file"
hash_md5 = hashlib.md5()

81
spike.py Normal file
View File

@ -0,0 +1,81 @@
# tl = Timeloop()
#
#
#
# # @tl.job(interval=timedelta(seconds=1))
# def update_progress(player, talk_at, silent_at):
# elapsed_time = player.get_time()
# total_time = player.get_length()
# remaining_time = total_time - elapsed_time
# talk_time = remaining_time - (total_time - talk_at)
# silent_time = remaining_time - (total_time - silent_at)
# end_time = (datetime.now() + timedelta(
# milliseconds=remaining_time)).strftime("%H:%M:%S")
# print(
# f"\t{ms_to_mmss(elapsed_time)}/"
# f"{ms_to_mmss(total_time)}\t\t"
# f"Talk in: {ms_to_mmss(talk_time)} "
# f"Silent in: {ms_to_mmss(silent_time)} "
# f"Ends at: {end_time} [{ms_to_mmss(remaining_time)}]"
# , end="\r")
#
#
# # Print name of current song, print name of next song. Play current when
# # return pressed, Pri--current-song-output-lengthnt remaining time every
# # second. When it ends, print name of new current and next song.
#
#
# def test():
# track = "wibg.mp3"
# segment = AudioSegment.from_mp3(trm.ack)
# print(f"Track: {track}")
# print(f"Leading silence: {ms_to_mmss(leading_silence(segment),
# decimals=1)}")
# talk_at = significant_fade(segment)
# silent_at = trailing_silence(segment)
# print(f"Talkover fade: {ms_to_mmss(talk_at)}")
# print(f"Track silent from: {ms_to_mmss(silent_at)}")
# p = vlc.MediaPlayer("wibg.mp3")
# _ = input("")
# p.play()
# print()
# rt = RepeatedTimer(0.5, update_progress, p, talk_at, silent_at)
# sleep(1)
# while p.is_playing():
# sleep(1)
# rt.stop() # better in a try/finally block to make sure the program ends!
# print("End")
#def kae2(self, index):
# print(f"table header click, index={index}")
#def kae(self, a, b, c):
# self.data.append(f"a={a}, b={b}, c={c}")
#def mousePressEvent(self, QMouseEvent):
# print("mouse press")
#def mouseReleaseEvent(self, QMouseEvent):
# print("mouse release")
# # QMessageBox.about(
# # self,
# # "About Sample Editor",
# # "\n".join(self.data)
# # )
#def eventFilter(self, obj, event):
# # you could be doing different groups of actions
# # for different types of widgets and either filtering
# # the event or not.
# # Here we just check if its one of the layout widgets
# # if self.layout.indexOf(obj) != -1:
# # print(f"event received: {event.type()}")
# if event.type() == QEvent.MouseButtonPress:
# print("Widget click")
# # if I returned True right here, the event
# # would be filtered and not reach the obj,
# # meaning that I decided to handle it myself
# # regardless, just do the default
# return super().eventFilter(obj, event)