tef-animation 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/tef/Animation/Animatable.rb +155 -2
- data/lib/tef/Animation/Animation_Handler.rb +81 -3
- data/lib/tef/Animation/Color.rb +70 -0
- data/lib/tef/Animation/Coordinate.rb +10 -0
- data/lib/tef/Animation/Eyes.rb +2 -0
- data/lib/tef/Animation/Value.rb +75 -1
- data/lib/tef/ParameterStack/Override.rb +47 -0
- data/lib/tef/ParameterStack/Stack.rb +64 -0
- data/lib/tef/ProgramSelection/ProgramID.rb +46 -0
- data/lib/tef/ProgramSelection/ProgramSelector.rb +54 -0
- data/lib/tef/ProgramSelection/SequenceCollection.rb +70 -4
- data/lib/tef/ProgramSelection/SoundCollection.rb +59 -22
- data/lib/tef/Sequencing/BaseSequence.rb +44 -2
- data/lib/tef/Sequencing/EventCollector.rb +74 -0
- data/lib/tef/Sequencing/SequencePlayer.rb +41 -1
- data/lib/tef/Sequencing/Sheet.rb +48 -0
- data/lib/tef/Sequencing/SheetSequence.rb +49 -1
- metadata +1 -1
@@ -6,7 +6,25 @@ require_relative 'SheetSequence.rb'
|
|
6
6
|
|
7
7
|
module TEF
|
8
8
|
module Sequencing
|
9
|
+
# Sequene Player class.
|
10
|
+
#
|
11
|
+
# This class is meant as a easy means to play {BaseSequence}s.
|
12
|
+
# It allows the user to start and stop sequences, play them in parallel,
|
13
|
+
# or overwrite them.
|
14
|
+
#
|
15
|
+
# Register hooks to be called after an execution step with {#after_exec}.
|
16
|
+
#
|
17
|
+
# Start playing a sequence by using {#[]=}, then use {#delete} to stop
|
18
|
+
# it prematurely.
|
19
|
+
#
|
20
|
+
# @todo Add pausing of sequences. Requires the BaseSequence to have a
|
21
|
+
# time conversion built-in as well.
|
9
22
|
class Player
|
23
|
+
|
24
|
+
# Initialize a player instance
|
25
|
+
#
|
26
|
+
# It can immediately be used to play {BaseSequence}s or {Sheet}s, though
|
27
|
+
# {#after_exec} callbacks should first be registered.
|
10
28
|
def initialize()
|
11
29
|
@activeSequences = {}
|
12
30
|
@sequenceMutex = Mutex.new
|
@@ -24,10 +42,31 @@ module TEF
|
|
24
42
|
@playThread.abort_on_exception = true
|
25
43
|
end
|
26
44
|
|
45
|
+
# Add a callback to be executed after a animation step.
|
46
|
+
#
|
47
|
+
# The block passed to this function will be executed after each
|
48
|
+
# {EventCollector#execute!}, i.e. after every tick of the animation
|
49
|
+
# system.
|
50
|
+
# This makes it possible to connect it to the Animation system,
|
51
|
+
# for example by calling {Animation::Handler#update_tick},
|
52
|
+
# as well as the parameter stack by calling
|
53
|
+
# {ParameterStack::Stack#process_changes}
|
27
54
|
def after_exec(&block)
|
28
55
|
@post_exec_cbs << block if block_given?
|
29
56
|
end
|
30
57
|
|
58
|
+
# Insert and start a new program.
|
59
|
+
#
|
60
|
+
# This will:
|
61
|
+
# - Stop and tear the currently playing program under 'key' down.
|
62
|
+
# - Instantiate a {SheetSequence} IF the program is a {Sheet}
|
63
|
+
# - Immediately start playing the new program.
|
64
|
+
#
|
65
|
+
# The inserted program is returned.
|
66
|
+
# {#delete} can be used to stop a given program.
|
67
|
+
#
|
68
|
+
# @param key Arbitrary key to identify the program with.
|
69
|
+
# @param [BaseSequence, Sheet] program Program to start playing.
|
31
70
|
def []=(key, program)
|
32
71
|
@sequenceMutex.synchronize do
|
33
72
|
if @activeSequences[key]
|
@@ -35,7 +74,6 @@ module TEF
|
|
35
74
|
end
|
36
75
|
|
37
76
|
if program.is_a? Sheet
|
38
|
-
puts "Inited sheet with start at #{Time.now()}"
|
39
77
|
program = SheetSequence.new(Time.now(), 1, sheet: program)
|
40
78
|
end
|
41
79
|
|
@@ -48,6 +86,8 @@ module TEF
|
|
48
86
|
program
|
49
87
|
end
|
50
88
|
|
89
|
+
# Delete a given program by its key.
|
90
|
+
# This will stop and tear the specified program down.
|
51
91
|
def delete(key)
|
52
92
|
@sequenceMutex.synchronize do
|
53
93
|
if @activeSequences[key]
|
data/lib/tef/Sequencing/Sheet.rb
CHANGED
@@ -1,16 +1,51 @@
|
|
1
1
|
|
2
|
+
require_relative 'EventCollector.rb'
|
2
3
|
|
3
4
|
module TEF
|
4
5
|
module Sequencing
|
6
|
+
# Sheet class
|
7
|
+
#
|
8
|
+
# This class is meant as a container for the minimum
|
9
|
+
# amount of information necessary to instantiate a {SheetSequence}.
|
10
|
+
#
|
11
|
+
# It provides a clean and easy way for the user to define
|
12
|
+
# a sequence of events, as well as minimally necessary information
|
13
|
+
# such as the speed of the sequence or the starting and ending
|
14
|
+
# times.
|
5
15
|
class Sheet
|
16
|
+
# @return [Numeric] The local starting time. Defaults to
|
17
|
+
# 0, i.e the sheet will start playing immediately.
|
18
|
+
# This does not affect the actual time scaling, but instead
|
19
|
+
# is merely used to know when to instantiate the {SheetSequence}
|
6
20
|
attr_accessor :start_time
|
21
|
+
|
22
|
+
# @return [Numeric] The local ending-time. Defaults to nil, i.e.
|
23
|
+
# it will be auto-determined by the notes in the sheet.
|
24
|
+
# Affects when the sheet is torn down and stops
|
25
|
+
# execution!
|
7
26
|
attr_accessor :end_time
|
8
27
|
|
28
|
+
# @return [Numeric, nil] Tempo of the sheet. Defines the execution
|
29
|
+
# speed in BPM. If left nil, the execution speed of the parent
|
30
|
+
# sheet is used.
|
9
31
|
attr_accessor :tempo
|
10
32
|
|
33
|
+
# @return [nil, Proc] Block to call when setting up the {SheetSequence}.
|
34
|
+
# This is the main way of letting the user configure the {SheetSequence},
|
35
|
+
# as this block is called from the context of the sheet itself.
|
36
|
+
# Look at the functions of the Sheet Sequence for more details.
|
37
|
+
#
|
38
|
+
# @see SheetSequence#at
|
39
|
+
# @see SheetSequence#after
|
40
|
+
# @see SheetSequence#play
|
11
41
|
attr_reader :setup_block
|
12
42
|
attr_reader :teardown_block
|
13
43
|
|
44
|
+
# Initialize a new Sheet.
|
45
|
+
#
|
46
|
+
# The user should configure the sheet by writing into
|
47
|
+
# {#start_time}, {#end_time} and by supplying at least a
|
48
|
+
# {#sequence}
|
14
49
|
def initialize()
|
15
50
|
@start_time = 0;
|
16
51
|
@end_time = nil;
|
@@ -21,10 +56,23 @@ module TEF
|
|
21
56
|
@teardown_block = nil;
|
22
57
|
end
|
23
58
|
|
59
|
+
# Configure a block to call when setting up the {SheetSequence}.
|
60
|
+
# This is the main way of letting the user configure the {SheetSequence},
|
61
|
+
# as this block is called from the context of the sheet itself.
|
62
|
+
# Look at the functions of the Sheet Sequence for more details.
|
63
|
+
#
|
64
|
+
# @see SheetSequence#at
|
65
|
+
# @see SheetSequence#after
|
66
|
+
# @see SheetSequence#play
|
24
67
|
def sequence(&block)
|
25
68
|
@setup_block = block;
|
26
69
|
end
|
27
70
|
|
71
|
+
# Configure the block to call when the {SheetSequence} is about to
|
72
|
+
# be torn down. Use this to stop or delete any resources allocated
|
73
|
+
# to the sheet.
|
74
|
+
#
|
75
|
+
# Guaranteed to always be called.
|
28
76
|
def teardown(&block)
|
29
77
|
@teardown_block = block;
|
30
78
|
end
|
@@ -4,7 +4,25 @@ require_relative 'Sheet.rb'
|
|
4
4
|
|
5
5
|
module TEF
|
6
6
|
module Sequencing
|
7
|
+
# Sheet Sequence class.
|
8
|
+
#
|
9
|
+
# This is the main way for the user to specify an exact sequence of events
|
10
|
+
# to execute. It is construced with the help of a {Sheet}, which
|
11
|
+
# acts as specification for this Sheet Sequence.
|
12
|
+
#
|
13
|
+
# Think of the {Sheet} as being the script for a play or movie, while
|
14
|
+
# the {SheetSequence} has the job of actually performing everything.
|
7
15
|
class SheetSequence < BaseSequence
|
16
|
+
|
17
|
+
# Initialize a SheetSequence.
|
18
|
+
#
|
19
|
+
# This is mostly done via {Player#[]=} by passing a {Sheet}.
|
20
|
+
# However, a sequence can also be manually instantiated.
|
21
|
+
#
|
22
|
+
# After initialization, the sheet's {Sheet#setup_block} is called
|
23
|
+
# to fill this SheetSequence with actual content.
|
24
|
+
# The user may also call {#at} and {#after} manually to add additional
|
25
|
+
# events.
|
8
26
|
def initialize(offset, slope, **options)
|
9
27
|
super(offset, slope, **options);
|
10
28
|
|
@@ -55,6 +73,23 @@ module TEF
|
|
55
73
|
super();
|
56
74
|
end
|
57
75
|
|
76
|
+
# Insert an event or subsheet into the event list.
|
77
|
+
#
|
78
|
+
# This is the main way of adding events to this sequence.
|
79
|
+
# Each call to the function will insert a new event at the specified
|
80
|
+
# time, which will call the passed block.
|
81
|
+
# If, instead, a parameter called :sheet or :sequence is passed,
|
82
|
+
# instead the the passed sequence will be instantiated and
|
83
|
+
# added to the list of programs.
|
84
|
+
# Any further options are directly passed to the constructor
|
85
|
+
# of the class specified by the :sequence parameter
|
86
|
+
#
|
87
|
+
# If a block was passed, it will be instance_exec'd at the specified
|
88
|
+
# time.
|
89
|
+
#
|
90
|
+
# Note that any used or created resources shall be destroyed in
|
91
|
+
# the {Sheet#teardown} block. Sub-Sequences as well as notes
|
92
|
+
# played by {#play} are automatically torn down.
|
58
93
|
def at(time, **options, &block)
|
59
94
|
@latest_note_time = time;
|
60
95
|
|
@@ -82,10 +117,22 @@ module TEF
|
|
82
117
|
@notes.insert((i || -1), new_event);
|
83
118
|
end
|
84
119
|
|
120
|
+
# Similar to {#at}, but specifies time relative to the
|
121
|
+
# last event time.
|
122
|
+
# @see #at
|
85
123
|
def after(time, **options, &block)
|
86
124
|
at(time + (@latest_note_time || 0) , **options, &block);
|
87
125
|
end
|
88
126
|
|
127
|
+
# Play a music file, using `play`
|
128
|
+
#
|
129
|
+
# The PID of the music playing task is saved, and the process
|
130
|
+
# will be killed when this sheet is torn down. The user does not
|
131
|
+
# have to do anything else, but may choose to prematurely kill
|
132
|
+
# the playback by using {#kill}
|
133
|
+
#
|
134
|
+
# @param [String] music_piece Path of the file to play.
|
135
|
+
# @return [Numeric] The PID of the spawned process.
|
89
136
|
def play(music_piece, volume = 0.3)
|
90
137
|
play_pid = spawn(*%W{play -q --volume #{volume} #{music_piece}});
|
91
138
|
|
@@ -98,11 +145,12 @@ module TEF
|
|
98
145
|
play_pid
|
99
146
|
end
|
100
147
|
|
148
|
+
# Shorthand to kill
|
101
149
|
def kill(pid)
|
102
150
|
Process.kill('QUIT', pid);
|
103
151
|
end
|
104
152
|
|
105
|
-
def overload_append_events(collector)
|
153
|
+
private def overload_append_events(collector)
|
106
154
|
i = 0
|
107
155
|
loop do
|
108
156
|
next_program = @subprograms[i]
|