Skip to content

Commit 836b8d5

Browse files
committed
Track: Add exclusive arg to mute()
1 parent 4d88517 commit 836b8d5

2 files changed

Lines changed: 81 additions & 1 deletion

File tree

isobar/timelines/track.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,10 +569,17 @@ def nudge(self, nudge_by: float):
569569
"""
570570
self.next_event_time += nudge_by
571571

572-
def mute(self) -> None:
572+
def mute(self, exclusive: bool = False) -> None:
573573
"""
574574
Mutes the track. Subsequent events will be silenced until an unmute() is received.
575+
576+
Args:
577+
exclusive (bool): If True, unmutes all other tracks.
575578
"""
579+
if exclusive:
580+
for track in self.timeline.tracks:
581+
if track is not self:
582+
track.unmute()
576583
self.is_muted = True
577584

578585
def unmute(self) -> None:

tests/test_track_mute.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
from . import dummy_timeline
2+
3+
def test_track_mute(dummy_timeline):
4+
"""
5+
Test basic mute functionality.
6+
"""
7+
track1 = dummy_timeline.schedule({"note": 60})
8+
track2 = dummy_timeline.schedule({"note": 62})
9+
10+
# Neither track muted: both should play
11+
dummy_timeline.tick()
12+
assert dummy_timeline.output_device.events == [
13+
[0, 'note_on', 60, 64, 0], [0, 'note_on', 62, 64, 0]
14+
]
15+
dummy_timeline.output_device.clear()
16+
17+
# Mute track 1: only track 2 should play
18+
track1.mute()
19+
assert track1.is_muted
20+
assert not track2.is_muted
21+
22+
for n in range(dummy_timeline.ticks_per_beat):
23+
dummy_timeline.tick()
24+
25+
assert dummy_timeline.output_device.events == [
26+
[1, 'note_off', 60, 0],
27+
[1, 'note_off', 62, 0],
28+
[1, 'note_on', 62, 64, 0]
29+
]
30+
dummy_timeline.output_device.clear()
31+
32+
# Unmute track 1: both should play
33+
track1.unmute()
34+
assert not track1.is_muted
35+
for n in range(dummy_timeline.ticks_per_beat):
36+
dummy_timeline.tick()
37+
38+
assert dummy_timeline.output_device.events == [
39+
[2, 'note_on', 60, 64, 0],
40+
[2, 'note_off', 62, 0],
41+
[2, 'note_on', 62, 64, 0]
42+
]
43+
44+
def test_track_mute_exclusive(dummy_timeline):
45+
"""
46+
Test exclusive mute functionality.
47+
"""
48+
track1 = dummy_timeline.schedule({"note": 60})
49+
track2 = dummy_timeline.schedule({"note": 62})
50+
track3 = dummy_timeline.schedule({"note": 64})
51+
52+
# Mute track 1 and 3 normally
53+
track1.mute()
54+
track3.mute()
55+
assert track1.is_muted
56+
assert not track2.is_muted
57+
assert track3.is_muted
58+
59+
# Exclusive mute track 2: should unmute others
60+
track2.mute(exclusive=True)
61+
62+
# Track 2 should be muted
63+
assert track2.is_muted
64+
65+
# Tracks 1 and 3 should be unmuted
66+
assert not track1.is_muted
67+
assert not track3.is_muted
68+
69+
dummy_timeline.tick()
70+
# 60 and 64 should play, 62 should not
71+
events = dummy_timeline.output_device.events
72+
notes = sorted([e[2] for e in events if e[1] == 'note_on'])
73+
assert notes == [60, 64]

0 commit comments

Comments
 (0)