class Media::Transmogrifier
Attributes
Public Class Methods
# File lib/media/transmogrifier.rb, line 104 def self.add(trans) self.list[trans.name] ||= trans end
# File lib/media/transmogrifier.rb, line 202 def self.command_available?(command) command and File.file?(command) and File.executable?(command) end
# File lib/media/transmogrifier.rb, line 124 def self.converts_from?(input_type) input_types.include? input_type end
# File lib/media/transmogrifier.rb, line 128 def self.converts_to?(output_type) output_types.include? output_type end
returns transmogrifier class, if any, that can tranform input_type
into output_type
# File lib/media/transmogrifier.rb, line 112 def self.find_class(input_type, output_type) transmog = list.values. select{|tm| tm.converts_from?(input_type)}. select{|tm| tm.converts_to?(output_type)}. select{|tm| tm.available?}. first return transmog if transmog logger.error 'could not find a transmogrifier for "%s" -> "%s"' % [input_type, output_type] return nil end
# File lib/media/transmogrifier.rb, line 86 def self.inherited(base) add base end
maps mine type to an array of transmogrifiers that take that type as an imput
# File lib/media/transmogrifier.rb, line 98 def self.input_map; @@input_map ||= Hash.new([]); end
CLASS METHODS
# File lib/media/transmogrifier.rb, line 94 def self.list(); @@list ||= {}; end
takes a hash of options, some of which are required:
-
:input_file or (:input and :input_type)
-
:output_file or :output_type
# File lib/media/transmogrifier.rb, line 47 def initialize(options=nil) options = options.dup self.input = options.delete(:input) self.input_file = options.delete(:input_file) self.input_type = options.delete(:input_type) self.output_file = options.delete(:output_file) self.output_type = options.delete(:output_type) self.options = options if input and input_type.nil? raise ArgumentError.new('input_type required if input specified') elsif input and input_file.nil? self.input_file = Media::TempFile.new(input, input_type) elsif input and input_file raise ArgumentError.new('cannot have both input and input_file') elsif input_file and input_type.nil? self.input_type = Media::MimeType.mime_type_from_extension(input_file) elsif input.nil? and input_file.nil? raise ArgumentError.new('input or input_file is required') end if output_file.nil? and output_type.nil? raise ArgumentError.new('output_file or output_type is required') elsif output_file.nil? self.output_file = Media::TempFile.new(nil, output_type) elsif output_type.nil? self.output_type = Media::MimeType.mime_type_from_extension(output_file) end debug self.class.name + " converting" + " #{input_file } ( #{input_type} ) to" + " #{output_file} ( #{output_type} )" set_temporary_outfile end
maps mine type to an array of transmogrifiers that produce that type as an output
# File lib/media/transmogrifier.rb, line 102 def self.output_map; @@output_map ||= Hash.new([]); end
runs a shell command, passing each line that is output, as it is output to the block.
returns
* the status of the command, as one of the following symbols: :success, :failure, :not_found, :error * the output to STDOUT and STDERR of the command
# File lib/media/transmogrifier.rb, line 151 def self.run_command(*args) # run the command cmdstr = command_string(*args) output = "" before = Time.now IO.popen(cmdstr + ' 2>&1', 'r') do |pipe| while line = pipe.gets if block_given? yield(line) end output << line << "\n" end end took = Time.now - before # set the status status = case $?.exitstatus when 0 then :success when 1 then :failure when 127 then :not_found else :error end if status == :success log_command cmdstr debug "took #{took} seconds." debug output else msg = ' exited with "%s"' % $?.exitstatus error cmdstr error msg error output if !output.empty? yield(msg) if block_given? end return status, output end
Protected Class Methods
PROTECTED
# File lib/media/transmogrifier.rb, line 214 def self.log_command(command) debug "COMMAND " + command end
Private Class Methods
PRIVATE
# File lib/media/transmogrifier.rb, line 265 def self.command_string(*args) args.collect {|arg| shell_escape(arg.to_s)}.join(' ') end
# File lib/media/transmogrifier.rb, line 269 def self.shell_escape(str) if str.empty? "''" elsif str =~ %r{\A[0-9A-Za-z+_-]+\z} str else result = '' str.scan(/('+)|[^']+/) do if $1 result << %q{\'} * $1.length else result << %Q{'#{$&}'} end end result end end
Public Instance Methods
# File lib/media/transmogrifier.rb, line 189 def run_command(*args) status, self.command_output = self.class.run_command(*args) # restore the original output_file name unless restore_temporary_outfile msg = 'could not restore temporary outfile' error msg yield(msg) if block_given? status = :failure end return status end
Protected Instance Methods
# File lib/media/transmogrifier.rb, line 238 def extension(mime_type) Media::MimeType.extension_from_mime_type(mime_type) end
returns a filename with the same base but a new extension
# File lib/media/transmogrifier.rb, line 221 def replace_extension(filename, new_extension) old_extension = (File.extname(filename) || '').to_s new_extension = new_extension.to_s if !old_extension.empty? base = File.basename(filename, old_extension) else base = filename end if new_extension !~ /^\./ new_extension = "." + new_extension end if base =~ /\.$/ new_extension = new_extension.chomp end "#{base}#{new_extension}" end
usage:
replace_file :from => filea, :to => fileb
# File lib/media/transmogrifier.rb, line 247 def replace_file(args={}) from = args[:from].to_s to = args[:to].to_s raise ArgumentError if from.empty? || to.empty? if File.exist?(from) if File.exist?(to) FileUtils.rm(to) end FileUtils.mv(from, to) end end
Private Instance Methods
returns true if the file as a suffix that matches the mime_type
# File lib/media/transmogrifier.rb, line 290 def compatible_extension?(file, type) file = file.to_s ext = Media::MimeType.extension_from_mime_type(type) if ext.nil? return true # ^^ if there is no defined extension for this type, then # whatever the file has is fine else file_ext_type = Media::MimeType.mime_type_from_extension(file) return Media::MimeType.compatible_types?(type, file_ext_type) end end
moves the current output_file
to match the filename we are supposed to return (which is stored in @outfile_to_return by set_temporary_outfile
)
# File lib/media/transmogrifier.rb, line 321 def restore_temporary_outfile if @temporary_outfile debug "moving output from #{output_file} to #{@outfile_to_return}" replace_file from: output_file, to: @outfile_to_return self.output_file = @outfile_to_return end return true end
ensure that the output_file
has the correct suffix by setting a temporary one if the current one is not good.
# File lib/media/transmogrifier.rb, line 307 def set_temporary_outfile @temporary_outfile = false if !compatible_extension?(output_file, output_type) @temporary_outfile = true @outfile_to_return = output_file self.output_file = Media::TempFile.new(nil, output_type) end end