Browse Source

stuff

master
Nils 5 years ago
parent
commit
9f55bb5e55
  1. BIN
      desktop/icon32x32.png
  2. 21
      engine/api.py
  3. 8
      engine/main.py
  4. 20
      engine/pattern.py
  5. 7
      engine/track.py
  6. 26
      qtgui/pattern_grid.py
  7. 7455
      qtgui/resources.py
  8. BIN
      qtgui/resources/aboutlogo.png
  9. BIN
      qtgui/resources/icon.png

BIN
desktop/icon32x32.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 942 B

After

Width:  |  Height:  |  Size: 575 B

21
engine/api.py

@ -168,19 +168,21 @@ def startEngine(nsmClient):
callbacks._subdivisionsChanged() callbacks._subdivisionsChanged()
callbacks._quarterNotesPerMinuteChanged() callbacks._quarterNotesPerMinuteChanged()
session.eventLoop.fastConnect(cbox.call_on_idle)
for track in session.data.tracks: for track in session.data.tracks:
callbacks._trackMetaDataChanged(track) #for colors, scale and noteNames callbacks._trackMetaDataChanged(track) #for colors, scale and simpleNoteNames
session.data.buildAllTracks() session.data.buildAllTracks()
updatePlayback() updatePlayback()
cbox.Transport.stop()
seek(0)
def toggleLoop(): def toggleLoop():
"""Plays the current measure as loop. """Plays the current measure as loop.
Current measure is where the playback cursor is""" Current measure is where the playback cursor is
session.inLoopMode is a tuple (start, end)
"""
if session.inLoopMode: if session.inLoopMode:
session.data.buildSongDuration() #no parameter removes the loop session.data.buildSongDuration() #no parameter removes the loop
updatePlayback() updatePlayback()
@ -189,6 +191,7 @@ def toggleLoop():
else: else:
now = loopMeasureAroundPpqn=cbox.Transport.status().pos_ppqn now = loopMeasureAroundPpqn=cbox.Transport.status().pos_ppqn
loopStart, loopEnd = session.data.buildSongDuration(now) loopStart, loopEnd = session.data.buildSongDuration(now)
updatePlayback() updatePlayback()
session.inLoopMode = (loopStart, loopEnd) session.inLoopMode = (loopStart, loopEnd)
@ -211,7 +214,7 @@ def seek(value):
cbox.Transport.seek_ppqn(value) cbox.Transport.seek_ppqn(value)
##Score ##Score
def set_quarterNotesPerMinute(value): def set_quarterNotesPerMinute(value:int):
if value is None: if value is None:
session.data.tempoMap.isTransportMaster = False #triggers rebuild session.data.tempoMap.isTransportMaster = False #triggers rebuild
elif value == "on": elif value == "on":
@ -300,7 +303,7 @@ def createSiblingTrack(trackId):
(if any)""" (if any)"""
track = session.data.trackById(trackId) track = session.data.trackById(trackId)
assert type(track.pattern.scale) == tuple assert type(track.pattern.scale) == tuple
newTrack = session.data.addTrack(name=track.sequencerInterface.name, scale=track.pattern.scale, color=track.color, noteNames=track.pattern.noteNames) #track name increments itself from "Track A" to "Track B" or "Track 1" -> "Track 2" newTrack = session.data.addTrack(name=track.sequencerInterface.name, scale=track.pattern.scale, color=track.color, simpleNoteNames=track.pattern.simpleNoteNames) #track name increments itself from "Track A" to "Track B" or "Track 1" -> "Track 2"
newTrack.pattern.averageVelocity = track.pattern.averageVelocity newTrack.pattern.averageVelocity = track.pattern.averageVelocity
jackConnections = cbox.JackIO.get_connected_ports(track.sequencerInterface.cboxPortName()) jackConnections = cbox.JackIO.get_connected_ports(track.sequencerInterface.cboxPortName())
for port in jackConnections: for port in jackConnections:
@ -511,11 +514,11 @@ def setScale(trackId, scale):
updatePlayback() updatePlayback()
callbacks._trackMetaDataChanged(track) callbacks._trackMetaDataChanged(track)
def setNoteNames(trackId, noteNames): def setSimpleNoteNames(trackId, simpleNoteNames):
"""note names is a list of strings with length 128. One name for each midi note. """note names is a list of strings with length 128. One name for each midi note.
It is saved to file""" It is saved to file"""
track = session.data.trackById(trackId) track = session.data.trackById(trackId)
track.pattern.noteNames = noteNames track.pattern.simpleNoteNames = simpleNoteNames
callbacks._trackMetaDataChanged(track) callbacks._trackMetaDataChanged(track)
def transposeHalftoneSteps(trackId, steps): def transposeHalftoneSteps(trackId, steps):

8
engine/main.py

@ -31,7 +31,7 @@ from calfbox import cbox
from template.engine.data import Data as TemplateData from template.engine.data import Data as TemplateData
import template.engine.sequencer import template.engine.sequencer
from template.engine.duration import D4 from template.engine.duration import D4
from template.engine.pitch import noteNames from template.engine.pitch import simpleNoteNames
#Our modules #Our modules
from .track import Track from .track import Track
@ -56,7 +56,7 @@ class Data(template.engine.sequencer.Score):
self.numberOfMeasures = 64 self.numberOfMeasures = 64
self.measuresPerGroup = 8 # meta data, has no effect on playback. self.measuresPerGroup = 8 # meta data, has no effect on playback.
self.subdivisions = 1 self.subdivisions = 1
self.lastUsedNotenames = noteNames["English"] #The default value for new tracks/patterns. Changed each time the user picks a new representation via api.setNoteNames . noteNames are saved with the patterns. self.lastUsedNotenames = simpleNoteNames["English"] #The default value for new tracks/patterns. Changed each time the user picks a new representation via api.setNoteNames . noteNames are saved with the patterns.
self.addTrack(name="Melody A", color="#ffff00") self.addTrack(name="Melody A", color="#ffff00")
self.tracks[0].structure=set((0,)) #Already have the first pattern activated, so 'play' after startup already produces sounding notes. This is less confusing for a new user. self.tracks[0].structure=set((0,)) #Already have the first pattern activated, so 'play' after startup already produces sounding notes. This is less confusing for a new user.
@ -68,9 +68,9 @@ class Data(template.engine.sequencer.Score):
def _processAfterInit(self): def _processAfterInit(self):
pass pass
def addTrack(self, name="", scale=None, color=None, noteNames=None): def addTrack(self, name="", scale=None, color=None, simpleNoteNames=None):
"""Overrides the simpler template version""" """Overrides the simpler template version"""
track = Track(parentScore=self, name=name, scale=scale, color=color, noteNames=noteNames) track = Track(parentScore=self, name=name, scale=scale, color=color, simpleNoteNames=simpleNoteNames)
self.tracks.append(track) self.tracks.append(track)
return track return track

20
engine/pattern.py

@ -48,12 +48,12 @@ class Pattern(object):
The pattern has always its maximum length. The pattern has always its maximum length.
""" """
def __init__(self, parentTrack, data:List[dict]=None, scale:Tuple[int]=None, noteNames:List[str]=None): def __init__(self, parentTrack, data:List[dict]=None, scale:Tuple[int]=None, simpleNoteNames:List[str]=None):
self._prepareBeforeInit() self._prepareBeforeInit()
self.parentTrack = parentTrack self.parentTrack = parentTrack
self.scale = scale if scale else (72, 71, 69, 67, 65, 64, 62, 60) #Scale needs to be set first because on init/load data already depends on it, at least the default scale. The scale is part of the track meta callback. self.scale = scale if scale else (72, 71, 69, 67, 65, 64, 62, 60) #Scale needs to be set first because on init/load data already depends on it, at least the default scale. The scale is part of the track meta callback.
self.data = data if data else list() #For content see docstring. this cannot be the default parameter because we would set the same list for all instances. self.data = data if data else list() #For content see docstring. this cannot be the default parameter because we would set the same list for all instances.
self.noteNames = noteNames if noteNames else self.parentTrack.parentScore.lastUsedNotenames #This is mostly for the GUI or other kinds of representation instead midi notes self.simpleNoteNames = simpleNoteNames if simpleNoteNames else self.parentTrack.parentScore.lastUsedNotenames #This is mostly for the GUI or other kinds of representation instead midi notes
self._processAfterInit() self._processAfterInit()
def _prepareBeforeInit(self): def _prepareBeforeInit(self):
@ -81,13 +81,13 @@ class Pattern(object):
self.createCachedTonalRange() self.createCachedTonalRange()
@property @property
def noteNames(self): def simpleNoteNames(self):
return self._noteNames return self._simpleNoteNames
@noteNames.setter @simpleNoteNames.setter
def noteNames(self, value): def simpleNoteNames(self, value):
self._noteNames = tuple(value) #we keep it immutable, this is safer to avoid accidental linked structures when creating a clone. self._simpleNoteNames = tuple(value) #we keep it immutable, this is safer to avoid accidental linked structures when creating a clone.
self.parentTrack.parentScore.lastUsedNotenames = self._noteNames #new default for new tracks self.parentTrack.parentScore.lastUsedNotenames = self._simpleNoteNames #new default for new tracks
def fill(self): def fill(self):
"""Create a 2 dimensional array""" """Create a 2 dimensional array"""
@ -221,7 +221,7 @@ class Pattern(object):
return { return {
"scale": self.scale, "scale": self.scale,
"data": self.data, "data": self.data,
"noteNames": self.noteNames, "simpleNoteNames": self.simpleNoteNames,
} }
@classmethod @classmethod
@ -233,7 +233,7 @@ class Pattern(object):
#Use setters to trigger side effects like createCachedTonalRange() #Use setters to trigger side effects like createCachedTonalRange()
self.scale = serializedData["scale"] #Scale needs to be set first because on init/load data already depends on it, at least the default scale. The scale is part of the track meta callback. self.scale = serializedData["scale"] #Scale needs to be set first because on init/load data already depends on it, at least the default scale. The scale is part of the track meta callback.
self.data = serializedData["data"] #For content see docstring. self.data = serializedData["data"] #For content see docstring.
self.noteNames = serializedData["noteNames"] #This is mostly for the GUI or other kinds of representation instead midi notes self.simpleNoteNames = serializedData["simpleNoteNames"] #This is mostly for the GUI or other kinds of representation instead midi notes
self._processAfterInit() self._processAfterInit()
return self return self

7
engine/track.py

@ -44,13 +44,12 @@ class Track(object): #injection at the bottom of this file!
color:str=None, color:str=None,
whichPatternsAreScaleTransposed:Dict[int,int]=None, whichPatternsAreScaleTransposed:Dict[int,int]=None,
whichPatternsAreHalftoneTransposed:Dict[int,int]=None, whichPatternsAreHalftoneTransposed:Dict[int,int]=None,
noteNames:List[str]=None): simpleNoteNames:List[str]=None):
self.parentScore = parentScore self.parentScore = parentScore
self.sequencerInterface = template.engine.sequencer.SequencerInterface(parentTrack=self, name=name) #needs parentScore self.sequencerInterface = template.engine.sequencer.SequencerInterface(parentTrack=self, name=name) #needs parentScore
self.color = color if color else "#00FFFF" # "#rrggbb" in hex. no alpha. a convenience slot for the GUI to save a color. self.color = color if color else "#00FFFF" # "#rrggbb" in hex. no alpha. a convenience slot for the GUI to save a color.
self.pattern = Pattern(parentTrack=self, scale=scale, noteNames=noteNames) self.pattern = Pattern(parentTrack=self, scale=scale, simpleNoteNames=simpleNoteNames)
self.structure = structure if structure else set() #see buildTrack(). This is the main track data structure besides the pattern. Just integers (starts at 0) as switches which are positions where to play the patterns. In between are automatic rests. self.structure = structure if structure else set() #see buildTrack(). This is the main track data structure besides the pattern. Just integers (starts at 0) as switches which are positions where to play the patterns. In between are automatic rests.
self.whichPatternsAreScaleTransposed = whichPatternsAreScaleTransposed if whichPatternsAreScaleTransposed else {} #position:integers between -7 and 7. Reversed pitch, row based: -7 is higher than 7!! self.whichPatternsAreScaleTransposed = whichPatternsAreScaleTransposed if whichPatternsAreScaleTransposed else {} #position:integers between -7 and 7. Reversed pitch, row based: -7 is higher than 7!!
self.whichPatternsAreHalftoneTransposed = whichPatternsAreHalftoneTransposed if whichPatternsAreHalftoneTransposed else {} #position:integers between -7 and 7. Reversed pitch, row based: -7 is higher than 7!! self.whichPatternsAreHalftoneTransposed = whichPatternsAreHalftoneTransposed if whichPatternsAreHalftoneTransposed else {} #position:integers between -7 and 7. Reversed pitch, row based: -7 is higher than 7!!
@ -122,7 +121,7 @@ class Track(object): #injection at the bottom of this file!
"structure" : sorted(self.structure), "structure" : sorted(self.structure),
"pattern": self.pattern.exportCache, "pattern": self.pattern.exportCache,
"scale": self.pattern.scale, "scale": self.pattern.scale,
"noteNames": self.pattern.noteNames, "simpleNoteNames": self.pattern.simpleNoteNames,
"numberOfMeasures": self.parentScore.numberOfMeasures, "numberOfMeasures": self.parentScore.numberOfMeasures,
"whichPatternsAreScaleTransposed": self.whichPatternsAreScaleTransposed, "whichPatternsAreScaleTransposed": self.whichPatternsAreScaleTransposed,
"whichPatternsAreHalftoneTransposed": self.whichPatternsAreHalftoneTransposed, "whichPatternsAreHalftoneTransposed": self.whichPatternsAreHalftoneTransposed,

26
qtgui/pattern_grid.py

@ -171,7 +171,7 @@ class PatternGrid(QtWidgets.QGraphicsScene):
self._steps[(x,y)].on(velocityAndFactor=velocityAndFactor, exceedsPlayback=noteDict["exceedsPlayback"]) self._steps[(x,y)].on(velocityAndFactor=velocityAndFactor, exceedsPlayback=noteDict["exceedsPlayback"])
self.scale.setScale(exportDict["scale"]) self.scale.setScale(exportDict["scale"])
self.scale.setNoteNames(exportDict["noteNames"]) self.scale.setNoteNames(exportDict["simpleNoteNames"])
self.parentView.setViewportUpdateMode(updateMode) self.parentView.setViewportUpdateMode(updateMode)
@ -578,13 +578,13 @@ class Scale(QtWidgets.QGraphicsRectItem):
super().__init__(0,0,0,0) super().__init__(0,0,0,0)
self.parentScene = parentScene self.parentScene = parentScene
self.pitchWidgets = [] #sorted from top to bottom in Step Rect and scene coordinates self.pitchWidgets = [] #sorted from top to bottom in Step Rect and scene coordinates
self.noteNames = [] #list of 128 notes. use index with note name. Can be changed at runtime. self.simpleNoteNames = [] #list of 128 notes. use index with note name. Can be changed at runtime.
api.callbacks.trackMetaDataChanged.append(self.callback_trackMetaDataChanged) api.callbacks.trackMetaDataChanged.append(self.callback_trackMetaDataChanged)
self.buildScale() #also sets the positions of the buttons above self.buildScale() #also sets the positions of the buttons above
def callback_trackMetaDataChanged(self, exportDict): def callback_trackMetaDataChanged(self, exportDict):
#Order matters. We need to set the notenames before the scale. #Order matters. We need to set the notenames before the scale.
self.setNoteNames(exportDict["noteNames"]) self.setNoteNames(exportDict["simpleNoteNames"])
self.setScale(exportDict["scale"]) self.setScale(exportDict["scale"])
def buildScale(self): def buildScale(self):
@ -608,9 +608,9 @@ class Scale(QtWidgets.QGraphicsRectItem):
def setNoteNames(self, pNoteNames): def setNoteNames(self, pNoteNames):
"""A list of 128 strings. Gets only called by the callback.""" """A list of 128 strings. Gets only called by the callback."""
#if pNoteNames in pitch.notenames.keys(): #if pNoteNames in pitch.notenames.keys():
# self.noteNames = pitch.notenames[pNoteNames] # self.simpleNoteNames = pitch.notenames[pNoteNames]
#else: #else:
self.noteNames = pNoteNames self.simpleNoteNames = pNoteNames
for pitchWidget in self.pitchWidgets: for pitchWidget in self.pitchWidgets:
pitchWidget.spinBoxValueChanged() #change all current pitchWidgets pitchWidget.spinBoxValueChanged() #change all current pitchWidgets
@ -680,7 +680,7 @@ class TransposeControls(QtWidgets.QWidget):
self._comboBoxNoteNames = QtWidgets.QComboBox() self._comboBoxNoteNames = QtWidgets.QComboBox()
translatedNotenames = [QtCore.QCoreApplication.translate("Scale", scheme) for scheme in sorted(list(pitch.noteNames.keys()))] translatedNotenames = [QtCore.QCoreApplication.translate("Scale", scheme) for scheme in sorted(list(pitch.simpleNoteNames.keys()))]
self._comboBoxNoteNames.addItems([QtCore.QCoreApplication.translate("TransposeControls","Set Notenames to:")] + translatedNotenames) self._comboBoxNoteNames.addItems([QtCore.QCoreApplication.translate("TransposeControls","Set Notenames to:")] + translatedNotenames)
self._comboBoxNoteNames.activated.connect(self._changeNoteNamesByDropdown) #activated, not changend. even when choosing the same item self._comboBoxNoteNames.activated.connect(self._changeNoteNamesByDropdown) #activated, not changend. even when choosing the same item
self._comboBoxNoteNames.setToolTip(QtCore.QCoreApplication.translate("TransposeControls", "Use this scheme as note names.")) self._comboBoxNoteNames.setToolTip(QtCore.QCoreApplication.translate("TransposeControls", "Use this scheme as note names."))
@ -690,10 +690,10 @@ class TransposeControls(QtWidgets.QWidget):
if index > 0: if index > 0:
index -= 1 # we inserted our "Set NoteNames to" at index 0 shifting the real values +1. index -= 1 # we inserted our "Set NoteNames to" at index 0 shifting the real values +1.
schemes = sorted(pitch.noteNames.keys()) schemes = sorted(pitch.simpleNoteNames.keys())
noteNamesAsString = sorted(pitch.noteNames.keys())[index] noteNamesAsString = sorted(pitch.simpleNoteNames.keys())[index]
noteNames = pitch.noteNames[noteNamesAsString] simpleNoteNames = pitch.simpleNoteNames[noteNamesAsString]
api.setNoteNames(trackId=self.parentScene.parentView.parentMainWindow.currentTrackId, noteNames=noteNames) api.setSimpleNoteNames(trackId=self.parentScene.parentView.parentMainWindow.currentTrackId, simpleNoteNames=simpleNoteNames)
self._comboBoxNoteNames.blockSignals(True) self._comboBoxNoteNames.blockSignals(True)
self._comboBoxNoteNames.setCurrentIndex(0) self._comboBoxNoteNames.setCurrentIndex(0)
self._comboBoxNoteNames.blockSignals(False) self._comboBoxNoteNames.blockSignals(False)
@ -773,12 +773,12 @@ class PitchWidget(QtWidgets.QGraphicsProxyWidget):
#self.spinBox.setStyleSheet(arrowsLeftStylesheet) #self.spinBox.setStyleSheet(arrowsLeftStylesheet)
def midiToNotename(self, midipitch): def midiToNotename(self, midipitch):
assert self.parentItem.noteNames, self.parentItem.noteNames assert self.parentItem.simpleNoteNames, self.parentItem.simpleNoteNames
try: try:
return self.parentItem.noteNames[midipitch] #includes octave names return self.parentItem.simpleNoteNames[midipitch] #includes octave names
except IndexError: except IndexError:
print (midipitch) print (midipitch)
print (self.parentItem.noteNames) print (self.parentItem.simpleNoteNames)
exit() exit()
def spinBoxValueChanged(self): def spinBoxValueChanged(self):

7455
qtgui/resources.py

File diff suppressed because it is too large

BIN
qtgui/resources/aboutlogo.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 57 KiB

BIN
qtgui/resources/icon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 942 B

After

Width:  |  Height:  |  Size: 575 B

Loading…
Cancel
Save