class FinalCutPro::XMLParser::XMEML::Version5

Public Class Methods

parse_clips(xml, options = { }) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 8
def self.parse_clips(xml, options = { })
  parser = new
  parser.parse_clips(xml_as_document(xml, options))
end
parse_files(xml, options = { }) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 18
def self.parse_files(xml, options = { })
  parser = new
  parser.parse_files(xml, options)
end
parse_sequences(xml, options = { }) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 13
def self.parse_sequences(xml, options = { })
  parser = new
  parser.parse_sequences(xml_as_document(xml, options))
end

Public Instance Methods

build_file_hash(node) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 162
def build_file_hash(node)
  file_id = node.attributes.get_attribute('id').value.to_s
  logger.debug { "Processing File with an ID of: #{file_id}" }

  path_url_element = node.find('./pathurl').first
  unless !path_url_element.nil?
    logger.debug { 'Skipping File Node. No pathurl attribute found.' }
    return false
  end

  file_name = node.find('./name').first.content.to_s # Should equal the base name from the path url
  file_path_url = path_url_element.content.to_s
  file_hash = {
    :id => file_id,
    :name => file_name,
    :path_url => file_path_url
  }

  # a plus (+) would be converted to a space using CGI.unescape so we only escape %## encoded values from the pathurl
  #file_hash[:path_on_file_system] = CGI::unescape(URI(file_hash[:path_url]).path)
  file_hash[:path_on_file_system] = URI(file_path_url).path.gsub(/(%(?:[2-9]|[A-F])(?:\d|[A-F]))/) { |v| CGI.unescape(v) }
  file_hash[:file_node_full] = xml_node_to_hash node
  file_hash[:project_name] = get_project_name node
  file_hash[:bin_path] = get_bin_path node
  file_hash[:clipitem_node_full] = get_clipitem_hash node

  file_hash[:clipitems] = get_file_clipitems(node, file_id)

  master_clip_id = file_hash[:clipitem_node_full][:masterclipid]
  file_hash[:masterclip_node_full] = (master_clip_id.nil? or master_clip_id.empty?) ? { } : get_clip_hash_by_id(node.doc, master_clip_id)
  file_hash[:metadata] = get_all_metadata node
  file_hash[:labels] = get_all_labels node
  file_hash[:comments] = get_all_comments node
  file_hash[:logginginfo] = get_logging_info node
  file_hash
end
build_file_hash_array(doc, options = { }) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 142
def build_file_hash_array(doc, options = { })
  _files = []

  nodes = get_files_as_nodes(doc)
  total_files = nodes.count

  counter = 0

  nodes.each do |node|
    counter += 1
    logger.debug { "Processing file #{counter} of #{total_files}" }
    file_hash = build_file_hash(node)
    next unless file_hash
    logger.debug { "file_hash => #{file_hash}" }
    _files << file_hash
  end

  return _files
end
build_file_hash_hash(params = {}) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 134
def build_file_hash_hash(params = {})
  _files = { }
  key = params[:key_on] || :id
  files_array = build_file_hash_array(@xml_document)
  files_array.each {|file| _files[file[key]] = file }
  _files
end
get_all_comments(node) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 90
def get_all_comments(node)
  comments = []
  node.find('ancestor::bin/comments|ancestor::clip/comments|ancestor::sequence/comments|ancestor::clipitem/comments|ancestor::generatoritem/comments').each do |comments_node|
    parent = comments_node.parent
    first_from = parent.find('./name|@id').first

    # Name field responds to .content where as id attribute value is found with .value
    from_name_or_id = first_from.respond_to?(:content) ? first_from.content : first_from.value

    comment_set = {}
    comment_set[:from] = { parent.name.to_s => from_name_or_id }
    comment_set[:comments] = []
    comments_node.find('./*').each do |comment_node_item|
      comment_set[:comments] << {comment_node_item.name.to_s => comment_node_item.content.to_s} unless comment_node_item.content.nil? or comment_node_item.content.empty?
    end
    comments << comment_set
  end
  return comments
end
get_all_labels(node) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 68
def get_all_labels(node)
  labels = []
  node.find('ancestor::bin/labels|ancestor::clip/labels|ancestor::sequence/labels|ancestor::clipitem/labels|ancestor::generatoritem/labels').each do |labels_node|
    parent = labels_node.parent
    first_from = parent.find('./name|@id').first

    # Name field responds to .content where as id attribute value is found with .value
    from_name_or_id = first_from.respond_to?(:content) ? first_from.content : first_from.value

    label_set = {}
    label_set[:from] = { parent.name.to_s => from_name_or_id }
    label_set[:labels] = []

    labels_node.find('./*').each do |label_node_item|
      label_node_item_content = label_node_item.content
      label_set[:labels] << {label_node_item.name.to_s => label_node_item_content.to_s} unless label_node_item_content.nil? or label_node_item_content.empty?
    end
    labels << label_set
  end
  return labels
end
get_all_metadata(node) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 60
def get_all_metadata(node)
  metadata = {}
  node.find('descendant::metadata|metadata').each do |metadata_node|
    metadata[metadata_node.find('./key').first.content.to_s] = metadata_node.find('./value').first.content.to_s unless metadata_node.find('./key').first.nil? or metadata_node.find('./key').first.empty? or  metadata_node.find('./value').first.nil? or  metadata_node.find('./value').first.empty?
  end
  return metadata
end
get_bin_path(node) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 35
def get_bin_path(node)
  bin_path = []
  node.find('ancestor::bin').each do |ancestor_node|
    bin_path << ancestor_node.find('./name').first.content.to_s unless ancestor_node.find('./name').first.content.to_s.empty?
  end
  return '' if bin_path.empty?
  return "/#{bin_path.join('/')}/"
end
get_clip_hash_by_id(doc, id) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 44
def get_clip_hash_by_id(doc, id)
  #puts "ID: #{id}"
  id = id.dup.gsub(/["\s]/, ' ' => "\\s", '"' => '&quot;')
  clip = doc.find("//clip[@id=\"#{id}\"]").first
  return { } unless clip
  return xml_node_to_hash(clip) || { }
end
get_clipitem_hash(node) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 52
def get_clipitem_hash(node)
  return xml_node_to_hash(node.parent)
end
get_file_clipitems(node, file_id = nil) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 56
def get_file_clipitems(node, file_id = nil)

end
get_files_as_nodes(doc) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 130
def get_files_as_nodes(doc)
  doc.find('//file[pathurl]')
end
get_logging_info(node) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 110
def get_logging_info(node)
  logginginfos = []
  node.find('ancestor::clip/logginginfo|ancestor::sequence/logginginfo|ancestor::clipitem/logginginfo|ancestor::generatoritem/logginginfo').each do |logginginfo_node|
    parent = logginginfo_node.parent
    first_from = parent.find('./name|@id').first

    # Name field responds to .content where as id attribute value is found with .value
    from_name_or_id = first_from.respond_to?(:content) ? first_from.content : first_from.value

    logginginfo_set = {}
    logginginfo_set[:from] = { parent.name.to_s => from_name_or_id }
    logginginfo_set[:logginginfo] = {}
    logginginfo_node.find('./*').each do |logginginfo_node_item|
      logginginfo_set[:logginginfo][logginginfo_node_item.name.to_s] = logginginfo_node_item.content.to_s unless logginginfo_node_item.content.nil? or logginginfo_node_item.content.empty?
    end
    logginginfos << logginginfo_set
  end
  return logginginfos
end
get_project_name(node) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 23
def get_project_name(node)
  #@project_name = node.find('ancestor::project').first.find('./name').first.content.to_s
  project_node = node.find_first('ancestor::project')
  unless project_node.nil?
    project_name_node = project_node.find_first('./name')
    unless project_name_node.nil? or project_name_node.content.nil?
      project_name = project_name_node.content.to_s
      return project_name
    end
  end
end
parse(xml = @xml_document, options = { }) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 199
def parse(xml = @xml_document, options = { })
  xml_doc = self.class.xml_as_document(xml)
  @files = parse_files(xml_doc, options)
  @sequences = parse_sequences(xml_doc, options)
  @clips = parse_clips(xml_doc)
  return self
end
parse_clips(xml = @xml_document, options = { }) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 211
def parse_clips(xml = @xml_document, options = { })
  self.class.xml_as_document(xml).find('//clip').map do |clip_node|
    # 'clipitem[(not(enabled) or enabled[text()="TRUE"]) and ancestor::video/track[enabled[text()="TRUE"]]]'
    # enabled tag may be missing on some clipitems such as those that link to other clipitems. This could cause a problem following links.
    clip_items = clip_node.find('clipitem[(not(enabled) or enabled[text()="TRUE"]) and ../../../../media/video/track[enabled[text()="TRUE"]]]').map do |clip_item_node|
      xml_node_to_hash(clip_item_node)
    end
    xml_node_to_hash(clip_node).merge({ :clip_items => clip_items })
  end
end
parse_files(xml = @xml_document, options = { }) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 207
def parse_files(xml = @xml_document, options = { })
  build_file_hash_array(self.class.xml_as_document(xml), options = { }) || [ ]
end
parse_sequences(xml = @xml_document, options = { }) click to toggle source
# File lib/final_cut_pro/xml_parser/xmeml/version_5.rb, line 222
def parse_sequences(xml = @xml_document, options = { })
  self.class.xml_as_document(xml).find('//sequence').map do |sequence_node|
    clip_items = sequence_node.find('media/video/track/clipitem[not(enabled) or enabled[text()="TRUE"]]').map do |clip_item_node|
      xml_node_to_hash(clip_item_node)
    end
    xml_node_to_hash(sequence_node).merge({ :clip_items => clip_items })
  end
end