mediainfo 0.6.2 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog +5 -0
- data/Manifest +1 -0
- data/README.markdown +1 -0
- data/Rakefile +3 -1
- data/index.html.template +9 -0
- data/lib/mediainfo.rb +268 -168
- data/lib/mediainfo/attr_readers.rb +26 -29
- data/mediainfo.gemspec +5 -5
- data/test/mediainfo_awaywego_test.rb +64 -67
- data/test/mediainfo_broken_embraces_test.rb +59 -62
- data/test/mediainfo_dinner_test.rb +64 -67
- data/test/mediainfo_hats_test.rb +58 -61
- data/test/mediainfo_multiple_streams_test.rb +516 -0
- data/test/mediainfo_omen_image_test.rb +42 -44
- data/test/mediainfo_test.rb +5 -0
- data/test/mediainfo_vimeo_test.rb +59 -62
- metadata +15 -5
data/Changelog
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
v0.7.0 Multiple Stream Support
|
2
|
+
- ***NOTE*** MAJOR API CHANGE ***NOTE***
|
3
|
+
- updated API to support files with multiple streams of one type,
|
4
|
+
e.g. a Quicktime with multiple video tracks
|
5
|
+
|
1
6
|
v0.6.2 XML Configuration Examples
|
2
7
|
- added examples on how to configure XML back end
|
3
8
|
|
data/Manifest
CHANGED
data/README.markdown
CHANGED
@@ -54,3 +54,4 @@ generate XML output, and is no longer supported.
|
|
54
54
|
|
55
55
|
* Seth Thomas Rasmussen - [http://greatseth.com](http://greatseth.com)
|
56
56
|
* Peter Vandenberk - [http://github.com/pvdb](http://github.com/pvdb)
|
57
|
+
* Ned Campion - [http://github.com/nedcampion](http://github.com/nedcampion)
|
data/Rakefile
CHANGED
@@ -18,7 +18,7 @@ class Echoe
|
|
18
18
|
end
|
19
19
|
|
20
20
|
Echoe.new "mediainfo" do |p|
|
21
|
-
p.description = "Mediainfo is a class wrapping the mediainfo CLI (http://mediainfo.sourceforge.net)"
|
21
|
+
p.description = p.summary = "Mediainfo is a class wrapping the mediainfo CLI (http://mediainfo.sourceforge.net)"
|
22
22
|
p.author = "Seth Thomas Rasmussen"
|
23
23
|
p.email = "sethrasmussen@gmail.com"
|
24
24
|
p.url = "http://greatseth.github.com/mediainfo"
|
@@ -59,3 +59,5 @@ task :fixture do
|
|
59
59
|
puts "Error generating fixture. #{fixture} not created."
|
60
60
|
end
|
61
61
|
end
|
62
|
+
|
63
|
+
# require 'github/pages/tasks'
|
data/index.html.template
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
6
|
+
<title>mediainfo</title>
|
7
|
+
</head>
|
8
|
+
<body>body</body>
|
9
|
+
</html>
|
data/lib/mediainfo.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "forwardable"
|
1
2
|
require "mediainfo/string"
|
2
3
|
require "mediainfo/attr_readers"
|
3
4
|
|
@@ -55,155 +56,268 @@ Previous versions of this gem(<= 0.5.1) worked against v0.7.11, which did not
|
|
55
56
|
generate XML output, and is no longer supported.
|
56
57
|
=end
|
57
58
|
class Mediainfo
|
59
|
+
extend Forwardable
|
58
60
|
extend AttrReaders
|
59
61
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
mediainfo_attr_reader :codec_id, "Codec ID"
|
65
|
-
|
66
|
-
mediainfo_duration_reader :duration
|
67
|
-
|
68
|
-
mediainfo_attr_reader :format
|
69
|
-
mediainfo_attr_reader :format_profile
|
70
|
-
mediainfo_attr_reader :format_info
|
71
|
-
mediainfo_attr_reader :overall_bit_rate
|
72
|
-
mediainfo_attr_reader :writing_application
|
73
|
-
mediainfo_attr_reader :writing_library
|
74
|
-
|
75
|
-
def size; File.size(@full_filename) if @full_filename; end
|
76
|
-
|
77
|
-
mediainfo_date_reader :mastered_date
|
78
|
-
mediainfo_date_reader :tagged_date
|
79
|
-
mediainfo_date_reader :encoded_date
|
80
|
-
|
81
|
-
### VIDEO
|
82
|
-
|
83
|
-
mediainfo_section_query :video
|
84
|
-
|
85
|
-
mediainfo_attr_reader :video_stream_id, "ID"
|
86
|
-
|
87
|
-
mediainfo_duration_reader :video_duration
|
88
|
-
|
89
|
-
mediainfo_attr_reader :video_stream_size
|
90
|
-
mediainfo_attr_reader :video_bit_rate
|
91
|
-
mediainfo_attr_reader :video_nominal_bit_rate
|
92
|
-
|
93
|
-
mediainfo_attr_reader :video_bit_rate_mode
|
94
|
-
def cbr?; video? and "Constant" == video_bit_rate_mode; end
|
95
|
-
def vbr?; video? and not cbr?; end
|
96
|
-
|
97
|
-
mediainfo_attr_reader :video_scan_order
|
98
|
-
mediainfo_attr_reader :video_scan_type
|
99
|
-
def interlaced?; video? and "Interlaced" == video_scan_type; end
|
100
|
-
def progressive?; video? and not interlaced? end
|
101
|
-
|
102
|
-
mediainfo_int_reader :video_resolution
|
103
|
-
|
104
|
-
mediainfo_attr_reader :video_colorimetry
|
105
|
-
alias_method :video_colorspace, :video_colorimetry
|
106
|
-
|
107
|
-
mediainfo_attr_reader :video_format
|
108
|
-
mediainfo_attr_reader :video_format_profile
|
109
|
-
mediainfo_attr_reader :video_format_version
|
110
|
-
mediainfo_attr_reader :video_format_settings_cabac, "Format settings, CABAC"
|
111
|
-
mediainfo_attr_reader :video_format_settings_reframes, "Format settings, ReFrames"
|
112
|
-
mediainfo_attr_reader :video_format_settings_matrix, "Format settings, Matrix"
|
113
|
-
# Format settings, BVOP : Yes
|
114
|
-
# Format settings, QPel : No
|
115
|
-
# Format settings, GMC : No warppoints
|
116
|
-
# mediainfo_attr_reader :video_format_settings_qpel, "Format settings, QPel"
|
117
|
-
mediainfo_attr_reader :video_color_primaries
|
118
|
-
mediainfo_attr_reader :video_transfer_characteristics
|
119
|
-
mediainfo_attr_reader :video_matrix_coefficients
|
120
|
-
|
121
|
-
mediainfo_attr_reader :video_codec_id, "Codec ID"
|
122
|
-
mediainfo_attr_reader :video_codec_info, "Codec ID/Info"
|
123
|
-
|
124
|
-
mediainfo_attr_reader :video_frame_rate
|
125
|
-
def fps; video_frame_rate[/[\d.]+/].to_f if video?; end
|
126
|
-
alias_method :framerate, :fps
|
127
|
-
|
128
|
-
mediainfo_attr_reader :video_minimum_frame_rate
|
129
|
-
def min_fps; video_minimum_frame_rate[/[\d.]+/].to_f if video?; end
|
130
|
-
alias_method :min_framerate, :min_fps
|
131
|
-
|
132
|
-
mediainfo_attr_reader :video_maximum_frame_rate
|
133
|
-
def max_fps; video_maximum_frame_rate[/[\d.]+/].to_f if video?; end
|
134
|
-
alias_method :max_framerate, :max_fps
|
135
|
-
|
136
|
-
mediainfo_attr_reader :video_frame_rate_mode
|
137
|
-
|
138
|
-
mediainfo_attr_reader :video_display_aspect_ratio
|
139
|
-
alias_method :display_aspect_ratio, :video_display_aspect_ratio
|
140
|
-
|
141
|
-
mediainfo_attr_reader :video_bits_pixel_frame, "Bits/(Pixel*Frame)"
|
142
|
-
|
143
|
-
mediainfo_int_reader :video_width
|
144
|
-
mediainfo_int_reader :video_height
|
62
|
+
class Error < StandardError; end
|
63
|
+
class ExecutionError < Error; end
|
64
|
+
class IncompatibleVersionError < Error; end
|
145
65
|
|
146
|
-
def
|
147
|
-
|
148
|
-
|
66
|
+
def self.delegate(method_name, stream_type = nil)
|
67
|
+
if stream_type == :general
|
68
|
+
def_delegator :"@#{stream_type}_stream", method_name
|
69
|
+
else
|
70
|
+
def_delegator :"@#{stream_type}_stream", method_name, "#{stream_type}_#{method_name}"
|
71
|
+
end
|
72
|
+
end
|
149
73
|
|
150
|
-
|
151
|
-
|
74
|
+
def self.version
|
75
|
+
@version ||= `#{path} --Version`[/v([\d.]+)/, 1]
|
76
|
+
end
|
152
77
|
|
153
|
-
|
78
|
+
# AttrReaders depends on this.
|
79
|
+
def self.supported_attributes; @supported_attributes ||= []; end
|
154
80
|
|
155
|
-
|
81
|
+
SECTIONS = [:general, :video, :audio, :image]
|
82
|
+
NON_GENERAL_SECTIONS = SECTIONS - [:general]
|
156
83
|
|
157
|
-
|
84
|
+
attr_reader :streams
|
158
85
|
|
159
|
-
|
86
|
+
# Size of source file as reported by File.size.
|
87
|
+
# Returns nil if you haven't yet fired off the system command.
|
88
|
+
def size; File.size(@full_filename) if @full_filename; end
|
160
89
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
90
|
+
class StreamProxy
|
91
|
+
def initialize(mediainfo, stream_type)
|
92
|
+
unless Mediainfo::SECTIONS.include? stream_type
|
93
|
+
raise ArgumentError, "invalid stream_type: #{stream_type.inspect}"
|
94
|
+
end
|
95
|
+
|
96
|
+
@stream_type = stream_type
|
97
|
+
@mediainfo = mediainfo
|
98
|
+
@streams = @mediainfo.streams.select { |x| x.send("#{stream_type}?") }
|
99
|
+
end
|
100
|
+
|
101
|
+
def [](id); @streams[id]; end
|
102
|
+
def count; @streams.size; end
|
103
|
+
attr_reader :streams
|
104
|
+
attr_reader :stream_type
|
105
|
+
|
106
|
+
class SingleStreamAPIError < RuntimeError; end
|
107
|
+
class NoStreamsForProxyError < NoMethodError; end
|
108
|
+
|
109
|
+
def method_missing(m, *a, &b)
|
110
|
+
if streams.size > 1
|
111
|
+
raise SingleStreamAPIError, "You cannot use the single stream, convenience API on a multi-stream file."
|
112
|
+
else
|
113
|
+
if relevant_stream = streams.detect { |s| s.respond_to?(m) }
|
114
|
+
relevant_stream.send(m, *a, &b)
|
115
|
+
else
|
116
|
+
raise NoStreamsForProxyError, "there are no :#{stream_type} streams to send :#{m} to"
|
117
|
+
end
|
118
|
+
end
|
170
119
|
end
|
171
|
-
number.to_i
|
172
120
|
end
|
173
|
-
alias_method :audio_sampling_rate, :audio_sample_rate
|
174
|
-
|
175
|
-
mediainfo_attr_reader :audio_stream_size
|
176
|
-
mediainfo_attr_reader :audio_bit_rate
|
177
|
-
mediainfo_attr_reader :audio_bit_rate_mode
|
178
|
-
mediainfo_attr_reader :audio_interleave_duration, "Interleave, duration"
|
179
121
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
122
|
+
class Stream
|
123
|
+
class InvalidStreamType < Mediainfo::Error; end
|
124
|
+
|
125
|
+
def self.inherited(stream_type)
|
126
|
+
stream_type.extend(AttrReaders)
|
127
|
+
|
128
|
+
def stream_type.method_added(method_name)
|
129
|
+
if stream_type = name[/[^:]+$/][/^(#{SECTIONS.map { |x| x.to_s.capitalize } * '|'})/]
|
130
|
+
stream_type.downcase!
|
131
|
+
stream_type = stream_type.to_sym
|
132
|
+
else
|
133
|
+
raise "could not determine stream type, please report bug!"
|
134
|
+
end
|
135
|
+
|
136
|
+
Mediainfo.delegate(method_name, stream_type)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.create(stream_type)
|
141
|
+
raise ArgumentError, "need a stream_type, received #{stream_type.inspect}" if stream_type.nil?
|
142
|
+
|
143
|
+
stream_class_name = "#{stream_type}Stream"
|
144
|
+
|
145
|
+
if Mediainfo.const_defined?(stream_class_name)
|
146
|
+
Mediainfo.const_get(stream_class_name).new(stream_type)
|
147
|
+
else
|
148
|
+
raise InvalidStreamType, "bad stream type: #{stream_type.inspect}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def initialize(stream_type)
|
153
|
+
raise ArgumentError, "need a stream_type, received #{stream_type.inspect}" if stream_type.nil?
|
154
|
+
|
155
|
+
@stream_type = stream_type.downcase.to_sym
|
156
|
+
|
157
|
+
# TODO @parsed_response is not the best name anymore, but I'm leaving it
|
158
|
+
# alone to focus on refactoring the interface to the streams
|
159
|
+
# before I refactor the attribute reader implementations.
|
160
|
+
@parsed_response = { @stream_type => {} }
|
161
|
+
end
|
162
|
+
|
163
|
+
def [](k); @parsed_response[@stream_type][k]; end
|
164
|
+
def []=(k,v); @parsed_response[@stream_type][k] = v; end
|
165
|
+
|
166
|
+
Mediainfo::SECTIONS.each { |t| define_method("#{t}?") { t == @stream_type } }
|
167
|
+
end
|
191
168
|
|
192
|
-
|
193
|
-
|
194
|
-
|
169
|
+
class GeneralStream < Stream
|
170
|
+
mediainfo_attr_reader :codec_id, "Codec ID"
|
171
|
+
|
172
|
+
mediainfo_duration_reader :duration
|
173
|
+
|
174
|
+
mediainfo_attr_reader :format
|
175
|
+
mediainfo_attr_reader :format_profile
|
176
|
+
mediainfo_attr_reader :format_info
|
177
|
+
mediainfo_attr_reader :overall_bit_rate
|
178
|
+
mediainfo_attr_reader :writing_application
|
179
|
+
mediainfo_attr_reader :writing_library
|
180
|
+
|
181
|
+
mediainfo_date_reader :mastered_date
|
182
|
+
mediainfo_date_reader :tagged_date
|
183
|
+
mediainfo_date_reader :encoded_date
|
184
|
+
end
|
195
185
|
|
196
|
-
|
197
|
-
|
186
|
+
class VideoStream < Stream
|
187
|
+
mediainfo_attr_reader :stream_id, "ID"
|
188
|
+
|
189
|
+
mediainfo_duration_reader :duration
|
190
|
+
|
191
|
+
mediainfo_attr_reader :stream_size
|
192
|
+
mediainfo_attr_reader :bit_rate
|
193
|
+
mediainfo_attr_reader :nominal_bit_rate
|
194
|
+
|
195
|
+
mediainfo_attr_reader :bit_rate_mode
|
196
|
+
def cbr?; video? and "Constant" == bit_rate_mode; end
|
197
|
+
def vbr?; video? and not cbr?; end
|
198
|
+
|
199
|
+
mediainfo_attr_reader :scan_order
|
200
|
+
mediainfo_attr_reader :scan_type
|
201
|
+
def interlaced?; video? and "Interlaced" == scan_type; end
|
202
|
+
def progressive?; video? and not interlaced? end
|
203
|
+
|
204
|
+
mediainfo_int_reader :resolution
|
205
|
+
|
206
|
+
mediainfo_attr_reader :colorimetry
|
207
|
+
alias_method :colorspace, :colorimetry
|
208
|
+
|
209
|
+
mediainfo_attr_reader :format
|
210
|
+
mediainfo_attr_reader :format_info
|
211
|
+
mediainfo_attr_reader :format_profile
|
212
|
+
mediainfo_attr_reader :format_version
|
213
|
+
mediainfo_attr_reader :format_settings_cabac, "Format settings, CABAC"
|
214
|
+
mediainfo_attr_reader :format_settings_reframes, "Format settings, ReFrames"
|
215
|
+
mediainfo_attr_reader :format_settings_matrix, "Format settings, Matrix"
|
216
|
+
# Format settings, BVOP : Yes
|
217
|
+
# Format settings, QPel : No
|
218
|
+
# Format settings, GMC : No warppoints
|
219
|
+
# mediainfo_attr_reader :format_settings_qpel, "Format settings, QPel"
|
220
|
+
mediainfo_attr_reader :color_primaries
|
221
|
+
mediainfo_attr_reader :transfer_characteristics
|
222
|
+
mediainfo_attr_reader :matrix_coefficients
|
223
|
+
|
224
|
+
mediainfo_attr_reader :codec_id, "Codec ID"
|
225
|
+
mediainfo_attr_reader :codec_info, "Codec ID/Info"
|
226
|
+
alias_method :codec_id_info, :codec_info
|
227
|
+
|
228
|
+
mediainfo_attr_reader :frame_rate
|
229
|
+
def fps; frame_rate[/[\d.]+/].to_f if frame_rate; end
|
230
|
+
alias_method :framerate, :fps
|
231
|
+
|
232
|
+
mediainfo_attr_reader :minimum_frame_rate
|
233
|
+
def min_fps; minimum_frame_rate[/[\d.]+/].to_f if video?; end
|
234
|
+
alias_method :min_framerate, :min_fps
|
235
|
+
|
236
|
+
mediainfo_attr_reader :maximum_frame_rate
|
237
|
+
def max_fps; maximum_frame_rate[/[\d.]+/].to_f if video?; end
|
238
|
+
alias_method :max_framerate, :max_fps
|
239
|
+
|
240
|
+
mediainfo_attr_reader :frame_rate_mode
|
241
|
+
|
242
|
+
mediainfo_attr_reader :display_aspect_ratio
|
243
|
+
# alias_method :display_aspect_ratio, :display_aspect_ratio
|
244
|
+
|
245
|
+
mediainfo_attr_reader :bits_pixel_frame, "Bits/(Pixel*Frame)"
|
246
|
+
|
247
|
+
mediainfo_int_reader :width
|
248
|
+
mediainfo_int_reader :height
|
249
|
+
|
250
|
+
def frame_size; "#{width}x#{height}" if width or height; end
|
251
|
+
|
252
|
+
mediainfo_date_reader :encoded_date
|
253
|
+
mediainfo_date_reader :tagged_date
|
254
|
+
|
255
|
+
mediainfo_attr_reader :standard
|
256
|
+
end
|
198
257
|
|
199
|
-
|
258
|
+
class AudioStream < Stream
|
259
|
+
mediainfo_attr_reader :stream_id, "ID"
|
260
|
+
|
261
|
+
mediainfo_duration_reader :duration
|
262
|
+
|
263
|
+
mediainfo_attr_reader :sampling_rate
|
264
|
+
def sample_rate
|
265
|
+
return unless rate = sampling_rate_before_type_cast
|
266
|
+
number = rate.gsub(/[^\d.]+/, "").to_f
|
267
|
+
number = case rate
|
268
|
+
when /KHz/ then number * 1000
|
269
|
+
when /Hz/ then number
|
270
|
+
else
|
271
|
+
raise "unhandled sample rate! please report bug!"
|
272
|
+
end
|
273
|
+
number.to_i
|
274
|
+
end
|
275
|
+
alias_method :sampling_rate, :sample_rate
|
276
|
+
|
277
|
+
mediainfo_attr_reader :stream_size
|
278
|
+
mediainfo_attr_reader :bit_rate
|
279
|
+
mediainfo_attr_reader :bit_rate_mode
|
280
|
+
mediainfo_attr_reader :interleave_duration, "Interleave, duration"
|
281
|
+
|
282
|
+
mediainfo_int_reader :resolution
|
283
|
+
alias_method :sample_bit_depth, :resolution
|
284
|
+
|
285
|
+
mediainfo_attr_reader :format
|
286
|
+
mediainfo_attr_reader :format_profile
|
287
|
+
mediainfo_attr_reader :format_version
|
288
|
+
mediainfo_attr_reader :format_info, "Format/Info"
|
289
|
+
mediainfo_attr_reader :format_settings_sbr, "Format settings, SBR"
|
290
|
+
mediainfo_attr_reader :format_settings_endianness, "Format settings, Endianness"
|
291
|
+
mediainfo_attr_reader :format_settings_sign, "Format settings, Sign"
|
292
|
+
mediainfo_attr_reader :codec_id, "Codec ID"
|
293
|
+
mediainfo_attr_reader :codec_info, "Codec ID/Info"
|
294
|
+
mediainfo_attr_reader :codec_id_hint
|
295
|
+
mediainfo_attr_reader :channel_positions
|
296
|
+
|
297
|
+
mediainfo_int_reader :channels, "Channel(s)"
|
298
|
+
def stereo?; 2 == channels; end
|
299
|
+
def mono?; 1 == channels; end
|
300
|
+
|
301
|
+
mediainfo_date_reader :encoded_date
|
302
|
+
mediainfo_date_reader :tagged_date
|
303
|
+
end
|
200
304
|
|
201
|
-
|
202
|
-
|
203
|
-
|
305
|
+
class ImageStream < Stream
|
306
|
+
mediainfo_attr_reader :resolution
|
307
|
+
mediainfo_attr_reader :format
|
308
|
+
|
309
|
+
mediainfo_int_reader :width
|
310
|
+
mediainfo_int_reader :height
|
311
|
+
|
312
|
+
def frame_size; "#{width}x#{height}" if width or height; end
|
313
|
+
end
|
204
314
|
|
205
|
-
|
206
|
-
|
315
|
+
Mediainfo::SECTIONS.each do |stream_type|
|
316
|
+
class_eval %{
|
317
|
+
def #{stream_type}; @#{stream_type}_proxy ||= StreamProxy.new(self, :#{stream_type}); end
|
318
|
+
def #{stream_type}?; streams.any? { |x| x.#{stream_type}? }; end
|
319
|
+
}, __FILE__, __LINE__
|
320
|
+
end
|
207
321
|
|
208
322
|
###
|
209
323
|
|
@@ -212,16 +326,6 @@ class Mediainfo
|
|
212
326
|
|
213
327
|
###
|
214
328
|
|
215
|
-
class Error < StandardError; end
|
216
|
-
class ExecutionError < Error; end
|
217
|
-
class IncompatibleVersionError < Error; end
|
218
|
-
|
219
|
-
def self.version
|
220
|
-
@version ||= `#{path} --Version`[/v([\d.]+)/, 1]
|
221
|
-
end
|
222
|
-
|
223
|
-
###
|
224
|
-
|
225
329
|
def initialize(full_filename = nil)
|
226
330
|
if mediainfo_version < "0.7.25"
|
227
331
|
raise IncompatibleVersionError,
|
@@ -229,6 +333,8 @@ class Mediainfo
|
|
229
333
|
"is not compatible with this gem. >= 0.7.25 required."
|
230
334
|
end
|
231
335
|
|
336
|
+
@streams = []
|
337
|
+
|
232
338
|
if full_filename
|
233
339
|
@full_filename = File.expand_path full_filename
|
234
340
|
@path = File.dirname @full_filename
|
@@ -280,14 +386,12 @@ class Mediainfo
|
|
280
386
|
def self.default_mediainfo_path!; self.path = "mediainfo"; end
|
281
387
|
default_mediainfo_path! unless path
|
282
388
|
|
283
|
-
def mediainfo_version
|
284
|
-
self.class.version
|
285
|
-
end
|
389
|
+
def mediainfo_version; self.class.version; end
|
286
390
|
|
287
391
|
attr_reader :last_command
|
288
392
|
|
289
393
|
def inspect
|
290
|
-
super.sub
|
394
|
+
super.sub(/@raw_response=".+?", @/, %{@raw_response="...", @})
|
291
395
|
end
|
292
396
|
|
293
397
|
private
|
@@ -312,48 +416,44 @@ private
|
|
312
416
|
require "rexml/document"
|
313
417
|
end
|
314
418
|
|
315
|
-
@parsed_response = {}
|
316
|
-
|
317
419
|
case xml_parser
|
318
420
|
when "nokogiri"
|
319
421
|
Nokogiri::XML(@raw_response).xpath("//track").each { |t|
|
320
|
-
|
321
|
-
|
422
|
+
s = Stream.create(t['type'])
|
322
423
|
t.xpath("*").each do |c|
|
323
|
-
|
424
|
+
s[key_for(c)] = c.content.strip
|
324
425
|
end
|
426
|
+
@streams << s
|
325
427
|
}
|
326
428
|
when "hpricot"
|
327
429
|
Hpricot::XML(@raw_response).search("track").each { |t|
|
328
|
-
|
329
|
-
|
430
|
+
s = Stream.create(t['type'])
|
330
431
|
t.children.select { |n| n.is_a? Hpricot::Elem }.each do |c|
|
331
|
-
|
432
|
+
s[key_for(c)] = c.inner_html.strip
|
332
433
|
end
|
434
|
+
@streams << s
|
333
435
|
}
|
334
436
|
else
|
335
437
|
REXML::Document.new(@raw_response).elements.each("/Mediainfo/File/track") { |t|
|
336
|
-
|
337
|
-
|
438
|
+
s = Stream.create(t.attributes['type'])
|
338
439
|
t.children.select { |n| n.is_a? REXML::Element }.each do |c|
|
339
|
-
|
440
|
+
s[key_for(c)] = c.text.strip
|
340
441
|
end
|
442
|
+
@streams << s
|
341
443
|
}
|
342
444
|
end
|
445
|
+
|
446
|
+
SECTIONS.each do |section|
|
447
|
+
default_target_stream = if send("#{section}?")
|
448
|
+
send(section).streams.first
|
449
|
+
else
|
450
|
+
Mediainfo.const_get("#{section.to_s.capitalize}Stream").new(section.to_s.capitalize)
|
451
|
+
end
|
452
|
+
instance_variable_set "@#{section}_stream", default_target_stream
|
453
|
+
end
|
343
454
|
end
|
344
455
|
|
345
456
|
def key_for(attribute_node)
|
346
457
|
attribute_node.name.downcase.gsub(/_+/, "_").gsub(/_s(\W|$)/, "s").strip
|
347
458
|
end
|
348
|
-
|
349
|
-
def bucket_for(section)
|
350
|
-
section = section.downcase if section
|
351
|
-
|
352
|
-
if section == "general"
|
353
|
-
@parsed_response
|
354
|
-
else
|
355
|
-
@parsed_response[section] ||= {}
|
356
|
-
@parsed_response[section]
|
357
|
-
end
|
358
|
-
end
|
359
459
|
end
|