mmplayer 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +13 -0
- data/README.md +62 -0
- data/lib/mmplayer.rb +33 -0
- data/lib/mmplayer/context.rb +47 -0
- data/lib/mmplayer/helper/numbers.rb +26 -0
- data/lib/mmplayer/instructions/midi.rb +46 -0
- data/lib/mmplayer/instructions/player.rb +31 -0
- data/lib/mmplayer/midi.rb +105 -0
- data/lib/mmplayer/player.rb +142 -0
- data/test/context_test.rb +64 -0
- data/test/helper.rb +6 -0
- data/test/helper/numbers_test.rb +57 -0
- data/test/instructions/midi_test.rb +78 -0
- data/test/instructions/player_test.rb +46 -0
- data/test/midi_test.rb +130 -0
- data/test/player_test.rb +125 -0
- metadata +240 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b444046bc6129a272ad1354fd79e0226d3fed0f6
|
4
|
+
data.tar.gz: 7a58cbaec278585178e5ea420e3be977711a5f65
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7d73ce2e7db56b04f05bde2ce3a713a0b15cb6ed37f944d6d9de8d45859ad6e70265c3f818056aa6e5e8b70f536ae64f265301e39b2986829c0f7080b26ba2aa
|
7
|
+
data.tar.gz: 137bf592cad461210938a051ffad361b48019a55d87a788f76a48bdde80cd767c3729238fcb9c983c5094e44337bef934a13eeed852d1a57799e1ab483eb6689
|
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2015 Ari Russo
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# mmplayer
|
2
|
+
|
3
|
+
![image](http://i.imgur.com/Te9nymX.png)
|
4
|
+
|
5
|
+
Control [MPlayer](http://en.wikipedia.org/wiki/MPlayer) with MIDI
|
6
|
+
|
7
|
+
## Install
|
8
|
+
|
9
|
+
You'll need to install MPlayer before using this. That can usually be accomplished with a package manager eg `brew install mplayer` depending on what OS you're using.
|
10
|
+
|
11
|
+
This project itself can be installed as a Ruby Gem using
|
12
|
+
|
13
|
+
`gem install mmplayer`
|
14
|
+
|
15
|
+
Or if you're using Bundler, add this to your Gemfile
|
16
|
+
|
17
|
+
`gem "mmplayer"`
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
MMplayer provides a Ruby DSL to define interactions between MIDI input and MPlayer
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require "mmplayer"
|
25
|
+
|
26
|
+
@input = UniMIDI::Input.gets
|
27
|
+
|
28
|
+
@player = MMPlayer.new(@input, :mplayer_flags => "-fs") do
|
29
|
+
|
30
|
+
rx_channel 0
|
31
|
+
|
32
|
+
system(:start) { play("1.mov") }
|
33
|
+
|
34
|
+
note(1) { play("2.mov") }
|
35
|
+
note("C2") { play("3.mov") }
|
36
|
+
|
37
|
+
cc(1) { |value| volume(:set, value) }
|
38
|
+
cc(20) { |value| seek(to_percent(value), :percent) }
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
@player.start
|
43
|
+
|
44
|
+
```
|
45
|
+
|
46
|
+
An annotated breakdown of this example can be found [here](https://github.com/arirusso/mmplayer/blob/master/examples/simple.rb)
|
47
|
+
|
48
|
+
[The MPlayer Man Page](http://www.mplayerhq.hu/DOCS/man/en/mplayer.1.html#GENERAL OPTIONS) has a full list of MPlayer startup flags
|
49
|
+
|
50
|
+
All MPlayer runtime commands enabled by the [mplayer-ruby](https://rubygems.org/gems/mplayer-ruby) project are available here too. (eg `seek` and `volume` in the example above)
|
51
|
+
|
52
|
+
[The RDOC for mplayer-ruby](http://mplayer-ruby.rubyforge.org/mplayer-ruby/index.html) has a full list of runtime commands
|
53
|
+
|
54
|
+
##Author
|
55
|
+
|
56
|
+
* [Ari Russo](http://github.com/arirusso) <ari.russo at gmail.com>
|
57
|
+
|
58
|
+
##License
|
59
|
+
|
60
|
+
Apache 2.0, See LICENSE file
|
61
|
+
|
62
|
+
Copyright (c) 2015 [Ari Russo](http://arirusso.com)
|
data/lib/mmplayer.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# MMPlayer
|
2
|
+
# Control MPlayer with MIDI
|
3
|
+
#
|
4
|
+
# (c)2015 Ari Russo
|
5
|
+
# Apache 2.0 License
|
6
|
+
|
7
|
+
# libs
|
8
|
+
require "forwardable"
|
9
|
+
require "midi-eye"
|
10
|
+
require "mplayer-ruby"
|
11
|
+
require "scale"
|
12
|
+
require "unimidi"
|
13
|
+
|
14
|
+
# modules
|
15
|
+
require "mmplayer/helper/numbers"
|
16
|
+
require "mmplayer/instructions/midi"
|
17
|
+
require "mmplayer/instructions/player"
|
18
|
+
|
19
|
+
# classes
|
20
|
+
require "mmplayer/context"
|
21
|
+
require "mmplayer/midi"
|
22
|
+
require "mmplayer/player"
|
23
|
+
|
24
|
+
module MMPlayer
|
25
|
+
|
26
|
+
VERSION = "0.0.1"
|
27
|
+
|
28
|
+
# Shortcut to Context constructor
|
29
|
+
def self.new(*args, &block)
|
30
|
+
Context.new(*args, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module MMPlayer
|
2
|
+
|
3
|
+
# DSL context for interfacing an instance of MPlayer with MIDI
|
4
|
+
class Context
|
5
|
+
|
6
|
+
include Helper::Numbers
|
7
|
+
include Instructions::MIDI
|
8
|
+
include Instructions::Player
|
9
|
+
|
10
|
+
attr_reader :midi, :player
|
11
|
+
|
12
|
+
# @param [UniMIDI::Input] midi_input
|
13
|
+
# @param [Hash] options
|
14
|
+
# @option options [String] :mplayer_flags The command-line flags to invoke MPlayer with
|
15
|
+
# @option options [Fixnum] :receive_channel (also: :rx_channel) A MIDI channel to subscribe to. By default, responds to all
|
16
|
+
# @yield
|
17
|
+
def initialize(midi_input, options = {}, &block)
|
18
|
+
@midi = MIDI.new(midi_input, :receive_channel => options[:receive_channel] || options[:rx_channel])
|
19
|
+
@player = Player.new(:flags => options[:mplayer_flags])
|
20
|
+
instance_eval(&block) if block_given?
|
21
|
+
end
|
22
|
+
|
23
|
+
# Start listening for MIDI
|
24
|
+
# Note that MPlayer will start when Context#play (aka Instructions::Player#play) is called
|
25
|
+
# @param [Hash] options
|
26
|
+
# @option options [Boolean] :background Whether to run in a background thread
|
27
|
+
# @return [Boolean]
|
28
|
+
def start(options = {})
|
29
|
+
@midi.start
|
30
|
+
unless !!options[:background]
|
31
|
+
loop { sleep(0.1) } until @player.active?
|
32
|
+
loop { sleep(0.1) } while @player.active?
|
33
|
+
end
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
# Stop the player
|
38
|
+
# @return [Boolean]
|
39
|
+
def stop
|
40
|
+
@midi.stop
|
41
|
+
@player.quit
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module MMPlayer
|
2
|
+
|
3
|
+
module Helper
|
4
|
+
|
5
|
+
# Number conversion
|
6
|
+
module Numbers
|
7
|
+
|
8
|
+
# Converts a percentage to a 7-bit int value eg 50 -> 0x40
|
9
|
+
# @param [Fixnum] num
|
10
|
+
# @return [Fixnum]
|
11
|
+
def to_midi_value(num)
|
12
|
+
Scale.transform(num).from(0..100).to(0..127.0).round
|
13
|
+
end
|
14
|
+
|
15
|
+
# Converts a MIDI 7-bit int value to a percentage eg 0x40 -> 50
|
16
|
+
# @param [Fixnum] num
|
17
|
+
# @return [Fixnum]
|
18
|
+
def to_percent(num)
|
19
|
+
Scale.transform(num).from(0..127).to(0..100.0).round
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module MMPlayer
|
2
|
+
|
3
|
+
module Instructions
|
4
|
+
|
5
|
+
# Instructions for dealing with MIDI
|
6
|
+
module MIDI
|
7
|
+
|
8
|
+
# Set the MIDI channel to receive messages on
|
9
|
+
# @param [Fixnum, nil] num The channel number 0-15 or nil for all
|
10
|
+
def receive_channel(num)
|
11
|
+
@midi.channel = num
|
12
|
+
end
|
13
|
+
alias_method :rx_channel, :receive_channel
|
14
|
+
|
15
|
+
# Assign a callback for a given MIDI system command
|
16
|
+
# @param [String, Symbol] note A MIDI system command eg :start, :continue, :stop
|
17
|
+
# @param [Proc] callback The callback to execute when a matching message is received
|
18
|
+
# @return [Hash]
|
19
|
+
def on_system(command, &callback)
|
20
|
+
@midi.add_system_callback(command, &callback)
|
21
|
+
end
|
22
|
+
alias_method :system, :on_system
|
23
|
+
|
24
|
+
# Assign a callback for a given MIDI note
|
25
|
+
# @param [Fixnum, String] note A MIDI note eg 64 "F4"
|
26
|
+
# @param [Proc] callback The callback to execute when a matching message is received
|
27
|
+
# @return [Hash]
|
28
|
+
def on_note(note, &callback)
|
29
|
+
@midi.add_note_callback(note, &callback)
|
30
|
+
end
|
31
|
+
alias_method :note, :on_note
|
32
|
+
|
33
|
+
# Assign a callback for the given MIDI control change
|
34
|
+
# @param [Fixnum] index The MIDI control change index to assign the callback for
|
35
|
+
# @param [Proc] callback The callback to execute when a matching message is received
|
36
|
+
# @return [Hash]
|
37
|
+
def on_cc(index, &callback)
|
38
|
+
@midi.add_cc_callback(index, &callback)
|
39
|
+
end
|
40
|
+
alias_method :cc, :on_cc
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module MMPlayer
|
2
|
+
|
3
|
+
module Instructions
|
4
|
+
|
5
|
+
# Instructions dealing with the MPlayer
|
6
|
+
module Player
|
7
|
+
|
8
|
+
# Add delegators to local player methods
|
9
|
+
def self.included(base)
|
10
|
+
base.send(:extend, Forwardable)
|
11
|
+
base.send(:def_delegators, :@player, :active?, :play, :progress)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Add all of the MPlayer::Slave methods to the context as instructions
|
15
|
+
def method_missing(method, *args, &block)
|
16
|
+
if @player.mplayer_respond_to?(method)
|
17
|
+
@player.mplayer_send(method, *args, &block)
|
18
|
+
else
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Add all of the MPlayer::Slave methods to the context as instructions
|
24
|
+
def respond_to_missing?(method, include_private = false)
|
25
|
+
super || @player.mplayer_respond_to?(method)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module MMPlayer
|
2
|
+
|
3
|
+
# Wrapper for MIDI functionality
|
4
|
+
class MIDI
|
5
|
+
|
6
|
+
attr_reader :channel, :config, :listener
|
7
|
+
|
8
|
+
# @param [UniMIDI::Input] input
|
9
|
+
# @param [Hash] options
|
10
|
+
# @option options [Fixnum] :receive_channel A MIDI channel to subscribe to. By default, responds to all
|
11
|
+
def initialize(input, options = {})
|
12
|
+
@channel = options[:receive_channel]
|
13
|
+
@config = {
|
14
|
+
:cc => {},
|
15
|
+
:note => {},
|
16
|
+
:system => {}
|
17
|
+
}
|
18
|
+
@listener = MIDIEye::Listener.new(input)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Add a callback for a given MIDI system message
|
22
|
+
# @param [String, Symbol] command The MIDI system command eg :start, :stop
|
23
|
+
# @param [Proc] callback The callback to execute when the given MIDI command is received
|
24
|
+
# @return [Hash]
|
25
|
+
def add_system_callback(command, &callback)
|
26
|
+
@config[:system][command] = callback
|
27
|
+
@config[:system]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Add a callback for a given MIDI note
|
31
|
+
# @param [Fixnum, String] note The MIDI note to add a callback for eg 64 "E4"
|
32
|
+
# @param [Proc] callback The callback to execute when the given MIDI note is received
|
33
|
+
# @return [Hash]
|
34
|
+
def add_note_callback(note, &callback)
|
35
|
+
@config[:note][note] = callback
|
36
|
+
@config[:note]
|
37
|
+
end
|
38
|
+
|
39
|
+
# Add a callback for a given MIDI control change
|
40
|
+
# @param [Fixnum] index The MIDI control change index to add a callback for eg 10
|
41
|
+
# @param [Proc] callback The callback to execute when the given MIDI control change is received
|
42
|
+
# @return [Hash]
|
43
|
+
def add_cc_callback(index, &callback)
|
44
|
+
@config[:cc][index] = callback
|
45
|
+
@config[:cc]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Stop the MIDI listener
|
49
|
+
# @return [Boolean]
|
50
|
+
def stop
|
51
|
+
@listener.stop
|
52
|
+
end
|
53
|
+
|
54
|
+
# Change the subscribed MIDI channel (or nil for all)
|
55
|
+
# @param [Fixnum, nil] channel
|
56
|
+
# @return [Fixnum, nil]
|
57
|
+
def channel=(channel)
|
58
|
+
@listener.event.clear
|
59
|
+
@channel = channel
|
60
|
+
populate_listener if @listener.running?
|
61
|
+
@channel
|
62
|
+
end
|
63
|
+
|
64
|
+
# Start the MIDI listener
|
65
|
+
# @return [Boolean]
|
66
|
+
def start
|
67
|
+
populate_listener
|
68
|
+
@listener.start(:background => true)
|
69
|
+
true
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
# Populate the MIDI listener events
|
75
|
+
def populate_listener
|
76
|
+
# Channel messages
|
77
|
+
listener_options = {}
|
78
|
+
# omni by default
|
79
|
+
listener_options[:channel] = @channel unless @channel.nil?
|
80
|
+
@listener.on_message(listener_options.merge(:class => MIDIMessage::NoteOn)) do |event|
|
81
|
+
message = event[:message]
|
82
|
+
unless (callback = @config[:note][message.note] || @config[:note][message.name]).nil?
|
83
|
+
callback.call(message.velocity)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
@listener.on_message(listener_options.merge(:class => MIDIMessage::ControlChange)) do |event|
|
87
|
+
message = event[:message]
|
88
|
+
unless (callback = @config[:cc][message.index] || @config[:cc][message.name]).nil?
|
89
|
+
callback.call(message.value)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
# Short messages
|
93
|
+
@listener.on_message(:class => MIDIMessage::SystemRealtime) do |event|
|
94
|
+
message = event[:message]
|
95
|
+
name = message.name.downcase.to_sym
|
96
|
+
unless (callback = @config[:system][name]).nil?
|
97
|
+
callback.call
|
98
|
+
end
|
99
|
+
end
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module MMPlayer
|
2
|
+
|
3
|
+
# Wrapper for MPlayer functionality
|
4
|
+
class Player
|
5
|
+
|
6
|
+
# @param [Hash] options
|
7
|
+
# @option options [String] :flags MPlayer command-line flags to use on startup
|
8
|
+
def initialize(options = {})
|
9
|
+
@mplayer_messages = []
|
10
|
+
@flags = "-fixed-vo -idle"
|
11
|
+
@flags += " #{options[:flags]}" unless options[:flags].nil?
|
12
|
+
end
|
13
|
+
|
14
|
+
# Play a media file
|
15
|
+
# @param [String] file
|
16
|
+
# @return [Boolean]
|
17
|
+
def play(file)
|
18
|
+
ensure_player(file)
|
19
|
+
if @player.nil?
|
20
|
+
false
|
21
|
+
else
|
22
|
+
@player.load_file(file)
|
23
|
+
true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Is MPlayer active?
|
28
|
+
# @return [Boolean]
|
29
|
+
def active?
|
30
|
+
!@player.nil? && !@player.stdout.gets.nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
# Media progress information
|
34
|
+
# eg {
|
35
|
+
# :length => 90.3,
|
36
|
+
# :percent => 44,
|
37
|
+
# :position => 40.1
|
38
|
+
# }
|
39
|
+
# Length and position are in seconds
|
40
|
+
# @return [Hash, nil]
|
41
|
+
def progress
|
42
|
+
unless (time = poll_mplayer_progress).nil?
|
43
|
+
time[:percent] = get_percentage(time)
|
44
|
+
time
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Shortcut to send a message to the MPlayer
|
49
|
+
# @return [Object]
|
50
|
+
def mplayer_send(method, *args, &block)
|
51
|
+
if @player.nil? && MPlayer::Slave.method_defined?(method)
|
52
|
+
# warn
|
53
|
+
else
|
54
|
+
send_mplayer_message { @player.send(method, *args, &block) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Does the MPlayer respond to the given message?
|
59
|
+
# @return [Boolean]
|
60
|
+
def mplayer_respond_to?(method, include_private = false)
|
61
|
+
(@player.nil? && MPlayer::Slave.method_defined?(method)) ||
|
62
|
+
@player.respond_to?(method)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Cause MPlayer to exit
|
66
|
+
# @return [Boolean]
|
67
|
+
def quit
|
68
|
+
@player.quit
|
69
|
+
@player_thread.kill
|
70
|
+
true
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
# Sweep for leftover/hanging message threads
|
76
|
+
def sweep_messages
|
77
|
+
if @mplayer_messages.empty?
|
78
|
+
false
|
79
|
+
else
|
80
|
+
sleep(0.01)
|
81
|
+
@mplayer_messages.each(&:kill)
|
82
|
+
true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Send mplayer a message async
|
87
|
+
def send_mplayer_message(&block)
|
88
|
+
sweep_messages
|
89
|
+
thread = Thread.new do
|
90
|
+
begin
|
91
|
+
yield
|
92
|
+
rescue Exception => exception
|
93
|
+
Thread.main.raise(exception)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
thread.abort_on_exception = true
|
97
|
+
@mplayer_messages << thread
|
98
|
+
thread
|
99
|
+
end
|
100
|
+
|
101
|
+
# Get progress percentage from the MPlayer report
|
102
|
+
def get_percentage(report)
|
103
|
+
percent = (report[:position] / report[:length]) * 100
|
104
|
+
percent.round
|
105
|
+
end
|
106
|
+
|
107
|
+
# Poll MPlayer for progress information
|
108
|
+
def poll_mplayer_progress
|
109
|
+
time = nil
|
110
|
+
send_mplayer_message do
|
111
|
+
time = {
|
112
|
+
:length => get_mplayer_float("time_length"),
|
113
|
+
:position => get_mplayer_float("time_pos")
|
114
|
+
}
|
115
|
+
end
|
116
|
+
time
|
117
|
+
end
|
118
|
+
|
119
|
+
# Poll a single MPlayer value for the given key
|
120
|
+
def get_mplayer_float(key)
|
121
|
+
@player.get(key).strip.to_f
|
122
|
+
end
|
123
|
+
|
124
|
+
# Ensure that the MPlayer process is invoked
|
125
|
+
# @param [String] file The media file to invoke MPlayer with
|
126
|
+
# @return [MPlayer::Slave]
|
127
|
+
def ensure_player(file)
|
128
|
+
if @player.nil?
|
129
|
+
@player_thread = Thread.new do
|
130
|
+
begin
|
131
|
+
@player = MPlayer::Slave.new(file, :options => @flags)
|
132
|
+
rescue Exception => exception
|
133
|
+
Thread.main.raise(exception)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
@player_thread.abort_on_exception = true
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class MMPlayer::ContextTest < Minitest::Test
|
4
|
+
|
5
|
+
context "Context" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@input = Object.new
|
9
|
+
@context = MMPlayer::Context.new(@input)
|
10
|
+
@player = Object.new
|
11
|
+
@context.player.stubs(:ensure_player).returns(@player)
|
12
|
+
@context.player.stubs(:quit).returns(true)
|
13
|
+
@context.player.stubs(:active?).returns(true)
|
14
|
+
end
|
15
|
+
|
16
|
+
teardown do
|
17
|
+
@context.player.unstub(:ensure_player)
|
18
|
+
@context.player.unstub(:quit)
|
19
|
+
@context.player.unstub(:active?)
|
20
|
+
end
|
21
|
+
|
22
|
+
context "#start" do
|
23
|
+
|
24
|
+
setup do
|
25
|
+
@context.midi.listener.expects(:on_message).times(3)
|
26
|
+
@context.midi.listener.expects(:start).once
|
27
|
+
end
|
28
|
+
|
29
|
+
teardown do
|
30
|
+
@context.midi.listener.unstub(:on_message)
|
31
|
+
@context.midi.listener.unstub(:start)
|
32
|
+
end
|
33
|
+
|
34
|
+
should "activate player" do
|
35
|
+
assert @context.start(:background => true)
|
36
|
+
@context.stop
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
context "#stop" do
|
42
|
+
|
43
|
+
setup do
|
44
|
+
@context.midi.listener.expects(:on_message).times(3)
|
45
|
+
@context.midi.listener.expects(:start).once
|
46
|
+
@context.midi.listener.expects(:stop).once
|
47
|
+
@context.player.expects(:quit).once
|
48
|
+
assert @context.start(:background => true)
|
49
|
+
end
|
50
|
+
|
51
|
+
teardown do
|
52
|
+
@context.midi.listener.unstub(:on_message)
|
53
|
+
@context.midi.listener.unstub(:start)
|
54
|
+
@context.player.unstub(:quit)
|
55
|
+
end
|
56
|
+
|
57
|
+
should "stop player" do
|
58
|
+
@context.stop
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class MMPlayer::Helper::NumbersTest < Minitest::Test
|
4
|
+
|
5
|
+
context "Numbers" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@util = Object.new
|
9
|
+
@util.class.send(:include, MMPlayer::Helper::Numbers)
|
10
|
+
end
|
11
|
+
|
12
|
+
context "#to_midi_value" do
|
13
|
+
|
14
|
+
should "convert 0" do
|
15
|
+
val = @util.to_midi_value(0)
|
16
|
+
refute_nil val
|
17
|
+
assert_equal 0x0, val
|
18
|
+
end
|
19
|
+
|
20
|
+
should "convert 64" do
|
21
|
+
val = @util.to_midi_value(50)
|
22
|
+
refute_nil val
|
23
|
+
assert_equal 0x40, val
|
24
|
+
end
|
25
|
+
|
26
|
+
should "convert 127" do
|
27
|
+
val = @util.to_midi_value(100)
|
28
|
+
refute_nil val
|
29
|
+
assert_equal 0x7F, val
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
context "#to_percent" do
|
35
|
+
|
36
|
+
should "convert 0%" do
|
37
|
+
val = @util.to_percent(0x0)
|
38
|
+
refute_nil val
|
39
|
+
assert_equal 0, val
|
40
|
+
end
|
41
|
+
|
42
|
+
should "convert 50%" do
|
43
|
+
val = @util.to_percent(0x40)
|
44
|
+
refute_nil val
|
45
|
+
assert_equal 50, val
|
46
|
+
end
|
47
|
+
|
48
|
+
should "convert 100%" do
|
49
|
+
val = @util.to_percent(0x7F)
|
50
|
+
refute_nil val
|
51
|
+
assert_equal 100, val
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class MMPlayer::Instructions::MIDITest < Minitest::Test
|
4
|
+
|
5
|
+
context "MIDI" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@input = Object.new
|
9
|
+
@context = MMPlayer::Context.new(@input)
|
10
|
+
assert @context.kind_of?(MMPlayer::Instructions::MIDI)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "#note" do
|
14
|
+
|
15
|
+
setup do
|
16
|
+
@context.midi.expects(:add_note_callback).once.returns({})
|
17
|
+
end
|
18
|
+
|
19
|
+
teardown do
|
20
|
+
@context.midi.unstub(:add_note_callback)
|
21
|
+
end
|
22
|
+
|
23
|
+
should "assign callback" do
|
24
|
+
refute_nil @context.note(1) { something }
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
context "#cc" do
|
30
|
+
|
31
|
+
setup do
|
32
|
+
@context.midi.expects(:add_cc_callback).once.returns({})
|
33
|
+
end
|
34
|
+
|
35
|
+
teardown do
|
36
|
+
@context.midi.unstub(:add_cc_callback)
|
37
|
+
end
|
38
|
+
|
39
|
+
should "assign callback" do
|
40
|
+
refute_nil @context.cc(1) { |val| something }
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
context "#system" do
|
46
|
+
|
47
|
+
setup do
|
48
|
+
@context.midi.expects(:add_system_callback).once.returns({})
|
49
|
+
end
|
50
|
+
|
51
|
+
teardown do
|
52
|
+
@context.midi.unstub(:add_system_callback)
|
53
|
+
end
|
54
|
+
|
55
|
+
should "assign callback" do
|
56
|
+
refute_nil @context.system(:stop) { something }
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
context "#receive_channel" do
|
62
|
+
|
63
|
+
setup do
|
64
|
+
@context.midi.expects(:channel=).once.with(3).returns(3)
|
65
|
+
end
|
66
|
+
|
67
|
+
teardown do
|
68
|
+
@context.midi.unstub(:channel=)
|
69
|
+
end
|
70
|
+
|
71
|
+
should "assign callback" do
|
72
|
+
refute_nil @context.receive_channel(3)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class MMPlayer::Instructions::PlayerTest < Minitest::Test
|
4
|
+
|
5
|
+
context "Player" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@input = Object.new
|
9
|
+
@context = MMPlayer::Context.new(@input)
|
10
|
+
assert @context.kind_of?(MMPlayer::Instructions::Player)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "#method_missing" do
|
14
|
+
|
15
|
+
setup do
|
16
|
+
@context.player.expects(:mplayer_send).once.with(:seek, 50, :percent).returns(true)
|
17
|
+
end
|
18
|
+
|
19
|
+
teardown do
|
20
|
+
@context.player.unstub(:mplayer_send)
|
21
|
+
end
|
22
|
+
|
23
|
+
should "delegate" do
|
24
|
+
refute_nil @context.seek(50, :percent)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
context "#respond_to?" do
|
30
|
+
|
31
|
+
setup do
|
32
|
+
@context.player.expects(:mplayer_respond_to?).once.with(:seek).returns(true)
|
33
|
+
end
|
34
|
+
|
35
|
+
teardown do
|
36
|
+
@context.player.unstub(:mplayer_respond_to?)
|
37
|
+
end
|
38
|
+
|
39
|
+
should "delegate" do
|
40
|
+
refute_nil @context.respond_to?(:seek)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
data/test/midi_test.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class MMPlayer::MIDITest < Minitest::Test
|
4
|
+
|
5
|
+
context "MIDI" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@input = Object.new
|
9
|
+
@midi = MMPlayer::MIDI.new(@input)
|
10
|
+
end
|
11
|
+
|
12
|
+
context "#start" do
|
13
|
+
|
14
|
+
setup do
|
15
|
+
@midi.listener.expects(:on_message).times(3)
|
16
|
+
@midi.listener.expects(:start).once
|
17
|
+
end
|
18
|
+
|
19
|
+
teardown do
|
20
|
+
@midi.listener.unstub(:on_message)
|
21
|
+
@midi.listener.unstub(:start)
|
22
|
+
end
|
23
|
+
|
24
|
+
should "activate callbacks" do
|
25
|
+
assert @midi.start
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
context "#add_note_callback" do
|
31
|
+
|
32
|
+
setup do
|
33
|
+
@var = nil
|
34
|
+
@midi.add_note_callback(10) { |vel| @var = vel }
|
35
|
+
end
|
36
|
+
|
37
|
+
should "store callback" do
|
38
|
+
refute_nil @midi.config[:note][10]
|
39
|
+
assert_equal Proc, @midi.config[:note][10].class
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
context "#add_system_callback" do
|
45
|
+
|
46
|
+
setup do
|
47
|
+
@var = nil
|
48
|
+
@midi.add_system_callback(:start) { |val| @var = val }
|
49
|
+
end
|
50
|
+
|
51
|
+
should "store callback" do
|
52
|
+
refute_nil @midi.config[:system][:start]
|
53
|
+
assert_equal Proc, @midi.config[:system][:start].class
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
context "#add_cc_callback" do
|
59
|
+
|
60
|
+
setup do
|
61
|
+
@var = nil
|
62
|
+
@midi.add_cc_callback(2) { |val| @var = val }
|
63
|
+
end
|
64
|
+
|
65
|
+
should "store callback" do
|
66
|
+
refute_nil @midi.config[:cc][2]
|
67
|
+
assert_equal Proc, @midi.config[:cc][2].class
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
context "#channel=" do
|
73
|
+
|
74
|
+
setup do
|
75
|
+
# stub out MIDIEye
|
76
|
+
@listener = Object.new
|
77
|
+
@listener.stubs(:event).returns([])
|
78
|
+
@midi.instance_variable_set("@listener", @listener)
|
79
|
+
end
|
80
|
+
|
81
|
+
teardown do
|
82
|
+
@listener.unstub(:clear)
|
83
|
+
@listener.unstub(:on_message)
|
84
|
+
@listener.unstub(:event)
|
85
|
+
@listener.unstub(:running?)
|
86
|
+
end
|
87
|
+
|
88
|
+
context "before listener is started" do
|
89
|
+
|
90
|
+
setup do
|
91
|
+
@listener.stubs(:running?).returns(false)
|
92
|
+
@listener.expects(:clear).never
|
93
|
+
@listener.expects(:on_message).never
|
94
|
+
end
|
95
|
+
|
96
|
+
should "change channel" do
|
97
|
+
assert_equal 3, @midi.channel = 3
|
98
|
+
assert_equal 3, @midi.channel
|
99
|
+
end
|
100
|
+
|
101
|
+
should "set channel nil" do
|
102
|
+
assert_equal nil, @midi.channel = nil
|
103
|
+
assert_nil @midi.channel
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context "after listener is started" do
|
108
|
+
|
109
|
+
setup do
|
110
|
+
@listener.stubs(:running?).returns(true)
|
111
|
+
@listener.expects(:clear).once
|
112
|
+
@listener.expects(:on_message).times(3)
|
113
|
+
end
|
114
|
+
|
115
|
+
should "change channel" do
|
116
|
+
assert_equal 3, @midi.channel = 3
|
117
|
+
assert_equal 3, @midi.channel
|
118
|
+
end
|
119
|
+
|
120
|
+
should "set channel nil" do
|
121
|
+
assert_equal nil, @midi.channel = nil
|
122
|
+
assert_nil @midi.channel
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
data/test/player_test.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class MMPlayer::PlayerTest < Minitest::Test
|
4
|
+
|
5
|
+
context "Player" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
# Stub out MPlayer completely
|
9
|
+
class MPlayer
|
10
|
+
def get(*args)
|
11
|
+
"0.1\n"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
@player = MMPlayer::Player.new
|
15
|
+
@mplayer = MPlayer.new
|
16
|
+
@player.stubs(:ensure_player).returns(@mplayer)
|
17
|
+
@player.instance_variable_set("@player", @mplayer)
|
18
|
+
@player.instance_variable_set("@player_thread", Thread.new {})
|
19
|
+
@player.send(:ensure_player, "")
|
20
|
+
end
|
21
|
+
|
22
|
+
context "#mplayer_send" do
|
23
|
+
|
24
|
+
setup do
|
25
|
+
@mplayer.expects(:hello).once.returns(true)
|
26
|
+
@mplayer.expects(:send).once.with(:hello).returns(true)
|
27
|
+
end
|
28
|
+
|
29
|
+
teardown do
|
30
|
+
@mplayer.unstub(:send)
|
31
|
+
end
|
32
|
+
|
33
|
+
should "send messages to mplayer" do
|
34
|
+
assert @player.mplayer_send(:hello)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
context "#mplayer_respond_to?" do
|
40
|
+
|
41
|
+
setup do
|
42
|
+
@player.send(:ensure_player, "")
|
43
|
+
@mplayer.expects(:respond_to?).with(:hello).once.returns(true)
|
44
|
+
end
|
45
|
+
|
46
|
+
teardown do
|
47
|
+
@mplayer.unstub(:respond_to?)
|
48
|
+
end
|
49
|
+
|
50
|
+
should "send messages to mplayer" do
|
51
|
+
assert @player.mplayer_respond_to?(:hello)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
context "#get_percentage" do
|
57
|
+
|
58
|
+
should "calcuate percentage" do
|
59
|
+
val = @player.send(:get_percentage, { :length => 10.1, :position => 5.5 })
|
60
|
+
refute_nil val
|
61
|
+
assert_equal Fixnum, val.class
|
62
|
+
assert_equal 54, val
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
context "#quit" do
|
68
|
+
|
69
|
+
setup do
|
70
|
+
@mplayer.expects(:quit).once
|
71
|
+
@player.instance_variable_get("@player_thread").expects(:kill).once
|
72
|
+
end
|
73
|
+
|
74
|
+
teardown do
|
75
|
+
@mplayer.unstub(:quit)
|
76
|
+
@player.instance_variable_get("@player_thread").unstub(:kill)
|
77
|
+
end
|
78
|
+
|
79
|
+
should "exit MPlayer and kill the player thread" do
|
80
|
+
assert @player.quit
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
context "#progress" do
|
86
|
+
# TODO
|
87
|
+
end
|
88
|
+
|
89
|
+
context "#poll_mplayer_progress" do
|
90
|
+
# TODO
|
91
|
+
end
|
92
|
+
|
93
|
+
context "#get_mplayer_float" do
|
94
|
+
|
95
|
+
should "convert string to float" do
|
96
|
+
val = @player.send(:get_mplayer_float, "key")
|
97
|
+
refute_nil val
|
98
|
+
assert_equal Float, val.class
|
99
|
+
assert_equal 0.1, val
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
context "#play" do
|
105
|
+
|
106
|
+
setup do
|
107
|
+
@player.expects(:ensure_player).once.returns(@mplayer)
|
108
|
+
@mplayer.expects(:load_file).once
|
109
|
+
end
|
110
|
+
|
111
|
+
teardown do
|
112
|
+
@player.unstub(:ensure_player)
|
113
|
+
@mplayer.unstub(:load_file)
|
114
|
+
end
|
115
|
+
|
116
|
+
should "lazily invoke mplayer and play" do
|
117
|
+
assert @player.play("file.mov")
|
118
|
+
refute_nil @player.instance_variable_get("@player")
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
metadata
ADDED
@@ -0,0 +1,240 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mmplayer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ari Russo
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-04-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.5'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 5.5.0
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '5.5'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 5.5.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: mocha
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.1'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.1.0
|
43
|
+
type: :development
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.1'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.1.0
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: rake
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '10.4'
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 10.4.2
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '10.4'
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 10.4.2
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: shoulda-context
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '1.2'
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.2.1
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.2'
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 1.2.1
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: analog
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0.3'
|
103
|
+
type: :runtime
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0.3'
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: midi-eye
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0.3'
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 0.3.9
|
123
|
+
type: :runtime
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0.3'
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 0.3.9
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
name: midi-message
|
135
|
+
requirement: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0.4'
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 0.4.1
|
143
|
+
type: :runtime
|
144
|
+
prerelease: false
|
145
|
+
version_requirements: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - "~>"
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0.4'
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 0.4.1
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: mplayer-ruby
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0.2'
|
160
|
+
- - ">="
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: 0.2.0
|
163
|
+
type: :runtime
|
164
|
+
prerelease: false
|
165
|
+
version_requirements: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - "~>"
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0.2'
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: 0.2.0
|
173
|
+
- !ruby/object:Gem::Dependency
|
174
|
+
name: unimidi
|
175
|
+
requirement: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - "~>"
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '0.4'
|
180
|
+
- - ">="
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: 0.4.3
|
183
|
+
type: :runtime
|
184
|
+
prerelease: false
|
185
|
+
version_requirements: !ruby/object:Gem::Requirement
|
186
|
+
requirements:
|
187
|
+
- - "~>"
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0.4'
|
190
|
+
- - ">="
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: 0.4.3
|
193
|
+
description: Define interactions between MIDI input and MPlayer
|
194
|
+
email:
|
195
|
+
- ari.russo@gmail.com
|
196
|
+
executables: []
|
197
|
+
extensions: []
|
198
|
+
extra_rdoc_files: []
|
199
|
+
files:
|
200
|
+
- LICENSE
|
201
|
+
- README.md
|
202
|
+
- lib/mmplayer.rb
|
203
|
+
- lib/mmplayer/context.rb
|
204
|
+
- lib/mmplayer/helper/numbers.rb
|
205
|
+
- lib/mmplayer/instructions/midi.rb
|
206
|
+
- lib/mmplayer/instructions/player.rb
|
207
|
+
- lib/mmplayer/midi.rb
|
208
|
+
- lib/mmplayer/player.rb
|
209
|
+
- test/context_test.rb
|
210
|
+
- test/helper.rb
|
211
|
+
- test/helper/numbers_test.rb
|
212
|
+
- test/instructions/midi_test.rb
|
213
|
+
- test/instructions/player_test.rb
|
214
|
+
- test/midi_test.rb
|
215
|
+
- test/player_test.rb
|
216
|
+
homepage: http://github.com/arirusso/mmplayer
|
217
|
+
licenses:
|
218
|
+
- Apache 2.0
|
219
|
+
metadata: {}
|
220
|
+
post_install_message:
|
221
|
+
rdoc_options: []
|
222
|
+
require_paths:
|
223
|
+
- lib
|
224
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
225
|
+
requirements:
|
226
|
+
- - ">="
|
227
|
+
- !ruby/object:Gem::Version
|
228
|
+
version: '0'
|
229
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
230
|
+
requirements:
|
231
|
+
- - ">="
|
232
|
+
- !ruby/object:Gem::Version
|
233
|
+
version: 1.3.6
|
234
|
+
requirements: []
|
235
|
+
rubyforge_project: mmplayer
|
236
|
+
rubygems_version: 2.4.6
|
237
|
+
signing_key:
|
238
|
+
specification_version: 4
|
239
|
+
summary: Control MPlayer with MIDI
|
240
|
+
test_files: []
|