vcs_ruby 1.1.8 → 1.1.9
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.
- checksums.yaml +7 -0
- data/bin/vcs.rb +171 -169
- data/lib/FFmpeg/ffmpeg.rb +121 -121
- data/lib/FFmpeg/ffmpeg_audio_stream.rb +37 -37
- data/lib/FFmpeg/ffmpeg_meta_info.rb +36 -36
- data/lib/FFmpeg/ffmpeg_video_stream.rb +62 -56
- data/lib/MPlayer/mplayer.rb +101 -101
- data/lib/MPlayer/mplayer_audio_stream.rb +33 -33
- data/lib/MPlayer/mplayer_meta_info.rb +39 -39
- data/lib/MPlayer/mplayer_video_stream.rb +44 -44
- data/lib/black.yml +12 -12
- data/lib/capturer.rb +69 -69
- data/lib/command.rb +51 -51
- data/lib/configuration.rb +150 -150
- data/lib/contact_sheet.rb +380 -366
- data/lib/defaults.yml +39 -39
- data/lib/font.rb +81 -81
- data/lib/frame.rb +161 -161
- data/lib/libAV/libav.rb +151 -151
- data/lib/libAV/libav_audio_stream.rb +37 -37
- data/lib/libAV/libav_meta_info.rb +36 -36
- data/lib/libAV/libav_video_stream.rb +62 -56
- data/lib/oldstyle.yml +22 -22
- data/lib/stream.rb +24 -24
- data/lib/time_index.rb +121 -121
- data/lib/tools.rb +81 -70
- data/lib/vcs.rb +26 -26
- data/lib/version.info +1 -1
- data/lib/version.rb +25 -25
- data/lib/video.rb +92 -88
- data/lib/white.yml +12 -12
- metadata +39 -47
data/lib/capturer.rb
CHANGED
@@ -1,69 +1,69 @@
|
|
1
|
-
#
|
2
|
-
# Capturer Baseclass
|
3
|
-
#
|
4
|
-
|
5
|
-
require 'vcs'
|
6
|
-
|
7
|
-
module VCSRuby
|
8
|
-
class Capturer
|
9
|
-
$formats = { :png => 'png', :bmp => 'bmp', :tiff => 'tif', :mjpeg => 'jpg', :jpeg => 'jpg', :jpg => 'jpg' }
|
10
|
-
|
11
|
-
def available?
|
12
|
-
false
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.initialize_capturers video
|
16
|
-
capturers = []
|
17
|
-
|
18
|
-
puts "Available capturers: #{available_capturers.map{ |c| c.to_s }.join(', ')}" if Tools.verbose?
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.create
|
22
|
-
capturers = []
|
23
|
-
|
24
|
-
capturers << LibAV.new(video)
|
25
|
-
capturers << MPlayer.new(video)
|
26
|
-
capturers << FFmpeg.new(video)
|
27
|
-
|
28
|
-
return capturers.first
|
29
|
-
end
|
30
|
-
|
31
|
-
def format
|
32
|
-
@format || available_formats.first
|
33
|
-
end
|
34
|
-
|
35
|
-
def format_extension
|
36
|
-
$formats[format]
|
37
|
-
end
|
38
|
-
|
39
|
-
def format= format
|
40
|
-
if available_formats.include? format
|
41
|
-
@format = format
|
42
|
-
else
|
43
|
-
raise "Capturer '#{name}' does not support format: '#{format}'"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
def probe_meta_information
|
49
|
-
check_cache
|
50
|
-
return parse_meta_info
|
51
|
-
rescue Exception => e
|
52
|
-
puts e
|
53
|
-
return false
|
54
|
-
end
|
55
|
-
|
56
|
-
def parse_meta_info
|
57
|
-
parse_format && parse_audio_streams && parse_video_streams
|
58
|
-
end
|
59
|
-
|
60
|
-
def get_hash defines
|
61
|
-
result = {}
|
62
|
-
defines.lines.each do |line|
|
63
|
-
kv = line.split("=")
|
64
|
-
result[kv[0].strip] = kv[1].strip if kv.count == 2
|
65
|
-
end
|
66
|
-
result
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
1
|
+
#
|
2
|
+
# Capturer Baseclass
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'vcs'
|
6
|
+
|
7
|
+
module VCSRuby
|
8
|
+
class Capturer
|
9
|
+
$formats = { :png => 'png', :bmp => 'bmp', :tiff => 'tif', :mjpeg => 'jpg', :jpeg => 'jpg', :jpg => 'jpg' }
|
10
|
+
|
11
|
+
def available?
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.initialize_capturers video
|
16
|
+
capturers = []
|
17
|
+
|
18
|
+
puts "Available capturers: #{available_capturers.map{ |c| c.to_s }.join(', ')}" if Tools.verbose?
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.create
|
22
|
+
capturers = []
|
23
|
+
|
24
|
+
capturers << LibAV.new(video)
|
25
|
+
capturers << MPlayer.new(video)
|
26
|
+
capturers << FFmpeg.new(video)
|
27
|
+
|
28
|
+
return capturers.first
|
29
|
+
end
|
30
|
+
|
31
|
+
def format
|
32
|
+
@format || available_formats.first
|
33
|
+
end
|
34
|
+
|
35
|
+
def format_extension
|
36
|
+
$formats[format]
|
37
|
+
end
|
38
|
+
|
39
|
+
def format= format
|
40
|
+
if available_formats.include? format
|
41
|
+
@format = format
|
42
|
+
else
|
43
|
+
raise "Capturer '#{name}' does not support format: '#{format}'"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def probe_meta_information
|
49
|
+
check_cache
|
50
|
+
return parse_meta_info
|
51
|
+
rescue Exception => e
|
52
|
+
puts e
|
53
|
+
return false
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_meta_info
|
57
|
+
parse_format && parse_audio_streams && parse_video_streams
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_hash defines
|
61
|
+
result = {}
|
62
|
+
defines.lines.each do |line|
|
63
|
+
kv = line.split("=")
|
64
|
+
result[kv[0].strip] = kv[1].strip if kv.count == 2
|
65
|
+
end
|
66
|
+
result
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/command.rb
CHANGED
@@ -1,51 +1,51 @@
|
|
1
|
-
#
|
2
|
-
# Command
|
3
|
-
#
|
4
|
-
|
5
|
-
module VCSRuby
|
6
|
-
class Command
|
7
|
-
attr_reader :name
|
8
|
-
def initialize name, command
|
9
|
-
@name = name
|
10
|
-
@command = which(command)
|
11
|
-
@available = !!@command
|
12
|
-
end
|
13
|
-
|
14
|
-
def available?
|
15
|
-
@available
|
16
|
-
end
|
17
|
-
|
18
|
-
def execute parameter, streams = 0, no_error = false
|
19
|
-
raise "Command '#{name}' not available" unless available?
|
20
|
-
puts "#{@command} #{parameter}" if Configuration.instance.verbose?
|
21
|
-
result = nil
|
22
|
-
if Tools::windows?
|
23
|
-
streams = '2> nul' if streams === 0
|
24
|
-
|
25
|
-
result = `cmd /C #{@command} #{parameter} #{streams}`
|
26
|
-
else
|
27
|
-
streams = "2> /dev/null" if streams === 0
|
28
|
-
|
29
|
-
result
|
30
|
-
end
|
31
|
-
|
32
|
-
raise "#{@command} failed with return value '#{$?}'" unless $?.to_i == 0 || no_error
|
33
|
-
return result
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
# http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby
|
38
|
-
def which cmd
|
39
|
-
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
40
|
-
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
41
|
-
exts.each do |ext|
|
42
|
-
exe = File.join(path, "#{cmd}#{ext}")
|
43
|
-
if File.executable?(exe) && !File.directory?(exe)
|
44
|
-
return exe
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
return nil
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
1
|
+
#
|
2
|
+
# Command
|
3
|
+
#
|
4
|
+
|
5
|
+
module VCSRuby
|
6
|
+
class Command
|
7
|
+
attr_reader :name
|
8
|
+
def initialize name, command
|
9
|
+
@name = name
|
10
|
+
@command = which(command)
|
11
|
+
@available = !!@command
|
12
|
+
end
|
13
|
+
|
14
|
+
def available?
|
15
|
+
@available
|
16
|
+
end
|
17
|
+
|
18
|
+
def execute parameter, streams = 0, no_error = false
|
19
|
+
raise "Command '#{name}' not available" unless available?
|
20
|
+
puts "#{@command} #{parameter}" if Configuration.instance.verbose?
|
21
|
+
result = nil
|
22
|
+
if Tools::windows?
|
23
|
+
streams = '2> nul' if streams === 0
|
24
|
+
|
25
|
+
result = `cmd /S /C ""#{@command}" #{parameter} #{streams}"`
|
26
|
+
else
|
27
|
+
streams = "2> /dev/null" if streams === 0
|
28
|
+
|
29
|
+
result =`"#{@command} #{parameter}" #{streams}`
|
30
|
+
end
|
31
|
+
|
32
|
+
raise "#{@command} failed with return value '#{$?}'" unless $?.to_i == 0 || no_error
|
33
|
+
return result
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
# http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby
|
38
|
+
def which cmd
|
39
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
40
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
41
|
+
exts.each do |ext|
|
42
|
+
exe = File.join(path, "#{cmd}#{ext}")
|
43
|
+
if File.executable?(exe) && !File.directory?(exe)
|
44
|
+
return exe
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
return nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/configuration.rb
CHANGED
@@ -1,150 +1,150 @@
|
|
1
|
-
#
|
2
|
-
# Configuration
|
3
|
-
#
|
4
|
-
|
5
|
-
require 'font'
|
6
|
-
require 'singleton'
|
7
|
-
|
8
|
-
class ::Hash
|
9
|
-
def deep_merge(second)
|
10
|
-
merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
|
11
|
-
self.merge(second, &merger)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
module VCSRuby
|
16
|
-
class Configuration
|
17
|
-
include Singleton
|
18
|
-
|
19
|
-
attr_reader :header_font, :title_font, :timestamp_font, :signature_font
|
20
|
-
attr_writer :verbose, :quiet, :capturer
|
21
|
-
|
22
|
-
def initialize
|
23
|
-
default_config_file = File.expand_path("defaults.yml", File.dirname(__FILE__))
|
24
|
-
@config = ::YAML::load_file(default_config_file)
|
25
|
-
|
26
|
-
local_config_files = ['~/.vcs.rb.yml']
|
27
|
-
local_config_files.select{ |f| File.exists?(f) }.each do |local_config_file|
|
28
|
-
local_config = YAML::load_file(local_config_file)
|
29
|
-
@config = @config.deep_merge(local_config)
|
30
|
-
end
|
31
|
-
|
32
|
-
@header_font = Font.new @config['style']['header']['font'], @config['style']['header']['size']
|
33
|
-
@title_font = Font.new @config['style']['title']['font'], @config['style']['title']['size']
|
34
|
-
@timestamp_font = Font.new @config['style']['timestamp']['font'], @config['style']['timestamp']['size']
|
35
|
-
@signature_font = Font.new @config['style']['signature']['font'], @config['style']['signature']['size']
|
36
|
-
end
|
37
|
-
|
38
|
-
def load_profile profile
|
39
|
-
profiles = [File.expand_path("#{profile}.yml", File.dirname(__FILE__)), "~/#{profile}.yml"]
|
40
|
-
|
41
|
-
found = false
|
42
|
-
profiles.each do |profile|
|
43
|
-
if File.exists?(profile)
|
44
|
-
puts "Profile loaded: #{profile}" if verbose?
|
45
|
-
config = YAML::load_file(profile)
|
46
|
-
@config = @config.deep_merge(config)
|
47
|
-
found = true
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
raise "No profile '#{profile}' found" unless found
|
52
|
-
end
|
53
|
-
|
54
|
-
def verbose?
|
55
|
-
@verbose
|
56
|
-
end
|
57
|
-
|
58
|
-
def quiet?
|
59
|
-
@quiet
|
60
|
-
end
|
61
|
-
|
62
|
-
def capturer
|
63
|
-
@capturer || :any
|
64
|
-
end
|
65
|
-
|
66
|
-
def rows
|
67
|
-
@config['main']['rows'] ? @config['main']['rows'].to_i : nil
|
68
|
-
end
|
69
|
-
|
70
|
-
def columns
|
71
|
-
@config['main']['columns'] ? @config['main']['columns'].to_i : nil
|
72
|
-
end
|
73
|
-
|
74
|
-
def interval
|
75
|
-
@config['main']['interval'] ? TimeIndex.new(@config['main']['interval']) : nil
|
76
|
-
end
|
77
|
-
|
78
|
-
def padding
|
79
|
-
@config['main']['padding'] ? @config['main']['padding'].to_i : 2
|
80
|
-
end
|
81
|
-
|
82
|
-
def quality
|
83
|
-
@config['main']['quality'] ? @config['main']['quality'].to_i : 90
|
84
|
-
end
|
85
|
-
|
86
|
-
def header_background
|
87
|
-
@config['style']['header']['background']
|
88
|
-
end
|
89
|
-
|
90
|
-
def header_color
|
91
|
-
@config['style']['header']['color']
|
92
|
-
end
|
93
|
-
|
94
|
-
def title_background
|
95
|
-
@config['style']['title']['background']
|
96
|
-
end
|
97
|
-
|
98
|
-
def title_color
|
99
|
-
@config['style']['title']['color']
|
100
|
-
end
|
101
|
-
|
102
|
-
def highlight_background
|
103
|
-
@config['style']['highlight']['background']
|
104
|
-
end
|
105
|
-
|
106
|
-
def contact_background
|
107
|
-
@config['style']['contact']['background']
|
108
|
-
end
|
109
|
-
|
110
|
-
def timestamp_background
|
111
|
-
@config['style']['timestamp']['background']
|
112
|
-
end
|
113
|
-
|
114
|
-
def timestamp_color
|
115
|
-
@config['style']['timestamp']['color']
|
116
|
-
end
|
117
|
-
|
118
|
-
def signature_background
|
119
|
-
@config['style']['signature']['background']
|
120
|
-
end
|
121
|
-
|
122
|
-
def signature_color
|
123
|
-
@config['style']['signature']['color']
|
124
|
-
end
|
125
|
-
|
126
|
-
def blank_threshold
|
127
|
-
@config['lowlevel']['blank_threshold'].to_f
|
128
|
-
end
|
129
|
-
|
130
|
-
def blank_evasion?
|
131
|
-
@config['lowlevel']['blank_evasion']
|
132
|
-
end
|
133
|
-
|
134
|
-
def blank_alternatives
|
135
|
-
@config['lowlevel']['blank_alternatives'].map{ |e| TimeIndex.new e.to_i }
|
136
|
-
end
|
137
|
-
|
138
|
-
def timestamp
|
139
|
-
!!@config['filter']['timestamp']
|
140
|
-
end
|
141
|
-
|
142
|
-
def polaroid
|
143
|
-
!!@config['filter']['polaroid']
|
144
|
-
end
|
145
|
-
|
146
|
-
def softshadow
|
147
|
-
!!@config['filter']['softshadow']
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
1
|
+
#
|
2
|
+
# Configuration
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'font'
|
6
|
+
require 'singleton'
|
7
|
+
|
8
|
+
class ::Hash
|
9
|
+
def deep_merge(second)
|
10
|
+
merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
|
11
|
+
self.merge(second, &merger)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module VCSRuby
|
16
|
+
class Configuration
|
17
|
+
include Singleton
|
18
|
+
|
19
|
+
attr_reader :header_font, :title_font, :timestamp_font, :signature_font
|
20
|
+
attr_writer :verbose, :quiet, :capturer
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
default_config_file = File.expand_path("defaults.yml", File.dirname(__FILE__))
|
24
|
+
@config = ::YAML::load_file(default_config_file)
|
25
|
+
|
26
|
+
local_config_files = ['~/.vcs.rb.yml']
|
27
|
+
local_config_files.select{ |f| File.exists?(f) }.each do |local_config_file|
|
28
|
+
local_config = YAML::load_file(local_config_file)
|
29
|
+
@config = @config.deep_merge(local_config)
|
30
|
+
end
|
31
|
+
|
32
|
+
@header_font = Font.new @config['style']['header']['font'], @config['style']['header']['size']
|
33
|
+
@title_font = Font.new @config['style']['title']['font'], @config['style']['title']['size']
|
34
|
+
@timestamp_font = Font.new @config['style']['timestamp']['font'], @config['style']['timestamp']['size']
|
35
|
+
@signature_font = Font.new @config['style']['signature']['font'], @config['style']['signature']['size']
|
36
|
+
end
|
37
|
+
|
38
|
+
def load_profile profile
|
39
|
+
profiles = [File.expand_path("#{profile}.yml", File.dirname(__FILE__)), "~/#{profile}.yml"]
|
40
|
+
|
41
|
+
found = false
|
42
|
+
profiles.each do |profile|
|
43
|
+
if File.exists?(profile)
|
44
|
+
puts "Profile loaded: #{profile}" if verbose?
|
45
|
+
config = YAML::load_file(profile)
|
46
|
+
@config = @config.deep_merge(config)
|
47
|
+
found = true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
raise "No profile '#{profile}' found" unless found
|
52
|
+
end
|
53
|
+
|
54
|
+
def verbose?
|
55
|
+
@verbose
|
56
|
+
end
|
57
|
+
|
58
|
+
def quiet?
|
59
|
+
@quiet
|
60
|
+
end
|
61
|
+
|
62
|
+
def capturer
|
63
|
+
@capturer || :any
|
64
|
+
end
|
65
|
+
|
66
|
+
def rows
|
67
|
+
@config['main']['rows'] ? @config['main']['rows'].to_i : nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def columns
|
71
|
+
@config['main']['columns'] ? @config['main']['columns'].to_i : nil
|
72
|
+
end
|
73
|
+
|
74
|
+
def interval
|
75
|
+
@config['main']['interval'] ? TimeIndex.new(@config['main']['interval']) : nil
|
76
|
+
end
|
77
|
+
|
78
|
+
def padding
|
79
|
+
@config['main']['padding'] ? @config['main']['padding'].to_i : 2
|
80
|
+
end
|
81
|
+
|
82
|
+
def quality
|
83
|
+
@config['main']['quality'] ? @config['main']['quality'].to_i : 90
|
84
|
+
end
|
85
|
+
|
86
|
+
def header_background
|
87
|
+
@config['style']['header']['background']
|
88
|
+
end
|
89
|
+
|
90
|
+
def header_color
|
91
|
+
@config['style']['header']['color']
|
92
|
+
end
|
93
|
+
|
94
|
+
def title_background
|
95
|
+
@config['style']['title']['background']
|
96
|
+
end
|
97
|
+
|
98
|
+
def title_color
|
99
|
+
@config['style']['title']['color']
|
100
|
+
end
|
101
|
+
|
102
|
+
def highlight_background
|
103
|
+
@config['style']['highlight']['background']
|
104
|
+
end
|
105
|
+
|
106
|
+
def contact_background
|
107
|
+
@config['style']['contact']['background']
|
108
|
+
end
|
109
|
+
|
110
|
+
def timestamp_background
|
111
|
+
@config['style']['timestamp']['background']
|
112
|
+
end
|
113
|
+
|
114
|
+
def timestamp_color
|
115
|
+
@config['style']['timestamp']['color']
|
116
|
+
end
|
117
|
+
|
118
|
+
def signature_background
|
119
|
+
@config['style']['signature']['background']
|
120
|
+
end
|
121
|
+
|
122
|
+
def signature_color
|
123
|
+
@config['style']['signature']['color']
|
124
|
+
end
|
125
|
+
|
126
|
+
def blank_threshold
|
127
|
+
@config['lowlevel']['blank_threshold'].to_f
|
128
|
+
end
|
129
|
+
|
130
|
+
def blank_evasion?
|
131
|
+
@config['lowlevel']['blank_evasion']
|
132
|
+
end
|
133
|
+
|
134
|
+
def blank_alternatives
|
135
|
+
@config['lowlevel']['blank_alternatives'].map{ |e| TimeIndex.new e.to_i }
|
136
|
+
end
|
137
|
+
|
138
|
+
def timestamp
|
139
|
+
!!@config['filter']['timestamp']
|
140
|
+
end
|
141
|
+
|
142
|
+
def polaroid
|
143
|
+
!!@config['filter']['polaroid']
|
144
|
+
end
|
145
|
+
|
146
|
+
def softshadow
|
147
|
+
!!@config['filter']['softshadow']
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|