You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

253 lines
11 KiB

#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),
This is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import logging; logger = logging.getLogger(__name__); logger.info("import")
#Standard Library Modules
#Third Party Modules
from PyQt5 import QtWidgets, QtCore, QtGui
#Template
from template.qtgui.submenus import Submenu
import template.engine.midi as midi
from template.engine.pitch import simpleNoteNames
translatedNoteNames = simpleNoteNames[QtCore.QCoreApplication.translate("languageDictKey", "English")]
#Our Modules
import engine.api as api
#Small Widgets
class BarBeatTempoClock(QtWidgets.QWidget):
def __init__(self, mainWindow):
super().__init__(mainWindow)
layout = QtWidgets.QVBoxLayout()
layout.setSpacing(0)
#layout.setMargin(0)
layout.setContentsMargins(0,0,0,0)
self.clock = QtWidgets.QLabel()
self.bbt = QtWidgets.QLabel()
layout.addWidget(self.clock)
layout.addWidget(self.bbt)
self.setLayout(layout)
api.callbacks.barBeatTempo.append(self.updateLabel)
api.callbacks.clock.append(self.updateClock)
def updateClock(self, time:str):
self.clock.setText(time)
def updateLabel(self, exportDict):
if exportDict:
t = exportDict["tempo"]
time = exportDict["timesig"]
bar = exportDict["bar"]
beat = exportDict["beat"]
s = f"{bar}: {beat}\n\nbpm:\n{t}\n\n{time}"
self.bbt.setText(s)
else:
self.bbt.setText("")
#Submenus
class VelocityChange(Submenu):
def __init__(self, mainWindow):
super().__init__(mainWindow, QtCore.QCoreApplication.translate("submenus", "Change velocity of selected events.\nUse + or - for relative changes.\nWithout any sign results in one absolute value for all events."))
self.mainWindow = mainWindow
self.lineEdit = QtWidgets.QLineEdit()
self.layout.addWidget(self.lineEdit)
self.__call__()
def process(self):
text = self.lineEdit.text()
try:
value = int(text)
except ValueError:
value = None
if value:
listOfEngineIDs = self.mainWindow.scoreView.scoreScene.selectedItemsToListOfEngineIds()
if "+" in text or "-" in text:
api.changeVelocitiesRelative(listOfEngineIDs, value)
else: #absolute change
api.setVelocities(listOfEngineIDs, value)
self.done(True)
class CompressVelocity(Submenu):
def __init__(self, mainWindow):
super().__init__(mainWindow, QtCore.QCoreApplication.translate("submenus", "Compress velocity of selected events.\nGive lower and upper bounds."))
self.mainWindow = mainWindow
self.lowerBound = QtWidgets.QSpinBox()
self.lowerBound.setRange(0, 127)
self.lowerBound.setValue(0)
self.layout.addRow("Lower", self.lowerBound)
self.upperBound = QtWidgets.QSpinBox()
self.upperBound.setRange(0, 127)
self.upperBound.setValue(127)
self.layout.addRow("Upper", self.upperBound)
self.__call__()
def process(self):
if self.lowerBound.value() < self.upperBound.value():
low = self.lowerBound.value()
hi = self.upperBound.value()
else:
hi = self.lowerBound.value()
low = self.upperBound.value()
listOfEngineIDs = self.mainWindow.scoreView.scoreScene.selectedItemsToListOfEngineIds()
api.compressVelocities(listOfEngineIDs, low, hi)
self.done(True)
class CCSubmenu(Submenu):
"""Appears every time the user changes to CC input mode.
We use the GUI storage directly here and in inputCursor."""
def __init__(self, mainWindow):
super().__init__(mainWindow, QtCore.QCoreApplication.translate("submenus", "Choose a Control Change type."))
self.mainWindow = mainWindow
self.numberInput = QtWidgets.QSpinBox()
self.numberInput.setRange(0, 127)
self.numberInput.setValue(api.session.guiSharedDataToSave["lastCCtype"])
self.layout.addRow(QtCore.QCoreApplication.translate("submenus", "by number"), self.numberInput)
self.list = QtWidgets.QComboBox()
self.list.insertItems(0, midi.enumeratedCCList)
self.list.setCurrentIndex(api.session.guiSharedDataToSave["lastCCtype"])
self.layout.addRow(QtCore.QCoreApplication.translate("submenus", "by choice"), self.list)
self.numberInput.valueChanged.connect(self.list.setCurrentIndex)
self.list.currentIndexChanged.connect(self.numberInput.setValue)
self.__call__()
def process(self):
assert self.numberInput.value() == self.list.currentIndex()
api.session.guiSharedDataToSave["lastCCtype"] = self.numberInput.value() #used by the inputCursor directly
self.done(True)
class PolyAfterTouchSubmenu(Submenu):
"""Appears every time the user changes to PolyAftgertouch input mode to select a
corresponding pitch/key.
We use the GUI storage directly here and in inputCursor."""
def __init__(self, mainWindow):
super().__init__(mainWindow, QtCore.QCoreApplication.translate("submenus", "Choose a Control Change type."))
self.mainWindow = mainWindow
self.numberInput = QtWidgets.QSpinBox()
self.numberInput.setRange(0, 127)
self.numberInput.setValue(api.session.guiSharedDataToSave["lastPolyphonicAftertouchNote"])
self.layout.addRow(QtCore.QCoreApplication.translate("submenus", "by number"), self.numberInput)
self.list = QtWidgets.QComboBox()
self.list.insertItems(0, translatedNoteNames)
self.list.setCurrentIndex(api.session.guiSharedDataToSave["lastPolyphonicAftertouchNote"])
self.layout.addRow(QtCore.QCoreApplication.translate("submenus", "by choice"), self.list)
self.numberInput.valueChanged.connect(self.list.setCurrentIndex)
self.list.currentIndexChanged.connect(self.numberInput.setValue)
self.__call__()
def process(self):
assert self.numberInput.value() == self.list.currentIndex()
api.session.guiSharedDataToSave["lastPolyphonicAftertouchNote"] = self.numberInput.value() #used by the inputCursor directly
self.done(True)
class EventFilterAndMover(Submenu):
def __init__(self, mainWindow, allLayers):
super().__init__(mainWindow, QtCore.QCoreApplication.translate("submenus", "Filter and Move Events"))
self.mainWindow = mainWindow
self.allLayers = allLayers
if allLayers:
self.layout.addRow(QtCore.QCoreApplication.translate("submenus", "Source Layer"), QtWidgets.QLabel(QtCore.QCoreApplication.translate("submenus", "All")))
else:
self.sourceLayer = QtWidgets.QSpinBox()
self.sourceLayer.setRange(0, 9)
self.sourceLayer.setValue(api.getActiveLayer())
self.layout.addRow(QtCore.QCoreApplication.translate("submenus", "Source Layer"), self.sourceLayer)
self.targetLayer = QtWidgets.QSpinBox()
self.targetLayer.setRange(0, 9)
if allLayers:
self.targetLayer.setValue(api.getActiveLayer())
else:
self.targetLayer.setValue(0)
self.layout.addRow(QtCore.QCoreApplication.translate("submenus", "Target Layer"), self.targetLayer)
typeDict = api.statusToName.copy()
del typeDict[0x90]
del typeDict[0x80]
typeDict[0x90] = "Note"
self.statusByte = QtWidgets.QComboBox()
for status, name in sorted(typeDict.items()):
self.statusByte.addItem(name, userData = status)
#self.statusByte.setCurrentIndex(api.session.guiShardDataToSave["lastCCtype"])
self.layout.addRow(QtCore.QCoreApplication.translate("submenus", "Event Type"), self.statusByte)
self.byte1Minimum = QtWidgets.QSpinBox()
self.byte1Minimum.setRange(0, 127)
self.byte1Minimum.setValue(0)
self.layout.addRow(QtCore.QCoreApplication.translate("submenus", "Byte 1 Minimum"), self.byte1Minimum)
self.byte1Maximum = QtWidgets.QSpinBox()
self.byte1Maximum.setRange(0, 127)
self.byte1Maximum.setValue(127)
self.layout.addRow(QtCore.QCoreApplication.translate("submenus", "Byte 1 Maximum"), self.byte1Maximum)
self.byte2Minimum = QtWidgets.QSpinBox()
self.byte2Minimum.setRange(0, 127)
self.byte2Minimum.setValue(0)
self.layout.addRow(QtCore.QCoreApplication.translate("submenus", "Byte2 Minimum"), self.byte2Minimum)
self.byte2Maximum = QtWidgets.QSpinBox()
self.byte2Maximum.setRange(0, 127)
self.byte2Maximum.setValue(127)
self.layout.addRow(QtCore.QCoreApplication.translate("submenus", "Byte2 Maximum"), self.byte2Maximum)
self.__call__()
def process(self):
if self.allLayers:
api.filterAndMoveAllLayers(self.targetLayer.value(), self.statusByte.currentData(), self.byte1Minimum.value(), self.byte1Maximum.value(), self.byte2Minimum.value(), self.byte2Maximum.value())
else:
api.layerFilterAndMove(self.sourceLayer.value(), self.targetLayer.value(), self.statusByte.currentData(), self.byte1Minimum.value(), self.byte1Maximum.value(), self.byte2Minimum.value(), self.byte2Maximum.value())
self.done(True)