aboutsummaryrefslogtreecommitdiffstats
path: root/solo_tool_qt.py
diff options
context:
space:
mode:
authorEddy Pedroni <epedroni@pm.me>2024-11-09 20:35:56 +0100
committerEddy Pedroni <epedroni@pm.me>2024-11-09 20:35:56 +0100
commitcda8197669409689be291660f93cb288ab2d31b3 (patch)
tree81db9b0c7c0491e0737cbffb39af6b935c0dfeb8 /solo_tool_qt.py
parenta2257a900d4fffd6f94b73f1c48c62370ed1d684 (diff)
Migrate to project-based structure
Diffstat (limited to 'solo_tool_qt.py')
-rw-r--r--solo_tool_qt.py258
1 files changed, 0 insertions, 258 deletions
diff --git a/solo_tool_qt.py b/solo_tool_qt.py
deleted file mode 100644
index 86557a7..0000000
--- a/solo_tool_qt.py
+++ /dev/null
@@ -1,258 +0,0 @@
-import sys
-
-from PyQt5.QtGui import *
-from PyQt5.QtWidgets import *
-from PyQt5.QtCore import *
-from MainWindow import Ui_MainWindow
-
-from solo_tool import SoloTool
-from midi_controller_launchpad_mini import MidiController
-
-POSITION_FACTOR = 100000
-RATE_FACTOR = 10
-UI_REFRESH_PERIOD_MS = 500
-
-CHANGE_GUI = 0
-CHANGE_INTERNAL = 1
-
-class PlaylistModel(QAbstractListModel):
- def __init__(self, soloTool, *args, **kwargs):
- super(PlaylistModel, self).__init__(*args, **kwargs)
- self.soloTool = soloTool
-
- def data(self, index, role):
- if role == Qt.DisplayRole:
- from pathlib import Path
- path = Path(self.soloTool.getSongs()[index.row()])
- return path.name
-
- def rowCount(self, index):
- return len(self.soloTool.getSongs())
-
-class ABListModel(QAbstractListModel):
- def __init__(self, soloTool, *args, **kwargs):
- super(ABListModel, self).__init__(*args, **kwargs)
- self.soloTool = soloTool
-
- def data(self, index, role):
- if role == Qt.DisplayRole:
- ab = self.soloTool.getStoredAbLimits()[index.row()]
- return f"{ab[0]} - {ab[1]}"
-
- def rowCount(self, index):
- return len(self.soloTool.getStoredAbLimits())
-
-class MainWindow(QMainWindow, Ui_MainWindow):
- songChangeSignal = pyqtSignal(int)
- abLimitsChangeSignal = pyqtSignal(int)
-
- def __init__(self, *args, **kwargs):
- super(MainWindow, self).__init__(*args, **kwargs)
-
- self.setupUi(self)
-
- self.timer = QTimer(self)
- self.timer.setInterval(UI_REFRESH_PERIOD_MS)
- self.timer.timeout.connect(self.timerCallback)
-
- self.soloTool = SoloTool()
- self.midiController = MidiController(self.soloTool)
-
- self.playlistModel = PlaylistModel(self.soloTool)
- self.songListView.setModel(self.playlistModel)
- self.songListView.selectionModel().selectionChanged.connect(self.playlistSelectionChanged)
- self.songChangePending = None
- self.songChangeSignal.connect(self.currentSongChanged)
- self.soloTool.registerCurrentSongCallback(self.songChangeSignal.emit)
-
- self.abListModel = ABListModel(self.soloTool)
- self.abListView.setModel(self.abListModel)
- self.abListView.selectionModel().selectionChanged.connect(self.abListSelectionChanged)
- self.abLimitsChangePending = None
- self.abLimitsChangeSignal.connect(self.currentAbLimitsChanged)
- self.soloTool.registerCurrentAbLimitsCallback(self.abLimitsChangeSignal.emit)
-
- self.songSlider.setMaximum(POSITION_FACTOR)
- self.songSlider.sliderPressed.connect(self.songSliderPressed)
- self.songSlider.sliderReleased.connect(self.songSliderReleased)
-
- self.aSlider.setMaximum(POSITION_FACTOR)
- self.aSlider.sliderReleased.connect(self.abSliderReleased)
- self.bSlider.setMaximum(POSITION_FACTOR)
- self.bSlider.sliderReleased.connect(self.abSliderReleased)
-
- self.rateSlider.setRange(int(0.5 * RATE_FACTOR), int(1.2 * RATE_FACTOR))
- self.rateSlider.setSingleStep(int(0.1 * RATE_FACTOR))
- self.rateSlider.setValue(int(1.0 * RATE_FACTOR))
- self.rateSlider.sliderReleased.connect(self.rateSliderReleased)
-
- self.playButton.pressed.connect(self.soloTool.play)
- self.pauseButton.pressed.connect(self.soloTool.pause)
- self.storeAbButton.pressed.connect(self.storeAbLimits)
- self.setAButton.pressed.connect(self.setA)
- self.setBButton.pressed.connect(self.setB)
- self.saveSessionButton.pressed.connect(self.saveSession)
- self.loadSessionButton.pressed.connect(self.loadSession)
- self.addSongButton.pressed.connect(self.addSong)
- self.abRepeatCheckBox.clicked.connect(self.toggleAbRepeat)
- self.initMidiButton.pressed.connect(self.initMidi)
-
- self.timer.start()
-
- if len(sys.argv) > 1:
- self.loadSession(sys.argv[1])
-
- self.show()
-
- def timerCallback(self):
- position = self.soloTool.getPlaybackPosition() * POSITION_FACTOR
- self.songSlider.setValue(int(position))
- self.soloTool.tick()
-
- def addSong(self):
- path, _ = QFileDialog.getOpenFileName(self, "Open file", "", "mp3 Audio (*.mp3);FLAC audio (*.flac);All files (*.*)")
- if path:
- self.soloTool.addSong(path)
- self.playlistModel.layoutChanged.emit()
-
- def storeAbLimits(self):
- a = self.aSlider.value() / float(POSITION_FACTOR)
- b = self.bSlider.value() / float(POSITION_FACTOR)
- self.soloTool.storeAbLimits(a, b)
- self.abListModel.layoutChanged.emit()
-
- def setA(self):
- position = self.songSlider.value()
- self.aSlider.setValue(position)
- self.abSliderReleased()
-
- def setB(self):
- position = self.songSlider.value()
- self.bSlider.setValue(position)
- self.abSliderReleased()
-
- def toggleAbRepeat(self):
- enable = self.abRepeatCheckBox.isChecked()
- self.soloTool.setAbLimitEnable(enable)
-
- def saveSession(self):
- path, _ = QFileDialog.getSaveFileName(self, "Open file", "", "session file (*.json)")
- if path:
- self.soloTool.saveSession(path)
-
- def loadSession(self, path=None):
- if path is None:
- path, _ = QFileDialog.getOpenFileName(self, "Open file", "", "session file (*.json)")
- if path is not None:
- self.soloTool.loadSession(path)
- self.playlistModel.layoutChanged.emit()
- self.abListModel.layoutChanged.emit()
-
- def songSliderPressed(self):
- self.timer.stop()
-
- def songSliderReleased(self):
- position = self.songSlider.value() / float(POSITION_FACTOR)
- self.soloTool.setPlaybackPosition(position)
- self.timer.start()
-
- def clearListViewSelection(self, listView):
- i = listView.selectionModel().currentIndex()
- listView.selectionModel().select(i, QItemSelectionModel.Deselect)
-
- def abSliderReleased(self):
- a = self.aSlider.value() / float(POSITION_FACTOR)
- b = self.bSlider.value() / float(POSITION_FACTOR)
- self.soloTool.setAbLimits(a, b)
- self.clearListViewSelection(self.abListView)
-
- def rateSliderReleased(self):
- rate = self.rateSlider.value() / float(RATE_FACTOR)
- self.soloTool.setPlaybackRate(rate)
-
- def playlistSelectionChanged(self, i):
- if self.songChangePending == CHANGE_INTERNAL:
- self.songChangePending = None
- else:
- assert self.songChangePending is None
- self.songChangePending = CHANGE_GUI
- index = i.indexes()[0].row()
- self.soloTool.setSong(index)
-
- self.clearListViewSelection(self.abListView)
- self.abListModel.layoutChanged.emit()
-
- def currentSongChanged(self, songIndex):
- if self.songChangePending == CHANGE_GUI:
- self.songChangePending = None
- else:
- assert self.songChangePending is None
- self.songChangePending = CHANGE_INTERNAL
- i = self.playlistModel.createIndex(songIndex, 0)
- self.songListView.selectionModel().select(i, QItemSelectionModel.ClearAndSelect)
-
- def abListSelectionChanged(self, i):
- if self.abLimitsChangePending == CHANGE_INTERNAL:
- print("Ack internal change")
- self.abLimitsChangePending = None
- else:
- assert self.abLimitsChangePending is None
- if i is not None and not i.isEmpty():
- print("Processing GUI change")
- self.abLimitsChangePending = CHANGE_GUI
- index = i.indexes()[0].row()
- ab = self.soloTool.getStoredAbLimits()[index]
- self.soloTool.loadAbLimits(index)
- self.aSlider.setValue(int(ab[0] * POSITION_FACTOR))
- self.bSlider.setValue(int(ab[1] * POSITION_FACTOR))
-
- def currentAbLimitsChanged(self, abIndex):
- if self.abLimitsChangePending == CHANGE_GUI:
- print("Ack GUI change")
- self.abLimitsChangePending = None
- else:
- assert self.abLimitsChangePending is None
- print("Processing internal change")
- self.abLimitsChangePending = CHANGE_INTERNAL
- i = self.abListModel.createIndex(abIndex, 0)
- self.abListView.selectionModel().select(i, QItemSelectionModel.ClearAndSelect)
- ab = self.soloTool.getStoredAbLimits()[abIndex]
- self.aSlider.setValue(int(ab[0] * POSITION_FACTOR))
- self.bSlider.setValue(int(ab[1] * POSITION_FACTOR))
-
- def initMidi(self):
- try:
- self.midiController.connect()
- except Exception as e:
- print("Error: could not connect to MIDI controller")
- print(e)
-
- def keyPressEvent(self, event):
- if event.key() == Qt.Key_Super_L:
- self.soloTool.jumpToA()
-
-if __name__ == '__main__':
- app = QApplication([])
- app.setApplicationName("Solo Tool")
- app.setStyle("Fusion")
-
- # Fusion dark palette from https://gist.github.com/QuantumCD/6245215.
- palette = QPalette()
- palette.setColor(QPalette.Window, QColor(53, 53, 53))
- palette.setColor(QPalette.WindowText, Qt.white)
- palette.setColor(QPalette.Base, QColor(25, 25, 25))
- palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
- palette.setColor(QPalette.ToolTipBase, Qt.white)
- palette.setColor(QPalette.ToolTipText, Qt.white)
- palette.setColor(QPalette.Text, Qt.white)
- palette.setColor(QPalette.Button, QColor(53, 53, 53))
- palette.setColor(QPalette.ButtonText, Qt.white)
- palette.setColor(QPalette.BrightText, Qt.red)
- palette.setColor(QPalette.Link, QColor(42, 130, 218))
- palette.setColor(QPalette.Highlight, QColor(42, 130, 218))
- palette.setColor(QPalette.HighlightedText, Qt.black)
- app.setPalette(palette)
- app.setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }")
-
- window = MainWindow()
- app.exec_()