tef-animation 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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]
@@ -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]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tef-animation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - TheSystem