added singleton

master
Jakub Kuźma 2011-05-31 23:21:15 +02:00
parent e7db196a29
commit 4a6b2d5739
5 changed files with 130 additions and 96 deletions

View File

@ -1,94 +1,109 @@
module Sane class Sane
include Singleton
class << self class << self
def init extend Forwardable
version_code = FFI::MemoryPointer.new(:int) delegate [:init, :exit, :get_devices, :open, :close, :get_option_descriptor, :get_option, :set_option, :strstatus] => :instance
check_status!(API.sane_init(version_code, FFI::Pointer::NULL)) end
version_code.read_int
end
def exit def initialize
API.sane_exit init
end end
def get_devices def init
devices_pointer = FFI::MemoryPointer.new(:pointer) version_code = FFI::MemoryPointer.new(:int)
check_status!(API.sane_get_devices(devices_pointer, 0)) check_status!(API.sane_init(version_code, FFI::Pointer::NULL))
devices = devices_pointer.read_pointer version_code.read_int
[].tap do |result| end
until devices.read_pointer.null?
result << API::Device.new(devices.read_pointer) def exit
devices += FFI.type_size(:pointer) API.sane_exit
end end
def get_devices
devices_pointer = FFI::MemoryPointer.new(:pointer)
check_status!(API.sane_get_devices(devices_pointer, 0))
devices = devices_pointer.read_pointer
[].tap do |result|
until devices.read_pointer.null?
result << API::Device.new(devices.read_pointer)
devices += FFI.type_size(:pointer)
end end
end end
end
def open(device_name)
device_handle_pointer = FFI::MemoryPointer.new(:pointer) def open(device_name)
check_status!(API.sane_open(device_name.to_s, device_handle_pointer)) device_handle_pointer = FFI::MemoryPointer.new(:pointer)
device_handle_pointer.read_pointer check_status!(API.sane_open(device_name, device_handle_pointer))
end device_handle_pointer.read_pointer
end
def close(device_handle)
API.sane_close(device_handle) def close(device_handle)
end API.sane_close(device_handle)
end
def get_option_descriptor(device_handle, option)
result = API.sane_get_option_descriptor(device_handle, option) def get_option_descriptor(device_handle, option)
API::OptionDescriptor.new(result) result = API.sane_get_option_descriptor(device_handle, option)
end API::OptionDescriptor.new(result)
end
def get_option(device_handle, option)
descriptor = get_option_descriptor(device_handle, option) def get_option(device_handle, option)
descriptor = get_option_descriptor(device_handle, option)
case descriptor[:type]
when :string case descriptor[:type]
value_pointer = FFI::MemoryPointer.new(:pointer) when :string
when :bool, :int, :fixed value_pointer = FFI::MemoryPointer.new(:pointer)
value_pointer = FFI::MemoryPointer.new(:int) when :bool, :int, :fixed
else value_pointer = FFI::MemoryPointer.new(:int)
return nil else
end return nil
end
check_status!(API.sane_control_option(device_handle, option, :get_value, value_pointer, FFI::Pointer::NULL))
check_status!(API.sane_control_option(device_handle, option, :get_value, value_pointer, FFI::Pointer::NULL))
case descriptor[:type]
when :string case descriptor[:type]
value_pointer.read_string when :string
when :bool value_pointer.read_string
!value_pointer.read_int.zero? when :bool
when :int, :fixed !value_pointer.read_int.zero?
value_pointer.read_int when :int, :fixed
end value_pointer.read_int
end end
end
def set_option(device_handle, option, value)
descriptor = get_option_descriptor(device_handle, option) def set_option(device_handle, option, value)
descriptor = get_option_descriptor(device_handle, option)
case descriptor[:type]
when :string case descriptor[:type]
value_pointer = FFI::MemoryPointer.from_string(value) when :string
when :int, :fixed value_pointer = FFI::MemoryPointer.from_string(value)
value_pointer = FFI::MemoryPointer.new(:int).write_int(value) when :int, :fixed
when :bool value_pointer = FFI::MemoryPointer.new(:int).write_int(value)
value_pointer = FFI::MemoryPointer.new(:int).write_int(value ? 1 : 0) when :bool
else value_pointer = FFI::MemoryPointer.new(:int).write_int(value ? 1 : 0)
return nil else
end return nil
end
check_status!(API.sane_control_option(device_handle, option, :set_value, value_pointer, FFI::Pointer::NULL))
check_status!(API.sane_control_option(device_handle, option, :set_value, value_pointer, FFI::Pointer::NULL))
case descriptor[:type]
when :string case descriptor[:type]
value_pointer.read_string when :string
when :bool value_pointer.read_string
!value_pointer.read_int.zero? when :bool
when :int, :fixed !value_pointer.read_int.zero?
value_pointer.read_int when :int, :fixed
end value_pointer.read_int
end end
end
def check_status!(status)
raise Error.new(API.sane_strstatus(status), status) if status != :good def strstatus(status)
end API.sane_strstatus(status)
end
private
def check_status!(status)
raise Error.new(strstatus(status), status) if status != :good
end end
end end

View File

@ -1,4 +1,4 @@
module Sane class Sane
module API module API
extend FFI::Library extend FFI::Library
@ -12,9 +12,6 @@ module Sane
class Device < FFI::Struct class Device < FFI::Struct
layout :name, :string, :vendor, :string, :model, :string, :type, :string layout :name, :string, :vendor, :string, :model, :string, :type, :string
def to_s; self[:name] end
def inspect; "#<#{self.class.name}:'#{to_s}'>" end
end end
class OptionDescriptor < FFI::Struct class OptionDescriptor < FFI::Struct

View File

@ -1,11 +1,29 @@
module Sane class Sane
class Device class Device
def initialize(handle) def initialize(name)
@handle = handle @name = name
@handle = nil
end
def open
@handle = Sane.open(@name) if closed?
if block_given?
yield self
close
end
end
def closed?
@handle.nil?
end
def opened?
!closed?
end end
def close def close
Sane.close(@handle) Sane.close(@handle) if opened?
@handle = nil
end end
end end
end end

View File

@ -1,4 +1,4 @@
module Sane class Sane
class Error < StandardError class Error < StandardError
attr_reader :status attr_reader :status

View File

@ -1,8 +1,12 @@
require "singleton"
require "forwardable"
require "ffi" require "ffi"
require "sane" require "sane"
require "sane/api" require "sane/api"
require "sane/error" require "sane/error"
require "sane/device"
module Scanner module Scanner