Separate out model
This commit is contained in:
parent
dab05c079a
commit
a6b089a5ae
99
app.py
99
app.py
@ -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
70
model.py
Normal 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()
|
||||
64
songdb.py
64
songdb.py
@ -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
81
spike.py
Normal 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)
|
||||
Loading…
Reference in New Issue
Block a user