Skip to content

Commit

Permalink
new method activeScorestruct, replaces .scorestruct(resolve=True)
Browse files Browse the repository at this point in the history
  • Loading branch information
gesellkammer committed May 21, 2024
1 parent 25c6466 commit 94e489b
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 35 deletions.
16 changes: 8 additions & 8 deletions maelzel/core/chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -1214,7 +1214,7 @@ def eventsWithOffset(self,
self._dur = totaldur
self._cachedEventsWithOffset = eventpairs
if start is not None or end is not None:
struct = self.scorestruct(resolve=True)
struct = self.activeScorestruct()
start = struct.asBeat(start) if start else F0
end = struct.asBeat(end) if end else F(sys.maxsize)
eventpairs = _eventPairsBetween(eventpairs,
Expand Down Expand Up @@ -1402,7 +1402,7 @@ def addSymbolAt(self, location: time_t | tuple[int, time_t], symbol: symbols.Sym
.. seealso:: :meth:`Chain.beamBreak`
"""
offset = self.scorestruct(resolve=True).asBeat(location)
offset = self.activeScorestruct().asBeat(location)
event = self.eventAt(offset)
if event and event.absOffset() == offset:
event.addSymbol(symbol)
Expand Down Expand Up @@ -1532,7 +1532,7 @@ def itemsBetween(self,
.. seealso:: :meth:`Chain.itemsWithOffset`, :meth:`Chain.eventsBetween`
"""
sco = self.scorestruct(resolve=True)
sco = self.activeScorestruct()
startbeat = sco.asBeat(start)
endbeat = sco.asBeat(end)
out = []
Expand Down Expand Up @@ -1573,7 +1573,7 @@ def splitEventsAtMeasures(self,
included (similar to how python's builtin `range` behaves`
"""
if scorestruct is None:
scorestruct = self.scorestruct(resolve=True)
scorestruct = self.activeScorestruct()
else:
if self.scorestruct():
clsname = type(self).__name__
Expand Down Expand Up @@ -1648,7 +1648,7 @@ def splitEventsAtOffsets(self,
if not offsets:
raise ValueError("No locations given")
items = []
sco = self.scorestruct(resolve=True)
sco = self.activeScorestruct()
absoffsets = [sco.asBeat(offset) for offset in offsets]
for item, offset in self.itemsWithOffset():
if isinstance(item, Chain):
Expand Down Expand Up @@ -1742,8 +1742,8 @@ def matchOrfanSpanners(self, removeUnmatched=False) -> None:
obj.symbols.remove(spanner)
spanner.anchor = None

def remap(self: _MObjT, deststruct: ScoreStruct, sourcestruct: ScoreStruct = None
) -> _MObjT:
def remap(self, deststruct: ScoreStruct, sourcestruct: ScoreStruct = None
) -> Self:
remappedEvents = [ev.remap(deststruct, sourcestruct=sourcestruct)
for ev in self]
return self.clone(items=remappedEvents)
Expand Down Expand Up @@ -1817,7 +1817,7 @@ def cropped(self, start: beat_t, end: beat_t) -> Self | None:
Returns:
a Chain cropped at the given beat range
"""
sco = self.scorestruct(resolve=True)
sco = self.activeScorestruct()
startbeat = sco.asBeat(start)
endbeat = sco.asBeat(end)
cropped = _cropped(self, startbeat=startbeat, endbeat=endbeat)
Expand Down
4 changes: 2 additions & 2 deletions maelzel/core/clip.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ def dur(self) -> F:
return self._explicitDur

absoffset = self.absOffset()
struct = self.scorestruct(resolve=True)
struct = self.activeScorestruct()

if self._dur and self._durContext is not None:
cachedstruct, cachedbeat = self._durContext
Expand All @@ -317,7 +317,7 @@ def _calculateDuration(self, absoffset: F = None, struct: ScoreStruct = None
if absoffset is None:
absoffset = self.absOffset()
if struct is None:
struct = self.scorestruct(resolve=True)
struct = self.activeScorestruct()
dur = struct.beatDelta(absoffset, absoffset + self.durSecs())
self._dur = dur
self._durContext = (struct, absoffset)
Expand Down
33 changes: 11 additions & 22 deletions maelzel/core/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
from .config import CoreConfig
from typing import Callable, Any, Sequence, Iterator
from ._typedefs import *
from typing_extensions import Self


__all__ = (
Expand Down Expand Up @@ -359,7 +360,7 @@ def __eq__(self, other: Note | str | float) -> bool:
else:
return False

def copy(self) -> Note:
def copy(self) -> Self:
out = Note(self.pitch, dur=self.dur, amp=self.amp, gliss=self._gliss, tied=self.tied,
dynamic=self.dynamic, offset=self.offset, label=self.label,
_init=False)
Expand All @@ -376,7 +377,7 @@ def clone(self,
gliss: pitch_t | bool | None = None,
label: str = None,
tied: bool = None,
dynamic: str = None) -> Note:
dynamic: str = None) -> Self:
"""
Clone this note with overridden attributes
Expand Down Expand Up @@ -446,7 +447,7 @@ def timeShift(self, timeoffset: time_t) -> Self:
f"resulting offset: {reloffset}. ({self=})")
return self.clone(offset=reloffset)

def freqShift(self, freq: float) -> Note:
def freqShift(self, freq: float) -> Self:
"""
Return a copy of self, shifted in freq.
Expand Down Expand Up @@ -481,7 +482,7 @@ def __gt__(self, other: pitch_t | Note) -> bool:
else:
raise NotImplementedError()

def __abs__(self) -> Note:
def __abs__(self) -> Self:
if self.pitch >= 0:
return self
return self.clone(pitch=-self.pitch)
Expand Down Expand Up @@ -523,18 +524,6 @@ def cents(self) -> int:
"""The fractional part of this pitch, rounded to the cent"""
return _tools.midicents(self.pitch)

def overtone(self, n: float) -> Note:
"""
Return a new Note representing the `nth` overtone of this Note
Args:
n: the overtone number (1 = fundamental)
Returns:
a new Note
"""
return Note(pt.f2m(self.freq * n), _init=False)

def scoringEvents(self,
groupid='',
config: CoreConfig = None,
Expand Down Expand Up @@ -646,20 +635,20 @@ def __float__(self) -> float: return float(self.pitch)

def __int__(self) -> int: return int(self.pitch)

def __add__(self, other: num_t) -> Note:
def __add__(self, other: num_t) -> Self:
if isinstance(other, (int, float)):
out = self.copy()
out._setpitch(self.pitch + other)
out._gliss = self.gliss if isinstance(self.gliss, bool) else self.gliss + other
return out
raise TypeError(f"can't add {other} ({other.__class__}) to a Note")

def __xor__(self, freq) -> Note: return self.freqShift(freq)
def __xor__(self, freq) -> Self: return self.freqShift(freq)

def __sub__(self, other: num_t) -> Note:
def __sub__(self, other: num_t) -> Self:
return self + (-other)

def quantizePitch(self, step=0.) -> Note:
def quantizePitch(self, step=0.) -> Self:
"""
Returns a new Note, rounded to step.
Expand Down Expand Up @@ -782,7 +771,7 @@ def resolveDynamic(self, conf: CoreConfig = None) -> str:
# TODO: query the parent to see the currently active dynamic
return self.dynamic or conf['play.defaultDynamic']

def pitchTransform(self, pitchmap: Callable[[float], float]) -> Note:
def pitchTransform(self, pitchmap: Callable[[float], float]) -> Self:
if self.isRest():
return self
pitch = pitchmap(self.pitch)
Expand Down Expand Up @@ -1090,7 +1079,7 @@ def glissTarget(self) -> list[str]:
elif self._glissTarget:
return self._glissTarget if isinstance(self._glissTarget, str) else pt.m2n(self._glissTarget)
elif not isinstance(self._gliss, bool):
return pt.m2n(self._gliss)
return [pt.m2n(pitch) for pitch in self._gliss]
elif self.parent:
self.parent._resolveGlissandi()
return self._glissTarget if isinstance(self._glissTarget, str) else pt.m2n(self._glissTarget)
Expand Down
2 changes: 1 addition & 1 deletion maelzel/core/eventbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def cropped(self, start: beat_t, end: beat_t
the cropped event
"""
scorestruct = self.scorestruct(resolve=True)
scorestruct = self.activeScorestruct()
startbeat = start if isinstance(start, F) else scorestruct.asBeat(start)
endbeat = end if isinstance(end, F) else scorestruct.asBeat(end)
absoffset = self.absOffset()
Expand Down
20 changes: 19 additions & 1 deletion maelzel/core/mobj.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ def remap(self, deststruct: ScoreStruct, sourcestruct: ScoreStruct = None
"""
if sourcestruct is None:
sourcestruct = self.scorestruct(resolve=True)
sourcestruct = self.activeScorestruct()
offset, dur = deststruct.remapSpan(sourcestruct, self.absOffset(), self.dur)
return self.clone(offset=offset, dur=dur)

Expand Down Expand Up @@ -974,6 +974,21 @@ def _scoringAnnotation(self, text: str = None, config: CoreConfig = None
weight='bold' if labelstyle.bold else '',
color=labelstyle.color)

def activeScorestruct(self) -> ScoreStruct:
"""
Returns the ScoreStruct active for this obj or its parent.
Otherwise returns the scorestruct for the active workspace
Returns:
the active scorestruct for this object
.. seealso:: :meth:`MObj.scorestruct`
"""
if not self.parent:
return Workspace.getActive().scorestruct
return self.parent.activeScorestruct()

def scorestruct(self, resolve=False) -> ScoreStruct | None:
"""
Returns the ScoreStruct active for this obj or its parent (recursively)
Expand Down Expand Up @@ -1003,6 +1018,9 @@ def scorestruct(self, resolve=False) -> ScoreStruct | None:
>>> n.scorestruct()
ScoreStruct(timesig=(3, 4), tempo=72)
"""
if resolve:
logger.warning("The resolve paremeter is deprecated, use the "
"method .activeScorestruct")
if not self.parent:
return Workspace.active.scorestruct if resolve else None
return self.parent.scorestruct(resolve=resolve)
Expand Down
2 changes: 1 addition & 1 deletion maelzel/core/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ def plotVoices(voices: list[Voice],
ledgerLineColor=ledgerLineColor)

if not scorestruct:
scorestruct = voices[0].scorestruct(resolve=True)
scorestruct = voices[0].activeScorestruct()

scoreend = max(voice.dur for voice in voices)
measureOffsets = _measureOffsetsIncluding(scorestruct, scoreend, realtime=realtime)
Expand Down

0 comments on commit 94e489b

Please sign in to comment.