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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7277724b68e5a47757cd221b47c6522bc74cf0c
|
4
|
+
data.tar.gz: 19a56e502c9d73feb2c0fdeb114dcaf98162d665
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eaf8db920f751616a47ba9a46bcc252684d04120cf82703071ce66f6bf46fa9896165f26c383fa66866b453c3a27a6f0aa139ee8a542a4238dfa4084c5887014
|
7
|
+
data.tar.gz: 01bf1845e930f5ad7ee4cf4e0a929a869b986e1fb3ddc94f8c33547d4dff0d6ea782906ce1f84e958151cd479de2d88360e62de7ee5e5e8b2b49071dc7da2f22
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,25 +1,54 @@
|
|
1
1
|
# ActiveVlc
|
2
2
|
|
3
|
-
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/activevlc.png)](http://badge.fury.io/rb/activevlc)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/elthariel/activevlc.png)](https://codeclimate.com/github/elthariel/activevlc)
|
5
|
+
[![Build Status](https://travis-ci.org/elthariel/activevlc.png?branch=master)](https://travis-ci.org/elthariel/activevlc)
|
6
|
+
|
7
|
+
Do you know VLC, the famous media player ? I'm pretty sure you do !
|
4
8
|
Do you know this is also a pretty powerfull media processing and streaming framework ? Maybe...
|
5
|
-
Do you understand something about the command line syntax to access vlc's underlying
|
9
|
+
Do you understand something about the command line syntax to access vlc's underlying
|
6
10
|
powers ? If you don't this tool is for you !
|
7
11
|
|
8
|
-
ActiveVlc provides a simple syntax to configure and run transcoding/streaming/processing
|
12
|
+
ActiveVlc provides a simple syntax to configure and run transcoding/streaming/processing
|
9
13
|
operations using VLC. Here's a simple example :
|
10
14
|
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
First and foremost, you must have VLC and libvlc installed on your system and
|
18
|
+
the vlc binary must be in your PATH since we doesn't provide yet a cool
|
19
|
+
configuration system for this (contribution welcomed !)
|
20
|
+
|
21
|
+
Add this line to your application's Gemfile:
|
22
|
+
|
23
|
+
gem 'activevlc'
|
24
|
+
|
25
|
+
And then execute:
|
26
|
+
|
27
|
+
$ bundle
|
28
|
+
|
29
|
+
Or use the master branch on GitHub to test de development version by replacing
|
30
|
+
the line in your Gemfile by this one:
|
31
|
+
|
32
|
+
gem 'activevlc', github: 'elthariel/activevlc'
|
33
|
+
|
34
|
+
Or install it yourself as:
|
35
|
+
|
36
|
+
$ gem install activevlc
|
37
|
+
|
11
38
|
## Example
|
12
39
|
|
13
|
-
|
40
|
+
### Command line
|
41
|
+
|
42
|
+
Let's say you want to read an mp4 file, transcode it using different options, save the result to
|
14
43
|
another file while displaying it to control what's happening. Using the standard vlc's chain syntax
|
15
44
|
you'd have to write
|
16
45
|
|
17
46
|
vlc input.mp4 :sout="#transcode{deinterlace, acodec=aac, ab=128, channels=2, vcodec=h264, venc=x264{bpyramid=strict, bframes=4, no-cabac}, vb=512}:duplicate{dst=standard{mux=mp4, dst='output.mp4'}, dst=display}"
|
18
|
-
|
47
|
+
|
19
48
|
Not very readable isn't it ? Let's try the same with ActiveVlc :
|
20
49
|
|
21
50
|
```ruby
|
22
|
-
AtiveVlc::
|
51
|
+
AtiveVlc::pipe do
|
23
52
|
transcode do
|
24
53
|
deinterlace
|
25
54
|
audio :aac do
|
@@ -45,45 +74,71 @@ AtiveVlc::Pipeline.for 'input.mp4' do
|
|
45
74
|
end
|
46
75
|
```
|
47
76
|
|
48
|
-
This sintax might be a lot more verbose than the original vlc's one,
|
77
|
+
This sintax might be a lot more verbose than the original vlc's one,
|
49
78
|
it is still A LOT more readable and understandable, and since this is plain ruby
|
50
79
|
you can add comment and arbitrary code !
|
51
80
|
Then you can run it using :
|
52
81
|
|
53
|
-
activevlc exec /path/to/the/pipeline.rb
|
54
|
-
|
55
|
-
## Development status
|
82
|
+
activevlc exec /path/to/the/pipeline.rb input.mp4
|
56
83
|
|
57
|
-
|
58
|
-
development althought it might already be usable for many usages
|
84
|
+
### From Ruby code
|
59
85
|
|
60
|
-
|
86
|
+
You can also use ActiveVlc programmatically from your ruby code :
|
61
87
|
|
62
|
-
|
63
|
-
|
64
|
-
|
88
|
+
```ruby
|
89
|
+
def my_encoding_method(input, output)
|
90
|
+
# Create the pipeline.
|
91
|
+
pipe = ActiveVlc::pipe input do
|
92
|
+
transcode do
|
93
|
+
# Same syntax as above, also see spec/pipes
|
94
|
+
end
|
95
|
+
to :file, output
|
96
|
+
end
|
65
97
|
|
66
|
-
|
98
|
+
# Run it synchronously
|
99
|
+
ActiveVlc::Runner.new(pipe).run
|
100
|
+
# Your transcoding operation is over (except if there were strong errors)
|
101
|
+
end
|
102
|
+
```
|
67
103
|
|
68
|
-
|
104
|
+
## Development status
|
69
105
|
|
70
|
-
|
106
|
+
This gem is still under active development
|
107
|
+
althought it might already be usable for many usages.
|
71
108
|
|
72
|
-
|
109
|
+
If you have any trouble, idea or question, please use GitHub issue
|
110
|
+
system. If you have an idea with code attached to it, got to the
|
111
|
+
'Contributing' section below.
|
73
112
|
|
74
|
-
|
113
|
+
## Supported system/rubies
|
75
114
|
|
76
|
-
|
115
|
+
Ruby 1.8 is _NOT_ supported.
|
116
|
+
|
117
|
+
This gem is developped using MRI 2.0.0 on Debian 7 / Ubuntu 13.04 but it should work OOB on MRI 1.9 and other GNU/Linux systems.
|
118
|
+
|
119
|
+
Altough there might me some threading issues between the interpreter and libvlc, the specs are eported to pass against :
|
120
|
+
* Jruby (1.7)
|
121
|
+
* Rubinius (head) (with some minor problems)
|
122
|
+
|
123
|
+
I doesn't have access to any OSX boxes so but it should work as well, please let me know if you encounter any issue.
|
77
124
|
|
78
125
|
## Usage
|
79
126
|
|
80
|
-
Currently, the best documentation is to have a look to the spec (/spec/pipes)
|
127
|
+
Currently, the best documentation is to have a look to the spec (/spec/pipes)
|
81
128
|
or to run the CLI tool to get the embedded help.
|
82
129
|
|
130
|
+
## Known Issues
|
131
|
+
|
132
|
+
* We use a pretty ugly hack to be able to run pipelines synchronously
|
133
|
+
* You cannot (yet) configure output(s) from the command line, only with ruby
|
134
|
+
* There's currently almost no error reporting except from the one vlc's outputting on STDOUT. Vlc's logging and error reporting is pretty complex, i still need to take some time to figure it out.
|
135
|
+
|
83
136
|
## Contributing
|
84
137
|
|
85
138
|
1. Fork it
|
86
139
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
87
|
-
3.
|
88
|
-
4.
|
89
|
-
5.
|
140
|
+
3. Write some specs for your feature
|
141
|
+
4. Implements your feature and make your test pass
|
142
|
+
5. Commit your changes (`git commit -am 'Add some feature'`)
|
143
|
+
6. Push to the branch (`git push origin my-new-feature`)
|
144
|
+
7. Create new Pull Request
|
data/Rakefile
CHANGED
data/TODO.md
CHANGED
@@ -6,7 +6,6 @@ TODO file for ActiveVlc
|
|
6
6
|
- Preset support (this is also a cool way of documenting vlc's features
|
7
7
|
- vlc team suggestions (jb/etix)
|
8
8
|
- Some syntactic sugar for http-live will be helpfull, pay attention to this shitty module
|
9
|
-
- duplicate -> transcode, transcode -> duplicate
|
10
9
|
- Long-term ideas
|
11
10
|
- carrierwave integration
|
12
11
|
|
data/activevlc.gemspec
CHANGED
@@ -19,11 +19,12 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
-
spec.add_development_dependency "rspec", "~> 2.
|
22
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
23
23
|
spec.add_development_dependency "simplecov"
|
24
24
|
spec.add_development_dependency "rake"
|
25
|
-
spec.add_development_dependency "debugger"
|
25
|
+
#spec.add_development_dependency "debugger"
|
26
26
|
|
27
27
|
spec.add_dependency 'thor'
|
28
28
|
spec.add_dependency 'activesupport'
|
29
|
+
spec.add_dependency 'ffi'
|
29
30
|
end
|
data/examples/basic.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
##
|
2
|
+
## basic.rb
|
3
|
+
## Login : <lta@still>
|
4
|
+
## Started on Wed Jun 12 14:41:04 2013 Lta Akr
|
5
|
+
## $Id$
|
6
|
+
##
|
7
|
+
## Author(s):
|
8
|
+
## - Lta Akr <>
|
9
|
+
##
|
10
|
+
## Copyright (C) 2013 Lta Akr
|
11
|
+
|
12
|
+
# Basic pipe for rspec testing
|
13
|
+
|
14
|
+
ActiveVlc::Pipeline.for 'input.mp4'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
##
|
2
|
+
## duplicate.rb
|
3
|
+
## Login : <lta@still>
|
4
|
+
## Started on Wed Sep 4 17:29:45 2013 Lta Akr
|
5
|
+
## $Id$
|
6
|
+
##
|
7
|
+
## Author(s):
|
8
|
+
## - Lta Akr <>
|
9
|
+
##
|
10
|
+
## Copyright (C) 2013 Lta Akr
|
11
|
+
|
12
|
+
# input.mp3 :sout="#duplicate{dst=display, dst=std{dst='output.mp3'}}"
|
13
|
+
ActiveVlc::Pipeline.for 'input.mp3' do
|
14
|
+
duplicate do
|
15
|
+
to :display
|
16
|
+
to file: 'output.mp3'
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
##
|
2
|
+
## duplicate_then_transcode.rb
|
3
|
+
## Login : <lta@still>
|
4
|
+
## Started on Tue Sep 10 18:30:41 2013 Lta Akr
|
5
|
+
## $Id$
|
6
|
+
##
|
7
|
+
## Author(s):
|
8
|
+
## - Lta Akr <>
|
9
|
+
##
|
10
|
+
## Copyright (C) 2013 Lta Akr
|
11
|
+
|
12
|
+
ActiveVlc::Pipeline.for 'input.mp4' do
|
13
|
+
duplicate do
|
14
|
+
to :chain do
|
15
|
+
#debugger
|
16
|
+
transcode do
|
17
|
+
audio :aac
|
18
|
+
video :h264
|
19
|
+
subtitle :svcd
|
20
|
+
end
|
21
|
+
to :file do
|
22
|
+
mux :mp4
|
23
|
+
dst 'output.mp4'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
to :display
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
##
|
2
|
+
## transcode_and_display.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_for 'input.mp4' do
|
13
|
+
transcode do
|
14
|
+
audio :aac
|
15
|
+
video :h264
|
16
|
+
subtitle :svcd
|
17
|
+
end
|
18
|
+
duplicate do
|
19
|
+
to :file do
|
20
|
+
mux :mp4
|
21
|
+
dst 'output.mp4'
|
22
|
+
end
|
23
|
+
to :display
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
##
|
2
|
+
## transcode_and_display.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::Pipeline.for 'input.mp4' do
|
13
|
+
gather
|
14
|
+
transcode do
|
15
|
+
deinterlace
|
16
|
+
audio :aac do
|
17
|
+
bitrate 128 # 128 kpbs
|
18
|
+
channels 2
|
19
|
+
end
|
20
|
+
video :h264 do
|
21
|
+
encoder :x264 do
|
22
|
+
bpyramid :strict
|
23
|
+
bframes 4
|
24
|
+
cabac false
|
25
|
+
end
|
26
|
+
bitrate 512 # 512 kbps
|
27
|
+
end
|
28
|
+
end
|
29
|
+
duplicate do
|
30
|
+
to :file do
|
31
|
+
mux :mp4
|
32
|
+
dst 'output.mp4'
|
33
|
+
end
|
34
|
+
to :display
|
35
|
+
end
|
36
|
+
end
|
data/lib/activevlc/cli.rb
CHANGED
@@ -29,10 +29,10 @@ module ActiveVlc
|
|
29
29
|
puts "ActiveVlc version #{ActiveVlc::VERSION}"
|
30
30
|
end
|
31
31
|
|
32
|
-
desc 'vlc
|
32
|
+
desc 'vlc ', 'VLC specific commands. See activevlc help vlc for details'
|
33
33
|
subcommand 'vlc', ActiveVlc::CLI::Vlc
|
34
34
|
|
35
|
-
desc 'fragment
|
35
|
+
desc 'fragment path', 'Outputs vlc \':sout=...\' string for the pipeline defined in the \'path\' file'
|
36
36
|
def fragment(path)
|
37
37
|
if File.readable?(path)
|
38
38
|
pipe = eval(File.read(path))
|
@@ -43,11 +43,12 @@ module ActiveVlc
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
desc 'exec
|
47
|
-
def exec(path)
|
46
|
+
desc 'exec path [input_file_1 [input_file_2] [...]]', 'Launch vlc executable to run the pipeline described in path file'
|
47
|
+
def exec(path, *inputs)
|
48
48
|
if File.readable?(path)
|
49
49
|
begin
|
50
|
-
pipe =
|
50
|
+
pipe = ActiveVlc::parse(path)
|
51
|
+
pipe.inputs << inputs
|
51
52
|
fragment = pipe.fragment
|
52
53
|
rescue
|
53
54
|
puts "Error while parsing pipe file"
|
@@ -60,7 +61,25 @@ module ActiveVlc
|
|
60
61
|
exit $?.exitstatus
|
61
62
|
end
|
62
63
|
|
63
|
-
desc '
|
64
|
+
desc 'run path [input_file_1 [input_file_2] [...]]', 'Run the path pipeline using LibVlc (usually better than exec)'
|
65
|
+
def run(path, *inputs)
|
66
|
+
if File.readable?(path)
|
67
|
+
begin
|
68
|
+
pipe = ActiveVlc::parse(path)
|
69
|
+
pipe.inputs << inputs
|
70
|
+
fragment = pipe.fragment
|
71
|
+
rescue
|
72
|
+
puts "Error while parsing pipe file"
|
73
|
+
exit 43
|
74
|
+
end
|
75
|
+
ActiveVlc::Runner.new(pipe).run
|
76
|
+
else
|
77
|
+
puts "Error: file [#{path}] doesn't exist or reading permission denied."
|
78
|
+
end
|
79
|
+
exit 0
|
80
|
+
end
|
81
|
+
|
82
|
+
desc 'dump path', 'Dump the internal representation of the pipeline defined in the file path'
|
64
83
|
def dump(path)
|
65
84
|
if File.readable?(path)
|
66
85
|
puts eval(File.read(path)).dump
|
@@ -0,0 +1,196 @@
|
|
1
|
+
##
|
2
|
+
## api.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
|
+
module ActiveVlc::LibVlc
|
13
|
+
def self.version
|
14
|
+
Api.libvlc_get_version
|
15
|
+
end
|
16
|
+
def self.compiler
|
17
|
+
Api.libvlc_get_compiler
|
18
|
+
end
|
19
|
+
|
20
|
+
module Api
|
21
|
+
extend FFI::Library
|
22
|
+
ffi_lib ActiveVlc::LibVlc::VLC_SO_NAMES
|
23
|
+
|
24
|
+
#
|
25
|
+
# Core functions
|
26
|
+
#
|
27
|
+
callback :exit_handler, [:pointer], :void
|
28
|
+
|
29
|
+
core_functions = {
|
30
|
+
new: [[:int, :pointer], :pointer],
|
31
|
+
release: [[:pointer], :void],
|
32
|
+
retain: [[:pointer], :void],
|
33
|
+
add_intf: [[:pointer, :string], :int],
|
34
|
+
set_exit_handler: [[:pointer, :exit_handler, :pointer], :void],
|
35
|
+
wait: [[:pointer], :void],
|
36
|
+
set_user_agent: [[:pointer, :string, :string], :void],
|
37
|
+
get_version: [[], :string],
|
38
|
+
get_compiler: [[], :string],
|
39
|
+
free: [[:pointer], :void]
|
40
|
+
}
|
41
|
+
|
42
|
+
#
|
43
|
+
# Media functions
|
44
|
+
#
|
45
|
+
media_functions = {
|
46
|
+
media_new_location: [[:pointer, :string], :pointer],
|
47
|
+
media_new_path: [[:pointer, :string], :pointer],
|
48
|
+
media_add_option: [[:pointer, :string], :void],
|
49
|
+
media_add_option_flag: [[:pointer, :string, :int], :void],
|
50
|
+
media_duplicate: [[:pointer], :pointer],
|
51
|
+
media_event_manager: [[:pointer], :pointer],
|
52
|
+
media_retain: [[:pointer], :void],
|
53
|
+
media_release: [[:pointer], :void],
|
54
|
+
media_get_mrl: [[:pointer], :string]
|
55
|
+
}
|
56
|
+
|
57
|
+
#
|
58
|
+
# Media List functions
|
59
|
+
#
|
60
|
+
media_list_functions = {
|
61
|
+
media_list_new: [[:pointer], :pointer],
|
62
|
+
media_list_retain: [[:pointer], :void],
|
63
|
+
media_list_release: [[:pointer], :void],
|
64
|
+
media_list_lock: [[:pointer], :void],
|
65
|
+
media_list_unlock: [[:pointer], :void],
|
66
|
+
media_list_event_manager: [[:pointer], :pointer],
|
67
|
+
media_list_set_media: [[:pointer, :pointer], :void],
|
68
|
+
media_list_add_media: [[:pointer, :pointer], :int],
|
69
|
+
media_list_insert_media: [[:pointer, :pointer, :int], :int],
|
70
|
+
media_list_count: [[:pointer], :int]
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
#
|
75
|
+
# Media Player functions and type
|
76
|
+
#
|
77
|
+
PlayerState = enum(:NothingSpecial,
|
78
|
+
:Opening,
|
79
|
+
:Buffering,
|
80
|
+
:Playing,
|
81
|
+
:Paused,
|
82
|
+
:Stopped,
|
83
|
+
:Ended,
|
84
|
+
:Error)
|
85
|
+
|
86
|
+
media_player_functions = {
|
87
|
+
media_player_new: [[:pointer], :pointer],
|
88
|
+
media_player_new_from_media: [[:pointer], :pointer],
|
89
|
+
media_player_retain: [[:pointer], :void],
|
90
|
+
media_player_release: [[:pointer], :void],
|
91
|
+
media_player_set_media: [[:pointer, :pointer], :void],
|
92
|
+
media_player_get_media: [[:pointer], :pointer],
|
93
|
+
media_player_event_manager: [[:pointer], :pointer],
|
94
|
+
media_player_is_playing: [[:pointer], :int],
|
95
|
+
media_player_play: [[:pointer], :int],
|
96
|
+
media_player_pause: [[:pointer], :void],
|
97
|
+
media_player_stop: [[:pointer], :void],
|
98
|
+
media_player_get_state: [[:pointer], PlayerState]
|
99
|
+
}
|
100
|
+
|
101
|
+
#
|
102
|
+
# Media List Player functions
|
103
|
+
#
|
104
|
+
media_list_player_functions = {
|
105
|
+
media_list_player_new: [[:pointer], :pointer],
|
106
|
+
media_list_player_retain: [[:pointer], :void],
|
107
|
+
media_list_player_release: [[:pointer], :void],
|
108
|
+
media_list_player_event_manager: [[:pointer], :pointer],
|
109
|
+
media_list_player_set_media_list: [[:pointer, :pointer], :void],
|
110
|
+
media_list_player_set_media_player: [[:pointer, :pointer], :void],
|
111
|
+
media_list_player_play: [[:pointer], :void],
|
112
|
+
media_list_player_pause: [[:pointer], :void],
|
113
|
+
media_list_player_stop: [[:pointer], :void],
|
114
|
+
media_list_player_next: [[:pointer], :void],
|
115
|
+
media_list_player_previous: [[:pointer], :void],
|
116
|
+
media_list_player_is_playing: [[:pointer], :int]
|
117
|
+
}
|
118
|
+
|
119
|
+
#
|
120
|
+
# Event manager functions and types
|
121
|
+
#
|
122
|
+
callback :event_handler, [:pointer, :pointer], :void
|
123
|
+
|
124
|
+
EventType = enum(
|
125
|
+
:MediaMetaChanged, 0,
|
126
|
+
:MediaSubItemAdded,
|
127
|
+
:MediaDurationChanged,
|
128
|
+
:MediaParsedChanged,
|
129
|
+
:MediaFreed,
|
130
|
+
:MediaStateChanged,
|
131
|
+
|
132
|
+
:MediaPlayerMediaChanged, 0x100,
|
133
|
+
:MediaPlayerNothingSpecial,
|
134
|
+
:MediaPlayerOpening,
|
135
|
+
:MediaPlayerBuffering,
|
136
|
+
:MediaPlayerPlaying,
|
137
|
+
:MediaPlayerPaused,
|
138
|
+
:MediaPlayerStopped,
|
139
|
+
:MediaPlayerForward,
|
140
|
+
:MediaPlayerBackward,
|
141
|
+
:MediaPlayerEndReached,
|
142
|
+
:MediaPlayerEncounteredError,
|
143
|
+
:MediaPlayerTimeChanged,
|
144
|
+
:MediaPlayerPositionChanged,
|
145
|
+
:MediaPlayerSeekableChanged,
|
146
|
+
:MediaPlayerPausableChanged,
|
147
|
+
:MediaPlayerTitleChanged,
|
148
|
+
:MediaPlayerSnapshotTaken,
|
149
|
+
:MediaPlayerLengthChanged,
|
150
|
+
:MediaPlayerVout,
|
151
|
+
|
152
|
+
:MediaListItemAdded, 0x200,
|
153
|
+
:MediaListWillAddItem,
|
154
|
+
:MediaListItemDeleted,
|
155
|
+
:MediaListWillDeleteItem,
|
156
|
+
|
157
|
+
:MediaListViewItemAdded, 0x300,
|
158
|
+
:MediaListViewWillAddItem,
|
159
|
+
:MediaListViewItemDeleted,
|
160
|
+
:MediaListViewWillDeleteItem,
|
161
|
+
|
162
|
+
:MediaListPlayerPlayed, 0x400,
|
163
|
+
:MediaListPlayerNextItemSet,
|
164
|
+
:MediaListPlayerStopped,
|
165
|
+
|
166
|
+
:MediaDiscovererStarted, 0x500,
|
167
|
+
:MediaDiscovererEnded,
|
168
|
+
|
169
|
+
:VlmMediaAdded, 0x600,
|
170
|
+
:VlmMediaRemoved,
|
171
|
+
:VlmMediaChanged,
|
172
|
+
:VlmMediaInstanceStarted,
|
173
|
+
:VlmMediaInstanceStopped,
|
174
|
+
:VlmMediaInstanceStatusInit,
|
175
|
+
:VlmMediaInstanceStatusOpening,
|
176
|
+
:VlmMediaInstanceStatusPlaying,
|
177
|
+
:VlmMediaInstanceStatusPause,
|
178
|
+
:VlmMediaInstanceStatusEnd,
|
179
|
+
:VlmMediaInstanceStatusError
|
180
|
+
)
|
181
|
+
|
182
|
+
event_manager_functions = {
|
183
|
+
event_attach: [[:pointer, EventType, :event_handler, :pointer], :int],
|
184
|
+
event_detach: [[:pointer, EventType, :event_handler, :pointer], :void],
|
185
|
+
event_type_name: [[:int], :string]
|
186
|
+
}
|
187
|
+
|
188
|
+
# Here we use all these data and actually attache the functions.
|
189
|
+
[ core_functions, media_functions, media_list_functions, media_player_functions,
|
190
|
+
media_list_player_functions, event_manager_functions].each do |functions|
|
191
|
+
functions.each do |symbol, args|
|
192
|
+
attach_function "libvlc_#{symbol}".to_sym, args[0], args[1]
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ActiveVlc::LibVlc
|
2
|
+
class Event < FFI::Struct
|
3
|
+
layout :type, :int,
|
4
|
+
:object, :pointer
|
5
|
+
end
|
6
|
+
|
7
|
+
class EventManager
|
8
|
+
EventType = Api::EventType
|
9
|
+
|
10
|
+
attr_reader :callbacks, :events_received
|
11
|
+
|
12
|
+
def initialize(ptr)
|
13
|
+
@ptr = ptr
|
14
|
+
@callbacks = {}
|
15
|
+
@events_received = 0
|
16
|
+
|
17
|
+
@event_handler = Proc.new { |event, void| _event(event, void) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def on(types, &block)
|
21
|
+
event_is_valid = true
|
22
|
+
types = [types] unless types.is_a? Array
|
23
|
+
# Get the enum value if we gat a Symbol or String
|
24
|
+
|
25
|
+
types.each do |type|
|
26
|
+
if type.is_a?(String) or type.is_a?(Symbol)
|
27
|
+
type = EventType[type.to_sym]
|
28
|
+
end
|
29
|
+
|
30
|
+
# If this is the first callback for this type, register the :event_handler
|
31
|
+
# using vlc's API and create the proc array for that 'type'.
|
32
|
+
unless @callbacks[type]
|
33
|
+
event_is_valid = Api.libvlc_event_attach(@ptr, type, @event_handler, nil) == 0
|
34
|
+
@callbacks[type] = Array.new if event_is_valid
|
35
|
+
end
|
36
|
+
@callbacks[type].push block if event_is_valid
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
def _event(event, void)
|
42
|
+
event = Event.new(event)
|
43
|
+
type = EventType[event[:type]]
|
44
|
+
|
45
|
+
@events_received += 1;
|
46
|
+
|
47
|
+
puts "Received event (#{@events_received}): #{EventType[event[:type]]}"
|
48
|
+
|
49
|
+
return unless @callbacks[event[:type]].is_a? Array
|
50
|
+
@callbacks[event[:type]].each { |proc| proc.call(type) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|