activevlc 0.0.1 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -0
- data/README.md +81 -26
- data/Rakefile +5 -0
- data/TODO.md +0 -1
- data/activevlc.gemspec +3 -2
- data/examples/basic.rb +14 -0
- data/examples/duplicate.rb +18 -0
- data/examples/duplicate_then_transcode.rb +29 -0
- data/examples/transcode_and_display.rb +25 -0
- data/examples/transcode_and_display_with_options.rb +36 -0
- data/lib/activevlc/cli.rb +25 -6
- data/lib/activevlc/libvlc/api.rb +196 -0
- data/lib/activevlc/libvlc/event_manager.rb +53 -0
- data/lib/activevlc/libvlc/instance.rb +71 -0
- data/lib/activevlc/libvlc/media.rb +32 -0
- data/lib/activevlc/libvlc/media_list.rb +55 -0
- data/lib/activevlc/libvlc/media_list_player.rb +64 -0
- data/lib/activevlc/libvlc/media_player.rb +63 -0
- data/lib/activevlc/libvlc.rb +33 -0
- data/lib/activevlc/pipeline.rb +4 -2
- data/lib/activevlc/pipeline_dump.rb +0 -2
- data/lib/activevlc/runner.rb +71 -0
- data/lib/activevlc/stage/input.rb +1 -0
- data/lib/activevlc/syntactic_sugar.rb +11 -0
- data/lib/activevlc/version.rb +1 -1
- data/lib/activevlc.rb +6 -3
- data/spec/event_manager_spec.rb +81 -0
- data/spec/libvlc_spec.rb +93 -0
- data/spec/pipeline_spec.rb +20 -1
- data/spec/pipes/no_input.rb +20 -0
- data/spec/pipes/transcode_and_display.rb +1 -1
- data/spec/runner_spec.rb +34 -0
- data/spec/samples/click.wav +0 -0
- data/spec/spec_helper.rb +24 -11
- metadata +34 -9
- data/examples/design.rb +0 -84
@@ -0,0 +1,71 @@
|
|
1
|
+
module ActiveVlc::LibVlc
|
2
|
+
# This is just a hack to have the libvlc_instance released when
|
3
|
+
# the Instance class is GC'ed
|
4
|
+
class InstancePtr < FFI::ManagedStruct
|
5
|
+
layout :nothing, :pointer
|
6
|
+
|
7
|
+
def self.release(ptr)
|
8
|
+
#puts "Releasing an InstancePtr #{ptr.inspect}"
|
9
|
+
Api.libvlc_release(ptr)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Instance
|
14
|
+
attr_reader :exit_callback, :ptr
|
15
|
+
|
16
|
+
def initialize(args = [""])
|
17
|
+
argc = args.length
|
18
|
+
@argv = args.map{ |a| FFI::MemoryPointer.from_string a}
|
19
|
+
test = FFI::MemoryPointer.new(:pointer, argc)
|
20
|
+
test.put_array_of_pointer(0, @argv)
|
21
|
+
|
22
|
+
@ptr = InstancePtr.new Api.libvlc_new(argc, test)
|
23
|
+
raise "Unable to create a libvlc_instance_t" if @ptr.null?
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_media(mrl)
|
27
|
+
if mrl =~ /\A[a-z]+:\/\/.+/
|
28
|
+
m = Api.libvlc_media_new_location(@ptr, mrl)
|
29
|
+
else
|
30
|
+
m = Api.libvlc_media_new_path(@ptr, mrl)
|
31
|
+
end
|
32
|
+
raise "Unable to create a libvlc_media_t" if m.null?
|
33
|
+
Media.new(m, mrl)
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_media_list
|
37
|
+
ml = Api.libvlc_media_list_new(@ptr)
|
38
|
+
raise "Unable to create a libvlc_media_list_t" if ml.null?
|
39
|
+
MediaList.new(ml)
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_list_player(list = nil, player = nil)
|
43
|
+
mlp = Api.libvlc_media_list_player_new(@ptr)
|
44
|
+
raise "Unable to create a libvlc_media_list_player_t" if mlp.null?
|
45
|
+
MediaListPlayer.new(mlp, list, player)
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_player(media = nil)
|
49
|
+
if media and media.is_a?(Media)
|
50
|
+
MediaPlayer.new(media)
|
51
|
+
else
|
52
|
+
MediaPlayer.new self
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def wait!
|
57
|
+
Api.libvlc_wait(@ptr)
|
58
|
+
end
|
59
|
+
|
60
|
+
def at_exit(&block)
|
61
|
+
Api.libvlc_set_exit_handler(@ptr, nil, nil)
|
62
|
+
@exit_callback = block
|
63
|
+
Api.libvlc_set_exit_handler(@ptr, @exit_callback, nil)
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_interface(name = nil)
|
67
|
+
Api.libvlc_add_intf(@ptr, name)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ActiveVlc::LibVlc
|
2
|
+
# See InstancePtr in instance.rb
|
3
|
+
class MediaPtr < FFI::ManagedStruct
|
4
|
+
layout :nothing, :pointer
|
5
|
+
|
6
|
+
def self.release(ptr)
|
7
|
+
# puts "Releasing a MediaPtr #{ptr.inspect}"
|
8
|
+
Api.libvlc_media_release(ptr)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Media
|
13
|
+
attr_reader :ptr, :mrl
|
14
|
+
|
15
|
+
def initialize(ptr, mrl)
|
16
|
+
@ptr = MediaPtr.new(ptr)
|
17
|
+
@mrl = mrl
|
18
|
+
end
|
19
|
+
|
20
|
+
def <<(option)
|
21
|
+
raise "option must be a String" unless option.is_a?(String)
|
22
|
+
|
23
|
+
Api.libvlc_media_add_option(@ptr, option)
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def event_manager
|
28
|
+
EventManager.new Api.libvlc_media_event_manager(@ptr)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module ActiveVlc::LibVlc
|
2
|
+
# See InstancePtr in instance.rb
|
3
|
+
class MediaListPtr < FFI::ManagedStruct
|
4
|
+
layout :media_list, :pointer
|
5
|
+
|
6
|
+
def self.release(ptr)
|
7
|
+
# puts "Releasing an MediaListPtr"
|
8
|
+
Api.libvlc_media_list_release(ptr)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class MediaList
|
13
|
+
attr_reader :ptr
|
14
|
+
|
15
|
+
def initialize(ptr)
|
16
|
+
@ptr = MediaListPtr.new(ptr)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Execute the given block with the media_list lock acquired.
|
20
|
+
def locked!
|
21
|
+
if block_given?
|
22
|
+
_lock!
|
23
|
+
res = yield
|
24
|
+
_unlock!
|
25
|
+
res
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def event_manager
|
30
|
+
EventManager.new Api.libvlc_media_list_event_manager(@ptr)
|
31
|
+
end
|
32
|
+
|
33
|
+
def media=(media)
|
34
|
+
Api.libvlc_media_list_set_media(@ptr, media.ptr)
|
35
|
+
end
|
36
|
+
|
37
|
+
def <<(media)
|
38
|
+
locked! { Api.libvlc_media_list_add_media(@ptr, media.ptr) }
|
39
|
+
end
|
40
|
+
|
41
|
+
def length
|
42
|
+
locked! { Api.libvlc_media_list_count(@ptr) }
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
def _lock!
|
47
|
+
Api.libvlc_media_list_lock(@ptr)
|
48
|
+
end
|
49
|
+
def _unlock!
|
50
|
+
Api.libvlc_media_list_unlock(@ptr)
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module ActiveVlc::LibVlc
|
2
|
+
class MediaListPlayerPtr < FFI::ManagedStruct
|
3
|
+
layout :nothing, :pointer
|
4
|
+
|
5
|
+
def self.release(ptr)
|
6
|
+
# puts "Releasing a MediaListPlayerPtr #{ptr.inspect}"
|
7
|
+
Api.libvlc_media_list_player_release(ptr)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class MediaListPlayer
|
12
|
+
attr_reader :ptr, :player, :list
|
13
|
+
|
14
|
+
def initialize(ptr, media_list = nil, media_player = nil)
|
15
|
+
@ptr = MediaListPlayerPtr.new(ptr)
|
16
|
+
@list = media_list
|
17
|
+
@player = media_player
|
18
|
+
|
19
|
+
self.media_list = media_list if media_list
|
20
|
+
self.media_player = media_player if media_player
|
21
|
+
end
|
22
|
+
|
23
|
+
def media_list=(list)
|
24
|
+
if list and list.is_a?(MediaList)
|
25
|
+
@list = list
|
26
|
+
Api.libvlc_media_list_player_set_media_list(@ptr, list.ptr)
|
27
|
+
else
|
28
|
+
raise "You must provide a valid MediaList"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def event_manager
|
33
|
+
EventManager.new Api.libvlc_media_list_player_event_manager(@ptr)
|
34
|
+
end
|
35
|
+
|
36
|
+
def playing?
|
37
|
+
Api.libvlc_media_list_player_is_playing(@ptr) != 0
|
38
|
+
end
|
39
|
+
|
40
|
+
def media_player=(player)
|
41
|
+
if player.is_a?(MediaPlayer) and not playing?
|
42
|
+
raise "Player already has a media" if player.media
|
43
|
+
@player = player
|
44
|
+
Api.libvlc_media_list_player_set_media_player(@ptr, player.ptr)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def play
|
49
|
+
Api.libvlc_media_list_player_play(@ptr)
|
50
|
+
end
|
51
|
+
def pause
|
52
|
+
Api.libvlc_media_list_player_pause(@ptr)
|
53
|
+
end
|
54
|
+
def stop
|
55
|
+
Api.libvlc_media_list_player_stop(@ptr)
|
56
|
+
end
|
57
|
+
def next
|
58
|
+
Api.libvlc_media_list_player_next(@ptr)
|
59
|
+
end
|
60
|
+
def previous
|
61
|
+
Api.libvlc_media_list_player_previous(@ptr)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module ActiveVlc::LibVlc
|
2
|
+
# See InstancePtr in instance.rb
|
3
|
+
class MediaPlayerPtr < FFI::ManagedStruct
|
4
|
+
layout :media_list, :pointer
|
5
|
+
|
6
|
+
def self.release(ptr)
|
7
|
+
# puts "Releasing an MediaPlayerPtr"
|
8
|
+
Api.libvlc_media_player_release(ptr)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class MediaPlayer
|
13
|
+
attr_reader :ptr, :media
|
14
|
+
|
15
|
+
def initialize(vlc_or_media)
|
16
|
+
@media = nil
|
17
|
+
if vlc_or_media.is_a?(Media)
|
18
|
+
@media = vlc_or_media
|
19
|
+
@ptr = Api.libvlc_media_player_new_from_media(vlc_or_media.ptr)
|
20
|
+
else
|
21
|
+
@ptr = Api.libvlc_media_player_new(vlc_or_media.ptr)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def event_manager
|
26
|
+
event_manger = Api.libvlc_media_player_event_manager(@ptr)
|
27
|
+
raise "Unable to get EventManager for MediaPlayer #{@ptr.inspect}" unless event_manger
|
28
|
+
EventManager.new event_manger
|
29
|
+
end
|
30
|
+
|
31
|
+
def media=(new_media)
|
32
|
+
raise "You must provide a valid Media" unless new_media and new_media.is_a?(Media)
|
33
|
+
@media = new_media
|
34
|
+
Api.libvlc_media_player_set_media(@ptr, @media.ptr)
|
35
|
+
end
|
36
|
+
|
37
|
+
def play
|
38
|
+
if_media { Api.libvlc_media_player_play @ptr }
|
39
|
+
end
|
40
|
+
def stop
|
41
|
+
if_media { Api.libvlc_media_player_stop @ptr }
|
42
|
+
end
|
43
|
+
def pause
|
44
|
+
if_media { Api.libvlc_media_player_pause @ptr}
|
45
|
+
end
|
46
|
+
|
47
|
+
def playing?
|
48
|
+
Api.libvlc_media_player_is_playing @ptr
|
49
|
+
end
|
50
|
+
|
51
|
+
def state
|
52
|
+
Api.libvlc_media_player_get_state @ptr
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
def if_media
|
57
|
+
if block_given?
|
58
|
+
raise "MediaPlayer: No media set" unless @media
|
59
|
+
yield
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
##
|
2
|
+
## libvlc.rb
|
3
|
+
## Login : <lta@still>
|
4
|
+
## Started on Wed Jun 12 20:46:52 2013 Lta Akr
|
5
|
+
## $Id$
|
6
|
+
##
|
7
|
+
## Author(s):
|
8
|
+
## - Lta Akr <>
|
9
|
+
##
|
10
|
+
## Copyright (C) 2013 Lta Akr
|
11
|
+
|
12
|
+
require "ffi"
|
13
|
+
|
14
|
+
module ActiveVlc
|
15
|
+
module LibVlc
|
16
|
+
VLC_SO_NAMES = [
|
17
|
+
'libvlc'.freeze,
|
18
|
+
'libvlc.so.5'.freeze
|
19
|
+
].freeze
|
20
|
+
VLCCORE_SO_NAMES = [
|
21
|
+
'libvlccore'.freeze,
|
22
|
+
'libvlccore.so.5'.freeze
|
23
|
+
].freeze
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'activevlc/libvlc/api'
|
28
|
+
require 'activevlc/libvlc/media'
|
29
|
+
require 'activevlc/libvlc/instance'
|
30
|
+
require 'activevlc/libvlc/media_player'
|
31
|
+
require 'activevlc/libvlc/media_list'
|
32
|
+
require 'activevlc/libvlc/media_list_player'
|
33
|
+
require 'activevlc/libvlc/event_manager'
|
data/lib/activevlc/pipeline.rb
CHANGED
@@ -20,9 +20,11 @@ module ActiveVlc
|
|
20
20
|
|
21
21
|
attr_reader :input, :sout
|
22
22
|
|
23
|
-
def initialize(input_array_or_string)
|
23
|
+
def initialize(input_array_or_string = nil, &block)
|
24
24
|
@input = Stage::Input.new(input_array_or_string)
|
25
|
-
@sout = Stage::Stream.new
|
25
|
+
@sout = Stage::Stream.new # SOut = Stream Out
|
26
|
+
|
27
|
+
::ActiveVlc::DSL::Stream.new(@sout).instance_eval(&block) if block_given?
|
26
28
|
end
|
27
29
|
|
28
30
|
def fragment
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#
|
2
|
+
# Small note about this file code's coverage
|
3
|
+
# Since most of the code is wan in another process
|
4
|
+
# (see #run), the code coverage cannot be reported.
|
5
|
+
# This file have around 100% of test code coverage
|
6
|
+
#
|
7
|
+
module ActiveVlc
|
8
|
+
class Runner
|
9
|
+
def initialize(pipeline, *args)
|
10
|
+
@pipeline = pipeline
|
11
|
+
@args = args
|
12
|
+
end
|
13
|
+
|
14
|
+
# Nobody can escape his faith.
|
15
|
+
def stop_runner!
|
16
|
+
@running = false
|
17
|
+
end
|
18
|
+
|
19
|
+
def run(fork = false)
|
20
|
+
if fork and Process.respond_to? :fork
|
21
|
+
pid = Process.fork { _run }
|
22
|
+
Process.wait pid
|
23
|
+
else
|
24
|
+
_run
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
# Here we setup the media/list/player/event_manager
|
30
|
+
# to run the pipeline using LibVlc. There's a big unavoidable
|
31
|
+
# hack to run synchronously / 'join' the libvlc instance.
|
32
|
+
def _run
|
33
|
+
# Preparing instance/list/player/sout fragment/event manager
|
34
|
+
@api = LibVlc::Instance.new @args
|
35
|
+
sout = @pipeline.sout.fragment
|
36
|
+
list = @api.create_media_list
|
37
|
+
player = @api.create_player
|
38
|
+
events = player.event_manager
|
39
|
+
|
40
|
+
sout.gsub!('\'', '').gsub!('"', '')
|
41
|
+
|
42
|
+
# Building the medias with the right options
|
43
|
+
medias = @pipeline.input.inputs.map do |input|
|
44
|
+
#puts sout
|
45
|
+
@api.create_media(input) << sout
|
46
|
+
end
|
47
|
+
medias.each { |media| list << media }
|
48
|
+
list_player = @api.create_list_player list, player
|
49
|
+
|
50
|
+
# Set callbacks to 'know' when the processing is over
|
51
|
+
stop_events = [
|
52
|
+
:MediaPlayerPaused,
|
53
|
+
:MediaPlayerStopped,
|
54
|
+
:MediaPlayerEndReached,
|
55
|
+
:MediaPlayerEncounteredError
|
56
|
+
]
|
57
|
+
events.on(stop_events) { stop_runner! }
|
58
|
+
|
59
|
+
# Let's rock and roll
|
60
|
+
list_player.play
|
61
|
+
|
62
|
+
# Busy Wait loop hack to synchronize with libvlc which doesn't have
|
63
|
+
# any synchronous interface (due to it's profound asynchronous nature)
|
64
|
+
@running = true
|
65
|
+
while @running
|
66
|
+
sleep 0.5
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
data/lib/activevlc/version.rb
CHANGED
data/lib/activevlc.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
module ActiveVlc
|
2
|
+
end
|
3
|
+
|
1
4
|
require 'active_support'
|
2
5
|
require 'activevlc/version'
|
3
6
|
require 'activevlc/pipeline'
|
4
7
|
require 'activevlc/dsl'
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
+
require 'activevlc/libvlc'
|
9
|
+
require 'activevlc/runner'
|
10
|
+
require 'activevlc/syntactic_sugar'
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe ActiveVlc::LibVlc::EventManager do
|
4
|
+
let(:vlc) { ActiveVlc::LibVlc::Instance.new [' ', '--play-and-exit'] }
|
5
|
+
let(:media) { vlc.create_media 'file:///tmp/test.mp4' }
|
6
|
+
let(:media2) { vlc.create_media '/tmp/test2.mp4' }
|
7
|
+
let(:player) { vlc.create_player }
|
8
|
+
let(:list) do
|
9
|
+
l = vlc.create_media_list
|
10
|
+
l << media
|
11
|
+
l << media2
|
12
|
+
l
|
13
|
+
end
|
14
|
+
let(:list_player) do
|
15
|
+
lp = vlc.create_list_player
|
16
|
+
lp.media_list = list
|
17
|
+
lp
|
18
|
+
end
|
19
|
+
let(:player_event) { player.event_manager }
|
20
|
+
let(:list_player_event) { list_player.event_manager }
|
21
|
+
|
22
|
+
it 'can be created' do
|
23
|
+
media.event_manager.should be_a_kind_of(ActiveVlc::LibVlc::EventManager)
|
24
|
+
list.event_manager.should be_a_kind_of(ActiveVlc::LibVlc::EventManager)
|
25
|
+
player.event_manager.should be_a_kind_of(ActiveVlc::LibVlc::EventManager)
|
26
|
+
list_player.event_manager.should be_a_kind_of(ActiveVlc::LibVlc::EventManager)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'registers and stores callbacks' do
|
30
|
+
event1 = ActiveVlc::LibVlc::Api::EventType[:MediaListPlayerStopped]
|
31
|
+
event2 = ActiveVlc::LibVlc::EventManager::EventType[:MediaListPlayerPlayed]
|
32
|
+
list_player_event.callbacks.keys.length.should eq(0)
|
33
|
+
list_player_event.on(event1) {}
|
34
|
+
list_player_event.on(event2) {}
|
35
|
+
list_player_event.on(:MediaListPlayerNextItemSet) {}
|
36
|
+
# For some reason the 'Played' event is invalid :-/ and the Stopped event
|
37
|
+
# is only triggered on very recent versions ...
|
38
|
+
list_player_event.callbacks.keys.length.should be >= 1
|
39
|
+
list_player.play
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'MediaPlayer\'s EventManger receives events' do
|
43
|
+
first_event = ActiveVlc::LibVlc::Api::EventType[:MediaPlayerMediaChanged]
|
44
|
+
last_event = ActiveVlc::LibVlc::Api::EventType[:MediaPlayerVout]
|
45
|
+
(first_event..last_event).to_a.each { |e| player_event.on(e) {} }
|
46
|
+
player.media = media
|
47
|
+
player_event.events_received.should eq(1)
|
48
|
+
player.play
|
49
|
+
sleep 0.25 # Avoid random deadlock in vlc :-/ and gives some time for vlc to run
|
50
|
+
player.stop
|
51
|
+
player_event.events_received.should eq(5)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'MediaListPlayer\'s EventManger receives events' do
|
55
|
+
list_player_event.on(:MediaListPlayerNextItemSet) {}
|
56
|
+
list_player_event.on(:MediaListPlayerStopped) {}
|
57
|
+
list_player.play
|
58
|
+
list_player.stop
|
59
|
+
list_player_event.events_received.should be >= 1
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'calls registered callback' do
|
63
|
+
@cbk1_called = false
|
64
|
+
list_player_event.on(:MediaListPlayerNextItemSet) { @cbk1_called = true }
|
65
|
+
list_player.play
|
66
|
+
list_player.stop
|
67
|
+
@cbk1_called.should be_true
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'MediaPlayer receives event when assigned as MediaListPlayer\' player' do
|
71
|
+
first_event = ActiveVlc::LibVlc::Api::EventType[:MediaPlayerMediaChanged]
|
72
|
+
last_event = ActiveVlc::LibVlc::Api::EventType[:MediaPlayerVout]
|
73
|
+
(first_event..last_event).to_a.each { |e| player_event.on(e) {} }
|
74
|
+
list_player.media_player = player
|
75
|
+
list_player.play
|
76
|
+
sleep 0.25
|
77
|
+
list_player.stop
|
78
|
+
player_event.events_received.should eq(5)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
data/spec/libvlc_spec.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe ActiveVlc::LibVlc do
|
5
|
+
describe "Low-level binding" do
|
6
|
+
it 'binds C functions' do
|
7
|
+
[ :new, :release, :retain, :add_intf, :wait, :set_user_agent,
|
8
|
+
:get_version, :get_compiler, :free, :set_exit_handler ].each do |sym|
|
9
|
+
ActiveVlc::LibVlc::Api.respond_to?("libvlc_#{sym}")
|
10
|
+
.should be_true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'create a libvlc instance' do
|
15
|
+
vlc = ActiveVlc::LibVlc::Api.libvlc_new(0, nil)
|
16
|
+
vlc.null?.should be_false
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'reports libvlc version' do
|
20
|
+
ActiveVlc::LibVlc::Api.libvlc_get_version.should match(/\d\.\d+\.\d+/)
|
21
|
+
ActiveVlc::LibVlc.version.should match(/\d\.\d+\.\d+/)
|
22
|
+
ActiveVlc::LibVlc.compiler.should match(/\d\.\d+\.\d+/)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'Ruby wrapper: Instance/MediaXXX/EventManger creation' do
|
27
|
+
let(:vlc) { ActiveVlc::LibVlc::Instance.new [' ', '--play-and-exit'] }
|
28
|
+
let(:media) { vlc.create_media 'file:///tmp/test.mp4' }
|
29
|
+
let(:media2) { vlc.create_media '/tmp/test2.mp4' }
|
30
|
+
let(:list) { vlc.create_media_list }
|
31
|
+
let(:list_player) { vlc.create_list_player }
|
32
|
+
|
33
|
+
it 'can creates an instance' do
|
34
|
+
vlc.should be_a_kind_of(ActiveVlc::LibVlc::Instance)
|
35
|
+
vlc.ptr.null?.should be_false
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'can creates a Media from an Instance using an MRL' do
|
39
|
+
media.should be_a_kind_of(ActiveVlc::LibVlc::Media)
|
40
|
+
media.ptr.null?.should be_false
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'can creates a Media from an Instance using a path' do
|
44
|
+
media_from_path = vlc.create_media('/tmp/pwet')
|
45
|
+
media_from_path.should be_a_kind_of(ActiveVlc::LibVlc::Media)
|
46
|
+
media_from_path.ptr.null?.should be_false
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'can set an option on a Media' do
|
50
|
+
media << ":sout='#display'"
|
51
|
+
expect { media << 42 }.to raise_error
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'can creates a MediaList from an Instance' do
|
55
|
+
list.should be_a_kind_of(ActiveVlc::LibVlc::MediaList)
|
56
|
+
list.ptr.null?.should be_false
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'allows setting media of a media list' do
|
60
|
+
list << media2
|
61
|
+
list.media = media
|
62
|
+
list.length.should eq(1)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'allows adding media to a MediaList' do
|
66
|
+
list << media
|
67
|
+
list << media2
|
68
|
+
list.length.should eq(2)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'allows the creation of a MediaListPlayer' do
|
72
|
+
list_player.should be_a_kind_of(ActiveVlc::LibVlc::MediaListPlayer)
|
73
|
+
list_player.ptr.null?.should be_false
|
74
|
+
list << media
|
75
|
+
list_player.media_list = list
|
76
|
+
expect {list_player.media_list = nil}.to raise_error
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'allows creation of a MediaPlayer with an Instance' do
|
80
|
+
player = vlc.create_player
|
81
|
+
player.should be_a_kind_of(ActiveVlc::LibVlc::MediaPlayer)
|
82
|
+
player.ptr.null?.should be_false
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'allows creation of a MediaPlayer with a Media' do
|
86
|
+
player = vlc.create_player media
|
87
|
+
player.should be_a_kind_of(ActiveVlc::LibVlc::MediaPlayer)
|
88
|
+
player.ptr.null?.should be_false
|
89
|
+
player.media.should be_a_kind_of(ActiveVlc::LibVlc::Media)
|
90
|
+
player.media.should be(media)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/spec/pipeline_spec.rb
CHANGED
@@ -71,7 +71,7 @@ describe ActiveVlc::Pipeline do
|
|
71
71
|
|
72
72
|
describe '\'duplicate_then_transcode\' pipeline' do
|
73
73
|
it 'is loaded' do
|
74
|
-
ActiveVlc::Pipeline
|
74
|
+
ActiveVlc::Pipeline::parse('spec/pipes/duplicate_then_transcode.rb').class
|
75
75
|
.should be(ActiveVlc::Pipeline)
|
76
76
|
end
|
77
77
|
|
@@ -81,4 +81,23 @@ describe ActiveVlc::Pipeline do
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
+
describe '\'no_input\' pipeline' do
|
85
|
+
it "is loaded" do
|
86
|
+
ActiveVlc::parse('spec/pipes/no_input.rb').class
|
87
|
+
.should be(ActiveVlc::Pipeline)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'produce the correct fragment' do
|
91
|
+
expect(ActiveVlc::parse('spec/pipes/no_input.rb').fragment)
|
92
|
+
.to eq(" :sout=\"#transcode{acodec=vorbis}:standard{mux=ogg, dst='output.ogg'}\"")
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'can be assigned inputs' do
|
96
|
+
pipe = ActiveVlc::parse('spec/pipes/no_input.rb')
|
97
|
+
pipe.input << "input.mp4"
|
98
|
+
pipe.input << "input2.mp4"
|
99
|
+
pipe.fragment.should eq("input.mp4 input2.mp4 :sout=\"#transcode{acodec=vorbis}:standard{mux=ogg, dst='output.ogg'}\"")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
84
103
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
##
|
2
|
+
## no_input.rb
|
3
|
+
## Login : <lta@still>
|
4
|
+
## Started on Wed Jun 12 14:45:36 2013 Lta Akr
|
5
|
+
## $Id$
|
6
|
+
##
|
7
|
+
## Author(s):
|
8
|
+
## - Lta Akr <>
|
9
|
+
##
|
10
|
+
## Copyright (C) 2013 Lta Akr
|
11
|
+
|
12
|
+
ActiveVlc::pipe do
|
13
|
+
transcode do
|
14
|
+
audio :vorbis
|
15
|
+
end
|
16
|
+
to(:file) do
|
17
|
+
mux :ogg
|
18
|
+
dst 'output.ogg'
|
19
|
+
end
|
20
|
+
end
|