#!/usr/bin/env ruby # # omptagger # http://github.com/omp/omptagger # Modify and display metadata of audio files. # # Copyright 2007-2010 David Vazgenovich Shakaryan # Distributed under the terms of the GNU General Public License v3. # See http://www.gnu.org/licenses/gpl.txt for the full license text. # # Dependencies: # Ruby http://www.ruby-lang.org/ # RubyGems http://rubygems.org/ # rtaglib http://rubygems.org/gems/rtaglib # ruby-filemagic http://rubygems.org/gems/ruby-filemagic # TagLib http://developer.kde.org/~wheeler/taglib.html require 'getoptlong' require 'rubygems' require 'TagLib' require 'filemagic' class String def colourise(colour) case colour when :green code = '32' when :yellow code = '33' when :cyan code = '36' else return self end return "\e[#{code}m#{self}\e[0m" end def format(type) case type when :file indent = '' colour = :yellow when :action indent = ' ' colour = :green when :tag indent = ' ' colour = :cyan when :info indent = ' ' colour = nil end if @@colour return indent + self.colourise(colour) else return indent + self end end end class Hash def longest_key_length self.keys.inject(0) do |longest, key| key.length > longest ? key.length : longest end end end class Metadata def output(tag, val, padding = 0) puts tag.format(:tag) + ' ' * (2 + padding) + val end private :output def initialize(file) puts (file + ':').format(:file) @filename = File.expand_path(file) @write = false end def view puts 'Viewing all tags:'.format(:action) if @tags.empty? puts 'No tags set.'.format(:info) throw :next end end def viewtag(tag) puts ('Viewing ' + tag + ' tag:').format(:action) unless @tags.has_key? tag puts 'Tag not set.'.format(:info) throw :next end end end class VorbisComment < Metadata def view super @tags.sort.each do |tag, val| val.each do |val| output(tag, val, @tags.longest_key_length - tag.length) end end end def viewtag(tag) super @tags[tag].each do |val| output(tag, val) end end end class FLAC < VorbisComment def initialize(file) super @file = TagLib::FLAC::File.new(file) @tags = @file.xiphComment.fieldListMap.hash end end class Vorbis < VorbisComment def initialize(file) super @file = TagLib::Vorbis::File.new(file) @tags = @file.tag.fieldListMap.hash end end def help puts <<-end Usage: omptagger [actions/options] [files] Actions: --view -v View all tags --view-tag -t View a tag --add-tag -a Add a tag --set-tag -s Set a tag --remove -r Remove all tags --remove-tag -d Remove a tag --generate -g Generate tags based on filename --rename -m Rename file based on tags --scheme -n Change file naming scheme Options: --no-colour -c Disable colourisation of output --pretend -p Disable finalisation of changes --help -h Display help information --info -i Display additional information end exit end actions = Array.new options = Array.new scheme = '%a - %t' GetoptLong.new( ['--view', '-v', GetoptLong::NO_ARGUMENT], ['--view-tag', '-t', GetoptLong::REQUIRED_ARGUMENT], ['--add-tag', '-a', GetoptLong::REQUIRED_ARGUMENT], ['--set-tag', '-s', GetoptLong::REQUIRED_ARGUMENT], ['--remove', '-r', GetoptLong::NO_ARGUMENT], ['--remove-tag', '-d', GetoptLong::REQUIRED_ARGUMENT], ['--generate', '-g', GetoptLong::NO_ARGUMENT], ['--rename', '-m', GetoptLong::NO_ARGUMENT], ['--scheme', '-n', GetoptLong::REQUIRED_ARGUMENT], ['--no-colour', '-c', GetoptLong::NO_ARGUMENT], ['--pretend', '-p', GetoptLong::NO_ARGUMENT], ['--help', '-h', GetoptLong::NO_ARGUMENT], ['--info', '-i', GetoptLong::NO_ARGUMENT] ).each do |option, argument| option = option.delete('-').intern case option when :scheme scheme = argument when :nocolour, :pretend, :help, :info options << option when :viewtag, :addtag, :settag, :removetag actions << [option, argument] when :generate, :rename actions << [option, scheme] else actions << [option] end end help if options.include?(:help) info if options.include?(:info) help if actions.empty? if ARGV.empty? puts 'No files specified.' exit end if options.include?(:nocolour) class String @@colour = false end else class String @@colour = true end end mime = FileMagic.mime mime.simplified = true ARGV.each do |file| begin raise 'File does not exist.' unless File.exist?(file) case mime.file(file) when 'audio/x-flac' track = FLAC.new(file) when 'application/ogg' track = Vorbis.new(file) else raise 'File extension not recognised.' end actions.each do |action| catch :next do track.send(*action) end end rescue RuntimeError => message $stderr.puts $0 + ': ' + file + ': ' + message end end