diff options
| author | Eddy Pedroni <epedroni@pm.me> | 2025-02-25 09:30:59 +0100 | 
|---|---|---|
| committer | Eddy Pedroni <epedroni@pm.me> | 2025-02-25 09:30:59 +0100 | 
| commit | 5f6d352aaa4c1273d95a740768c0079ae02005c5 (patch) | |
| tree | 8e46db6ec28b329fdaa8de68a0bf57c72723c5e7 | |
| parent | 625d7c970dc6cdacc8768bb4ae486009096f2191 (diff) | |
Remove legacy gui, update makefile and readme
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | gui-project/pyproject.toml | 24 | ||||
| -rw-r--r-- | gui-project/src/MainWindow.py | 111 | ||||
| -rw-r--r-- | gui-project/src/mainwindow.ui | 161 | ||||
| -rw-r--r-- | gui-project/src/solo_tool_gui.py | 265 | ||||
| -rw-r--r-- | pacman.txt | 6 | ||||
| -rw-r--r-- | readme.md | 8 | ||||
| -rw-r--r-- | requirements.txt | 1 | 
8 files changed, 9 insertions, 569 deletions
| @@ -11,7 +11,7 @@ clean:  .venv: .venv/touchfile -.venv/touchfile: requirements.txt solo-tool-project/pyproject.toml cli-project/pyproject.toml gui-project/pyproject.toml +.venv/touchfile: requirements.txt solo-tool-project/pyproject.toml cli-project/pyproject.toml web-project/pyproject.toml  	rm -rf venv  	uv venv  	uv pip install -r requirements.txt diff --git a/gui-project/pyproject.toml b/gui-project/pyproject.toml deleted file mode 100644 index 1e6fcf4..0000000 --- a/gui-project/pyproject.toml +++ /dev/null @@ -1,24 +0,0 @@ -[build-system] -requires = ["setuptools"] -build-backend = "setuptools.build_meta" - -[project] -name = "solo_tool_gui" -authors = [ -    { name = "Eddy Pedroni", email = "epedroni@pm.me" }, -] -description = "A Qt5-based GUI frontend for the solo_tool library" -requires-python = ">=3.12" -dependencies = [ -    "PyQt5>=5.6", -    "solo_tool" -] -dynamic = ["version"] - -[project.optional-dependencies] -dev = [ -] - -[project.gui-scripts] -solo-tool-gui = "solo_tool_gui:main" - diff --git a/gui-project/src/MainWindow.py b/gui-project/src/MainWindow.py deleted file mode 100644 index 137bd33..0000000 --- a/gui-project/src/MainWindow.py +++ /dev/null @@ -1,111 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'mainwindow.ui' -# -# Created by: PyQt5 UI code generator 5.15.6 -# -# 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(971, 767) -        self.centralwidget = QtWidgets.QWidget(MainWindow) -        self.centralwidget.setObjectName("centralwidget") -        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget) -        self.verticalLayout.setObjectName("verticalLayout") -        self.listsLayout = QtWidgets.QHBoxLayout() -        self.listsLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) -        self.listsLayout.setSpacing(6) -        self.listsLayout.setObjectName("listsLayout") -        self.songListView = QtWidgets.QListView(self.centralwidget) -        self.songListView.setObjectName("songListView") -        self.listsLayout.addWidget(self.songListView) -        self.abListView = QtWidgets.QListView(self.centralwidget) -        self.abListView.setObjectName("abListView") -        self.listsLayout.addWidget(self.abListView) -        self.verticalLayout.addLayout(self.listsLayout) -        self.slidersLayout = QtWidgets.QVBoxLayout() -        self.slidersLayout.setObjectName("slidersLayout") -        self.songSlider = QtWidgets.QSlider(self.centralwidget) -        self.songSlider.setMinimumSize(QtCore.QSize(0, 0)) -        self.songSlider.setOrientation(QtCore.Qt.Horizontal) -        self.songSlider.setObjectName("songSlider") -        self.slidersLayout.addWidget(self.songSlider) -        self.aSlider = QtWidgets.QSlider(self.centralwidget) -        self.aSlider.setOrientation(QtCore.Qt.Horizontal) -        self.aSlider.setObjectName("aSlider") -        self.slidersLayout.addWidget(self.aSlider) -        self.bSlider = QtWidgets.QSlider(self.centralwidget) -        self.bSlider.setOrientation(QtCore.Qt.Horizontal) -        self.bSlider.setObjectName("bSlider") -        self.slidersLayout.addWidget(self.bSlider) -        self.verticalLayout.addLayout(self.slidersLayout) -        self.buttonsLayout = QtWidgets.QGridLayout() -        self.buttonsLayout.setObjectName("buttonsLayout") -        self.pauseButton = QtWidgets.QPushButton(self.centralwidget) -        self.pauseButton.setObjectName("pauseButton") -        self.buttonsLayout.addWidget(self.pauseButton, 0, 1, 1, 1) -        self.initMidiButton = QtWidgets.QPushButton(self.centralwidget) -        self.initMidiButton.setObjectName("initMidiButton") -        self.buttonsLayout.addWidget(self.initMidiButton, 0, 4, 1, 1) -        self.rateSlider = QtWidgets.QSlider(self.centralwidget) -        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) -        sizePolicy.setHorizontalStretch(0) -        sizePolicy.setVerticalStretch(0) -        sizePolicy.setHeightForWidth(self.rateSlider.sizePolicy().hasHeightForWidth()) -        self.rateSlider.setSizePolicy(sizePolicy) -        self.rateSlider.setOrientation(QtCore.Qt.Horizontal) -        self.rateSlider.setObjectName("rateSlider") -        self.buttonsLayout.addWidget(self.rateSlider, 2, 0, 1, 1) -        self.playButton = QtWidgets.QPushButton(self.centralwidget) -        self.playButton.setObjectName("playButton") -        self.buttonsLayout.addWidget(self.playButton, 0, 0, 1, 1) -        self.saveSessionButton = QtWidgets.QPushButton(self.centralwidget) -        self.saveSessionButton.setObjectName("saveSessionButton") -        self.buttonsLayout.addWidget(self.saveSessionButton, 0, 2, 1, 1) -        self.storeAbButton = QtWidgets.QPushButton(self.centralwidget) -        self.storeAbButton.setObjectName("storeAbButton") -        self.buttonsLayout.addWidget(self.storeAbButton, 2, 3, 1, 1) -        self.loadSessionButton = QtWidgets.QPushButton(self.centralwidget) -        self.loadSessionButton.setObjectName("loadSessionButton") -        self.buttonsLayout.addWidget(self.loadSessionButton, 0, 3, 1, 1) -        self.abRepeatCheckBox = QtWidgets.QCheckBox(self.centralwidget) -        self.abRepeatCheckBox.setObjectName("abRepeatCheckBox") -        self.buttonsLayout.addWidget(self.abRepeatCheckBox, 2, 1, 1, 1) -        self.addSongButton = QtWidgets.QPushButton(self.centralwidget) -        self.addSongButton.setObjectName("addSongButton") -        self.buttonsLayout.addWidget(self.addSongButton, 2, 4, 1, 1) -        self.horizontalLayout = QtWidgets.QHBoxLayout() -        self.horizontalLayout.setObjectName("horizontalLayout") -        self.setAButton = QtWidgets.QPushButton(self.centralwidget) -        self.setAButton.setObjectName("setAButton") -        self.horizontalLayout.addWidget(self.setAButton) -        self.setBButton = QtWidgets.QPushButton(self.centralwidget) -        self.setBButton.setObjectName("setBButton") -        self.horizontalLayout.addWidget(self.setBButton) -        self.buttonsLayout.addLayout(self.horizontalLayout, 2, 2, 1, 1) -        self.verticalLayout.addLayout(self.buttonsLayout) -        MainWindow.setCentralWidget(self.centralwidget) - -        self.retranslateUi(MainWindow) -        QtCore.QMetaObject.connectSlotsByName(MainWindow) - -    def retranslateUi(self, MainWindow): -        _translate = QtCore.QCoreApplication.translate -        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) -        self.pauseButton.setText(_translate("MainWindow", "Pause")) -        self.initMidiButton.setText(_translate("MainWindow", "Connect MIDI")) -        self.playButton.setText(_translate("MainWindow", "Play")) -        self.saveSessionButton.setText(_translate("MainWindow", "Save session")) -        self.storeAbButton.setText(_translate("MainWindow", "Store AB")) -        self.loadSessionButton.setText(_translate("MainWindow", "Load session")) -        self.abRepeatCheckBox.setText(_translate("MainWindow", "AB repeat")) -        self.addSongButton.setText(_translate("MainWindow", "Add song")) -        self.setAButton.setText(_translate("MainWindow", "Set A")) -        self.setBButton.setText(_translate("MainWindow", "Set B")) diff --git a/gui-project/src/mainwindow.ui b/gui-project/src/mainwindow.ui deleted file mode 100644 index ac4d97b..0000000 --- a/gui-project/src/mainwindow.ui +++ /dev/null @@ -1,161 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>MainWindow</class> - <widget class="QMainWindow" name="MainWindow"> -  <property name="geometry"> -   <rect> -    <x>0</x> -    <y>0</y> -    <width>971</width> -    <height>767</height> -   </rect> -  </property> -  <property name="windowTitle"> -   <string>MainWindow</string> -  </property> -  <widget class="QWidget" name="centralwidget"> -   <layout class="QVBoxLayout" name="verticalLayout"> -    <item> -     <layout class="QHBoxLayout" name="listsLayout"> -      <property name="spacing"> -       <number>6</number> -      </property> -      <property name="sizeConstraint"> -       <enum>QLayout::SetDefaultConstraint</enum> -      </property> -      <item> -       <widget class="QListView" name="songListView"/> -      </item> -      <item> -       <widget class="QListView" name="abListView"/> -      </item> -     </layout> -    </item> -    <item> -     <layout class="QVBoxLayout" name="slidersLayout"> -      <item> -       <widget class="QSlider" name="songSlider"> -        <property name="minimumSize"> -         <size> -          <width>0</width> -          <height>0</height> -         </size> -        </property> -        <property name="orientation"> -         <enum>Qt::Horizontal</enum> -        </property> -       </widget> -      </item> -      <item> -       <widget class="QSlider" name="aSlider"> -        <property name="orientation"> -         <enum>Qt::Horizontal</enum> -        </property> -       </widget> -      </item> -      <item> -       <widget class="QSlider" name="bSlider"> -        <property name="orientation"> -         <enum>Qt::Horizontal</enum> -        </property> -       </widget> -      </item> -     </layout> -    </item> -    <item> -     <layout class="QGridLayout" name="buttonsLayout"> -      <item row="0" column="1"> -       <widget class="QPushButton" name="pauseButton"> -        <property name="text"> -         <string>Pause</string> -        </property> -       </widget> -      </item> -      <item row="0" column="4"> -       <widget class="QPushButton" name="initMidiButton"> -        <property name="text"> -         <string>Connect MIDI</string> -        </property> -       </widget> -      </item> -      <item row="2" column="0"> -       <widget class="QSlider" name="rateSlider"> -        <property name="sizePolicy"> -         <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> -          <horstretch>0</horstretch> -          <verstretch>0</verstretch> -         </sizepolicy> -        </property> -        <property name="orientation"> -         <enum>Qt::Horizontal</enum> -        </property> -       </widget> -      </item> -      <item row="0" column="0"> -       <widget class="QPushButton" name="playButton"> -        <property name="text"> -         <string>Play</string> -        </property> -       </widget> -      </item> -      <item row="0" column="2"> -       <widget class="QPushButton" name="saveSessionButton"> -        <property name="text"> -         <string>Save session</string> -        </property> -       </widget> -      </item> -      <item row="2" column="3"> -       <widget class="QPushButton" name="storeAbButton"> -        <property name="text"> -         <string>Store AB</string> -        </property> -       </widget> -      </item> -      <item row="0" column="3"> -       <widget class="QPushButton" name="loadSessionButton"> -        <property name="text"> -         <string>Load session</string> -        </property> -       </widget> -      </item> -      <item row="2" column="1"> -       <widget class="QCheckBox" name="abRepeatCheckBox"> -        <property name="text"> -         <string>AB repeat</string> -        </property> -       </widget> -      </item> -      <item row="2" column="4"> -       <widget class="QPushButton" name="addSongButton"> -        <property name="text"> -         <string>Add song</string> -        </property> -       </widget> -      </item> -      <item row="2" column="2"> -       <layout class="QHBoxLayout" name="horizontalLayout"> -        <item> -         <widget class="QPushButton" name="setAButton"> -          <property name="text"> -           <string>Set A</string> -          </property> -         </widget> -        </item> -        <item> -         <widget class="QPushButton" name="setBButton"> -          <property name="text"> -           <string>Set B</string> -          </property> -         </widget> -        </item> -       </layout> -      </item> -     </layout> -    </item> -   </layout> -  </widget> - </widget> - <resources/> - <connections/> -</ui> diff --git a/gui-project/src/solo_tool_gui.py b/gui-project/src/solo_tool_gui.py deleted file mode 100644 index cd73c9a..0000000 --- a/gui-project/src/solo_tool_gui.py +++ /dev/null @@ -1,265 +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 solo_tool.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() - -    def closeEvent(self, event): -        self.midiController.disconnect() -        event.accept() - -def 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_() - -if __name__ == '__main__': -    main() @@ -1,6 +1,8 @@  pkgconf  gst-plugins-good -qt5-multimedia - +For VLC backend:  vlc + +For mplayer backend: +mplayer @@ -10,16 +10,16 @@ Non-Python dependencies are listed in pacman.txt and should be manually installe  ## Usage -To set up the environment and run the tests, just use `make`: +To set up the environment and run the tests, run `make`:  ```  make  ``` -The GUI can then be executed in the venv: +The web GUI can also be run with `make`:  ``` -./venv/bin/solo_tool_gui +make gui  ```  Alternatively, the tool can be executed in headless mode. In this case all it does is load the provided session and connect to the MIDI controller: @@ -30,7 +30,7 @@ Alternatively, the tool can be executed in headless mode. In this case all it do  ## MIDI -It is currently possible to control the tool with MIDI. With the device plugged in, a connection can be established by clicking on "Connect MIDI" in the GUI or running the headless binary. Currently the only device supported is the Novation Launchpad Mini Mk II. +It is currently possible to control the tool with MIDI. With the device plugged in, a connection is automatically established by the CLI. Currently the only device supported is the Novation Launchpad Mini Mk II.  The MIDI device button mapping is documented in `doc/diagram.drawio`. diff --git a/requirements.txt b/requirements.txt index 7c19832..459ff68 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@  -e solo-tool-project[dev]  -e cli-project[dev] --e gui-project[dev]  -e web-project[dev] | 
