Compare commits

...

8 Commits

Author SHA1 Message Date
Keith Edmunds
79f1a6afa3 Set track end time when setting next track. Fixes #33 2021-07-24 17:38:53 +01:00
Keith Edmunds
194306bc1d Order functions alphabetically 2021-07-24 17:29:59 +01:00
Keith Edmunds
4f10ed7bad Normalise mp3's on import 2021-07-15 17:54:34 +01:00
Keith Edmunds
2edf12670f Add POC of audacity control 2021-07-04 19:28:18 +01:00
Keith Edmunds
a027cbe776 Greatly improve database update 2021-07-04 19:28:18 +01:00
Keith Edmunds
28396d136f Add ui/.py files to git 2021-07-04 19:28:18 +01:00
Keith Edmunds
2fc705dc6e Fix typo in run_prod 2021-07-04 19:23:11 +01:00
Keith Edmunds
6936b24129 Facilitate dev and prod databases - fixes #15 2021-07-04 19:21:28 +01:00
12 changed files with 921 additions and 47 deletions

1
.gitignore vendored
View File

@ -1,5 +1,4 @@
.mypy_cache/
*_ui.py
*.pyc
*.swp
tags

View File

@ -30,9 +30,9 @@ class Config(object):
MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS') is not None
MILLISECOND_SIGFIGS = 0
MYSQL_CONNECT = "mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster"
MYSQL_CONNECT = os.environ.get('MYSQL_CONNECT') or "mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_dev" # noqa E501
NORMALISE_ON_IMPORT = True
ROOT = "/home/kae/music"
ROOT = os.environ.get('ROOT') or "/home/kae/music"
TESTMODE = True
TIMER_MS = 500
VOLUME_VLC_DEFAULT = 81

View File

@ -14,6 +14,7 @@ from sqlalchemy import (
String,
func
)
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
from sqlalchemy.orm import relationship, sessionmaker
@ -106,6 +107,14 @@ class Playdates(Base):
track.update_lastplayed()
session.commit()
@staticmethod
def last_played(session, track):
"Return datetime track last played or None"
return session.query(Playdates).filter(
(Playdates.track_id == track.id)
).order_by(Playdates.lastplayed.desc()).first()
class Playlists(Base):
"""
@ -279,6 +288,20 @@ class PlaylistTracks(Base):
session.add(plt)
session.commit()
@staticmethod
def get_playlists_containing_track_id(session, track_id):
playlists = []
playlist_ids = session.query(PlaylistTracks.playlist_id).filter(
PlaylistTracks.track_id == track_id).all()
for p in playlist_ids:
playlist = session.query(Playlists).filter(
Playlists.id == p[0]).first()
if playlist:
playlists.append(playlist)
return playlists
@staticmethod
def move_track(session, from_playlist_id, row, to_playlist_id):
DEBUG(
@ -458,6 +481,44 @@ class Tracks(Base):
ERROR(f"get_track({id}): not found")
return None
@staticmethod
def get_track_from_filename(session, filename):
"""
Return track if one and only one track in database has passed
filename (ie, basename of path). Return None if zero or more
than one track matches.
"""
DEBUG(f"Tracks.get_track_from_filename({filename=})")
try:
track = session.query(Tracks).filter(Tracks.path.ilike(
# TODO: filename separator is hardcoded here
f'%/{filename}')).one()
return track
except (NoResultFound, MultipleResultsFound):
return None
@staticmethod
def get_track_from_path(session, path):
"""
Return track with passee path, or None.
"""
DEBUG(f"Tracks.get_track_from_path({path=})")
return session.query(Tracks).filter(Tracks.path == path).first()
@staticmethod
def remove_path(session, path):
"Remove track with passed path from database"
DEBUG(f"Tracks.remove_path({path=})")
try:
session.query(Tracks).filter(Tracks.path == path).delete()
except IntegrityError as exception:
ERROR(f"Can't remove track with {path=} ({exception=})")
@staticmethod
def search_titles(session, text):
return (
@ -473,3 +534,6 @@ class Tracks(Base):
def update_lastplayed(self):
self.lastplayed = datetime.now()
def update_path(self, newpath):
self.path = newpath

View File

@ -311,6 +311,15 @@ class PlaylistTab(QTableWidget):
return result
def get_selected_title(self):
"Return title of selected row or None"
if self.selectionModel().hasSelection():
row = self.currentRow()
return self.item(row, self.COL_TITLE).text()
else:
return None
def remove_rows(self, rows):
"Remove rows passed in rows list"
@ -323,15 +332,6 @@ class PlaylistTab(QTableWidget):
self._repaint()
def get_selected_title(self):
"Return title of selected row or None"
if self.selectionModel().hasSelection():
row = self.currentRow()
return self.item(row, self.COL_TITLE).text()
else:
return None
def play_started(self):
"""
Update current track to be what was next, and determine next track.
@ -834,6 +834,8 @@ class PlaylistTab(QTableWidget):
self._set_row_start_time(row, start_time)
next_start_time = self._calculate_next_start_time(
session, row, start_time)
# Set end time
self._set_row_end_time(row, next_start_time)
# Set colour
self._set_row_colour(
row, QColor(Config.COLOUR_NEXT_PLAYLIST))

View File

@ -7,8 +7,9 @@ import tempfile
from config import Config
from log import DEBUG, INFO
from model import Tracks, Session
from model import Tracks, Playdates, PlaylistTracks, Session
from mutagen.flac import FLAC
from mutagen.mp3 import MP3
from pydub import AudioSegment, effects
from tinytag import TinyTag
@ -22,7 +23,10 @@ def main():
p = argparse.ArgumentParser()
p.add_argument('-u', '--update',
action="store_true", dest="update",
default=True, help="Update database")
default=False, help="Update database")
p.add_argument('-f', '--full-update',
action="store_true", dest="full_update",
default=False, help="Update database")
args = p.parse_args()
# Run as required
@ -30,25 +34,32 @@ def main():
INFO("Updating database")
with Session() as session:
update_db(session)
elif args.full_update:
INFO("Full update of database")
with Session() as session:
full_update_db(session)
else:
INFO("No action specified")
INFO("Finished")
def create_track_from_file(session, path):
"""
Create track in database from passed path.
Create track in database from passed path, or update database entry
if path already in database.
Return track.
"""
track = Tracks.get_or_create(session, path)
tag = TinyTag.get(path)
audio = get_audio_segment(path)
t = get_music_info(path)
track.title = t['title']
track.artist = t['artist']
track.duration = int(round(
t['duration'], Config.MILLISECOND_SIGFIGS) * 1000)
track.title = tag.title
track.artist = tag.artist
track.duration = int(round(tag.duration,
Config.MILLISECOND_SIGFIGS) * 1000)
audio = get_audio_segment(path)
track.start_gap = leading_silence(audio)
track.fade_at = round(fade_point(audio) / 1000,
Config.MILLISECOND_SIGFIGS) * 1000
@ -58,6 +69,12 @@ def create_track_from_file(session, path):
session.commit()
if Config.NORMALISE_ON_IMPORT:
# Check type
ftype = os.path.splitext(path)[1][1:]
if ftype not in ['mp3', 'flac']:
INFO(f"File type {ftype} not implemented")
return track
# Get current file gid, uid and permissions
stats = os.stat(path)
try:
@ -68,30 +85,42 @@ def create_track_from_file(session, path):
DEBUG(f"songdb.create_track_from_file({path}): err1: {str(err)}")
return
# Overwrite original file with normalised output
normalised = effects.normalize(audio)
try:
normalised.export(path, format=os.path.splitext(path)[1][1:])
# Fix up permssions and ownership
os.chown(path, stats.st_uid, stats.st_gid)
os.chmod(path, stats.st_mode)
# Copy tags
src = FLAC(temp_path)
dst = FLAC(path)
for tag in src:
dst[tag] = src[tag]
dst.save()
except Exception as err:
DEBUG(f"songdb.create_track_from_file({path}): err2: {str(err)}")
# Restore original file
shutil.copyfile(path, temp_path)
finally:
if os.path.exists(temp_path):
os.remove(temp_path)
# Overwrite original file with normalised output
normalised = effects.normalize(audio)
try:
normalised.export(path, format=os.path.splitext(path)[1][1:])
# Fix up permssions and ownership
os.chown(path, stats.st_uid, stats.st_gid)
os.chmod(path, stats.st_mode)
# Copy tags
if ftype == 'flac':
tag_handler = FLAC
elif ftype == 'mp3':
tag_handler = MP3
else:
return track
src = tag_handler(temp_path)
dst = tag_handler(path)
for tag in src:
dst[tag] = src[tag]
dst.save()
except Exception as err:
DEBUG(f"songdb.create_track_from_file({path}): err2: {str(err)}")
# Restore original file
shutil.copyfile(path, temp_path)
finally:
if os.path.exists(temp_path):
os.remove(temp_path)
return track
def full_update_db():
"Rescan all entries in database"
print("Full scan not yet implemented")
def get_audio_segment(path):
try:
if path.endswith('.mp3'):
@ -102,6 +131,21 @@ def get_audio_segment(path):
return None
def get_music_info(path):
"""
Return a dictionary of title, artist, duration-in-milliseconds and path.
"""
tag = TinyTag.get(path)
return dict(
title=tag.title,
artist=tag.artist,
duration=tag.duration,
path=path
)
def leading_silence(audio_segment, silence_threshold=Config.DBFS_SILENCE,
chunk_size=Config.AUDIO_SEGMENT_CHUNK_SIZE):
"""
@ -187,14 +231,47 @@ def update_db(session):
os_paths_list.append(path)
os_paths = set(os_paths_list)
for path in list(db_paths - os_paths):
# TODO
INFO(f"To remove from database: {path}")
# If a track is moved, only the path will have changed.
# For any files we have found whose paths are not in the database,
# check to see whether the filename (basename) is present in the
# database:
for path in list(os_paths - db_paths):
# TODO
INFO(f"Adding to dataabase: {path}")
create_track_from_file(session, path)
DEBUG(f"songdb.update_db: {path=} not in database")
# is filename in database?
track = Tracks.get_track_from_filename(session, os.path.basename(path))
if not track:
DEBUG(f"songdb.update_db: Adding to database: {path}")
create_track_from_file(session, path)
else:
# Check track info matches found track
t = get_music_info(path)
if t['artist'] == track.artist and t['title'] == track.title:
track.update_path(path)
else:
create_track_from_file(session, path)
# Refresh database paths
db_paths = set(Tracks.get_all_paths(session))
# Remote any tracks from database whose paths don't exist
for path in list(db_paths - os_paths):
track = Tracks.get_track_from_path(session, path)
DEBUG(f"songdb.update_db(): remove from database: {path=} {track=}")
played = Playdates.last_played(session, track)
playlists = PlaylistTracks.get_playlists_containing_track_id(
session, track.id)
if played:
INFO(
f"songdb.update_db: Can't remove {track.id=} ({track.path=}) "
f"as it's in playdates.id={played.id}"
)
elif playlists:
INFO(
f"songdb.update_db: Can't remove {track.id=} ({track.path=} "
f"as it's in playlists {[p.name for p in playlists]}"
)
else:
Tracks.remove_path(session, path)
if __name__ == '__main__' and '__file__' in globals():

View File

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui/dlg_SelectPlaylist.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_dlgSelectPlaylist(object):
def setupUi(self, dlgSelectPlaylist):
dlgSelectPlaylist.setObjectName("dlgSelectPlaylist")
dlgSelectPlaylist.resize(276, 150)
self.verticalLayout = QtWidgets.QVBoxLayout(dlgSelectPlaylist)
self.verticalLayout.setObjectName("verticalLayout")
self.lstPlaylists = QtWidgets.QListWidget(dlgSelectPlaylist)
self.lstPlaylists.setObjectName("lstPlaylists")
self.verticalLayout.addWidget(self.lstPlaylists)
self.buttonBox = QtWidgets.QDialogButtonBox(dlgSelectPlaylist)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout.addWidget(self.buttonBox)
self.retranslateUi(dlgSelectPlaylist)
self.buttonBox.accepted.connect(dlgSelectPlaylist.accept)
self.buttonBox.rejected.connect(dlgSelectPlaylist.reject)
QtCore.QMetaObject.connectSlotsByName(dlgSelectPlaylist)
def retranslateUi(self, dlgSelectPlaylist):
_translate = QtCore.QCoreApplication.translate
dlgSelectPlaylist.setWindowTitle(_translate("dlgSelectPlaylist", "Dialog"))

View File

@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'app/ui/dlg_SearchDatabase.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(383, 270)
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
self.verticalLayout.setObjectName("verticalLayout")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.label = QtWidgets.QLabel(Dialog)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.searchString = QtWidgets.QLineEdit(Dialog)
self.searchString.setObjectName("searchString")
self.gridLayout.addWidget(self.searchString, 0, 1, 1, 1)
self.verticalLayout.addLayout(self.gridLayout)
self.matchList = QtWidgets.QListWidget(Dialog)
self.matchList.setObjectName("matchList")
self.verticalLayout.addWidget(self.matchList)
self.dbPath = QtWidgets.QLabel(Dialog)
self.dbPath.setText("")
self.dbPath.setObjectName("dbPath")
self.verticalLayout.addWidget(self.dbPath)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
spacerItem = QtWidgets.QSpacerItem(88, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.btnAdd = QtWidgets.QPushButton(Dialog)
self.btnAdd.setDefault(True)
self.btnAdd.setObjectName("btnAdd")
self.horizontalLayout.addWidget(self.btnAdd)
self.btnAddClose = QtWidgets.QPushButton(Dialog)
self.btnAddClose.setObjectName("btnAddClose")
self.horizontalLayout.addWidget(self.btnAddClose)
self.btnClose = QtWidgets.QPushButton(Dialog)
self.btnClose.setObjectName("btnClose")
self.horizontalLayout.addWidget(self.btnClose)
self.verticalLayout.addLayout(self.horizontalLayout)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label.setText(_translate("Dialog", "Title:"))
self.btnAdd.setText(_translate("Dialog", "&Add"))
self.btnAddClose.setText(_translate("Dialog", "A&dd and close"))
self.btnClose.setText(_translate("Dialog", "&Close"))

543
app/ui/main_window_ui.py Normal file
View File

@ -0,0 +1,543 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui/main_window.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1164, 857)
MainWindow.setStyleSheet("")
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout_3 = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout_3.setObjectName("gridLayout_3")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.verticalLayout_3 = QtWidgets.QVBoxLayout()
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.previous_track_2 = QtWidgets.QLabel(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.previous_track_2.sizePolicy().hasHeightForWidth())
self.previous_track_2.setSizePolicy(sizePolicy)
self.previous_track_2.setMaximumSize(QtCore.QSize(230, 16777215))
font = QtGui.QFont()
font.setFamily("Sans")
font.setPointSize(20)
self.previous_track_2.setFont(font)
self.previous_track_2.setStyleSheet("background-color: #f8d7da;\n"
"border: 1px solid rgb(85, 87, 83);")
self.previous_track_2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.previous_track_2.setObjectName("previous_track_2")
self.verticalLayout_3.addWidget(self.previous_track_2)
self.current_track_2 = QtWidgets.QLabel(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.current_track_2.sizePolicy().hasHeightForWidth())
self.current_track_2.setSizePolicy(sizePolicy)
self.current_track_2.setMaximumSize(QtCore.QSize(230, 16777215))
font = QtGui.QFont()
font.setFamily("Sans")
font.setPointSize(20)
self.current_track_2.setFont(font)
self.current_track_2.setStyleSheet("background-color: #d4edda;\n"
"border: 1px solid rgb(85, 87, 83);")
self.current_track_2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.current_track_2.setObjectName("current_track_2")
self.verticalLayout_3.addWidget(self.current_track_2)
self.next_track_2 = QtWidgets.QLabel(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.next_track_2.sizePolicy().hasHeightForWidth())
self.next_track_2.setSizePolicy(sizePolicy)
self.next_track_2.setMaximumSize(QtCore.QSize(230, 16777215))
font = QtGui.QFont()
font.setFamily("Sans")
font.setPointSize(20)
self.next_track_2.setFont(font)
self.next_track_2.setStyleSheet("background-color: #fff3cd;\n"
"border: 1px solid rgb(85, 87, 83);")
self.next_track_2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.next_track_2.setObjectName("next_track_2")
self.verticalLayout_3.addWidget(self.next_track_2)
self.horizontalLayout_3.addLayout(self.verticalLayout_3)
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.hdrPreviousTrack = QtWidgets.QLabel(self.centralwidget)
self.hdrPreviousTrack.setMinimumSize(QtCore.QSize(16, 0))
self.hdrPreviousTrack.setMaximumSize(QtCore.QSize(16777215, 16777215))
font = QtGui.QFont()
font.setFamily("Sans")
font.setPointSize(20)
self.hdrPreviousTrack.setFont(font)
self.hdrPreviousTrack.setStyleSheet("background-color: #f8d7da;\n"
"border: 1px solid rgb(85, 87, 83);")
self.hdrPreviousTrack.setText("")
self.hdrPreviousTrack.setObjectName("hdrPreviousTrack")
self.verticalLayout.addWidget(self.hdrPreviousTrack)
self.hdrCurrentTrack = QtWidgets.QLabel(self.centralwidget)
font = QtGui.QFont()
font.setFamily("Sans")
font.setPointSize(20)
self.hdrCurrentTrack.setFont(font)
self.hdrCurrentTrack.setStyleSheet("background-color: #d4edda;\n"
"border: 1px solid rgb(85, 87, 83);")
self.hdrCurrentTrack.setText("")
self.hdrCurrentTrack.setObjectName("hdrCurrentTrack")
self.verticalLayout.addWidget(self.hdrCurrentTrack)
self.hdrNextTrack = QtWidgets.QLabel(self.centralwidget)
font = QtGui.QFont()
font.setFamily("Sans")
font.setPointSize(20)
self.hdrNextTrack.setFont(font)
self.hdrNextTrack.setStyleSheet("background-color: #fff3cd;\n"
"border: 1px solid rgb(85, 87, 83);")
self.hdrNextTrack.setText("")
self.hdrNextTrack.setObjectName("hdrNextTrack")
self.verticalLayout.addWidget(self.hdrNextTrack)
self.horizontalLayout_3.addLayout(self.verticalLayout)
self.frame_2 = QtWidgets.QFrame(self.centralwidget)
self.frame_2.setMaximumSize(QtCore.QSize(230, 16777215))
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.gridLayout_2 = QtWidgets.QGridLayout(self.frame_2)
self.gridLayout_2.setObjectName("gridLayout_2")
self.lblTOD = QtWidgets.QLabel(self.frame_2)
self.lblTOD.setMinimumSize(QtCore.QSize(208, 109))
font = QtGui.QFont()
font.setPointSize(35)
self.lblTOD.setFont(font)
self.lblTOD.setAlignment(QtCore.Qt.AlignCenter)
self.lblTOD.setObjectName("lblTOD")
self.gridLayout_2.addWidget(self.lblTOD, 0, 0, 1, 1)
self.horizontalLayout_3.addWidget(self.frame_2)
self.gridLayout_3.addLayout(self.horizontalLayout_3, 0, 0, 1, 1)
self.frame_5 = QtWidgets.QFrame(self.centralwidget)
self.frame_5.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_5.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_5.setObjectName("frame_5")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame_5)
self.horizontalLayout.setObjectName("horizontalLayout")
self.btnPlay = QtWidgets.QPushButton(self.frame_5)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/icons/play"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btnPlay.setIcon(icon)
self.btnPlay.setIconSize(QtCore.QSize(30, 30))
self.btnPlay.setObjectName("btnPlay")
self.horizontalLayout.addWidget(self.btnPlay)
spacerItem = QtWidgets.QSpacerItem(68, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.btnSongInfo = QtWidgets.QPushButton(self.frame_5)
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(":/icons/wikipedia"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btnSongInfo.setIcon(icon1)
self.btnSongInfo.setIconSize(QtCore.QSize(30, 30))
self.btnSongInfo.setObjectName("btnSongInfo")
self.horizontalLayout.addWidget(self.btnSongInfo)
spacerItem1 = QtWidgets.QSpacerItem(70, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem1)
self.btnDatabase = QtWidgets.QPushButton(self.frame_5)
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(":/icons/search_db"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btnDatabase.setIcon(icon2)
self.btnDatabase.setIconSize(QtCore.QSize(30, 30))
self.btnDatabase.setObjectName("btnDatabase")
self.horizontalLayout.addWidget(self.btnDatabase)
self.btnAddFile = QtWidgets.QPushButton(self.frame_5)
icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap(":/icons/open_file"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btnAddFile.setIcon(icon3)
self.btnAddFile.setIconSize(QtCore.QSize(30, 30))
self.btnAddFile.setObjectName("btnAddFile")
self.horizontalLayout.addWidget(self.btnAddFile)
spacerItem2 = QtWidgets.QSpacerItem(68, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem2)
self.btnAddNote = QtWidgets.QPushButton(self.frame_5)
icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap(":/icons/note"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btnAddNote.setIcon(icon4)
self.btnAddNote.setIconSize(QtCore.QSize(30, 30))
self.btnAddNote.setObjectName("btnAddNote")
self.horizontalLayout.addWidget(self.btnAddNote)
self.btnSetNext = QtWidgets.QPushButton(self.frame_5)
icon5 = QtGui.QIcon()
icon5.addPixmap(QtGui.QPixmap(":/icons/set_next"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btnSetNext.setIcon(icon5)
self.btnSetNext.setIconSize(QtCore.QSize(30, 30))
self.btnSetNext.setObjectName("btnSetNext")
self.horizontalLayout.addWidget(self.btnSetNext)
spacerItem3 = QtWidgets.QSpacerItem(69, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem3)
self.btnFade = QtWidgets.QPushButton(self.frame_5)
icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap(":/icons/fade"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btnFade.setIcon(icon6)
self.btnFade.setIconSize(QtCore.QSize(30, 30))
self.btnFade.setObjectName("btnFade")
self.horizontalLayout.addWidget(self.btnFade)
self.btnStop = QtWidgets.QPushButton(self.frame_5)
icon7 = QtGui.QIcon()
icon7.addPixmap(QtGui.QPixmap(":/icons/stopsign"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btnStop.setIcon(icon7)
self.btnStop.setIconSize(QtCore.QSize(30, 30))
self.btnStop.setObjectName("btnStop")
self.horizontalLayout.addWidget(self.btnStop)
self.spnVolume = QtWidgets.QSpinBox(self.frame_5)
self.spnVolume.setMaximum(100)
self.spnVolume.setProperty("value", 100)
self.spnVolume.setObjectName("spnVolume")
self.horizontalLayout.addWidget(self.spnVolume)
self.gridLayout_3.addWidget(self.frame_5, 1, 0, 1, 1)
self.tabPlaylist = QtWidgets.QTabWidget(self.centralwidget)
self.tabPlaylist.setDocumentMode(False)
self.tabPlaylist.setTabsClosable(False)
self.tabPlaylist.setMovable(True)
self.tabPlaylist.setObjectName("tabPlaylist")
self.gridLayout_3.addWidget(self.tabPlaylist, 2, 0, 1, 1)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.frame = QtWidgets.QFrame(self.centralwidget)
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.gridLayout = QtWidgets.QGridLayout(self.frame)
self.gridLayout.setObjectName("gridLayout")
self.label_2 = QtWidgets.QLabel(self.frame)
self.label_2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1)
self.label_start_tod = QtWidgets.QLabel(self.frame)
font = QtGui.QFont()
font.setFamily("FreeSans")
font.setPointSize(16)
self.label_start_tod.setFont(font)
self.label_start_tod.setScaledContents(False)
self.label_start_tod.setObjectName("label_start_tod")
self.gridLayout.addWidget(self.label_start_tod, 0, 1, 1, 1)
self.label_3 = QtWidgets.QLabel(self.frame)
self.label_3.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 1, 0, 1, 1)
self.label_silent_tod = QtWidgets.QLabel(self.frame)
font = QtGui.QFont()
font.setFamily("FreeSans")
font.setPointSize(16)
self.label_silent_tod.setFont(font)
self.label_silent_tod.setScaledContents(False)
self.label_silent_tod.setObjectName("label_silent_tod")
self.gridLayout.addWidget(self.label_silent_tod, 1, 1, 1, 1)
self.label_7 = QtWidgets.QLabel(self.frame)
self.label_7.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_7.setObjectName("label_7")
self.gridLayout.addWidget(self.label_7, 2, 0, 1, 1)
self.label_fade_length = QtWidgets.QLabel(self.frame)
font = QtGui.QFont()
font.setFamily("FreeSans")
font.setPointSize(16)
self.label_fade_length.setFont(font)
self.label_fade_length.setScaledContents(False)
self.label_fade_length.setObjectName("label_fade_length")
self.gridLayout.addWidget(self.label_fade_length, 2, 1, 1, 1)
self.horizontalLayout_2.addWidget(self.frame)
self.frame_elapsed = QtWidgets.QFrame(self.centralwidget)
self.frame_elapsed.setStyleSheet("")
self.frame_elapsed.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_elapsed.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_elapsed.setObjectName("frame_elapsed")
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.frame_elapsed)
self.verticalLayout_5.setObjectName("verticalLayout_5")
self.label = QtWidgets.QLabel(self.frame_elapsed)
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setObjectName("label")
self.verticalLayout_5.addWidget(self.label)
self.label_elapsed_timer = QtWidgets.QLabel(self.frame_elapsed)
font = QtGui.QFont()
font.setFamily("FreeSans")
font.setPointSize(40)
font.setBold(False)
font.setWeight(50)
self.label_elapsed_timer.setFont(font)
self.label_elapsed_timer.setAlignment(QtCore.Qt.AlignCenter)
self.label_elapsed_timer.setObjectName("label_elapsed_timer")
self.verticalLayout_5.addWidget(self.label_elapsed_timer)
self.horizontalLayout_2.addWidget(self.frame_elapsed)
self.frame_fade = QtWidgets.QFrame(self.centralwidget)
self.frame_fade.setStyleSheet("")
self.frame_fade.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_fade.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_fade.setObjectName("frame_fade")
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.frame_fade)
self.verticalLayout_6.setObjectName("verticalLayout_6")
self.label_4 = QtWidgets.QLabel(self.frame_fade)
self.label_4.setAlignment(QtCore.Qt.AlignCenter)
self.label_4.setObjectName("label_4")
self.verticalLayout_6.addWidget(self.label_4)
self.label_fade_timer = QtWidgets.QLabel(self.frame_fade)
font = QtGui.QFont()
font.setFamily("FreeSans")
font.setPointSize(40)
font.setBold(False)
font.setWeight(50)
self.label_fade_timer.setFont(font)
self.label_fade_timer.setAlignment(QtCore.Qt.AlignCenter)
self.label_fade_timer.setObjectName("label_fade_timer")
self.verticalLayout_6.addWidget(self.label_fade_timer)
self.horizontalLayout_2.addWidget(self.frame_fade)
self.frame_silent = QtWidgets.QFrame(self.centralwidget)
self.frame_silent.setStyleSheet("")
self.frame_silent.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_silent.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_silent.setObjectName("frame_silent")
self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.frame_silent)
self.verticalLayout_7.setObjectName("verticalLayout_7")
self.label_5 = QtWidgets.QLabel(self.frame_silent)
self.label_5.setAlignment(QtCore.Qt.AlignCenter)
self.label_5.setObjectName("label_5")
self.verticalLayout_7.addWidget(self.label_5)
self.label_silent_timer = QtWidgets.QLabel(self.frame_silent)
font = QtGui.QFont()
font.setFamily("FreeSans")
font.setPointSize(40)
font.setBold(False)
font.setWeight(50)
self.label_silent_timer.setFont(font)
self.label_silent_timer.setAlignment(QtCore.Qt.AlignCenter)
self.label_silent_timer.setObjectName("label_silent_timer")
self.verticalLayout_7.addWidget(self.label_silent_timer)
self.horizontalLayout_2.addWidget(self.frame_silent)
self.frame_end = QtWidgets.QFrame(self.centralwidget)
self.frame_end.setStyleSheet("")
self.frame_end.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_end.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_end.setObjectName("frame_end")
self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.frame_end)
self.verticalLayout_8.setObjectName("verticalLayout_8")
self.label_6 = QtWidgets.QLabel(self.frame_end)
self.label_6.setAlignment(QtCore.Qt.AlignCenter)
self.label_6.setObjectName("label_6")
self.verticalLayout_8.addWidget(self.label_6)
self.label_end_timer = QtWidgets.QLabel(self.frame_end)
font = QtGui.QFont()
font.setFamily("FreeSans")
font.setPointSize(40)
font.setBold(False)
font.setWeight(50)
self.label_end_timer.setFont(font)
self.label_end_timer.setAlignment(QtCore.Qt.AlignCenter)
self.label_end_timer.setObjectName("label_end_timer")
self.verticalLayout_8.addWidget(self.label_end_timer)
self.horizontalLayout_2.addWidget(self.frame_end)
self.gridLayout_3.addLayout(self.horizontalLayout_2, 3, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1164, 29))
self.menubar.setObjectName("menubar")
self.menuFile = QtWidgets.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
self.menuPlaylist = QtWidgets.QMenu(self.menubar)
self.menuPlaylist.setObjectName("menuPlaylist")
self.menu_Tracks = QtWidgets.QMenu(self.menubar)
self.menu_Tracks.setObjectName("menu_Tracks")
self.menuTest = QtWidgets.QMenu(self.menubar)
self.menuTest.setObjectName("menuTest")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setEnabled(True)
self.statusbar.setStyleSheet("background-color: rgb(211, 215, 207);")
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.actionPlay_next = QtWidgets.QAction(MainWindow)
icon8 = QtGui.QIcon()
icon8.addPixmap(QtGui.QPixmap("ui/../../../../.designer/backup/icon-play.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionPlay_next.setIcon(icon8)
self.actionPlay_next.setObjectName("actionPlay_next")
self.actionSkip_next = QtWidgets.QAction(MainWindow)
icon9 = QtGui.QIcon()
icon9.addPixmap(QtGui.QPixmap(":/icons/next"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionSkip_next.setIcon(icon9)
self.actionSkip_next.setObjectName("actionSkip_next")
self.actionSearch_database = QtWidgets.QAction(MainWindow)
icon10 = QtGui.QIcon()
icon10.addPixmap(QtGui.QPixmap("ui/../../../../.designer/backup/icon_search_database.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionSearch_database.setIcon(icon10)
self.actionSearch_database.setObjectName("actionSearch_database")
self.actionAdd_file = QtWidgets.QAction(MainWindow)
icon11 = QtGui.QIcon()
icon11.addPixmap(QtGui.QPixmap("ui/../../../../.designer/backup/icon_open_file.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionAdd_file.setIcon(icon11)
self.actionAdd_file.setObjectName("actionAdd_file")
self.actionFade = QtWidgets.QAction(MainWindow)
icon12 = QtGui.QIcon()
icon12.addPixmap(QtGui.QPixmap("ui/../../../../.designer/backup/icon-fade.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionFade.setIcon(icon12)
self.actionFade.setObjectName("actionFade")
self.actionStop = QtWidgets.QAction(MainWindow)
icon13 = QtGui.QIcon()
icon13.addPixmap(QtGui.QPixmap(":/icons/stop"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.actionStop.setIcon(icon13)
self.actionStop.setObjectName("actionStop")
self.action_Clear_selection = QtWidgets.QAction(MainWindow)
self.action_Clear_selection.setObjectName("action_Clear_selection")
self.action_Resume_previous = QtWidgets.QAction(MainWindow)
icon14 = QtGui.QIcon()
icon14.addPixmap(QtGui.QPixmap(":/icons/previous"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.action_Resume_previous.setIcon(icon14)
self.action_Resume_previous.setObjectName("action_Resume_previous")
self.actionE_xit = QtWidgets.QAction(MainWindow)
self.actionE_xit.setObjectName("actionE_xit")
self.actionTest = QtWidgets.QAction(MainWindow)
self.actionTest.setObjectName("actionTest")
self.actionOpenPlaylist = QtWidgets.QAction(MainWindow)
self.actionOpenPlaylist.setObjectName("actionOpenPlaylist")
self.actionNewPlaylist = QtWidgets.QAction(MainWindow)
self.actionNewPlaylist.setObjectName("actionNewPlaylist")
self.actionTestFunction = QtWidgets.QAction(MainWindow)
self.actionTestFunction.setObjectName("actionTestFunction")
self.actionSkipToFade = QtWidgets.QAction(MainWindow)
self.actionSkipToFade.setObjectName("actionSkipToFade")
self.actionSkipToEnd = QtWidgets.QAction(MainWindow)
self.actionSkipToEnd.setObjectName("actionSkipToEnd")
self.actionClosePlaylist = QtWidgets.QAction(MainWindow)
self.actionClosePlaylist.setEnabled(True)
self.actionClosePlaylist.setObjectName("actionClosePlaylist")
self.actionRenamePlaylist = QtWidgets.QAction(MainWindow)
self.actionRenamePlaylist.setEnabled(False)
self.actionRenamePlaylist.setObjectName("actionRenamePlaylist")
self.actionDeletePlaylist = QtWidgets.QAction(MainWindow)
self.actionDeletePlaylist.setEnabled(False)
self.actionDeletePlaylist.setObjectName("actionDeletePlaylist")
self.actionMoveSelected = QtWidgets.QAction(MainWindow)
self.actionMoveSelected.setObjectName("actionMoveSelected")
self.actionExport_playlist = QtWidgets.QAction(MainWindow)
self.actionExport_playlist.setObjectName("actionExport_playlist")
self.actionSetNext = QtWidgets.QAction(MainWindow)
self.actionSetNext.setObjectName("actionSetNext")
self.actionSelect_next_track = QtWidgets.QAction(MainWindow)
self.actionSelect_next_track.setObjectName("actionSelect_next_track")
self.actionSelect_previous_track = QtWidgets.QAction(MainWindow)
self.actionSelect_previous_track.setObjectName("actionSelect_previous_track")
self.actionSelect_played_tracks = QtWidgets.QAction(MainWindow)
self.actionSelect_played_tracks.setObjectName("actionSelect_played_tracks")
self.actionSelect_unplayed_tracks = QtWidgets.QAction(MainWindow)
self.actionSelect_unplayed_tracks.setObjectName("actionSelect_unplayed_tracks")
self.menuFile.addAction(self.actionE_xit)
self.menuPlaylist.addAction(self.actionNewPlaylist)
self.menuPlaylist.addAction(self.actionOpenPlaylist)
self.menuPlaylist.addAction(self.actionClosePlaylist)
self.menuPlaylist.addAction(self.actionRenamePlaylist)
self.menuPlaylist.addAction(self.actionDeletePlaylist)
self.menuPlaylist.addSeparator()
self.menuPlaylist.addAction(self.actionSearch_database)
self.menuPlaylist.addAction(self.actionAdd_file)
self.menuPlaylist.addAction(self.action_Clear_selection)
self.menuPlaylist.addSeparator()
self.menuPlaylist.addAction(self.actionSelect_unplayed_tracks)
self.menuPlaylist.addAction(self.actionSelect_played_tracks)
self.menuPlaylist.addAction(self.actionMoveSelected)
self.menuPlaylist.addSeparator()
self.menuPlaylist.addAction(self.actionExport_playlist)
self.menuPlaylist.addSeparator()
self.menuPlaylist.addAction(self.actionSelect_next_track)
self.menuPlaylist.addAction(self.actionSelect_previous_track)
self.menu_Tracks.addAction(self.actionPlay_next)
self.menu_Tracks.addAction(self.actionSkip_next)
self.menu_Tracks.addAction(self.actionFade)
self.menu_Tracks.addAction(self.actionStop)
self.menu_Tracks.addAction(self.action_Resume_previous)
self.menu_Tracks.addSeparator()
self.menu_Tracks.addAction(self.actionSetNext)
self.menuTest.addAction(self.actionTestFunction)
self.menuTest.addSeparator()
self.menuTest.addAction(self.actionSkipToFade)
self.menuTest.addAction(self.actionSkipToEnd)
self.menubar.addAction(self.menuFile.menuAction())
self.menubar.addAction(self.menuPlaylist.menuAction())
self.menubar.addAction(self.menu_Tracks.menuAction())
self.menubar.addAction(self.menuTest.menuAction())
self.retranslateUi(MainWindow)
self.tabPlaylist.setCurrentIndex(-1)
self.actionE_xit.triggered.connect(MainWindow.close)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Music Muster"))
self.previous_track_2.setText(_translate("MainWindow", "Last track:"))
self.current_track_2.setText(_translate("MainWindow", "Current track:"))
self.next_track_2.setText(_translate("MainWindow", "Next track:"))
self.lblTOD.setText(_translate("MainWindow", "00:00:00"))
self.btnPlay.setText(_translate("MainWindow", " Play"))
self.btnSongInfo.setText(_translate("MainWindow", "Song info"))
self.btnDatabase.setText(_translate("MainWindow", "Database"))
self.btnAddFile.setText(_translate("MainWindow", "Add file"))
self.btnAddNote.setText(_translate("MainWindow", "Add note"))
self.btnSetNext.setText(_translate("MainWindow", "Set next"))
self.btnFade.setText(_translate("MainWindow", "Fade"))
self.btnStop.setText(_translate("MainWindow", "Stop"))
self.label_2.setText(_translate("MainWindow", "Started at:"))
self.label_start_tod.setText(_translate("MainWindow", "00:00:00"))
self.label_3.setText(_translate("MainWindow", "Silent at:"))
self.label_silent_tod.setText(_translate("MainWindow", "00:00:00"))
self.label_7.setText(_translate("MainWindow", "Fade length:"))
self.label_fade_length.setText(_translate("MainWindow", "0:00"))
self.label.setText(_translate("MainWindow", "Elapsed time"))
self.label_elapsed_timer.setText(_translate("MainWindow", "00:00"))
self.label_4.setText(_translate("MainWindow", "Fade"))
self.label_fade_timer.setText(_translate("MainWindow", "00:00"))
self.label_5.setText(_translate("MainWindow", "Silent"))
self.label_silent_timer.setText(_translate("MainWindow", "00:00"))
self.label_6.setText(_translate("MainWindow", "End"))
self.label_end_timer.setText(_translate("MainWindow", "00:00"))
self.menuFile.setTitle(_translate("MainWindow", "Fi&le"))
self.menuPlaylist.setTitle(_translate("MainWindow", "Pla&ylist"))
self.menu_Tracks.setTitle(_translate("MainWindow", "&Tracks"))
self.menuTest.setTitle(_translate("MainWindow", "TestMo&de"))
self.actionPlay_next.setText(_translate("MainWindow", "&Play next"))
self.actionPlay_next.setShortcut(_translate("MainWindow", "Return"))
self.actionSkip_next.setText(_translate("MainWindow", "Skip to &next"))
self.actionSkip_next.setShortcut(_translate("MainWindow", "Ctrl+Return"))
self.actionSearch_database.setText(_translate("MainWindow", "Search &database"))
self.actionSearch_database.setShortcut(_translate("MainWindow", "Ctrl+D"))
self.actionAdd_file.setText(_translate("MainWindow", "Add &file"))
self.actionAdd_file.setShortcut(_translate("MainWindow", "Ctrl+F"))
self.actionFade.setText(_translate("MainWindow", "F&ade"))
self.actionFade.setShortcut(_translate("MainWindow", "Ctrl+S"))
self.actionStop.setText(_translate("MainWindow", "S&top"))
self.action_Clear_selection.setText(_translate("MainWindow", "Clear &selection"))
self.action_Clear_selection.setShortcut(_translate("MainWindow", "Esc"))
self.action_Resume_previous.setText(_translate("MainWindow", "&Resume previous"))
self.actionE_xit.setText(_translate("MainWindow", "E&xit"))
self.actionTest.setText(_translate("MainWindow", "&Test"))
self.actionOpenPlaylist.setText(_translate("MainWindow", "O&pen..."))
self.actionNewPlaylist.setText(_translate("MainWindow", "&New..."))
self.actionTestFunction.setText(_translate("MainWindow", "&Test function"))
self.actionSkipToFade.setText(_translate("MainWindow", "&Skip to start of fade"))
self.actionSkipToEnd.setText(_translate("MainWindow", "Skip to &end of track"))
self.actionClosePlaylist.setText(_translate("MainWindow", "&Close"))
self.actionRenamePlaylist.setText(_translate("MainWindow", "&Rename..."))
self.actionDeletePlaylist.setText(_translate("MainWindow", "Dele&te..."))
self.actionMoveSelected.setText(_translate("MainWindow", "Mo&ve selected tracks to..."))
self.actionExport_playlist.setText(_translate("MainWindow", "E&xport playlist..."))
self.actionSetNext.setText(_translate("MainWindow", "Set &next"))
self.actionSetNext.setShortcut(_translate("MainWindow", "Ctrl+N"))
self.actionSelect_next_track.setText(_translate("MainWindow", "Select next track"))
self.actionSelect_next_track.setShortcut(_translate("MainWindow", "J"))
self.actionSelect_previous_track.setText(_translate("MainWindow", "Select previous track"))
self.actionSelect_previous_track.setShortcut(_translate("MainWindow", "K"))
self.actionSelect_played_tracks.setText(_translate("MainWindow", "Select played tracks"))
self.actionSelect_unplayed_tracks.setText(_translate("MainWindow", "Select unplayed tracks"))
import icons_rc

10
app/ui/playlist_ui.py Normal file
View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui/playlist.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.

80
audacity_control.py Normal file
View File

@ -0,0 +1,80 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Tests the audacity pipe.
Keep pipe_test.py short!!
You can make more complicated longer tests to test other functionality
or to generate screenshots etc in other scripts.
Make sure Audacity is running first and that mod-script-pipe is enabled
before running this script.
Requires Python 2.7 or later. Python 3 is strongly recommended.
"""
import os
import sys
if sys.platform == 'win32':
print("pipe-test.py, running on windows")
TONAME = '\\\\.\\pipe\\ToSrvPipe'
FROMNAME = '\\\\.\\pipe\\FromSrvPipe'
EOL = '\r\n\0'
else:
print("pipe-test.py, running on linux or mac")
TONAME = '/tmp/audacity_script_pipe.to.' + str(os.getuid())
FROMNAME = '/tmp/audacity_script_pipe.from.' + str(os.getuid())
EOL = '\n'
print("Write to \"" + TONAME + "\"")
if not os.path.exists(TONAME):
print(" does not exist. Ensure Audacity is running with mod-script-pipe.")
sys.exit()
print("Read from \"" + FROMNAME + "\"")
if not os.path.exists(FROMNAME):
print(" does not exist. Ensure Audacity is running with mod-script-pipe.")
sys.exit()
print("-- Both pipes exist. Good.")
TOFILE = open(TONAME, 'w')
print("-- File to write to has been opened")
FROMFILE = open(FROMNAME, 'rt')
print("-- File to read from has now been opened too\r\n")
def send_command(command):
"""Send a single command."""
print("Send: >>> \n"+command)
TOFILE.write(command + EOL)
TOFILE.flush()
def get_response():
"""Return the command response."""
result = ''
line = ''
while True:
result += line
line = FROMFILE.readline()
if line == '\n' and len(result) > 0:
break
return result
def do_command(command):
"""Send one command, and return the response."""
send_command(command)
response = get_response()
print("Rcvd: <<< \n" + response)
return response
def quick_test():
"""Example list of commands."""
do_command('Help: Command=Help')
do_command('Help: Command="GetInfo"')
# do_command('SetPreference: Name=GUI/Theme Value=classic Reload=1')
do_command('Import2: Filename=/home/kae/git/musicmuster/archive/boot.flac')

4
run_prod.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/bash
MYSQL_CONNECT="mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_prod"
ROOT="/home/kae/music"
./app/musicmuster.py