Fix fading; lots of tidying!
This commit is contained in:
parent
6643da84b6
commit
d3b739dc36
@ -8,6 +8,8 @@ class Config(object):
|
||||
DBFS_SILENCE = -50
|
||||
DISPLAY_SQL = False
|
||||
ERRORS_TO = ['kae@midnighthax.com']
|
||||
FADE_STEPS = 20
|
||||
FADE_TIME = 5000
|
||||
LOG_LEVEL_STDERR = logging.DEBUG
|
||||
LOG_LEVEL_SYSLOG = logging.DEBUG
|
||||
LOG_NAME = "musicmuster"
|
||||
|
||||
7
app/log.py
Executable file → Normal file
7
app/log.py
Executable file → Normal file
@ -35,9 +35,10 @@ syslog.addFilter(filter)
|
||||
stderr.addFilter(filter)
|
||||
|
||||
# create formatter and add it to the handlers
|
||||
formatter = logging.Formatter('[%(name)s] %(leveltag)s: %(message)s')
|
||||
stderr.setFormatter(formatter)
|
||||
syslog.setFormatter(formatter)
|
||||
stderr_fmt = logging.Formatter('%(leveltag)s: %(message)s')
|
||||
syslog_fmt = logging.Formatter('[%(name)s] %(leveltag)s: %(message)s')
|
||||
stderr.setFormatter(stderr_fmt)
|
||||
syslog.setFormatter(syslog_fmt)
|
||||
|
||||
# add the handlers to the log
|
||||
log.addHandler(stderr)
|
||||
|
||||
18
app/model.py
18
app/model.py
@ -17,11 +17,8 @@ from sqlalchemy.orm.exc import NoResultFound
|
||||
from sqlalchemy.orm import relationship, sessionmaker
|
||||
|
||||
from config import Config
|
||||
|
||||
from log import DEBUG, ERROR, INFO
|
||||
|
||||
INFO("Starting")
|
||||
|
||||
# Create session at the global level as per
|
||||
# https://docs.sqlalchemy.org/en/13/orm/session_basics.html
|
||||
|
||||
@ -138,8 +135,10 @@ class Playlists(Base):
|
||||
def get_only_playlist(cls):
|
||||
return session.query(Playlists).filter(Playlists.id == 1).one()
|
||||
|
||||
def add_track(self, track):
|
||||
self.tracks.append(track)
|
||||
def add_track(self, track, position):
|
||||
glue = PlaylistTracks(sort=position)
|
||||
glue.track_id = track.id
|
||||
self.tracks.append(glue)
|
||||
|
||||
def get_tracks(self):
|
||||
return [a.tracks for a in self.tracks]
|
||||
@ -181,10 +180,9 @@ class Tracks(Base):
|
||||
@staticmethod
|
||||
def get_path(id):
|
||||
try:
|
||||
path = session.query(Tracks.path).filter(Tracks.id == id).one()[0]
|
||||
return os.path.join(Config.ROOT, path)
|
||||
return session.query(Tracks.path).filter(Tracks.id == id).one()[0]
|
||||
except NoResultFound:
|
||||
print(f"Can't find track id {id}")
|
||||
ERROR(f"Can't find track id {id}")
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
@ -210,6 +208,9 @@ class Tracks(Base):
|
||||
return session.query(Tracks).filter(
|
||||
Tracks.id == id).one()
|
||||
|
||||
def update_lastplayed(self):
|
||||
self.lastplayed = datetime.now()
|
||||
|
||||
|
||||
class Playdates(Base):
|
||||
__tablename__ = 'playdates'
|
||||
@ -226,4 +227,5 @@ class Playdates(Base):
|
||||
pd.lastplayed = datetime.now()
|
||||
pd.track_id = track.id
|
||||
session.add(pd)
|
||||
track.update_lastplayed()
|
||||
session.commit()
|
||||
|
||||
@ -33,6 +33,7 @@ class Music:
|
||||
"player": None,
|
||||
"meta": None
|
||||
}
|
||||
self.fading = False
|
||||
|
||||
def get_current_artist(self):
|
||||
try:
|
||||
@ -101,15 +102,26 @@ class Music:
|
||||
return ""
|
||||
|
||||
def fade_current(self):
|
||||
if not self.playing():
|
||||
return
|
||||
thread = threading.Thread(target=self._fade_current)
|
||||
thread.start()
|
||||
|
||||
def _fade_current(self):
|
||||
fade_time = Config.FADE_TIME / 1000
|
||||
sleep_time = fade_time / Config.FADE_STEPS
|
||||
step_percent = int((100 / Config.FADE_STEPS) * -1)
|
||||
player = self.current_track['player']
|
||||
position = player.get_position()
|
||||
for i in range(100, 0, -10):
|
||||
for i in range(100, 0, step_percent):
|
||||
player.audio_set_volume(i)
|
||||
sleep(0.2)
|
||||
sleep(sleep_time)
|
||||
# If the user clicks "fade" and then, before the track has
|
||||
# finished fading, click "play next", the "play next" will also
|
||||
# call fade_current. When that second call to fade_current gets
|
||||
# to the player.pause() line below, it will unpause it. So, we
|
||||
# only pause if we're acutally playing.
|
||||
if player.is_playing():
|
||||
player.pause()
|
||||
player.audio_set_volume(100)
|
||||
player.set_position(position)
|
||||
@ -118,9 +130,11 @@ class Music:
|
||||
if self.previous_track['player']:
|
||||
self.previous_track['player'].release()
|
||||
if self.current_track['player']:
|
||||
self.current_track['player'].stop()
|
||||
self.fade_current()
|
||||
self.previous_track = self.current_track
|
||||
self.current_track = self.next_track
|
||||
# Next in case player was left in odd (ie, silenced) state
|
||||
self.current_track['player'].audio_set_volume(100)
|
||||
self.current_track['player'].play()
|
||||
Playdates.add_playdate(self.current_track['meta'])
|
||||
|
||||
@ -210,7 +224,11 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
self.actionPlay_next.triggered.connect(self.play_next)
|
||||
self.actionPlay_selected.triggered.connect(self.play_next)
|
||||
self.actionSearch_database.triggered.connect(self.selectFromDatabase)
|
||||
self.btnSearchDatabase.clicked.connect(self.selectFromDatabase)
|
||||
self.btnSkipNext.clicked.connect(self.play_next)
|
||||
self.btnStop.clicked.connect(self.fade)
|
||||
self.playlist.itemSelectionChanged.connect(self.set_next_track)
|
||||
|
||||
self.timer.timeout.connect(self.tick)
|
||||
|
||||
def selectFromDatabase(self):
|
||||
@ -400,7 +418,8 @@ class DbDialog(QDialog):
|
||||
|
||||
# Store in current playlist in database
|
||||
db_playlist = Playlists.get_only_playlist()
|
||||
db_playlist.add_track(track)
|
||||
# TODO: hack position to be at end of list
|
||||
db_playlist.add_track(track, 99999)
|
||||
|
||||
# Add to on-screen playlist
|
||||
self.parent().add_to_playlist(track)
|
||||
|
||||
8
app/songdb.py
Executable file → Normal file
8
app/songdb.py
Executable file → Normal file
@ -9,12 +9,12 @@ from model import Tracks, session
|
||||
from pydub import AudioSegment
|
||||
from tinytag import TinyTag
|
||||
|
||||
INFO("Starting")
|
||||
|
||||
|
||||
def main():
|
||||
"Main loop"
|
||||
|
||||
INFO("Starting")
|
||||
|
||||
# Parse command line
|
||||
p = argparse.ArgumentParser()
|
||||
p.add_argument('-u', '--update',
|
||||
@ -125,9 +125,9 @@ def update_db():
|
||||
session.commit()
|
||||
|
||||
elif ext not in [".jpg"]:
|
||||
print(f"Unrecognised file type: {path}")
|
||||
INFO(f"Unrecognised file type: {path}")
|
||||
|
||||
print(f"{count} files processed")
|
||||
INFO(f"{count} files processed")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@ -16,6 +16,10 @@
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="previous_track_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
@ -47,24 +51,7 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="previous_track">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans</family>
|
||||
<pointsize>20</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: #f8d7da;
|
||||
border: 1px solid rgb(85, 87, 83);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item>
|
||||
<widget class="QLabel" name="current_track_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
@ -96,24 +83,7 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="current_track">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans</family>
|
||||
<pointsize>20</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: #d4edda;
|
||||
border: 1px solid rgb(85, 87, 83);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item>
|
||||
<widget class="QLabel" name="next_track_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
@ -145,7 +115,45 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="previous_track">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans</family>
|
||||
<pointsize>20</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: #f8d7da;
|
||||
border: 1px solid rgb(85, 87, 83);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="current_track">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Sans</family>
|
||||
<pointsize>20</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: #d4edda;
|
||||
border: 1px solid rgb(85, 87, 83);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="next_track">
|
||||
<property name="font">
|
||||
<font>
|
||||
@ -162,7 +170,103 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="lblTOD">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>35</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>00:00:00</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnPrevious">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>previous.png</normaloff>previous.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>41</width>
|
||||
<height>41</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnStop">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>stop.png</normaloff>stop.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>41</width>
|
||||
<height>41</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnSkipNext">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>next.png</normaloff>next.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>41</width>
|
||||
<height>41</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QTableWidget" name="playlist">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
@ -230,11 +334,8 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<item row="2" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
@ -332,8 +433,8 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
<width>13</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@ -388,8 +489,8 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
<width>13</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@ -444,8 +545,8 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
<width>13</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@ -500,8 +601,8 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
<width>13</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@ -562,16 +663,49 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnAddFile">
|
||||
<property name="text">
|
||||
<string>Add &file...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnSearchDatabase">
|
||||
<property name="text">
|
||||
<string>Search &database</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnSetNextTrack">
|
||||
<property name="text">
|
||||
<string>Set &next track</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnTrackInfo">
|
||||
<property name="text">
|
||||
<string>Track &info</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>playlist</zorder>
|
||||
<zorder>current_track</zorder>
|
||||
<zorder>previous_track</zorder>
|
||||
<zorder>next_track</zorder>
|
||||
<zorder>current_track_2</zorder>
|
||||
<zorder>next_track_2</zorder>
|
||||
<zorder>previous_track_2</zorder>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
@ -610,36 +744,6 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
<string notr="true">background-color: rgb(211, 215, 207);</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="windowTitle">
|
||||
<string>toolBar</string>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="actionPlay_selected"/>
|
||||
<addaction name="actionPlay_next"/>
|
||||
<addaction name="actionFade"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionAdd_file"/>
|
||||
<addaction name="actionSearch_database"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionS_top"/>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="toolBar_2">
|
||||
<property name="windowTitle">
|
||||
<string>toolBar_2</string>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
<action name="actionPlay_selected">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
|
||||
BIN
app/ui/next.png
Normal file
BIN
app/ui/next.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 328 B |
BIN
app/ui/previous.png
Normal file
BIN
app/ui/previous.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 345 B |
BIN
app/ui/stop.png
Normal file
BIN
app/ui/stop.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 250 B |
Loading…
Reference in New Issue
Block a user