midi-topaz 0.0.4 → 0.0.5
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.
- data/lib/topaz/external_midi_tempo.rb +9 -15
- data/lib/topaz/internal_tempo.rb +19 -13
- data/lib/topaz/midi_sync_output.rb +3 -3
- data/lib/topaz/tempo.rb +41 -19
- data/lib/topaz/tempo_source.rb +20 -0
- data/lib/topaz.rb +2 -1
- metadata +3 -2
| @@ -3,12 +3,13 @@ module Topaz | |
| 3 3 |  | 
| 4 4 | 
             
              # trigger an event based on received midi clock messages
         | 
| 5 5 | 
             
              class ExternalMIDITempo
         | 
| 6 | 
            +
                
         | 
| 7 | 
            +
                include TempoSource
         | 
| 6 8 |  | 
| 7 | 
            -
                attr_accessor :action
         | 
| 8 9 | 
             
                attr_reader :clock
         | 
| 9 10 |  | 
| 10 | 
            -
                def initialize(input, options = {})
         | 
| 11 | 
            -
                  @ | 
| 11 | 
            +
                def initialize(actions, input, options = {})
         | 
| 12 | 
            +
                  @actions = actions
         | 
| 12 13 | 
             
                  self.interval = options[:interval] || 4
         | 
| 13 14 | 
             
                  @tempo_calculator = TempoCalculator.new
         | 
| 14 15 | 
             
                  @clock = MIDIEye::Listener.new(input)
         | 
| @@ -21,14 +22,12 @@ module Topaz | |
| 21 22 | 
             
                  @tempo_calculator.find_tempo
         | 
| 22 23 | 
             
                end
         | 
| 23 24 |  | 
| 24 | 
            -
                def start(*a)
         | 
| 25 | 
            -
                  @action[:on_start].call unless @action[:on_start].nil?
         | 
| 25 | 
            +
                def start(*a)      
         | 
| 26 26 | 
             
                  @clock.start(*a)
         | 
| 27 27 | 
             
                  self
         | 
| 28 28 | 
             
                end
         | 
| 29 29 |  | 
| 30 30 | 
             
                def stop(*a)
         | 
| 31 | 
            -
                  @action[:on_stop].call unless @action[:on_stop].nil?
         | 
| 32 31 | 
             
                  @clock.start(*a)
         | 
| 33 32 | 
             
                  self
         | 
| 34 33 | 
             
                end
         | 
| @@ -61,17 +60,12 @@ module Topaz | |
| 61 60 |  | 
| 62 61 | 
             
                def initialize_clock
         | 
| 63 62 | 
             
                  @counter = 0
         | 
| 64 | 
            -
                  @clock.listen_for(:name => "Clock") do |msg|
         | 
| 65 | 
            -
                    if  | 
| 66 | 
            -
             | 
| 67 | 
            -
                      return
         | 
| 68 | 
            -
                    end 
         | 
| 69 | 
            -
                    @action[:destinations].each do |output|
         | 
| 70 | 
            -
                      output.on_tick
         | 
| 71 | 
            -
                    end        
         | 
| 63 | 
            +
                  @clock.listen_for(:name => "Clock") do |msg|        
         | 
| 64 | 
            +
                    (stop and return) if stop?
         | 
| 65 | 
            +
                    do_midi_clock
         | 
| 72 66 | 
             
                    @tempo_calculator.timestamps << msg[:timestamp]
         | 
| 73 67 | 
             
                    if @counter.eql?(@per_tick)
         | 
| 74 | 
            -
                       | 
| 68 | 
            +
                      do_tick
         | 
| 75 69 | 
             
                      @counter = 0 
         | 
| 76 70 | 
             
                    else
         | 
| 77 71 | 
             
                      @counter += 1
         | 
    
        data/lib/topaz/internal_tempo.rb
    CHANGED
    
    | @@ -3,12 +3,13 @@ module Topaz | |
| 3 3 |  | 
| 4 4 | 
             
              class InternalTempo < Gamelan::Timer
         | 
| 5 5 |  | 
| 6 | 
            +
                include TempoSource
         | 
| 7 | 
            +
                
         | 
| 6 8 | 
             
                attr_accessor :action
         | 
| 7 9 |  | 
| 8 | 
            -
                def initialize(tempo, options = {})
         | 
| 9 | 
            -
                  @ | 
| 10 | 
            +
                def initialize(actions, tempo, options = {})
         | 
| 11 | 
            +
                  @actions = actions
         | 
| 10 12 | 
             
                  self.interval = options[:interval] || 4 
         | 
| 11 | 
            -
                  @destinations = options[:destinations]
         | 
| 12 13 | 
             
                  @last = 0
         | 
| 13 14 | 
             
                  @last_sync = 0
         | 
| 14 15 | 
             
                  super({:tempo => tempo})
         | 
| @@ -17,7 +18,6 @@ module Topaz | |
| 17 18 | 
             
                # start the internal timer
         | 
| 18 19 | 
             
                # pass :background => true to keep the timer in a background thread
         | 
| 19 20 | 
             
                def start(options = {})
         | 
| 20 | 
            -
                  @action[:on_start].call unless @action[:on_start].nil?
         | 
| 21 21 | 
             
                  run
         | 
| 22 22 | 
             
                  join unless options[:background]
         | 
| 23 23 | 
             
                  self
         | 
| @@ -34,7 +34,6 @@ module Topaz | |
| 34 34 |  | 
| 35 35 | 
             
                # stop the timer
         | 
| 36 36 | 
             
                def stop(*a)
         | 
| 37 | 
            -
                  @action[:on_stop].call unless @action[:on_stop].nil?
         | 
| 38 37 | 
             
                  super()
         | 
| 39 38 | 
             
                  self
         | 
| 40 39 | 
             
                end
         | 
| @@ -49,21 +48,28 @@ module Topaz | |
| 49 48 | 
             
                # Run all ready tasks.
         | 
| 50 49 | 
             
                def dispatch
         | 
| 51 50 | 
             
                  # stuff to do on every tick      
         | 
| 52 | 
            -
                   | 
| 51 | 
            +
                  if time_for_midi_clock?
         | 
| 53 52 | 
             
                    # look for stop
         | 
| 54 | 
            -
                    if  | 
| 55 | 
            -
             | 
| 56 | 
            -
                      return
         | 
| 57 | 
            -
                    end 
         | 
| 58 | 
            -
                    @action[:destinations].each { |dest| dest.on_tick }        
         | 
| 53 | 
            +
                    (stop and return) if stop?
         | 
| 54 | 
            +
                    do_midi_clock        
         | 
| 59 55 | 
             
                    @last_sync = (@phase * 24).to_i
         | 
| 60 56 | 
             
                  end
         | 
| 61 57 | 
             
                  # stuff to do on @interval
         | 
| 62 | 
            -
                   | 
| 63 | 
            -
                     | 
| 58 | 
            +
                  if time_for_tick?
         | 
| 59 | 
            +
                    do_tick
         | 
| 64 60 | 
             
                    @last = (@phase * @interval).to_i
         | 
| 65 61 | 
             
                  end      
         | 
| 66 62 | 
             
                end
         | 
| 63 | 
            +
                
         | 
| 64 | 
            +
                private
         | 
| 65 | 
            +
                
         | 
| 66 | 
            +
                def time_for_midi_clock?
         | 
| 67 | 
            +
                  !@last_sync.eql?((@phase * 24).to_i)
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
                
         | 
| 70 | 
            +
                def time_for_tick?
         | 
| 71 | 
            +
                  !@last.eql?((@phase * @interval).to_i)
         | 
| 72 | 
            +
                end
         | 
| 67 73 |  | 
| 68 74 | 
             
              end
         | 
| 69 75 |  | 
| @@ -9,17 +9,17 @@ module Topaz | |
| 9 9 | 
             
                end
         | 
| 10 10 |  | 
| 11 11 | 
             
                # send a start message
         | 
| 12 | 
            -
                def  | 
| 12 | 
            +
                def start(*a)
         | 
| 13 13 | 
             
                  @output.puts(MIDIMessage::SystemRealtime["Start"].new.to_a)
         | 
| 14 14 | 
             
                end
         | 
| 15 15 |  | 
| 16 16 | 
             
                # send a stop message
         | 
| 17 | 
            -
                def  | 
| 17 | 
            +
                def stop(*a)
         | 
| 18 18 | 
             
                  @output.puts(MIDIMessage::SystemRealtime["Stop"].new.to_a)
         | 
| 19 19 | 
             
                end
         | 
| 20 20 |  | 
| 21 21 | 
             
                # send a clock message
         | 
| 22 | 
            -
                def  | 
| 22 | 
            +
                def midi_clock(*a)
         | 
| 23 23 | 
             
                  @output.puts(MIDIMessage::SystemRealtime["Clock"].new.to_a)
         | 
| 24 24 | 
             
                end
         | 
| 25 25 |  | 
    
        data/lib/topaz/tempo.rb
    CHANGED
    
    | @@ -6,27 +6,30 @@ module Topaz | |
| 6 6 |  | 
| 7 7 | 
             
                extend Forwardable
         | 
| 8 8 |  | 
| 9 | 
            -
                attr_reader :source
         | 
| 9 | 
            +
                attr_reader :source, :destinations
         | 
| 10 10 |  | 
| 11 11 | 
             
                def_delegators :source, :tempo, :interval, :interval=, :join
         | 
| 12 12 |  | 
| 13 13 | 
             
                def initialize(*args, &event)
         | 
| 14 | 
            -
                  @destinations = []
         | 
| 14 | 
            +
                  @destinations = []      
         | 
| 15 | 
            +
                  @actions = { 
         | 
| 16 | 
            +
                    :start => nil,
         | 
| 17 | 
            +
                    :stop => nil,
         | 
| 18 | 
            +
                    :tick => nil,        
         | 
| 19 | 
            +
                    :midi_clock => Proc.new { @destinations.each { |d| d.send(:midi_clock) if d.respond_to?(:midi_clock) } },
         | 
| 20 | 
            +
                    :stop_when => nil
         | 
| 21 | 
            +
                  }
         | 
| 22 | 
            +
                  
         | 
| 23 | 
            +
                  on_tick(&event)
         | 
| 15 24 |  | 
| 16 25 | 
             
                  if args.first.kind_of?(Numeric)
         | 
| 17 | 
            -
                    @source = InternalTempo.new(args.shift)
         | 
| 26 | 
            +
                    @source = InternalTempo.new(@actions, args.shift)
         | 
| 18 27 | 
             
                  end
         | 
| 19 28 | 
             
                  options = args.first
         | 
| 20 29 |  | 
| 21 30 | 
             
                  initialize_midi_io(options)
         | 
| 22 31 | 
             
                  raise "You must specify an internal tempo rate or an external tempo source" if @source.nil?
         | 
| 23 | 
            -
                   | 
| 24 | 
            -
                    :on_start => nil,
         | 
| 25 | 
            -
                    :on_stop => nil,
         | 
| 26 | 
            -
                    :on_tick => event,        
         | 
| 27 | 
            -
                    :destinations => @destinations,
         | 
| 28 | 
            -
                    :stop_when => nil
         | 
| 29 | 
            -
                  }
         | 
| 32 | 
            +
                  
         | 
| 30 33 | 
             
                  @source.interval = options[:interval] unless options.nil? || options[:interval].nil? 
         | 
| 31 34 | 
             
                end
         | 
| 32 35 |  | 
| @@ -45,22 +48,26 @@ module Topaz | |
| 45 48 |  | 
| 46 49 | 
             
                # pass in a callback that is called when start is called
         | 
| 47 50 | 
             
                def on_start(&block)
         | 
| 48 | 
            -
                  @ | 
| 51 | 
            +
                  @actions[:start] = block
         | 
| 49 52 | 
             
                end
         | 
| 50 53 |  | 
| 51 54 | 
             
                # pass in a callback that is called when stop is called
         | 
| 52 55 | 
             
                def on_stop(&block)
         | 
| 53 | 
            -
                  @ | 
| 56 | 
            +
                  @actions[:stop] = block
         | 
| 54 57 | 
             
                end
         | 
| 55 58 |  | 
| 56 59 | 
             
                # pass in a callback which will 
         | 
| 57 60 | 
             
                def stop_when(&block)
         | 
| 58 | 
            -
                  @ | 
| 61 | 
            +
                  @actions[:stop_when] = block
         | 
| 59 62 | 
             
                end
         | 
| 60 63 |  | 
| 61 64 | 
             
                # pass in a callback which will be fired on each tick
         | 
| 62 65 | 
             
                def on_tick(&block)
         | 
| 63 | 
            -
                   | 
| 66 | 
            +
                  proc = Proc.new do |dests|
         | 
| 67 | 
            +
                    @destinations.each { |d| d.send(:tick) if d.respond_to?(:tick) }
         | 
| 68 | 
            +
                    yield
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
                  @actions[:tick] = proc
         | 
| 64 71 | 
             
                end
         | 
| 65 72 |  | 
| 66 73 | 
             
                # this will start the generator
         | 
| @@ -70,14 +77,16 @@ module Topaz | |
| 70 77 | 
             
                #
         | 
| 71 78 | 
             
                def start(options = {})
         | 
| 72 79 | 
             
                  @start_time = Time.now
         | 
| 73 | 
            -
                  @destinations.each { |dest| dest. | 
| 74 | 
            -
                  @source.start(options)
         | 
| 80 | 
            +
                  @destinations.each { |dest| dest.start(:parent => self) }
         | 
| 81 | 
            +
                  @source.start(options) if options[:parent].nil?
         | 
| 82 | 
            +
                  @actions[:start].call unless @actions[:start].nil?
         | 
| 75 83 | 
             
                end
         | 
| 76 84 |  | 
| 77 85 | 
             
                # this will stop tempo
         | 
| 78 86 | 
             
                def stop(options = {})
         | 
| 79 | 
            -
                  @destinations.each { |dest| dest. | 
| 80 | 
            -
                  @source.stop(options)
         | 
| 87 | 
            +
                  @destinations.each { |dest| dest.stop(:parent => self) }
         | 
| 88 | 
            +
                  @source.stop(options) if options[:parent].nil?
         | 
| 89 | 
            +
                  @actions[:stop].call unless @actions[:stop].nil?
         | 
| 81 90 | 
             
                  @start_time = nil
         | 
| 82 91 | 
             
                end
         | 
| 83 92 |  | 
| @@ -87,6 +96,19 @@ module Topaz | |
| 87 96 | 
             
                end
         | 
| 88 97 | 
             
                alias_method :time_since_start, :time
         | 
| 89 98 |  | 
| 99 | 
            +
                # add a destination
         | 
| 100 | 
            +
                # accepts MIDISyncOutput or another Tempo object
         | 
| 101 | 
            +
                def add_destination(tempo)
         | 
| 102 | 
            +
                  @destinations << tempo
         | 
| 103 | 
            +
                end
         | 
| 104 | 
            +
                alias_method :<<, :add_destination
         | 
| 105 | 
            +
                
         | 
| 106 | 
            +
                protected
         | 
| 107 | 
            +
                
         | 
| 108 | 
            +
                def tick
         | 
| 109 | 
            +
                  @actions[:tick].call
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
                
         | 
| 90 112 | 
             
                private
         | 
| 91 113 |  | 
| 92 114 | 
             
                def initialize_midi_io(args)
         | 
| @@ -95,7 +117,7 @@ module Topaz | |
| 95 117 | 
             
                    if ports.kind_of?(Array) 
         | 
| 96 118 | 
             
                      ports.each { |port| initialize_midi_io(port) }
         | 
| 97 119 | 
             
                    elsif ports.type.eql?(:input) && @source.nil?
         | 
| 98 | 
            -
                      @source = ExternalMIDITempo.new(ports) 
         | 
| 120 | 
            +
                      @source = ExternalMIDITempo.new(@actions, ports) 
         | 
| 99 121 | 
             
                    elsif ports.type.eql?(:output)
         | 
| 100 122 | 
             
                      @destinations << MIDISyncOutput.new(ports)
         | 
| 101 123 | 
             
                    end
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            module Topaz
         | 
| 3 | 
            +
              
         | 
| 4 | 
            +
              module TempoSource
         | 
| 5 | 
            +
                
         | 
| 6 | 
            +
                def do_midi_clock
         | 
| 7 | 
            +
                  @actions[:midi_clock].call
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
                
         | 
| 10 | 
            +
                def do_tick
         | 
| 11 | 
            +
                  @actions[:tick].call
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
                
         | 
| 14 | 
            +
                def stop?
         | 
| 15 | 
            +
                  !@actions[:stop_when].nil? && @actions[:stop_when].call
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
               
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
              
         | 
| 20 | 
            +
            end
         | 
    
        data/lib/topaz.rb
    CHANGED
    
    | @@ -9,6 +9,7 @@ require 'gamelan' | |
| 9 9 | 
             
            require 'midi-eye'
         | 
| 10 10 | 
             
            require 'midi-message'
         | 
| 11 11 |  | 
| 12 | 
            +
            require 'topaz/tempo_source'
         | 
| 12 13 | 
             
            require 'topaz/external_midi_tempo'
         | 
| 13 14 | 
             
            require 'topaz/internal_tempo'
         | 
| 14 15 | 
             
            require 'topaz/midi_sync_output'
         | 
| @@ -17,6 +18,6 @@ require 'topaz/tempo' | |
| 17 18 |  | 
| 18 19 | 
             
            module Topaz
         | 
| 19 20 |  | 
| 20 | 
            -
              VERSION = "0.0. | 
| 21 | 
            +
              VERSION = "0.0.5"
         | 
| 21 22 |  | 
| 22 23 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -2,7 +2,7 @@ | |
| 2 2 | 
             
            name: midi-topaz
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 4 | 
             
              prerelease: 
         | 
| 5 | 
            -
              version: 0.0. | 
| 5 | 
            +
              version: 0.0.5
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors: 
         | 
| 8 8 | 
             
            - Ari Russo
         | 
| @@ -10,7 +10,7 @@ autorequire: | |
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 12 |  | 
| 13 | 
            -
            date: 2011-06- | 
| 13 | 
            +
            date: 2011-06-25 00:00:00 -04:00
         | 
| 14 14 | 
             
            default_executable: 
         | 
| 15 15 | 
             
            dependencies: 
         | 
| 16 16 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| @@ -71,6 +71,7 @@ files: | |
| 71 71 | 
             
            - lib/topaz/midi_sync_output.rb
         | 
| 72 72 | 
             
            - lib/topaz/internal_tempo.rb
         | 
| 73 73 | 
             
            - lib/topaz/tempo_calculator.rb
         | 
| 74 | 
            +
            - lib/topaz/tempo_source.rb
         | 
| 74 75 | 
             
            - lib/topaz/external_midi_tempo.rb
         | 
| 75 76 | 
             
            - lib/topaz/tempo.rb
         | 
| 76 77 | 
             
            - test/helper.rb
         |