mvlc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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