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
def init
version_code = FFI::MemoryPointer.new(:int)
check_status!(API.sane_init(version_code, FFI::Pointer::NULL))
version_code.read_int
end
extend Forwardable
delegate [:init, :exit, :get_devices, :open, :close, :get_option_descriptor, :get_option, :set_option, :strstatus] => :instance
end
def exit
API.sane_exit
end
def initialize
init
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
def init
version_code = FFI::MemoryPointer.new(:int)
check_status!(API.sane_init(version_code, FFI::Pointer::NULL))
version_code.read_int
end
def exit
API.sane_exit
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
def open(device_name)
device_handle_pointer = FFI::MemoryPointer.new(:pointer)
check_status!(API.sane_open(device_name.to_s, device_handle_pointer))
device_handle_pointer.read_pointer
end
def close(device_handle)
API.sane_close(device_handle)
end
def get_option_descriptor(device_handle, option)
result = API.sane_get_option_descriptor(device_handle, option)
API::OptionDescriptor.new(result)
end
def get_option(device_handle, option)
descriptor = get_option_descriptor(device_handle, option)
case descriptor[:type]
when :string
value_pointer = FFI::MemoryPointer.new(:pointer)
when :bool, :int, :fixed
value_pointer = FFI::MemoryPointer.new(:int)
else
return nil
end
check_status!(API.sane_control_option(device_handle, option, :get_value, value_pointer, FFI::Pointer::NULL))
case descriptor[:type]
when :string
value_pointer.read_string
when :bool
!value_pointer.read_int.zero?
when :int, :fixed
value_pointer.read_int
end
end
def set_option(device_handle, option, value)
descriptor = get_option_descriptor(device_handle, option)
case descriptor[:type]
when :string
value_pointer = FFI::MemoryPointer.from_string(value)
when :int, :fixed
value_pointer = FFI::MemoryPointer.new(:int).write_int(value)
when :bool
value_pointer = FFI::MemoryPointer.new(:int).write_int(value ? 1 : 0)
else
return nil
end
check_status!(API.sane_control_option(device_handle, option, :set_value, value_pointer, FFI::Pointer::NULL))
case descriptor[:type]
when :string
value_pointer.read_string
when :bool
!value_pointer.read_int.zero?
when :int, :fixed
value_pointer.read_int
end
end
def check_status!(status)
raise Error.new(API.sane_strstatus(status), status) if status != :good
end
end
def open(device_name)
device_handle_pointer = FFI::MemoryPointer.new(:pointer)
check_status!(API.sane_open(device_name, device_handle_pointer))
device_handle_pointer.read_pointer
end
def close(device_handle)
API.sane_close(device_handle)
end
def get_option_descriptor(device_handle, option)
result = API.sane_get_option_descriptor(device_handle, option)
API::OptionDescriptor.new(result)
end
def get_option(device_handle, option)
descriptor = get_option_descriptor(device_handle, option)
case descriptor[:type]
when :string
value_pointer = FFI::MemoryPointer.new(:pointer)
when :bool, :int, :fixed
value_pointer = FFI::MemoryPointer.new(:int)
else
return nil
end
check_status!(API.sane_control_option(device_handle, option, :get_value, value_pointer, FFI::Pointer::NULL))
case descriptor[:type]
when :string
value_pointer.read_string
when :bool
!value_pointer.read_int.zero?
when :int, :fixed
value_pointer.read_int
end
end
def set_option(device_handle, option, value)
descriptor = get_option_descriptor(device_handle, option)
case descriptor[:type]
when :string
value_pointer = FFI::MemoryPointer.from_string(value)
when :int, :fixed
value_pointer = FFI::MemoryPointer.new(:int).write_int(value)
when :bool
value_pointer = FFI::MemoryPointer.new(:int).write_int(value ? 1 : 0)
else
return nil
end
check_status!(API.sane_control_option(device_handle, option, :set_value, value_pointer, FFI::Pointer::NULL))
case descriptor[:type]
when :string
value_pointer.read_string
when :bool
!value_pointer.read_int.zero?
when :int, :fixed
value_pointer.read_int
end
end
def strstatus(status)
API.sane_strstatus(status)
end
private
def check_status!(status)
raise Error.new(strstatus(status), status) if status != :good
end
end

View File

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

View File

@ -1,11 +1,29 @@
module Sane
class Sane
class Device
def initialize(handle)
@handle = handle
def initialize(name)
@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
def close
Sane.close(@handle)
Sane.close(@handle) if opened?
@handle = nil
end
end
end

View File

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

View File

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