#######################  camera.rb -- brent@mbari.org  #######################
# $Source: /home/cvs/ESP/gen2/software/esp/lib/camera.rb,v $
#    Copyright (C) 2003 MBARI
#    MBARI Proprietary Information. All rights reserved.
# $Id: camera.rb,v 1.4 2005/10/11 18:19:38 brent Exp $
#
#    Send commands to the Starlight Xpress camera camera
#
############################################################################

require 'log'

class Camera

  class Error < StandardError
  end

  SNAP = 'snap'  #path to the snap command (this assumes its on $PATH)
  
  FileType = {:tiff=>" -tiff", :fits=>" -fits", :deflated=>" -tiff=deflate"}
  

  def self.snap cmdString, showProgress=true
  # invoke external "snap" process on the given command string
  # raise Error if command fails
  #  otherwise, return the duration of the exposure
    
    progress = showProgress and FileTest.writable? '/dev/tty' ?
                 '3>/dev/tty' : '3>/dev/null'
    args = cmdString.strip
    cmd = "#{SNAP} #{args} 2>&1 #{progress}"
    Log.record "Camera: #{SNAP} #{args}"
    output = `#{cmd}`
    raise Error, output if $?>>8 != 0
    Log.record output
    output.each_line do |line|
      words = line.split
      if words.size >= 2 and words[-1].downcase=='seconds'
        return words[-2].to_f
      end
    end
    raise Error, "Missing Exposure Time (but no error from #{SNAP}?)"
  end

  def initialize defaults={}
  # define default configuration of the camera for subsequent exposures
    @defaults=defaults
  end
  attr_reader :defaults
  
  def expose options={}, options2={}
  # snap an exposure given this camera configuration
  # if first arg is a string, assume its the file name and that other options follow
    options = {:file=>options}.update options2 if options.is_a? String
    optHash = @defaults.update options
    opts = ""
    if bin=optHash[:binning]
      binning = expand(bin)
      opts << " -bin=#{binning.first},#{binning.last}"
    end
    if org=optHash[:origin]
      origin = expand(org)
      opts << " -origin=#{origin.first},#{origin.last}"
    end
    if sz=optHash[:size]
      size = expand(sz)
      opts << " -size=#{size.first},#{size.first}"
    end
    if optHash[:debug]
      opts << " -debug=#{optHash[:debug]}"
    end
    if optHash[:camera]
      opts << " -camera=#{optHash[:camera]}"
    end
    if optHash[:type]
      unless ftype = FileType[optHash[:type]]
        raise Error, "Unrecognized fileType #{optHash[:type]}"
      end
      opts << ftype
    end
    duration = optHash[:duration]
    duration = "auto" unless duration
    opts << (duration.is_a?(String) ? " -"<<duration : " #{duration}")    
    
    dir=optHash[:dir]
    file=optHash[:file]
    suffix=optHash[:suffix]
    path = 
      if file
        dir && file.index(File::Separator) != 0 ? 
                   dir + File::Separator + file : file
      else  #generate a unique file name if none specified
        prefix = optHash[:prefix]
        prefix = "image" unless prefix
        dir = '.' unless dir  #use the current directory if none specified
        newInstance=1
        newName = prefix+newInstance.to_s  #name is of the form prefix<instance#>
        prefixLen = prefix.length
        Dir.foreach dir do |entryName|
          if entryName.index(prefix) == 0 
            if (existingInstance=entryName[prefixLen..-1].to_i) >= newInstance
              newInstance = existingInstance+1
              newName = prefix+newInstance.to_s
            end
          end
        end
        dir + File::Separator + newName 
      end
    path << suffix if suffix
    type.snap (opts<<" #{path}")
  end
  alias_method :snap, :expose
  

private
  def expand opt
    return opt.respond_to?(:last) ? opt : [opt, opt]
  end
    
end #class Camera

