class Media::Transmogrifier

Attributes

command_output[RW]
input[RW]
input_file[RW]
input_type[RW]
options[RW]
output[RW]
output_file[RW]
output_type[RW]

Public Class Methods

add(trans) click to toggle source
# File lib/media/transmogrifier.rb, line 104
def self.add(trans)
  self.list[trans.name] ||= trans
end
command_available?(command) click to toggle source
# File lib/media/transmogrifier.rb, line 202
def self.command_available?(command)
  command and
  File.file?(command) and
  File.executable?(command)
end
converts_from?(input_type) click to toggle source
# File lib/media/transmogrifier.rb, line 124
def self.converts_from?(input_type)
  input_types.include? input_type
end
converts_to?(output_type) click to toggle source
# File lib/media/transmogrifier.rb, line 128
def self.converts_to?(output_type)
  output_types.include? output_type
end
find_class(input_type, output_type) click to toggle source

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
inherited(base) click to toggle source
# File lib/media/transmogrifier.rb, line 86
def self.inherited(base)
  add base
end
input_map() click to toggle source

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
list() click to toggle source

CLASS METHODS

# File lib/media/transmogrifier.rb, line 94
def self.list(); @@list ||= {}; end
new(options=nil) click to toggle source

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
output_map() click to toggle source

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
run_command(*args) { |line| ... } click to toggle source

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

log_command(command) click to toggle source

PROTECTED

# File lib/media/transmogrifier.rb, line 214
def self.log_command(command)
  debug "COMMAND " + command
end

Private Class Methods

command_string(*args) click to toggle source

PRIVATE

# File lib/media/transmogrifier.rb, line 265
def self.command_string(*args)
  args.collect {|arg| shell_escape(arg.to_s)}.join(' ')
end
shell_escape(str) click to toggle source
# 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

run_command(*args) { |msg| ... } click to toggle source
# 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

extension(mime_type) click to toggle source
# File lib/media/transmogrifier.rb, line 238
def extension(mime_type)
  Media::MimeType.extension_from_mime_type(mime_type)
end
replace_extension(filename, new_extension) click to toggle source

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
replace_file(args={}) click to toggle source

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

compatible_extension?(file, type) click to toggle source

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
restore_temporary_outfile() click to toggle source

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
set_temporary_outfile() click to toggle source

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