class Alda::EventContainer
The class for objects containing an event.
Alda::EventContainer
objects are literally everywhere if you are a heavy user of event list sugars. See Alda::EventList#method_missing
.
Attributes
The repetition counts. nil
if none.
Alda::Score.new do p((c*2).count) # => 2 p((d*3*5).count) # => 15 end
The contained Alda::Event
object.
Alda::Score.new do p c.event.class # => Alda::Note p((e/g).event.class) # => Alda::Chord p((a b).event.class) # => Alda::Sequence end
When setting this attribute, on_containing
is invoked.
The repetition labels. Empty if none.
Alda::Score.new do p((c%2).labels) # => [2] p((c%[2,4..6]).labels) # => [2, 4..6] end
Public Class Methods
Creates a new Alda::EventContainer
. Invokes on_containing
.
event
is the Alda::Event
object to be contained.
parent
is the Alda::EventList
object containing the event.
# File lib/alda-rb/event.rb, line 147 def initialize event, parent super() @event = event @labels = [] @count = 1 self.parent = parent on_containing end
Public Instance Methods
Marks alternative endings.
Alda::Score.new { (b a%1)*2 }.to_s # => "[b a'1]*2"
# File lib/alda-rb/event.rb, line 232 def % labels labels = [labels] unless labels.is_a? Array @labels.replace labels.to_a check_in_chord self end
Marks repetition.
For examples, see %
.
# File lib/alda-rb/event.rb, line 218 def * num @count = (@count || 1) * num check_in_chord self end
If at first event
is not an Alda::Part
, makes event
an Alda::Chord
object.
Alda::Score.new { piano_; c/-e/g }.play # (plays the chord Cm)
This usage assumes that other
is an Alda::EventContainer
and will extract the contained event out from other
. This will lose some information about other
, such as count
and labels
, and potentially lead to confusing results.
Because the labels
information about other
is lost, the label on d
disappears in the following example:
Alda::Score.new { c/(d%1) }.to_s # => "c/d"
The following example shows that the two ways of writing a chord with a label are equivalent: adding the label and then using slash, or using slash and then adding the label. This is because labels
and count
are retained while the event
is updated when /
is called.
Alda::Score.new { p c%1/d == c/d%1 }.to_s # (prints "true") => "c/d'1 c/d'1"
If at first event
is an Alda::Part
object, makes event
a new Alda::Part
object. The meaning is to play the two parts simultaneously.
Alda::Score.new { violin_/viola_/cello_; e; f; g}.play # (plays notes E, F, G with three instruments simultaneously)
# File lib/alda-rb/event.rb, line 188 def / other other.detach_from_parent @event = if @event.is_a? Alda::Part Alda::Part.new @event.names + other.event.names, other.event.arg else Alda::Chord.new @event, other.event end self end
Overrides Alda::Event#==
. Returns true if other
is an Alda::EventContainer
object and event
, count
and labels
are all equal (using ==
).
Alda::Event#==
# File lib/alda-rb/event.rb, line 312 def == other super || other.is_a?(Alda::EventContainer) && @event == other.event && @count == other.count && @labels == other.labels end
This method is called in %
, *
, and parent=
. It checks if parent
is an Alda::Chord
and warns about potential dangers. Returns true if there is no danger, and false otherwise.
Because Alda 2 does not support specifying alternative endings inside a chord (something like a'1/b
) (alda-lang/alda#383), this method will warn about this if such thing happens and we are using Alda 2.
Alda.v2! Alda::Score.new { x{a%1;b} }.to_s # (warns) => "a'1/b"
This method will warn about repetitions inside a chord in both generations because the resultant Alda code is not valid.
Alda::Score.new { x{a*2;b} }.to_s # (warns) => "a*2/b"
# File lib/alda-rb/event.rb, line 263 def check_in_chord if @parent.is_a?(Alda::Event) && @parent.is_event_of?(Alda::Chord) Alda::Utils.warn 'alternative endings in chord not allowed in v2' if Alda.v2? && !@labels&.empty? Alda::Utils.warn 'repetitions in chord not allowed' if @count && @count != 1 false else true end end
Overrides Alda::Event#is_event_of?
. Whether it is an event of the given class (klass
) or the contained event is.
Alda::Event#is_event_of?
# File lib/alda-rb/event.rb, line 301 def is_event_of? klass super || @event.is_event_of?(klass) end
Calls method on event
.
Note that if the method of event
returns event
itself, the method here returns the container itself.
Alda::Score.new do container = c p container.class # => Alda::EventContainer p container.respond_to? :pitch # => false p container.pitch # => "c" p container.respond_to? :+@ # => false p((+container).class) # => Alda::EventContainer p to_s # => "c+" end
# File lib/alda-rb/event.rb, line 335 def method_missing(...) result = @event.__send__(...) result == @event ? self : result end
Overrides Alda::Event#parent=
. Sets the Alda::Event#parent
of the container as well as that of event
.
# File lib/alda-rb/event.rb, line 279 def parent= event @parent = event check_in_chord @event.parent = event end
Overrides Alda::Event#to_alda_code
.
# File lib/alda-rb/event.rb, line 204 def to_alda_code result = @event.to_alda_code result.concat ?', @labels.map(&:to_alda_code).join(?,) unless @labels.empty? result.concat ?*, @count.to_alda_code if @count != 1 result end