qlab-ruby 0.1.2
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/.gitignore +21 -0
 - data/Gemfile +4 -0
 - data/LICENSE.txt +22 -0
 - data/README.md +59 -0
 - data/Rakefile +21 -0
 - data/lib/qlab-ruby.rb +34 -0
 - data/lib/qlab-ruby/commands.rb +223 -0
 - data/lib/qlab-ruby/communicator.rb +51 -0
 - data/lib/qlab-ruby/core-ext/osc-ruby.rb +6 -0
 - data/lib/qlab-ruby/core-ext/osc-ruby/message.rb +25 -0
 - data/lib/qlab-ruby/core-ext/osc-ruby/sending_socket.rb +47 -0
 - data/lib/qlab-ruby/core-ext/osc-ruby/tcp.rb +15 -0
 - data/lib/qlab-ruby/core-ext/osc-ruby/tcp_client.rb +125 -0
 - data/lib/qlab-ruby/cue.rb +87 -0
 - data/lib/qlab-ruby/cue_list.rb +72 -0
 - data/lib/qlab-ruby/machine.rb +94 -0
 - data/lib/qlab-ruby/reply.rb +51 -0
 - data/lib/qlab-ruby/version.rb +3 -0
 - data/lib/qlab-ruby/workspace.rb +110 -0
 - data/qlab-ruby.gemspec +24 -0
 - data/test/cue_test.rb +41 -0
 - data/test/machine_test.rb +26 -0
 - data/test/test_helper.rb +4 -0
 - data/test/workspace_test.rb +35 -0
 - metadata +106 -0
 
    
        data/.gitignore
    ADDED
    
    | 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            *.gem
         
     | 
| 
      
 2 
     | 
    
         
            +
            *.rbc
         
     | 
| 
      
 3 
     | 
    
         
            +
            .bundle
         
     | 
| 
      
 4 
     | 
    
         
            +
            .config
         
     | 
| 
      
 5 
     | 
    
         
            +
            .yardoc
         
     | 
| 
      
 6 
     | 
    
         
            +
            Gemfile.lock
         
     | 
| 
      
 7 
     | 
    
         
            +
            InstalledFiles
         
     | 
| 
      
 8 
     | 
    
         
            +
            _yardoc
         
     | 
| 
      
 9 
     | 
    
         
            +
            coverage
         
     | 
| 
      
 10 
     | 
    
         
            +
            doc/
         
     | 
| 
      
 11 
     | 
    
         
            +
            lib/bundler/man
         
     | 
| 
      
 12 
     | 
    
         
            +
            pkg
         
     | 
| 
      
 13 
     | 
    
         
            +
            rdoc
         
     | 
| 
      
 14 
     | 
    
         
            +
            spec/reports
         
     | 
| 
      
 15 
     | 
    
         
            +
            test/tmp
         
     | 
| 
      
 16 
     | 
    
         
            +
            test/version_tmp
         
     | 
| 
      
 17 
     | 
    
         
            +
            tmp
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            # local concerns
         
     | 
| 
      
 20 
     | 
    
         
            +
            .DS_Store
         
     | 
| 
      
 21 
     | 
    
         
            +
            .rake_tasks~
         
     | 
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE.txt
    ADDED
    
    | 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (c) 2013 Adam Bachman
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            MIT License
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining
         
     | 
| 
      
 6 
     | 
    
         
            +
            a copy of this software and associated documentation files (the
         
     | 
| 
      
 7 
     | 
    
         
            +
            "Software"), to deal in the Software without restriction, including
         
     | 
| 
      
 8 
     | 
    
         
            +
            without limitation the rights to use, copy, modify, merge, publish,
         
     | 
| 
      
 9 
     | 
    
         
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         
     | 
| 
      
 10 
     | 
    
         
            +
            permit persons to whom the Software is furnished to do so, subject to
         
     | 
| 
      
 11 
     | 
    
         
            +
            the following conditions:
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be
         
     | 
| 
      
 14 
     | 
    
         
            +
            included in all copies or substantial portions of the Software.
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         
     | 
| 
      
 17 
     | 
    
         
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         
     | 
| 
      
 18 
     | 
    
         
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         
     | 
| 
      
 19 
     | 
    
         
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         
     | 
| 
      
 20 
     | 
    
         
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         
     | 
| 
      
 21 
     | 
    
         
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         
     | 
| 
      
 22 
     | 
    
         
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,59 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # QLab
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Interact with QLab from Ruby.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            ## Installation
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Add this line to your application's Gemfile:
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                gem 'qlab-ruby'
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            And then execute:
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                $ bundle
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            Or install it yourself as:
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                $ gem install qlab-ruby
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            ## Usage
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                > require 'qlab-ruby'
         
     | 
| 
      
 22 
     | 
    
         
            +
                > machine = QLab.connect # defaults to ('localhost', 53000)
         
     | 
| 
      
 23 
     | 
    
         
            +
                > machine.workspaces.first.go
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            And you're off.
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            A `machine` has one or more `workspaces`. A `workspace` has one or more
         
     | 
| 
      
 28 
     | 
    
         
            +
            `cue_lists`. A `cue` can respond to any of the QLab OSC commands.
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                > cue.start
         
     | 
| 
      
 31 
     | 
    
         
            +
                > cue.stop
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            etc.
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            Most OSC commands that accept a single value can be called by their `=`
         
     | 
| 
      
 36 
     | 
    
         
            +
            versions. For example:
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                > cue.rate(0.5)
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            and
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                > cue.rate = 0.5
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            do the same thing.
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            OSC commands that require multiple arguments will still have to be called
         
     | 
| 
      
 47 
     | 
    
         
            +
            as methods.
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                > cue.sliderLevel(1, -5)
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            To set slider 1 to the value -5.
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            ## Contributing
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            1. Fork it
         
     | 
| 
      
 56 
     | 
    
         
            +
            2. Create your feature branch (`git checkout -b my-new-feature`)
         
     | 
| 
      
 57 
     | 
    
         
            +
            3. Commit your changes (`git commit -am 'Add some feature'`)
         
     | 
| 
      
 58 
     | 
    
         
            +
            4. Push to the branch (`git push origin my-new-feature`)
         
     | 
| 
      
 59 
     | 
    
         
            +
            5. Create new Pull Request
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'bundler/gem_tasks'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'rake/testtask'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            gem 'rdoc'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'rdoc/task'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Rake::TestTask.new do |t|
         
     | 
| 
      
 8 
     | 
    
         
            +
              t.libs << 'test'
         
     | 
| 
      
 9 
     | 
    
         
            +
              t.libs << 'qlab-ruby'
         
     | 
| 
      
 10 
     | 
    
         
            +
              t.test_files = FileList['test/*_test.rb']
         
     | 
| 
      
 11 
     | 
    
         
            +
              t.verbose = true
         
     | 
| 
      
 12 
     | 
    
         
            +
            end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            task :default => :test
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            RDoc::Task.new do |rdoc|
         
     | 
| 
      
 17 
     | 
    
         
            +
              rdoc.rdoc_dir = 'rdoc'
         
     | 
| 
      
 18 
     | 
    
         
            +
              rdoc.title = "qlab-ruby #{QLab::VERSION}"
         
     | 
| 
      
 19 
     | 
    
         
            +
              rdoc.rdoc_files.include('README*')
         
     | 
| 
      
 20 
     | 
    
         
            +
              rdoc.rdoc_files.include('lib/**/*.rb')
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/qlab-ruby.rb
    ADDED
    
    | 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "qlab-ruby/version"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "qlab-ruby/core-ext/osc-ruby"
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module QLab
         
     | 
| 
      
 5 
     | 
    
         
            +
              autoload :Commands, 'qlab-ruby/commands'
         
     | 
| 
      
 6 
     | 
    
         
            +
              autoload :Communicator, 'qlab-ruby/communicator'
         
     | 
| 
      
 7 
     | 
    
         
            +
              autoload :Cue, 'qlab-ruby/cue'
         
     | 
| 
      
 8 
     | 
    
         
            +
              autoload :CueList, 'qlab-ruby/cue_list'
         
     | 
| 
      
 9 
     | 
    
         
            +
              autoload :Machine, 'qlab-ruby/machine'
         
     | 
| 
      
 10 
     | 
    
         
            +
              autoload :Reply, 'qlab-ruby/reply'
         
     | 
| 
      
 11 
     | 
    
         
            +
              autoload :Workspace, 'qlab-ruby/workspace'
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 14 
     | 
    
         
            +
                def connect machine_address='localhost', port=53000
         
     | 
| 
      
 15 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 16 
     | 
    
         
            +
                    # global QLab connection
         
     | 
| 
      
 17 
     | 
    
         
            +
                    new_machine = Machine.new(machine_address, port)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  rescue Errno::ECONNREFUSED
         
     | 
| 
      
 19 
     | 
    
         
            +
                    puts "Failed to connect to QLab machine at #{machine_address}:#{port}, please make sure your values are correct and QLab is running."
         
     | 
| 
      
 20 
     | 
    
         
            +
                    raise
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  if new_machine.connected?
         
     | 
| 
      
 24 
     | 
    
         
            +
                    new_machine.alwaysReply = 1
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  new_machine
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def debug msg
         
     | 
| 
      
 31 
     | 
    
         
            +
                  # puts msg
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,223 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module QLab
         
     | 
| 
      
 2 
     | 
    
         
            +
              # All commands QLab accepts
         
     | 
| 
      
 3 
     | 
    
         
            +
              module Commands
         
     | 
| 
      
 4 
     | 
    
         
            +
                MACHINE = %w(
         
     | 
| 
      
 5 
     | 
    
         
            +
                  alwaysReply
         
     | 
| 
      
 6 
     | 
    
         
            +
                  connect
         
     | 
| 
      
 7 
     | 
    
         
            +
                  version
         
     | 
| 
      
 8 
     | 
    
         
            +
                  workingDirectory
         
     | 
| 
      
 9 
     | 
    
         
            +
                  workspaces
         
     | 
| 
      
 10 
     | 
    
         
            +
                )
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                WORKSPACE = %w(
         
     | 
| 
      
 13 
     | 
    
         
            +
                  cueLists
         
     | 
| 
      
 14 
     | 
    
         
            +
                  go
         
     | 
| 
      
 15 
     | 
    
         
            +
                  hardStop
         
     | 
| 
      
 16 
     | 
    
         
            +
                  new
         
     | 
| 
      
 17 
     | 
    
         
            +
                  panic
         
     | 
| 
      
 18 
     | 
    
         
            +
                  pause
         
     | 
| 
      
 19 
     | 
    
         
            +
                  reset
         
     | 
| 
      
 20 
     | 
    
         
            +
                  resume
         
     | 
| 
      
 21 
     | 
    
         
            +
                  runningCues
         
     | 
| 
      
 22 
     | 
    
         
            +
                  runningOrPausedCues
         
     | 
| 
      
 23 
     | 
    
         
            +
                  select
         
     | 
| 
      
 24 
     | 
    
         
            +
                  selectedCues
         
     | 
| 
      
 25 
     | 
    
         
            +
                  stop
         
     | 
| 
      
 26 
     | 
    
         
            +
                  thump
         
     | 
| 
      
 27 
     | 
    
         
            +
                  toggleFullScreen
         
     | 
| 
      
 28 
     | 
    
         
            +
                  updates
         
     | 
| 
      
 29 
     | 
    
         
            +
                )
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                CUE = %w(
         
     | 
| 
      
 32 
     | 
    
         
            +
                  actionElapsed
         
     | 
| 
      
 33 
     | 
    
         
            +
                  allowsEditingDuration
         
     | 
| 
      
 34 
     | 
    
         
            +
                  armed
         
     | 
| 
      
 35 
     | 
    
         
            +
                  children
         
     | 
| 
      
 36 
     | 
    
         
            +
                  colorName
         
     | 
| 
      
 37 
     | 
    
         
            +
                  continueMode
         
     | 
| 
      
 38 
     | 
    
         
            +
                  cueTargetId
         
     | 
| 
      
 39 
     | 
    
         
            +
                  cueTargetNumber
         
     | 
| 
      
 40 
     | 
    
         
            +
                  defaultName
         
     | 
| 
      
 41 
     | 
    
         
            +
                  displayName
         
     | 
| 
      
 42 
     | 
    
         
            +
                  duration
         
     | 
| 
      
 43 
     | 
    
         
            +
                  fileTarget
         
     | 
| 
      
 44 
     | 
    
         
            +
                  flagged
         
     | 
| 
      
 45 
     | 
    
         
            +
                  hardStop
         
     | 
| 
      
 46 
     | 
    
         
            +
                  hasCueTargets
         
     | 
| 
      
 47 
     | 
    
         
            +
                  hasFileTargets
         
     | 
| 
      
 48 
     | 
    
         
            +
                  isBroken
         
     | 
| 
      
 49 
     | 
    
         
            +
                  isLoaded
         
     | 
| 
      
 50 
     | 
    
         
            +
                  isPaused
         
     | 
| 
      
 51 
     | 
    
         
            +
                  isRunning
         
     | 
| 
      
 52 
     | 
    
         
            +
                  listName
         
     | 
| 
      
 53 
     | 
    
         
            +
                  load
         
     | 
| 
      
 54 
     | 
    
         
            +
                  loadAt
         
     | 
| 
      
 55 
     | 
    
         
            +
                  name
         
     | 
| 
      
 56 
     | 
    
         
            +
                  notes
         
     | 
| 
      
 57 
     | 
    
         
            +
                  number
         
     | 
| 
      
 58 
     | 
    
         
            +
                  panic
         
     | 
| 
      
 59 
     | 
    
         
            +
                  pause
         
     | 
| 
      
 60 
     | 
    
         
            +
                  percentActionElapsed
         
     | 
| 
      
 61 
     | 
    
         
            +
                  percentPostWaitElapsed
         
     | 
| 
      
 62 
     | 
    
         
            +
                  percentPreWaitElapsed
         
     | 
| 
      
 63 
     | 
    
         
            +
                  postWait
         
     | 
| 
      
 64 
     | 
    
         
            +
                  postWaitElapsed
         
     | 
| 
      
 65 
     | 
    
         
            +
                  preWait
         
     | 
| 
      
 66 
     | 
    
         
            +
                  preWaitElapsed
         
     | 
| 
      
 67 
     | 
    
         
            +
                  preview
         
     | 
| 
      
 68 
     | 
    
         
            +
                  reset
         
     | 
| 
      
 69 
     | 
    
         
            +
                  resume
         
     | 
| 
      
 70 
     | 
    
         
            +
                  sliderLevel
         
     | 
| 
      
 71 
     | 
    
         
            +
                  sliderLevels
         
     | 
| 
      
 72 
     | 
    
         
            +
                  start
         
     | 
| 
      
 73 
     | 
    
         
            +
                  stop
         
     | 
| 
      
 74 
     | 
    
         
            +
                  togglePause
         
     | 
| 
      
 75 
     | 
    
         
            +
                  type
         
     | 
| 
      
 76 
     | 
    
         
            +
                  uniqueID
         
     | 
| 
      
 77 
     | 
    
         
            +
                  valuesForKeys
         
     | 
| 
      
 78 
     | 
    
         
            +
                )
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                GROUP_CUE = %w(
         
     | 
| 
      
 81 
     | 
    
         
            +
                  playbackPositionId
         
     | 
| 
      
 82 
     | 
    
         
            +
                )
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                AUDIO_CUE = %w(
         
     | 
| 
      
 85 
     | 
    
         
            +
                  doFade
         
     | 
| 
      
 86 
     | 
    
         
            +
                  doPitchShift
         
     | 
| 
      
 87 
     | 
    
         
            +
                  endTime
         
     | 
| 
      
 88 
     | 
    
         
            +
                  infiniteLoop
         
     | 
| 
      
 89 
     | 
    
         
            +
                  level
         
     | 
| 
      
 90 
     | 
    
         
            +
                  patch
         
     | 
| 
      
 91 
     | 
    
         
            +
                  playCount
         
     | 
| 
      
 92 
     | 
    
         
            +
                  rate
         
     | 
| 
      
 93 
     | 
    
         
            +
                  sliderLevel
         
     | 
| 
      
 94 
     | 
    
         
            +
                  sliderLevels
         
     | 
| 
      
 95 
     | 
    
         
            +
                  startTime
         
     | 
| 
      
 96 
     | 
    
         
            +
                )
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                FADE_CUE = %w(
         
     | 
| 
      
 99 
     | 
    
         
            +
                  level
         
     | 
| 
      
 100 
     | 
    
         
            +
                  sliderLevel
         
     | 
| 
      
 101 
     | 
    
         
            +
                  sliderLevels
         
     | 
| 
      
 102 
     | 
    
         
            +
                )
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                MIC_CUE = %w(
         
     | 
| 
      
 105 
     | 
    
         
            +
                  level
         
     | 
| 
      
 106 
     | 
    
         
            +
                  sliderLevel
         
     | 
| 
      
 107 
     | 
    
         
            +
                  sliderLevels
         
     | 
| 
      
 108 
     | 
    
         
            +
                )
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                VIDEO_CUE = %w(
         
     | 
| 
      
 111 
     | 
    
         
            +
                  cueSize
         
     | 
| 
      
 112 
     | 
    
         
            +
                  doEffect
         
     | 
| 
      
 113 
     | 
    
         
            +
                  doFade
         
     | 
| 
      
 114 
     | 
    
         
            +
                  doPitchShift
         
     | 
| 
      
 115 
     | 
    
         
            +
                  effect
         
     | 
| 
      
 116 
     | 
    
         
            +
                  effectSet
         
     | 
| 
      
 117 
     | 
    
         
            +
                  endTime
         
     | 
| 
      
 118 
     | 
    
         
            +
                  fullScreen
         
     | 
| 
      
 119 
     | 
    
         
            +
                  infiniteLoop
         
     | 
| 
      
 120 
     | 
    
         
            +
                  layer
         
     | 
| 
      
 121 
     | 
    
         
            +
                  level
         
     | 
| 
      
 122 
     | 
    
         
            +
                  opacity
         
     | 
| 
      
 123 
     | 
    
         
            +
                  patch
         
     | 
| 
      
 124 
     | 
    
         
            +
                  playCount
         
     | 
| 
      
 125 
     | 
    
         
            +
                  preserveAspectRatio
         
     | 
| 
      
 126 
     | 
    
         
            +
                  quaternion
         
     | 
| 
      
 127 
     | 
    
         
            +
                  rate
         
     | 
| 
      
 128 
     | 
    
         
            +
                  scaleX
         
     | 
| 
      
 129 
     | 
    
         
            +
                  scaleY
         
     | 
| 
      
 130 
     | 
    
         
            +
                  sliderLevel
         
     | 
| 
      
 131 
     | 
    
         
            +
                  sliderLevels
         
     | 
| 
      
 132 
     | 
    
         
            +
                  startTime
         
     | 
| 
      
 133 
     | 
    
         
            +
                  surfaceID
         
     | 
| 
      
 134 
     | 
    
         
            +
                  surfaceList
         
     | 
| 
      
 135 
     | 
    
         
            +
                  surfaceSize
         
     | 
| 
      
 136 
     | 
    
         
            +
                  translationX
         
     | 
| 
      
 137 
     | 
    
         
            +
                  translationY
         
     | 
| 
      
 138 
     | 
    
         
            +
                )
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                # in blocks of: all, group, audio, video, osc, midi, devamp, script
         
     | 
| 
      
 141 
     | 
    
         
            +
                SET_CUES = %w(
         
     | 
| 
      
 142 
     | 
    
         
            +
                  number
         
     | 
| 
      
 143 
     | 
    
         
            +
                  name
         
     | 
| 
      
 144 
     | 
    
         
            +
                  notes
         
     | 
| 
      
 145 
     | 
    
         
            +
                  fileTarget
         
     | 
| 
      
 146 
     | 
    
         
            +
                  cueTargetNumber
         
     | 
| 
      
 147 
     | 
    
         
            +
                  cueTargetId
         
     | 
| 
      
 148 
     | 
    
         
            +
                  preWait
         
     | 
| 
      
 149 
     | 
    
         
            +
                  duration
         
     | 
| 
      
 150 
     | 
    
         
            +
                  postWait
         
     | 
| 
      
 151 
     | 
    
         
            +
                  continueMode
         
     | 
| 
      
 152 
     | 
    
         
            +
                  flagged
         
     | 
| 
      
 153 
     | 
    
         
            +
                  autoLoad
         
     | 
| 
      
 154 
     | 
    
         
            +
                  armed
         
     | 
| 
      
 155 
     | 
    
         
            +
                  colorName
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
                  playbackPositionId
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                  patch
         
     | 
| 
      
 160 
     | 
    
         
            +
                  startTime
         
     | 
| 
      
 161 
     | 
    
         
            +
                  endTime
         
     | 
| 
      
 162 
     | 
    
         
            +
                  playCount
         
     | 
| 
      
 163 
     | 
    
         
            +
                  infiniteLoop
         
     | 
| 
      
 164 
     | 
    
         
            +
                  rate
         
     | 
| 
      
 165 
     | 
    
         
            +
                  doPitchShift
         
     | 
| 
      
 166 
     | 
    
         
            +
                  doFade
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                  surfaceID
         
     | 
| 
      
 169 
     | 
    
         
            +
                  patch
         
     | 
| 
      
 170 
     | 
    
         
            +
                  fullScreen
         
     | 
| 
      
 171 
     | 
    
         
            +
                  layer
         
     | 
| 
      
 172 
     | 
    
         
            +
                  opacity
         
     | 
| 
      
 173 
     | 
    
         
            +
                  preserveAspectRatio
         
     | 
| 
      
 174 
     | 
    
         
            +
                  translationX
         
     | 
| 
      
 175 
     | 
    
         
            +
                  translationY
         
     | 
| 
      
 176 
     | 
    
         
            +
                  scaleX
         
     | 
| 
      
 177 
     | 
    
         
            +
                  scaleY
         
     | 
| 
      
 178 
     | 
    
         
            +
                  doEffect
         
     | 
| 
      
 179 
     | 
    
         
            +
                  effectSet
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                  messageType
         
     | 
| 
      
 182 
     | 
    
         
            +
                  qlabCommand
         
     | 
| 
      
 183 
     | 
    
         
            +
                  qlabCueNumber
         
     | 
| 
      
 184 
     | 
    
         
            +
                  qlabCueParameters
         
     | 
| 
      
 185 
     | 
    
         
            +
                  rawString
         
     | 
| 
      
 186 
     | 
    
         
            +
             
     | 
| 
      
 187 
     | 
    
         
            +
                  duration
         
     | 
| 
      
 188 
     | 
    
         
            +
                  messageType
         
     | 
| 
      
 189 
     | 
    
         
            +
                  status
         
     | 
| 
      
 190 
     | 
    
         
            +
                  channel
         
     | 
| 
      
 191 
     | 
    
         
            +
                  byte1
         
     | 
| 
      
 192 
     | 
    
         
            +
                  byte2
         
     | 
| 
      
 193 
     | 
    
         
            +
                  byteCombo
         
     | 
| 
      
 194 
     | 
    
         
            +
                  doFade
         
     | 
| 
      
 195 
     | 
    
         
            +
                  endValue
         
     | 
| 
      
 196 
     | 
    
         
            +
                  deviceID
         
     | 
| 
      
 197 
     | 
    
         
            +
                  commandFormat
         
     | 
| 
      
 198 
     | 
    
         
            +
                  command
         
     | 
| 
      
 199 
     | 
    
         
            +
                  qNumber
         
     | 
| 
      
 200 
     | 
    
         
            +
                  qList
         
     | 
| 
      
 201 
     | 
    
         
            +
                  qPath
         
     | 
| 
      
 202 
     | 
    
         
            +
                  macro
         
     | 
| 
      
 203 
     | 
    
         
            +
                  controlNumber
         
     | 
| 
      
 204 
     | 
    
         
            +
                  controlValue
         
     | 
| 
      
 205 
     | 
    
         
            +
                  timecodeString
         
     | 
| 
      
 206 
     | 
    
         
            +
                  hours
         
     | 
| 
      
 207 
     | 
    
         
            +
                  minutes
         
     | 
| 
      
 208 
     | 
    
         
            +
                  seconds
         
     | 
| 
      
 209 
     | 
    
         
            +
                  frames
         
     | 
| 
      
 210 
     | 
    
         
            +
                  subframes
         
     | 
| 
      
 211 
     | 
    
         
            +
                  timecodeFormat
         
     | 
| 
      
 212 
     | 
    
         
            +
                  rawString
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
                  startNextCueWhenSliceEnds
         
     | 
| 
      
 215 
     | 
    
         
            +
                  stopTargetWhenSliceEnds
         
     | 
| 
      
 216 
     | 
    
         
            +
             
     | 
| 
      
 217 
     | 
    
         
            +
                  scriptSource
         
     | 
| 
      
 218 
     | 
    
         
            +
                )
         
     | 
| 
      
 219 
     | 
    
         
            +
             
     | 
| 
      
 220 
     | 
    
         
            +
                ALL_CUES = (CUE + GROUP_CUE + AUDIO_CUE + FADE_CUE + MIC_CUE + VIDEO_CUE).uniq.sort
         
     | 
| 
      
 221 
     | 
    
         
            +
              end
         
     | 
| 
      
 222 
     | 
    
         
            +
            end
         
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module QLab
         
     | 
| 
      
 2 
     | 
    
         
            +
              # An abstract class providing communication behavior for objects that need to
         
     | 
| 
      
 3 
     | 
    
         
            +
              # interact with QLab.
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Communicator
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def send_message osc_address, *osc_arguments
         
     | 
| 
      
 7 
     | 
    
         
            +
                  osc_address = format_osc_address(osc_address)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  if osc_arguments.size > 0
         
     | 
| 
      
 10 
     | 
    
         
            +
                    osc_message = OSC::Message.new osc_address, *osc_arguments
         
     | 
| 
      
 11 
     | 
    
         
            +
                  else
         
     | 
| 
      
 12 
     | 
    
         
            +
                    osc_message = OSC::Message.new osc_address
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
                  responses = []
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  QLab.debug "[Action send_message] send #{ osc_message.encode }"
         
     | 
| 
      
 17 
     | 
    
         
            +
                  connection.send(osc_message) do |response|
         
     | 
| 
      
 18 
     | 
    
         
            +
                    responses << QLab::Reply.new(response)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  if responses.size == 1
         
     | 
| 
      
 22 
     | 
    
         
            +
                    q_reply = responses[0]
         
     | 
| 
      
 23 
     | 
    
         
            +
                    QLab.debug "[Action send_message] got one response: #{q_reply.inspect}"
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    if q_reply.has_data?
         
     | 
| 
      
 26 
     | 
    
         
            +
                      QLab.debug "[Action send_message] single response has data: #{q_reply.data.inspect}"
         
     | 
| 
      
 27 
     | 
    
         
            +
                      q_reply.data
         
     | 
| 
      
 28 
     | 
    
         
            +
                    elsif q_reply.has_status?
         
     | 
| 
      
 29 
     | 
    
         
            +
                      QLab.debug "[Action send_message] single response has status: #{q_reply.status.inspect}"
         
     | 
| 
      
 30 
     | 
    
         
            +
                      q_reply.status
         
     | 
| 
      
 31 
     | 
    
         
            +
                    else
         
     | 
| 
      
 32 
     | 
    
         
            +
                      QLab.debug "[Action send_message] single response has no data or status: #{q_reply.inspect}"
         
     | 
| 
      
 33 
     | 
    
         
            +
                      q_reply
         
     | 
| 
      
 34 
     | 
    
         
            +
                    end
         
     | 
| 
      
 35 
     | 
    
         
            +
                  else
         
     | 
| 
      
 36 
     | 
    
         
            +
                    responses
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                private
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def format_osc_address address
         
     | 
| 
      
 43 
     | 
    
         
            +
                  if %r[^/] !~ address.to_s
         
     | 
| 
      
 44 
     | 
    
         
            +
                    "/#{ address }"
         
     | 
| 
      
 45 
     | 
    
         
            +
                  else
         
     | 
| 
      
 46 
     | 
    
         
            +
                    address
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module OSC
         
     | 
| 
      
 2 
     | 
    
         
            +
              # Reopen the osc-ruby Message class to provide additional methods to support
         
     | 
| 
      
 3 
     | 
    
         
            +
              # QLab's use of OSC.
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Message
         
     | 
| 
      
 5 
     | 
    
         
            +
                def has_arguments?
         
     | 
| 
      
 6 
     | 
    
         
            +
                  to_a.size > 0
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                # attachable responder, for use with TCP::Server
         
     | 
| 
      
 10 
     | 
    
         
            +
                def responder
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @responder
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def responder=(val)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @responder = val
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def debug
         
     | 
| 
      
 19 
     | 
    
         
            +
                  types = to_a.map(&:class).map(&:to_s).join(', ')
         
     | 
| 
      
 20 
     | 
    
         
            +
                  args  = to_a
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  "#{ip_address}:#{ip_port} -- #{address} -- [#{ types }] -- #{ args.inspect }"
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module OSC
         
     | 
| 
      
 2 
     | 
    
         
            +
              module TCP
         
     | 
| 
      
 3 
     | 
    
         
            +
                # A wrapper around an open TCP socket providing SLIP encoding for outbound
         
     | 
| 
      
 4 
     | 
    
         
            +
                # messages.
         
     | 
| 
      
 5 
     | 
    
         
            +
                class SendingSocket
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize socket
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @socket = socket
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  # send SLIP encoded OSC messages
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def send msg
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @socket_buffer = []
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    enc_msg = msg.encode
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    send_char CHAR_END
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    enc_msg.bytes.each do |b|
         
     | 
| 
      
 19 
     | 
    
         
            +
                      case b
         
     | 
| 
      
 20 
     | 
    
         
            +
                      when CHAR_END
         
     | 
| 
      
 21 
     | 
    
         
            +
                        send_char CHAR_ESC
         
     | 
| 
      
 22 
     | 
    
         
            +
                        send_char CHAR_ESC_END
         
     | 
| 
      
 23 
     | 
    
         
            +
                      when CHAR_ESC
         
     | 
| 
      
 24 
     | 
    
         
            +
                        send_char CHAR_ESC
         
     | 
| 
      
 25 
     | 
    
         
            +
                        send_char CHAR_ESC_ESC
         
     | 
| 
      
 26 
     | 
    
         
            +
                      else
         
     | 
| 
      
 27 
     | 
    
         
            +
                        send_char b
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    send_char CHAR_END
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    flush
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  private
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  def flush
         
     | 
| 
      
 39 
     | 
    
         
            +
                    @socket.send @socket_buffer.join, 0
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  def send_char c
         
     | 
| 
      
 43 
     | 
    
         
            +
                    @socket_buffer << [c].pack('C')
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module OSC
         
     | 
| 
      
 2 
     | 
    
         
            +
              # SLIP encoding constants.
         
     | 
| 
      
 3 
     | 
    
         
            +
              module TCP
         
     | 
| 
      
 4 
     | 
    
         
            +
                CHAR_END     = 0300 # indicates end of packet
         
     | 
| 
      
 5 
     | 
    
         
            +
                CHAR_ESC     = 0333 # indicates byte stuffing
         
     | 
| 
      
 6 
     | 
    
         
            +
                CHAR_ESC_END = 0334 # ESC ESC_END means END data byte
         
     | 
| 
      
 7 
     | 
    
         
            +
                CHAR_ESC_ESC = 0335 # ESC ESC_ESC means ESC data byte
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                CHAR_END_ENC     = [0300].pack('C') # indicates end of packet
         
     | 
| 
      
 10 
     | 
    
         
            +
                CHAR_ESC_ENC     = [0333].pack('C') # indicates byte stuffing
         
     | 
| 
      
 11 
     | 
    
         
            +
                CHAR_ESC_END_ENC = [0334].pack('C') # ESC ESC_END means END data byte
         
     | 
| 
      
 12 
     | 
    
         
            +
                CHAR_ESC_ESC_ENC = [0335].pack('C') # ESC ESC_ESC means ESC data byte
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,125 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # A responsive OSC TCP client that sends and receives OSC messages on a single socket using the SLIP protocol.
         
     | 
| 
      
 2 
     | 
    
         
            +
            #
         
     | 
| 
      
 3 
     | 
    
         
            +
            # http://www.ietf.org/rfc/rfc1055.txt
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'socket'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module OSC
         
     | 
| 
      
 7 
     | 
    
         
            +
              module TCP
         
     | 
| 
      
 8 
     | 
    
         
            +
                class Client
         
     | 
| 
      
 9 
     | 
    
         
            +
                  def initialize host, port, handler=nil
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @host = host
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @port = port
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @handler = handler
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @socket = TCPSocket.new host, port
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @sending_socket = OSC::TCP::SendingSocket.new @socket
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def close
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @socket.close unless closed?
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def closed?
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @socket.closed?
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  # Send an OSC::Message and handle the response if one is given.
         
     | 
| 
      
 26 
     | 
    
         
            +
                  def send msg
         
     | 
| 
      
 27 
     | 
    
         
            +
                    @sending_socket.send(msg)
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                    if block_given? || @handler
         
     | 
| 
      
 30 
     | 
    
         
            +
                      messages = response
         
     | 
| 
      
 31 
     | 
    
         
            +
                      if !messages.nil?
         
     | 
| 
      
 32 
     | 
    
         
            +
                        messages.each do |message|
         
     | 
| 
      
 33 
     | 
    
         
            +
                          if block_given?
         
     | 
| 
      
 34 
     | 
    
         
            +
                            yield message
         
     | 
| 
      
 35 
     | 
    
         
            +
                          else
         
     | 
| 
      
 36 
     | 
    
         
            +
                            @handler.handle message
         
     | 
| 
      
 37 
     | 
    
         
            +
                          end
         
     | 
| 
      
 38 
     | 
    
         
            +
                        end
         
     | 
| 
      
 39 
     | 
    
         
            +
                      end
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  def response
         
     | 
| 
      
 44 
     | 
    
         
            +
                    if received_messages = receive_raw
         
     | 
| 
      
 45 
     | 
    
         
            +
                      received_messages.map do |message|
         
     | 
| 
      
 46 
     | 
    
         
            +
                        OSCPacket.messages_from_network(message)
         
     | 
| 
      
 47 
     | 
    
         
            +
                      end.flatten
         
     | 
| 
      
 48 
     | 
    
         
            +
                    else
         
     | 
| 
      
 49 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  def to_s
         
     | 
| 
      
 54 
     | 
    
         
            +
                    "#<OSC::TCP::Client:#{ object_id } @host:#{ @host.inspect }, @port:#{ @port.inspect }, @handler:#{ @handler.to_s }>"
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  private
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  def receive_raw
         
     | 
| 
      
 60 
     | 
    
         
            +
                    received = 0
         
     | 
| 
      
 61 
     | 
    
         
            +
                    messages = []
         
     | 
| 
      
 62 
     | 
    
         
            +
                    buffer   = []
         
     | 
| 
      
 63 
     | 
    
         
            +
                    failed   = false
         
     | 
| 
      
 64 
     | 
    
         
            +
                    received_any = false
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                    loop do
         
     | 
| 
      
 67 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 68 
     | 
    
         
            +
                        # get a character from the socket, fail if nothing is available
         
     | 
| 
      
 69 
     | 
    
         
            +
                        c = @socket.recv_nonblock(1)
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                        received_any = true
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                        case c
         
     | 
| 
      
 74 
     | 
    
         
            +
                        when CHAR_END_ENC
         
     | 
| 
      
 75 
     | 
    
         
            +
                          if received > 0
         
     | 
| 
      
 76 
     | 
    
         
            +
                            # add SLIP encoded message to list
         
     | 
| 
      
 77 
     | 
    
         
            +
                            messages << buffer.join
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                            # reset state and keep reading from the port until there's nothing left
         
     | 
| 
      
 80 
     | 
    
         
            +
                            buffer.clear
         
     | 
| 
      
 81 
     | 
    
         
            +
                            received = 0
         
     | 
| 
      
 82 
     | 
    
         
            +
                            failed = false
         
     | 
| 
      
 83 
     | 
    
         
            +
                          end
         
     | 
| 
      
 84 
     | 
    
         
            +
                        when CHAR_ESC_ENC
         
     | 
| 
      
 85 
     | 
    
         
            +
                          # get next character, blocking is okay
         
     | 
| 
      
 86 
     | 
    
         
            +
                          c = @socket.recv(1)
         
     | 
| 
      
 87 
     | 
    
         
            +
                          case c
         
     | 
| 
      
 88 
     | 
    
         
            +
                          when CHAR_ESC_END_ENC
         
     | 
| 
      
 89 
     | 
    
         
            +
                            c = CHAR_END_ENC
         
     | 
| 
      
 90 
     | 
    
         
            +
                          when CHAR_ESC_ESC_ENC
         
     | 
| 
      
 91 
     | 
    
         
            +
                            c = CHAR_ESC_ENC
         
     | 
| 
      
 92 
     | 
    
         
            +
                          else
         
     | 
| 
      
 93 
     | 
    
         
            +
                            received += 1
         
     | 
| 
      
 94 
     | 
    
         
            +
                            buffer << c
         
     | 
| 
      
 95 
     | 
    
         
            +
                          end
         
     | 
| 
      
 96 
     | 
    
         
            +
                        else
         
     | 
| 
      
 97 
     | 
    
         
            +
                          received += 1
         
     | 
| 
      
 98 
     | 
    
         
            +
                          buffer << c
         
     | 
| 
      
 99 
     | 
    
         
            +
                        end
         
     | 
| 
      
 100 
     | 
    
         
            +
                      rescue Errno::EAGAIN, Errno::EWOULDBLOCK
         
     | 
| 
      
 101 
     | 
    
         
            +
                        # If any messages have been received, assume sender is done sending.
         
     | 
| 
      
 102 
     | 
    
         
            +
                        if failed || received_any
         
     | 
| 
      
 103 
     | 
    
         
            +
                          break
         
     | 
| 
      
 104 
     | 
    
         
            +
                        end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                        # wait one second to see if the socket might become readable (and a
         
     | 
| 
      
 107 
     | 
    
         
            +
                        # response forthcoming). normal usage is send + receive response, but
         
     | 
| 
      
 108 
     | 
    
         
            +
                        # if app doesn't intend to respond we should eventually ignore it.
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                        IO.select([@socket], [], [], 0.2)
         
     | 
| 
      
 111 
     | 
    
         
            +
                        failed = true
         
     | 
| 
      
 112 
     | 
    
         
            +
                        retry
         
     | 
| 
      
 113 
     | 
    
         
            +
                      end
         
     | 
| 
      
 114 
     | 
    
         
            +
                    end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                    if messages.size > 0
         
     | 
| 
      
 117 
     | 
    
         
            +
                      messages
         
     | 
| 
      
 118 
     | 
    
         
            +
                    else
         
     | 
| 
      
 119 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 120 
     | 
    
         
            +
                    end
         
     | 
| 
      
 121 
     | 
    
         
            +
                  end
         
     | 
| 
      
 122 
     | 
    
         
            +
                end
         
     | 
| 
      
 123 
     | 
    
         
            +
              end
         
     | 
| 
      
 124 
     | 
    
         
            +
            end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,87 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module QLab
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Cue < Communicator
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_accessor :data
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                # Load a cue with the attributes given in `data`
         
     | 
| 
      
 6 
     | 
    
         
            +
                def initialize data, cue_list
         
     | 
| 
      
 7 
     | 
    
         
            +
                  self.data = data
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @cue_list = cue_list
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                # All cue commands for all cue types as listed in Figure53 QLab OSC Reference
         
     | 
| 
      
 12 
     | 
    
         
            +
                Commands::ALL_CUES.each do |command|
         
     | 
| 
      
 13 
     | 
    
         
            +
                  define_method(command.to_sym) do |*args|
         
     | 
| 
      
 14 
     | 
    
         
            +
                    if args.size > 0
         
     | 
| 
      
 15 
     | 
    
         
            +
                      send_message cue_command(command), *args
         
     | 
| 
      
 16 
     | 
    
         
            +
                    else
         
     | 
| 
      
 17 
     | 
    
         
            +
                      send_message cue_command(command)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                # Define commands with single settable values as command= methods
         
     | 
| 
      
 23 
     | 
    
         
            +
                # for convenience. All command-as-method commands will act as setters
         
     | 
| 
      
 24 
     | 
    
         
            +
                # if given an argument.
         
     | 
| 
      
 25 
     | 
    
         
            +
                #
         
     | 
| 
      
 26 
     | 
    
         
            +
                # For exmaple:
         
     | 
| 
      
 27 
     | 
    
         
            +
                #
         
     | 
| 
      
 28 
     | 
    
         
            +
                #   cue.name = "A Name"
         
     | 
| 
      
 29 
     | 
    
         
            +
                #
         
     | 
| 
      
 30 
     | 
    
         
            +
                # is functionally equivalent to
         
     | 
| 
      
 31 
     | 
    
         
            +
                #
         
     | 
| 
      
 32 
     | 
    
         
            +
                #   cue.name("A Name")
         
     | 
| 
      
 33 
     | 
    
         
            +
                #
         
     | 
| 
      
 34 
     | 
    
         
            +
                # as far as QLab is concerned
         
     | 
| 
      
 35 
     | 
    
         
            +
                #
         
     | 
| 
      
 36 
     | 
    
         
            +
                Commands::SET_CUES.each do |command|
         
     | 
| 
      
 37 
     | 
    
         
            +
                  define_method("#{ command }=".to_sym) do |value|
         
     | 
| 
      
 38 
     | 
    
         
            +
                    send_message cue_command(command), value
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                # The cue's `uniqueID`.
         
     | 
| 
      
 43 
     | 
    
         
            +
                def id
         
     | 
| 
      
 44 
     | 
    
         
            +
                  data['uniqueID']
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                # Check whether this cue has nested cues.
         
     | 
| 
      
 48 
     | 
    
         
            +
                def has_cues?
         
     | 
| 
      
 49 
     | 
    
         
            +
                  cues.size > 0
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                # Get the list of nested cues.
         
     | 
| 
      
 53 
     | 
    
         
            +
                def cues
         
     | 
| 
      
 54 
     | 
    
         
            +
                  if data['cues'].nil?
         
     | 
| 
      
 55 
     | 
    
         
            +
                    []
         
     | 
| 
      
 56 
     | 
    
         
            +
                  else
         
     | 
| 
      
 57 
     | 
    
         
            +
                    data['cues'].map {|c| Cue.new(c, @cue_list)}
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                # Compare with another Cue.
         
     | 
| 
      
 62 
     | 
    
         
            +
                def ==(other)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  if other.is_a?(Cue)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    self.data = other.data
         
     | 
| 
      
 65 
     | 
    
         
            +
                  else
         
     | 
| 
      
 66 
     | 
    
         
            +
                    false
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                # A reference to the cue's workspace.
         
     | 
| 
      
 71 
     | 
    
         
            +
                def workspace
         
     | 
| 
      
 72 
     | 
    
         
            +
                  @cue_list.workspace
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                protected
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                def connection
         
     | 
| 
      
 78 
     | 
    
         
            +
                  workspace.connection
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                private
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                def cue_command command
         
     | 
| 
      
 84 
     | 
    
         
            +
                  "/workspace/#{ workspace.id }/cue_id/#{ id }/#{ command }"
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
              end
         
     | 
| 
      
 87 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,72 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module QLab
         
     | 
| 
      
 2 
     | 
    
         
            +
              #  An array of cue objects:
         
     | 
| 
      
 3 
     | 
    
         
            +
              #
         
     | 
| 
      
 4 
     | 
    
         
            +
              #  [
         
     | 
| 
      
 5 
     | 
    
         
            +
              #      {
         
     | 
| 
      
 6 
     | 
    
         
            +
              #          "uniqueID": string,
         
     | 
| 
      
 7 
     | 
    
         
            +
              #          "number": string
         
     | 
| 
      
 8 
     | 
    
         
            +
              #          "name": string
         
     | 
| 
      
 9 
     | 
    
         
            +
              #          "type": string
         
     | 
| 
      
 10 
     | 
    
         
            +
              #          "colorName": string
         
     | 
| 
      
 11 
     | 
    
         
            +
              #          "flagged": number
         
     | 
| 
      
 12 
     | 
    
         
            +
              #          "armed": number
         
     | 
| 
      
 13 
     | 
    
         
            +
              #      }
         
     | 
| 
      
 14 
     | 
    
         
            +
              #  ]
         
     | 
| 
      
 15 
     | 
    
         
            +
              #
         
     | 
| 
      
 16 
     | 
    
         
            +
              #  If a given cue is a group, it will include the nested cues:
         
     | 
| 
      
 17 
     | 
    
         
            +
              #
         
     | 
| 
      
 18 
     | 
    
         
            +
              #  [
         
     | 
| 
      
 19 
     | 
    
         
            +
              #      {
         
     | 
| 
      
 20 
     | 
    
         
            +
              #          "uniqueID": string,
         
     | 
| 
      
 21 
     | 
    
         
            +
              #          "number": string
         
     | 
| 
      
 22 
     | 
    
         
            +
              #          "name": string
         
     | 
| 
      
 23 
     | 
    
         
            +
              #          "type": string
         
     | 
| 
      
 24 
     | 
    
         
            +
              #          "colorName": string
         
     | 
| 
      
 25 
     | 
    
         
            +
              #          "flagged": number
         
     | 
| 
      
 26 
     | 
    
         
            +
              #          "armed": number
         
     | 
| 
      
 27 
     | 
    
         
            +
              #          "cues": [ { }, { }, { } ]
         
     | 
| 
      
 28 
     | 
    
         
            +
              #      }
         
     | 
| 
      
 29 
     | 
    
         
            +
              #  ]
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              class CueList
         
     | 
| 
      
 32 
     | 
    
         
            +
                attr_accessor :data
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                # Load a cue list with the attributes given in `data`
         
     | 
| 
      
 35 
     | 
    
         
            +
                def initialize data, workspace
         
     | 
| 
      
 36 
     | 
    
         
            +
                  self.data = data
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @workspace = workspace
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def workspace
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @workspace
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                def id
         
     | 
| 
      
 45 
     | 
    
         
            +
                  data['uniqueID']
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def name
         
     | 
| 
      
 49 
     | 
    
         
            +
                  data['listName']
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def number
         
     | 
| 
      
 53 
     | 
    
         
            +
                  data['number']
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                def type
         
     | 
| 
      
 57 
     | 
    
         
            +
                  data['type']
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def cues
         
     | 
| 
      
 61 
     | 
    
         
            +
                  if data['cues'].nil?
         
     | 
| 
      
 62 
     | 
    
         
            +
                    []
         
     | 
| 
      
 63 
     | 
    
         
            +
                  else
         
     | 
| 
      
 64 
     | 
    
         
            +
                    data['cues'].map {|c| QLab::Cue.new(c, self)}
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                def has_cues?
         
     | 
| 
      
 69 
     | 
    
         
            +
                  cues.size > 0
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,94 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module QLab
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Machine < Communicator
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_accessor :name, :address, :port
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                # Connect to a running QLab instance. `address` can be a domain name or an
         
     | 
| 
      
 6 
     | 
    
         
            +
                # IP Address.
         
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(_address, _port)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  self.name = _address
         
     | 
| 
      
 9 
     | 
    
         
            +
                  self.address = _address
         
     | 
| 
      
 10 
     | 
    
         
            +
                  self.port = _port
         
     | 
| 
      
 11 
     | 
    
         
            +
                  connect
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                # auto-generate methods first so that manually defined methods will
         
     | 
| 
      
 15 
     | 
    
         
            +
                # override
         
     | 
| 
      
 16 
     | 
    
         
            +
                Commands::MACHINE.each do |command|
         
     | 
| 
      
 17 
     | 
    
         
            +
                  define_method(command.to_sym) do |*args|
         
     | 
| 
      
 18 
     | 
    
         
            +
                    if args.size > 0
         
     | 
| 
      
 19 
     | 
    
         
            +
                      send_message command, *args
         
     | 
| 
      
 20 
     | 
    
         
            +
                    else
         
     | 
| 
      
 21 
     | 
    
         
            +
                      send_message command
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                # Open and return a connection to the running QLab instance
         
     | 
| 
      
 27 
     | 
    
         
            +
                def connect
         
     | 
| 
      
 28 
     | 
    
         
            +
                  if !connected?
         
     | 
| 
      
 29 
     | 
    
         
            +
                    @connection = OSC::TCP::Client.new(@address, @port)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  else
         
     | 
| 
      
 31 
     | 
    
         
            +
                    connection
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                # Reference to the running QLab instance
         
     | 
| 
      
 36 
     | 
    
         
            +
                def connection
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @connection || connect
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                # The workspaces provided by the connected QLab instance
         
     | 
| 
      
 41 
     | 
    
         
            +
                def workspaces
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @workspaces || load_workspaces
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                # Find a workspace according to the given params.
         
     | 
| 
      
 47 
     | 
    
         
            +
                def find_workspace params={}
         
     | 
| 
      
 48 
     | 
    
         
            +
                  workspaces.find do |ws|
         
     | 
| 
      
 49 
     | 
    
         
            +
                    matches = true
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    # match each key to the given workspace
         
     | 
| 
      
 52 
     | 
    
         
            +
                    params.keys.each do |key|
         
     | 
| 
      
 53 
     | 
    
         
            +
                      matches = matches && (ws.send(key.to_sym) == params[key])
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                    matches
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def connected?
         
     | 
| 
      
 61 
     | 
    
         
            +
                  !(@connection.nil? || send_message('/version').nil?)
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                def close
         
     | 
| 
      
 65 
     | 
    
         
            +
                  @connection.close
         
     | 
| 
      
 66 
     | 
    
         
            +
                  @connection = nil
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                def refresh
         
     | 
| 
      
 70 
     | 
    
         
            +
                  close
         
     | 
| 
      
 71 
     | 
    
         
            +
                  connect
         
     | 
| 
      
 72 
     | 
    
         
            +
                  load_workspaces
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                def alwaysReply=(value)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  # send set command
         
     | 
| 
      
 77 
     | 
    
         
            +
                  alwaysReply(value)
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                private
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                def load_workspaces
         
     | 
| 
      
 83 
     | 
    
         
            +
                  @workspaces = []
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  data = send_message('/workspaces')
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  data.map do |ws|
         
     | 
| 
      
 88 
     | 
    
         
            +
                    @workspaces << QLab::Workspace.new(ws, self)
         
     | 
| 
      
 89 
     | 
    
         
            +
                  end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                  @workspaces
         
     | 
| 
      
 92 
     | 
    
         
            +
                end
         
     | 
| 
      
 93 
     | 
    
         
            +
              end
         
     | 
| 
      
 94 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module QLab
         
     | 
| 
      
 4 
     | 
    
         
            +
              # QLab OSC reply unpacker.
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Reply < Struct.new(:osc_message)
         
     | 
| 
      
 6 
     | 
    
         
            +
                def address
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @address ||= json['address']
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def data
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @data ||= json['data']
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def status
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @status ||= json['status']
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def has_data?
         
     | 
| 
      
 19 
     | 
    
         
            +
                  !data.nil?
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                def has_status?
         
     | 
| 
      
 23 
     | 
    
         
            +
                  !status.nil?
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def ok?
         
     | 
| 
      
 27 
     | 
    
         
            +
                  status == 'ok'
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def empty?
         
     | 
| 
      
 31 
     | 
    
         
            +
                  false
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 35 
     | 
    
         
            +
                  "<QLab::Reply address:'#{address}' status:'#{status}' data:#{data.inspect}>"
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                protected
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                # Actually perform the message unpacking
         
     | 
| 
      
 41 
     | 
    
         
            +
                def json
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @json ||= begin
         
     | 
| 
      
 43 
     | 
    
         
            +
                              JSON.parse(osc_message.to_a.first)
         
     | 
| 
      
 44 
     | 
    
         
            +
                            rescue => ex
         
     | 
| 
      
 45 
     | 
    
         
            +
                              puts ex.message
         
     | 
| 
      
 46 
     | 
    
         
            +
                              {}
         
     | 
| 
      
 47 
     | 
    
         
            +
                            end
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,110 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module QLab
         
     | 
| 
      
 2 
     | 
    
         
            +
              #
         
     | 
| 
      
 3 
     | 
    
         
            +
              #   "uniqueID": string,
         
     | 
| 
      
 4 
     | 
    
         
            +
              #   "displayName": string
         
     | 
| 
      
 5 
     | 
    
         
            +
              #   "hasPasscode": number
         
     | 
| 
      
 6 
     | 
    
         
            +
              #
         
     | 
| 
      
 7 
     | 
    
         
            +
              class Workspace < Communicator
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_accessor :data, :passcode
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                # Load a workspace with the attributes given in `data`
         
     | 
| 
      
 11 
     | 
    
         
            +
                def initialize data, machine
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @machine = machine
         
     | 
| 
      
 13 
     | 
    
         
            +
                  self.data = data
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                Commands::WORKSPACE.each do |command|
         
     | 
| 
      
 17 
     | 
    
         
            +
                  define_method(command.to_sym) do |*args|
         
     | 
| 
      
 18 
     | 
    
         
            +
                    if args.size > 0
         
     | 
| 
      
 19 
     | 
    
         
            +
                      send_message workspace_command(command), *args
         
     | 
| 
      
 20 
     | 
    
         
            +
                    else
         
     | 
| 
      
 21 
     | 
    
         
            +
                      send_message workspace_command(command)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def connection
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @machine.connection
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def name
         
     | 
| 
      
 31 
     | 
    
         
            +
                  data['displayName']
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def passcode?
         
     | 
| 
      
 35 
     | 
    
         
            +
                  !!data['hasPasscode']
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def id
         
     | 
| 
      
 39 
     | 
    
         
            +
                  data['uniqueID']
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                # all cues in this workspace in a flat list
         
     | 
| 
      
 43 
     | 
    
         
            +
                def cues
         
     | 
| 
      
 44 
     | 
    
         
            +
                  cue_lists.map do |cl|
         
     | 
| 
      
 45 
     | 
    
         
            +
                    load_cues(cl, [])
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end.flatten.compact
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def has_cues?
         
     | 
| 
      
 50 
     | 
    
         
            +
                  cues.size > 0
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                def cue_lists
         
     | 
| 
      
 54 
     | 
    
         
            +
                  refresh
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @cue_lists
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                def refresh
         
     | 
| 
      
 59 
     | 
    
         
            +
                  if passcode?
         
     | 
| 
      
 60 
     | 
    
         
            +
                    if passcode.nil?
         
     | 
| 
      
 61 
     | 
    
         
            +
                      raise WorkspaceConnectionError.new("Workspace '#{ name }' requires a passcode.")
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                    args = [workspace_command('connect'), ('%04i' % passcode)]
         
     | 
| 
      
 65 
     | 
    
         
            +
                  else
         
     | 
| 
      
 66 
     | 
    
         
            +
                    args = [workspace_command('connect')]
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
                  connect_response = send_message(*args)
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  if connect_response == 'ok'
         
     | 
| 
      
 71 
     | 
    
         
            +
                    @cue_lists = []
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                    cues_response = send_message workspace_command('cueLists')
         
     | 
| 
      
 74 
     | 
    
         
            +
                    cues_response.each do |cuelist|
         
     | 
| 
      
 75 
     | 
    
         
            +
                      @cue_lists << QLab::CueList.new(cuelist, self)
         
     | 
| 
      
 76 
     | 
    
         
            +
                    end
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                def find_cue params={}
         
     | 
| 
      
 81 
     | 
    
         
            +
                  cues.find do |cue|
         
     | 
| 
      
 82 
     | 
    
         
            +
                    matches = true
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                    # match each key to the given cue
         
     | 
| 
      
 85 
     | 
    
         
            +
                    params.keys.each do |key|
         
     | 
| 
      
 86 
     | 
    
         
            +
                      matches = matches && (cue.send(key.to_sym) == params[key])
         
     | 
| 
      
 87 
     | 
    
         
            +
                    end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                    matches
         
     | 
| 
      
 90 
     | 
    
         
            +
                  end
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                private
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                def workspace_command command
         
     | 
| 
      
 96 
     | 
    
         
            +
                  "/workspace/#{id}/#{ command }"
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                def load_cues parent_cue, cues
         
     | 
| 
      
 100 
     | 
    
         
            +
                  parent_cue.cues.each {|child_cue|
         
     | 
| 
      
 101 
     | 
    
         
            +
                    cues << child_cue
         
     | 
| 
      
 102 
     | 
    
         
            +
                    load_cues child_cue, cues
         
     | 
| 
      
 103 
     | 
    
         
            +
                  }
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                  cues
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
              class WorkspaceConnectionError < Exception; end
         
     | 
| 
      
 110 
     | 
    
         
            +
            end
         
     | 
    
        data/qlab-ruby.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            lib = File.expand_path('../lib', __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'qlab-ruby/version'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Gem::Specification.new do |gem|
         
     | 
| 
      
 7 
     | 
    
         
            +
              gem.name          = "qlab-ruby"
         
     | 
| 
      
 8 
     | 
    
         
            +
              gem.version       = QLab::VERSION
         
     | 
| 
      
 9 
     | 
    
         
            +
              gem.authors       = ["Adam Bachman"]
         
     | 
| 
      
 10 
     | 
    
         
            +
              gem.email         = ["adam@figure53.com"]
         
     | 
| 
      
 11 
     | 
    
         
            +
              gem.description   = %q{Interact with QLab in Ruby.}
         
     | 
| 
      
 12 
     | 
    
         
            +
              gem.summary       = %q{Interact with QLab in Ruby.}
         
     | 
| 
      
 13 
     | 
    
         
            +
              gem.homepage      = "https://github.com/Figure53/qlab-ruby"
         
     | 
| 
      
 14 
     | 
    
         
            +
              gem.license       = 'MIT'
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              gem.files         = `git ls-files`.split($/)
         
     | 
| 
      
 17 
     | 
    
         
            +
              gem.executables   = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
         
     | 
| 
      
 18 
     | 
    
         
            +
              gem.test_files    = gem.files.grep(%r{^(test|spec|features)/})
         
     | 
| 
      
 19 
     | 
    
         
            +
              gem.require_paths = ["lib"]
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              gem.add_runtime_dependency 'osc-ruby'
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              gem.add_development_dependency 'rdoc'
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
    
        data/test/cue_test.rb
    ADDED
    
    | 
         @@ -0,0 +1,41 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'test_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class CueTest < Minitest::Test
         
     | 
| 
      
 4 
     | 
    
         
            +
              def setup
         
     | 
| 
      
 5 
     | 
    
         
            +
                @machine = QLab.connect 'localhost', 53000
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              def teardown
         
     | 
| 
      
 9 
     | 
    
         
            +
                @machine.close
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              def test_a_cue_is_reachable
         
     | 
| 
      
 13 
     | 
    
         
            +
                workspace = @machine.workspaces.first
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                refute_nil workspace.cue_lists
         
     | 
| 
      
 16 
     | 
    
         
            +
                refute_nil workspace.cue_lists.first
         
     | 
| 
      
 17 
     | 
    
         
            +
                refute_nil workspace.cue_lists.first.cues
         
     | 
| 
      
 18 
     | 
    
         
            +
                refute_nil workspace.cue_lists.first.cues.first
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              def test_a_cue_has_a_name
         
     | 
| 
      
 22 
     | 
    
         
            +
                workspace = @machine.workspaces.first
         
     | 
| 
      
 23 
     | 
    
         
            +
                cue = workspace.cue_lists.first.cues.first
         
     | 
| 
      
 24 
     | 
    
         
            +
                assert cue.name
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              def test_changes_are_picked_up_immediately
         
     | 
| 
      
 28 
     | 
    
         
            +
                original_name = "Name 1"
         
     | 
| 
      
 29 
     | 
    
         
            +
                new_name = "Name 2"
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                workspace = @machine.workspaces.first
         
     | 
| 
      
 32 
     | 
    
         
            +
                cue = workspace.cue_lists.first.cues.first
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                cue.name = original_name
         
     | 
| 
      
 35 
     | 
    
         
            +
                assert_equal original_name, cue.name
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                cue.name = new_name
         
     | 
| 
      
 38 
     | 
    
         
            +
                assert_equal new_name, cue.name
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
            end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'test_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class MachineTest < Minitest::Test
         
     | 
| 
      
 4 
     | 
    
         
            +
              def test_can_connect
         
     | 
| 
      
 5 
     | 
    
         
            +
                machine = QLab.connect 'localhost', 53000
         
     | 
| 
      
 6 
     | 
    
         
            +
                assert machine.connected?
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              def test_can_load_workspaces
         
     | 
| 
      
 10 
     | 
    
         
            +
                machine = QLab.connect 'localhost', 53000
         
     | 
| 
      
 11 
     | 
    
         
            +
                assert machine.workspaces.size > 0
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              def test_can_find_workspaces
         
     | 
| 
      
 15 
     | 
    
         
            +
                machine = QLab.connect 'localhost', 53000
         
     | 
| 
      
 16 
     | 
    
         
            +
                assert machine.workspaces.size > 0
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                ws = machine.workspaces.first
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                assert_equal ws, machine.find_workspace(id: ws.id)
         
     | 
| 
      
 21 
     | 
    
         
            +
                assert_equal ws, machine.find_workspace(name: ws.name)
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                refute machine.find_workspace(id: 'nonsense')
         
     | 
| 
      
 24 
     | 
    
         
            +
                refute machine.find_workspace(name: 'nonsense')
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
    
        data/test/test_helper.rb
    ADDED
    
    
| 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'test_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class WorkspaceTest < Minitest::Test
         
     | 
| 
      
 4 
     | 
    
         
            +
              def setup
         
     | 
| 
      
 5 
     | 
    
         
            +
                @machine = QLab.connect 'localhost', 53000
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              def teardown
         
     | 
| 
      
 9 
     | 
    
         
            +
                @machine.close
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              def test_refresh_loads_cues
         
     | 
| 
      
 13 
     | 
    
         
            +
                workspace = @machine.workspaces.first
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                refute_nil workspace.connection
         
     | 
| 
      
 16 
     | 
    
         
            +
                refute_nil workspace.name
         
     | 
| 
      
 17 
     | 
    
         
            +
                refute_nil workspace.id
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                refute_nil workspace.cues
         
     | 
| 
      
 20 
     | 
    
         
            +
                assert workspace.cues.size > 0
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              def test_finds_cues
         
     | 
| 
      
 24 
     | 
    
         
            +
                workspace = @machine.workspaces.first
         
     | 
| 
      
 25 
     | 
    
         
            +
                cue = workspace.cues.first
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                assert_equal cue, workspace.find_cue(id: cue.id)
         
     | 
| 
      
 28 
     | 
    
         
            +
                assert_equal cue, workspace.find_cue(number: cue.number)
         
     | 
| 
      
 29 
     | 
    
         
            +
                assert_equal cue, workspace.find_cue(name: cue.name)
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                refute workspace.find_cue(id: 'asdf asdf asdf asdf asdf')
         
     | 
| 
      
 32 
     | 
    
         
            +
                refute workspace.find_cue(number: 'asdf asdf asdf asdf asdf')
         
     | 
| 
      
 33 
     | 
    
         
            +
                refute workspace.find_cue(name: 'asdf asdf asdf asdf asdf')
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,106 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: qlab-ruby
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.2
         
     | 
| 
      
 5 
     | 
    
         
            +
              prerelease: 
         
     | 
| 
      
 6 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 7 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 8 
     | 
    
         
            +
            - Adam Bachman
         
     | 
| 
      
 9 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 10 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 11 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2013-11-21 00:00:00.000000000 Z
         
     | 
| 
      
 13 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 14 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 15 
     | 
    
         
            +
              name: osc-ruby
         
     | 
| 
      
 16 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 17 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 18 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 19 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 20 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 21 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 22 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 23 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 24 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 25 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 26 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 27 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 28 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 29 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 30 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 31 
     | 
    
         
            +
              name: rdoc
         
     | 
| 
      
 32 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 33 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 34 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 35 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 36 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 37 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 38 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 39 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 40 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 41 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 42 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 43 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 44 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 45 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 46 
     | 
    
         
            +
            description: Interact with QLab in Ruby.
         
     | 
| 
      
 47 
     | 
    
         
            +
            email:
         
     | 
| 
      
 48 
     | 
    
         
            +
            - adam@figure53.com
         
     | 
| 
      
 49 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 50 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 51 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 52 
     | 
    
         
            +
            files:
         
     | 
| 
      
 53 
     | 
    
         
            +
            - .gitignore
         
     | 
| 
      
 54 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 55 
     | 
    
         
            +
            - LICENSE.txt
         
     | 
| 
      
 56 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 57 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 58 
     | 
    
         
            +
            - lib/qlab-ruby.rb
         
     | 
| 
      
 59 
     | 
    
         
            +
            - lib/qlab-ruby/commands.rb
         
     | 
| 
      
 60 
     | 
    
         
            +
            - lib/qlab-ruby/communicator.rb
         
     | 
| 
      
 61 
     | 
    
         
            +
            - lib/qlab-ruby/core-ext/osc-ruby.rb
         
     | 
| 
      
 62 
     | 
    
         
            +
            - lib/qlab-ruby/core-ext/osc-ruby/message.rb
         
     | 
| 
      
 63 
     | 
    
         
            +
            - lib/qlab-ruby/core-ext/osc-ruby/sending_socket.rb
         
     | 
| 
      
 64 
     | 
    
         
            +
            - lib/qlab-ruby/core-ext/osc-ruby/tcp.rb
         
     | 
| 
      
 65 
     | 
    
         
            +
            - lib/qlab-ruby/core-ext/osc-ruby/tcp_client.rb
         
     | 
| 
      
 66 
     | 
    
         
            +
            - lib/qlab-ruby/cue.rb
         
     | 
| 
      
 67 
     | 
    
         
            +
            - lib/qlab-ruby/cue_list.rb
         
     | 
| 
      
 68 
     | 
    
         
            +
            - lib/qlab-ruby/machine.rb
         
     | 
| 
      
 69 
     | 
    
         
            +
            - lib/qlab-ruby/reply.rb
         
     | 
| 
      
 70 
     | 
    
         
            +
            - lib/qlab-ruby/version.rb
         
     | 
| 
      
 71 
     | 
    
         
            +
            - lib/qlab-ruby/workspace.rb
         
     | 
| 
      
 72 
     | 
    
         
            +
            - qlab-ruby.gemspec
         
     | 
| 
      
 73 
     | 
    
         
            +
            - test/cue_test.rb
         
     | 
| 
      
 74 
     | 
    
         
            +
            - test/machine_test.rb
         
     | 
| 
      
 75 
     | 
    
         
            +
            - test/test_helper.rb
         
     | 
| 
      
 76 
     | 
    
         
            +
            - test/workspace_test.rb
         
     | 
| 
      
 77 
     | 
    
         
            +
            homepage: https://github.com/Figure53/qlab-ruby
         
     | 
| 
      
 78 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 79 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 80 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 81 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 82 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 83 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 84 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 85 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 86 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 87 
     | 
    
         
            +
              - - ! '>='
         
     | 
| 
      
 88 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 89 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 90 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 91 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 92 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 93 
     | 
    
         
            +
              - - ! '>='
         
     | 
| 
      
 94 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 95 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 96 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 97 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 98 
     | 
    
         
            +
            rubygems_version: 1.8.25
         
     | 
| 
      
 99 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 100 
     | 
    
         
            +
            specification_version: 3
         
     | 
| 
      
 101 
     | 
    
         
            +
            summary: Interact with QLab in Ruby.
         
     | 
| 
      
 102 
     | 
    
         
            +
            test_files:
         
     | 
| 
      
 103 
     | 
    
         
            +
            - test/cue_test.rb
         
     | 
| 
      
 104 
     | 
    
         
            +
            - test/machine_test.rb
         
     | 
| 
      
 105 
     | 
    
         
            +
            - test/test_helper.rb
         
     | 
| 
      
 106 
     | 
    
         
            +
            - test/workspace_test.rb
         
     |