mediainfo 0.6.2 → 0.7.0
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.
- 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
|