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