mvlc 0.0.1

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.
@@ -0,0 +1,14 @@
1
+ require "mvlc/player/state"
2
+ require "mvlc/player/wrapper"
3
+
4
+ module MVLC
5
+
6
+ module Player
7
+
8
+ def self.new(*args)
9
+ ::MVLC::Player::Wrapper.new(*args)
10
+ end
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,44 @@
1
+ module MVLC
2
+
3
+ module Player
4
+
5
+ class State
6
+
7
+ attr_accessor :eof, :pause, :play
8
+ alias_method :eof?, :eof
9
+ alias_method :pause?, :pause
10
+ alias_method :paused?, :pause
11
+ alias_method :play?, :play
12
+ alias_method :playing?, :play
13
+
14
+ def initialize
15
+ @eof = false
16
+ @play = false
17
+ @pause = false
18
+ end
19
+
20
+ def toggle_pause
21
+ @pause = !@pause
22
+ end
23
+
24
+ def progressing?
25
+ @play && !@pause
26
+ end
27
+
28
+ def eof_reached?
29
+ @play && !@eof && !@pause
30
+ end
31
+
32
+ def handle_eof
33
+ @eof = true
34
+ @play = false
35
+ end
36
+
37
+ def handle_start
38
+ @play = true
39
+ @eof = false
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,148 @@
1
+ module MVLC
2
+
3
+ module Player
4
+
5
+ # Wrapper for MPlayer functionality
6
+ class Wrapper
7
+
8
+ VOLUME_FACTOR = 2.4
9
+
10
+ extend Forwardable
11
+
12
+ attr_reader :state, :player
13
+
14
+ # @param [Hash] options
15
+ def initialize(options = {})
16
+ @callback = {}
17
+ @state = State.new
18
+ @player = VLC::System.new(headless: true)
19
+ end
20
+
21
+ def volume(value)
22
+ @player.volume(value * VOLUME_FACTOR)
23
+ end
24
+
25
+ def seek_percent(percent)
26
+ begin
27
+ length_in_seconds = @player.length
28
+ seconds = length_in_seconds * (percent / 100.0)
29
+ @player.seek(seconds)
30
+ rescue VLC::ReadTimeoutError
31
+ end
32
+ end
33
+
34
+ # Play a media file
35
+ # @param [String] file
36
+ # @return [Boolean]
37
+ def play(file)
38
+ if @player.nil?
39
+ false
40
+ else
41
+ @player.play(file)
42
+ handle_start
43
+ true
44
+ end
45
+ end
46
+
47
+ # Is MPlayer active?
48
+ # @return [Boolean]
49
+ def active?
50
+ !@player.nil?
51
+ end
52
+
53
+ # Toggles pause
54
+ # @return [Boolean]
55
+ def pause
56
+ @state.toggle_pause
57
+ @player.pause
58
+ @state.pause?
59
+ end
60
+
61
+ # Handle events while the player is running
62
+ # @return [Boolean]
63
+ def playback_loop
64
+ loop do
65
+ handle_eof if handle_eof?
66
+ sleep(0.05)
67
+ end
68
+ true
69
+ end
70
+
71
+ # Add a callback to be called when progress is updated during playback
72
+ # @param [Proc] block
73
+ # @return [Boolean]
74
+ def add_progress_callback(&block)
75
+ @callback[:progress] = block
76
+ true
77
+ end
78
+
79
+ # Add a callback to be called at the end of playback of a media file
80
+ # @param [Proc] block
81
+ # @return [Boolean]
82
+ def add_end_of_file_callback(&block)
83
+ @callback[:end_of_file] = block
84
+ true
85
+ end
86
+
87
+ # Cause MPlayer to exit
88
+ # @return [Boolean]
89
+ def quit
90
+ @player.connection.write("quit")
91
+ @player.connection.write("logout")
92
+ true
93
+ end
94
+
95
+ # Add all of the MPlayer::Slave methods to the context as instructions
96
+ def method_missing(method, *args, &block)
97
+ if @player.respond_to?(method)
98
+ @player.send(method, *args, &block)
99
+ else
100
+ super
101
+ end
102
+ end
103
+
104
+ # Add all of the MPlayer::Slave methods to the context as instructions
105
+ def respond_to_missing?(method, include_private = false)
106
+ super || @player.respond_to?(method)
107
+ end
108
+
109
+ private
110
+
111
+ def handle_progress?
112
+ @state.progressing? && progress_callback?
113
+ end
114
+
115
+ def progress_callback?
116
+ !@callback[:progress].nil?
117
+ end
118
+
119
+ def eof_callback?
120
+ !@callback[:end_of_file].nil?
121
+ end
122
+
123
+ def handle_eof?
124
+ eof? && eof_callback?
125
+ end
126
+
127
+ # Handle the end of playback for a single media file
128
+ def handle_eof
129
+ @callback[:end_of_file].call
130
+ @state.handle_eof
131
+ true
132
+ end
133
+
134
+ # Handle the beginning of playback for a single media file
135
+ def handle_start
136
+ @state.handle_start
137
+ end
138
+
139
+ # Has the end of a media file been reached?
140
+ # @return [Boolean]
141
+ def eof?
142
+ @state.eof_reached? && !@player.playing?
143
+ end
144
+
145
+ end
146
+
147
+ end
148
+ end
@@ -0,0 +1,28 @@
1
+ module MVLC
2
+
3
+ module Thread
4
+
5
+ extend self
6
+
7
+ def new(options = {}, &block)
8
+ thread = ::Thread.new do
9
+ begin
10
+ if options[:timeout] === false
11
+ yield
12
+ else
13
+ duration = options[:timeout] || 1
14
+ Timeout::timeout(duration) { yield }
15
+ end
16
+ rescue Timeout::Error
17
+ ::Thread.current.kill
18
+ rescue Exception => exception
19
+ ::Thread.main.raise(exception)
20
+ end
21
+ end
22
+ thread.abort_on_exception = true
23
+ thread
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,65 @@
1
+ require "helper"
2
+
3
+ class MVLC::ContextTest < Minitest::Test
4
+
5
+ context "Context" do
6
+
7
+ setup do
8
+ VLC::System.stubs(:new)
9
+ @input = Object.new
10
+ @context = MVLC::Context.new(@input)
11
+ @player = Object.new
12
+ @context.player.stubs(:player).returns(@player)
13
+ @context.player.stubs(:quit).returns(true)
14
+ @context.player.stubs(:active?).returns(true)
15
+ end
16
+
17
+ teardown do
18
+ @context.player.unstub(:player)
19
+ @context.player.unstub(:quit)
20
+ @context.player.unstub(:active?)
21
+ end
22
+
23
+ context "#start" do
24
+
25
+ setup do
26
+ @context.midi.listener.expects(:on_message).once
27
+ @context.midi.listener.expects(:start).once
28
+ end
29
+
30
+ teardown do
31
+ @context.midi.listener.unstub(:on_message)
32
+ @context.midi.listener.unstub(:start)
33
+ end
34
+
35
+ should "activate player" do
36
+ assert @context.start(:background => true)
37
+ assert @context.stop
38
+ end
39
+
40
+ end
41
+
42
+ context "#stop" do
43
+
44
+ setup do
45
+ @context.midi.listener.expects(:on_message).once
46
+ @context.midi.listener.expects(:start).once
47
+ @context.midi.listener.expects(:stop).once
48
+ @context.player.expects(:quit).once
49
+ assert @context.start(:background => true)
50
+ end
51
+
52
+ teardown do
53
+ @context.midi.listener.unstub(:on_message)
54
+ @context.midi.listener.unstub(:start)
55
+ @context.player.unstub(:quit)
56
+ end
57
+
58
+ should "stop player" do
59
+ assert @context.stop
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,6 @@
1
+ $:.unshift(File.join("..", "lib"))
2
+
3
+ require "minitest/autorun"
4
+ require "mocha/test_unit"
5
+ require "shoulda-context"
6
+ require "mvlc"
@@ -0,0 +1,57 @@
1
+ require "helper"
2
+
3
+ class MVLC::Helper::NumbersTest < Minitest::Test
4
+
5
+ context "Numbers" do
6
+
7
+ setup do
8
+ @util = Object.new
9
+ @util.class.send(:include, MVLC::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 MVLC::Instructions::MIDITest < Minitest::Test
4
+
5
+ context "MIDI" do
6
+
7
+ setup do
8
+ @input = Object.new
9
+ @context = MVLC::Context.new(@input)
10
+ assert @context.kind_of?(MVLC::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