class MusicBox::Catalog::Tags

Constants

TagFlags

Attributes

changes[RW]
current[RW]

Public Class Methods

load(file) click to toggle source
# File lib/musicbox/catalog/tags.rb, line 24
def self.load(file)
  new.tap { |t| t.load(file) }
end
new(params={}) click to toggle source
# File lib/musicbox/catalog/tags.rb, line 28
def initialize(params={})
  @current = {}
  @changes = {}
  params.each { |k, v| send("#{k}=", v) }
end

Public Instance Methods

[](key) click to toggle source
# File lib/musicbox/catalog/tags.rb, line 34
def [](key)
  @changes.has_key?(key) ? @changes[key] : @current[key]
end
[]=(key, value) click to toggle source
# File lib/musicbox/catalog/tags.rb, line 38
def []=(key, value)
  raise unless TagFlags[key]
  @changes[key] = value unless @current[key] == value
end
changed?() click to toggle source
# File lib/musicbox/catalog/tags.rb, line 43
def changed?
  !@changes.empty?
end
load(file) click to toggle source
# File lib/musicbox/catalog/tags.rb, line 51
def load(file)
  cmd = [
    'ffprobe',
    '-loglevel', 'error',
    '-show_entries', 'format',
    '-i', file,
  ].map(&:to_s)
  IO.popen(cmd, 'r') do |pipe|
    pipe.readlines.map(&:strip).each do |line|
      if line =~ /^TAG:(.*?)=(.*?)$/
        key, value = $1.to_sym, $2.strip
        info = case key
        when :date
          { year: value.to_i }
        when :track
          track, tracks = value.split('/').map(&:to_i)
          {
            track: track,
            tracks: tracks,
          }
        when :disc
          disc, discs = value.split('/').map(&:to_i)
          {
            disc: disc,
            discs: discs,
          }
        else
          if TagFlags[key]
            { key => value }
          else
            {}
          end
        end
        @current.update(info)
      end
    end
  end
  @current[:track] ||= file.basename.to_s.to_i
end
save(file, force: false) click to toggle source
# File lib/musicbox/catalog/tags.rb, line 91
def save(file, force: false)
  return unless changed? || force
  set_flags = {}
  remove_flags = []
  @current.merge(@changes).each do |key, value|
    flag = TagFlags[key] or raise
    if value
      set_flags[flag] = value
    else
      remove_flags << flag
    end
  end
  run_command('mp4tags',
    set_flags.map { |c, v| ["-#{c}", v] },
    !remove_flags.empty? ? ['-remove', remove_flags.join] : nil,
    file)
  run_command('mdimport',
    '-i',
    file)
end
update(hash) click to toggle source
# File lib/musicbox/catalog/tags.rb, line 47
def update(hash)
  hash.each { |k, v| self[k] = v }
end