commit 4a4769822e4d71e56533f060480d3ac1fac35a54 Author: Jakub Kuźma Date: Tue May 31 18:26:57 2011 +0200 initial import diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4040c6c --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.gem +.bundle +Gemfile.lock +pkg/* diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..8ecce0e --- /dev/null +++ b/Gemfile @@ -0,0 +1,4 @@ +source "http://rubygems.org" + +# Specify your gem's dependencies in scanner.gemspec +gemspec diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..14cfe0b --- /dev/null +++ b/Rakefile @@ -0,0 +1,2 @@ +require 'bundler' +Bundler::GemHelper.install_tasks diff --git a/lib/sane.rb b/lib/sane.rb new file mode 100644 index 0000000..07dd8e7 --- /dev/null +++ b/lib/sane.rb @@ -0,0 +1,39 @@ +module Sane + 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 + + 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 + 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 check_status!(status) + raise Error.new(API.sane_strstatus(status), status) if status != :good + end + end +end diff --git a/lib/sane/api.rb b/lib/sane/api.rb new file mode 100644 index 0000000..88d5201 --- /dev/null +++ b/lib/sane/api.rb @@ -0,0 +1,60 @@ +module Sane + module API + extend FFI::Library + + ffi_lib "sane" + + enum :status, [:good, 0, :unsupported, :cancelled, :device_busy, :inval, :eof, :jammed, :no_docs, :cover_open, :io_error, :no_mem, :access_denied] + enum :value_type, [:bool, 0, :int, :fixed, :string, :button, :group] + enum :unit, [:none, 0, :pixel, :bit, :mm, :dpi, :percent, :microsecond] + enum :action, [:get_value, 0, :set_value, :set_auto] + enum :frame, [:gray, :rgb, :red, :green, :blue] + + 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 + class ConstraintType < FFI::Union + layout :string_list, :pointer, :word_list, :pointer, :range, :pointer + end + layout :name, :string, :title, :string, :desc, :string, :type, :value_type, :unit, :unit, :size, :int, :cap, :int, :constraint_type, ConstraintType + end + + class Parameters < FFI::Struct + layout :format, :frame, :last_frame, :int, :bytes_per_line, :int, :pixels_per_line, :int, :lines, :int, :depth, :int + end + + # extern SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize); + attach_function :sane_init, [:pointer, :pointer], :status + # extern void sane_exit (void); + attach_function :sane_exit, [], :void + # extern SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only); + attach_function :sane_get_devices, [:pointer, :int], :status + # extern SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle); + attach_function :sane_open, [:string, :pointer], :status + # extern void sane_close (SANE_Handle handle); + attach_function :sane_close, [:pointer], :void + # extern const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option); + attach_function :sane_get_option_descriptor, [:pointer, :int], :pointer + # extern SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info); + attach_function :sane_control_option, [:pointer, :int, :action, :pointer, :pointer], :status + # extern SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params); + attach_function :sane_get_parameters, [:pointer, :pointer], :status + # extern SANE_Status sane_start (SANE_Handle handle); + attach_function :sane_start, [:pointer], :status + # extern SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length); + attach_function :sane_read, [:pointer, :pointer, :int, :pointer], :status + # extern void sane_cancel (SANE_Handle handle); + attach_function :sane_cancel, [:pointer], :void + # extern SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking); + attach_function :sane_set_io_mode, [:pointer, :int], :status + # extern SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd); + attach_function :sane_get_select_fd, [:pointer, :pointer], :status + # extern SANE_String_Const sane_strstatus (SANE_Status status); + attach_function :sane_strstatus, [:status], :string + end +end diff --git a/lib/sane/device.rb b/lib/sane/device.rb new file mode 100644 index 0000000..ed53351 --- /dev/null +++ b/lib/sane/device.rb @@ -0,0 +1,11 @@ +module Sane + class Device + def initialize(handle) + @handle = handle + end + + def close + Sane.close(@handle) + end + end +end diff --git a/lib/sane/error.rb b/lib/sane/error.rb new file mode 100644 index 0000000..d9ce8ee --- /dev/null +++ b/lib/sane/error.rb @@ -0,0 +1,10 @@ +module Sane + class Error < StandardError + attr_reader :status + + def initialize(message, status) + super(message) + @status = status + end + end +end diff --git a/lib/scanner.rb b/lib/scanner.rb new file mode 100644 index 0000000..0f4e542 --- /dev/null +++ b/lib/scanner.rb @@ -0,0 +1,9 @@ +require "ffi" + +require "sane" +require "sane/api" +require "sane/error" + +module Scanner + +end diff --git a/lib/scanner/sane.rb b/lib/scanner/sane.rb new file mode 100644 index 0000000..941467e --- /dev/null +++ b/lib/scanner/sane.rb @@ -0,0 +1,5 @@ +module Scanner + module Sane + + end +end diff --git a/lib/scanner/version.rb b/lib/scanner/version.rb new file mode 100644 index 0000000..5bb45b9 --- /dev/null +++ b/lib/scanner/version.rb @@ -0,0 +1,3 @@ +module Scanner + VERSION = "0.0.1" +end diff --git a/scanner.gemspec b/scanner.gemspec new file mode 100644 index 0000000..02e67cb --- /dev/null +++ b/scanner.gemspec @@ -0,0 +1,23 @@ +# -*- encoding: utf-8 -*- +$:.push File.expand_path("../lib", __FILE__) +require "scanner/version" + +Gem::Specification.new do |s| + s.name = "scanner" + s.version = Scanner::VERSION + s.platform = Gem::Platform::RUBY + s.authors = ["Jakub Kuźma"] + s.email = ["qoobaa@gmail.com"] + s.homepage = "" + s.summary = %q{SANE bindings} + s.description = %q{Scanner Access now Easier} + + # s.rubyforge_project = "scanner" + + s.add_dependency "ffi" + + s.files = `git ls-files`.split("\n") + s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") + s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } + s.require_paths = ["lib"] +end