Sha256: 8d2192261048a4b9af9f76019d299b70f546460cf6285f0be00df832c0f30b58

Contents?: true

Size: 1.54 KB

Versions: 1

Compression:

Stored size: 1.54 KB

Contents

require 'thread'
require 'set'

Thread.abort_on_exception = true

module Xi
  class Clock
    DEFAULT_CPS  = 1.0
    INTERVAL_SEC = 10 / 1000.0

    def initialize(cps: DEFAULT_CPS)
      @mutex = Mutex.new
      @cps = cps
      @playing = true
      @streams = [].to_set
      @play_thread = Thread.new { thread_routine }
    end

    def subscribe(stream)
      @mutex.synchronize { @streams << stream }
    end

    def unsubscribe(stream)
      @mutex.synchronize { @streams.delete(stream) }
    end

    def cps
      @mutex.synchronize { @cps }
    end

    def cps=(new_cps)
      @mutex.synchronize { @cps = new_cps }
    end

    def playing?
      @mutex.synchronize { @playing }
    end

    def stopped?
      !playing?
    end

    def now
      Time.now.to_f * cps
    end

    def play
      @mutex.synchronize { @playing = true }
      self
    end
    alias_method :start, :play

    def stop
      @mutex.synchronize { @playing = false }
      self
    end
    alias_method :pause, :play

    def seconds_per_cycle
      @mutex.synchronize { 1.0 / @cps }
    end

    def at(cycle_pos)
      Time.at(cycle_pos * seconds_per_cycle)
    end

    def inspect
      "#<#{self.class.name}:#{"0x%014x" % object_id} cps=#{cps.inspect} #{playing? ? :playing : :stopped}>"
    end

    private

    def thread_routine
      loop do
        do_tick
        sleep INTERVAL_SEC
      end
    end

    def do_tick
      cycles = Time.now.to_f * cps
      return unless playing?
      @streams.each { |s| s.notify(cycles) }
    rescue => err
      error(err)
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
xi-lang-0.1.3 lib/xi/clock.rb