class MediaInfo::Tracks
Attributes
attribute_standardization_rules[R]
track_types[R]
xml[R]
Public Class Methods
new(input = nil)
click to toggle source
# File lib/mediainfo/tracks.rb 13 def initialize(input = nil) 14 if input && input.include?('<?xml') 15 @xml = input.gsub(/(\n|.)*(\<\?xml)/,'<?xml') 16 @track_types = [] 17 @attribute_standardization_rules = YAML.load_file("#{Gem::Specification.find_by_name('mediainfo').gem_dir}/lib/attribute_standardization_rules.yml") 18 # Populate Streams 19 case MediaInfo.xml_parser 20 when 'nokogiri' 21 converted_xml = ::Nokogiri::XML(self.xml) 22 converted_xml.css('//track').each { |track| # Have to use .css here due to iphone6 MediaInfo structure 23 track_elements = Attributes.new(track.children.select{ |n| n.is_a? ::Nokogiri::XML::Element }.map{ |parameter| 24 parameter.name = standardize_element_name(parameter.name) # Turn various element names into standardized versions (Bit_rate to Bitrate) 25 if parameter.text.include?("\n") # if it has children (extra in iphone6+_video.mov.xml) 26 [parameter.name, parameter.children.select { |n| n.is_a? ::Nokogiri::XML::Element }.map{ |parameter| [parameter.name, parameter.text]}] 27 else 28 [parameter.name, parameter.text] 29 end 30 }) 31 track_type = sanitize_track_type(@track_types,track.attributes.map{ |k,v| { :name => v.name, :value => v.value } },track.children.css('ID').map{ |el| el.text }) 32 @track_types << track_type 33 MediaInfo.set_singleton_method(self,track_type,track_elements) 34 } 35 else # DEFAULT REXML 36 converted_xml = ::REXML::Document.new(self.xml) 37 converted_xml.elements.each('//track') { |track| 38 track_elements = Attributes.new(track.children.select { |n| n.is_a? ::REXML::Element }.map{ |parameter| 39 parameter.name = standardize_element_name(parameter.name) 40 if parameter.text.include?("\n") # if it has children (extra in iphone6+_video.mov.xml) 41 [parameter.name, parameter.children.select { |n| n.is_a? ::REXML::Element }.map{ |parameter| [parameter.name, parameter.text]}] 42 else 43 [parameter.name, parameter.text] 44 end 45 }) 46 track_type = sanitize_track_type(@track_types,track.attributes.map{ |attr| { :name => attr[0], :value => attr[1] } },track.elements.detect{|el| el.name == 'id' }.to_a) 47 @track_types << track_type 48 MediaInfo.set_singleton_method(self,track_type,track_elements) 49 } 50 end 51 52 # Add {type}? 53 @track_types.each{ |track_type| 54 define_singleton_method("#{track_type}?"){ # Can't use set_singleton_method due to ? 55 self.track_types.include?(__method__.to_s.gsub('?','')) 56 } 57 } 58 # Add {type}.count singleton_method 59 @track_types.each{ |track_type| 60 MediaInfo.set_singleton_method(self.instance_variable_get("@#{track_type}"),'count',@track_types.grep(/#{track_type}/).count) 61 } 62 63 else 64 raise ArgumentError, 'Input must be raw XML.' 65 end 66 end
Public Instance Methods
method_missing( name, *args )
click to toggle source
Needed so that .image?, when there is no Image track, doesn't throw NoMethodError
# File lib/mediainfo/tracks.rb 7 def method_missing( name, *args ) 8 nil # We use nil here instead of false as nil should be understood by the client/requester as false. We might not want to specifically return false for other missing methods 9 end
sanitize_track_type(track_types,track_attributes,track_id)
click to toggle source
Used for handling duplicate track types with differing streamid, etc Takes an array of attributes and returns the track_name
Parameters must meet the following structure:
TRACK_TYPES: ['video','video2','text'] or [] if nothing created yet TRACK_ATTRIBUTES: [{:name=>“type”, :value=>“Text” }] or [] if not found TRACK_ID: [“1”] or [] if not found
# File lib/mediainfo/tracks.rb 151 def sanitize_track_type(track_types,track_attributes,track_id) 152 raise("Unable to sanitize a track type due to missing 'type' attribute in on of the elements: \n #{track_attributes}") if (type_attr_value = track_attributes.detect{ |attr| attr[:name] == 'type' }[:value]).nil? 153 if (streamid = track_attributes.detect{ |attr| attr[:name] == 'streamid' || attr[:name] == 'typeorder' }).nil? # No StreamId, however, ensuring that if the streamid is there we use it ## We must still manually specify the id attr until https://sourceforge.net/p/mediainfo/discussion/297610/thread/f17a0cf5/ is answered 154 ## Even if no streamid we need to check for duplicate track names and append an integer. ONLY WORKS IF DUPLICATE TRACKS ARE CONSECUTIVE 155 if track_types.include?(type_attr_value.downcase) 156 if !track_id.nil? && !track_id.empty? && track_id.first.to_s.to_i > 1 ## If the track has an ID child, and it's an integer above 1 (if it's a string, to_i returns 0) (if to_i returns > 1 so we can match id convention of video vs video1; see code below this section), use that 157 type = "#{type_attr_value}#{track_id.first}" 158 else 159 type = "#{type_attr_value}#{track_types.grep(/#{type_attr_value.downcase}/).count + 1}" 160 end 161 else 162 type = type_attr_value 163 end 164 else 165 # For anything with a streamid of 1, ignore it. This is due to the logic of non-streamid duplicates not appending an integer for the first occurrence. We want to be consistent. 166 ## We use _ to separate the streamid so we can do easier matching for non-streamid duplicates 167 type = streamid[:value] == '1' ? type_attr_value : "#{type_attr_value}#{streamid[:value]}" 168 end 169 return type.downcase 170 end
standardize_element_name(name)
click to toggle source
Standardize our Element Names
Relies on valid YAML in lib/attribute_standardization_rules.yml
# File lib/mediainfo/tracks.rb 70 def standardize_element_name(name) 71 self.attribute_standardization_rules[name].nil? ? name : self.attribute_standardization_rules[name] 72 end