ffi-gphoto2 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +90 -0
- data/Rakefile +6 -0
- data/examples/intervalometer.rb +12 -0
- data/examples/live_view.rb +21 -0
- data/ffi-gphoto2.gemspec +30 -0
- data/lib/ffi/gphoto2.rb +85 -0
- data/lib/ffi/gphoto2/camera.rb +12 -0
- data/lib/ffi/gphoto2/camera_abilities.rb +37 -0
- data/lib/ffi/gphoto2/camera_abilities_list.rb +15 -0
- data/lib/ffi/gphoto2/camera_capture_type.rb +8 -0
- data/lib/ffi/gphoto2/camera_driver_status.rb +9 -0
- data/lib/ffi/gphoto2/camera_event_type.rb +10 -0
- data/lib/ffi/gphoto2/camera_file.rb +28 -0
- data/lib/ffi/gphoto2/camera_file_access_type.rb +8 -0
- data/lib/ffi/gphoto2/camera_file_operation.rb +11 -0
- data/lib/ffi/gphoto2/camera_file_path.rb +9 -0
- data/lib/ffi/gphoto2/camera_file_type.rb +11 -0
- data/lib/ffi/gphoto2/camera_folder_operation.rb +10 -0
- data/lib/ffi/gphoto2/camera_list.rb +15 -0
- data/lib/ffi/gphoto2/camera_operation.rb +12 -0
- data/lib/ffi/gphoto2/camera_widget.rb +33 -0
- data/lib/ffi/gphoto2/camera_widget_type.rb +14 -0
- data/lib/ffi/gphoto2/entry.rb +9 -0
- data/lib/ffi/gphoto2/gp_context.rb +31 -0
- data/lib/ffi/gphoto2/gphoto_device_type.rb +7 -0
- data/lib/ffi/gphoto2_port.rb +31 -0
- data/lib/ffi/gphoto2_port/gp_port_info.rb +11 -0
- data/lib/ffi/gphoto2_port/gp_port_info_list.rb +14 -0
- data/lib/ffi/gphoto2_port/gp_port_result.rb +35 -0
- data/lib/ffi/gphoto2_port/gp_port_type.rb +12 -0
- data/lib/gphoto2.rb +41 -0
- data/lib/gphoto2/camera.rb +219 -0
- data/lib/gphoto2/camera_abilities.rb +44 -0
- data/lib/gphoto2/camera_abilities_list.rb +64 -0
- data/lib/gphoto2/camera_file.rb +69 -0
- data/lib/gphoto2/camera_file_path.rb +21 -0
- data/lib/gphoto2/camera_folder.rb +82 -0
- data/lib/gphoto2/camera_list.rb +43 -0
- data/lib/gphoto2/camera_widgets/camera_widget.rb +112 -0
- data/lib/gphoto2/camera_widgets/date_camera_widget.rb +19 -0
- data/lib/gphoto2/camera_widgets/menu_camera_widget.rb +4 -0
- data/lib/gphoto2/camera_widgets/radio_camera_widget.rb +41 -0
- data/lib/gphoto2/camera_widgets/range_camera_widget.rb +37 -0
- data/lib/gphoto2/camera_widgets/section_camera_widget.rb +4 -0
- data/lib/gphoto2/camera_widgets/text_camera_widget.rb +14 -0
- data/lib/gphoto2/camera_widgets/toggle_camera_widget.rb +18 -0
- data/lib/gphoto2/camera_widgets/window_camera_widget.rb +4 -0
- data/lib/gphoto2/context.rb +31 -0
- data/lib/gphoto2/entry.rb +38 -0
- data/lib/gphoto2/port_info.rb +70 -0
- data/lib/gphoto2/port_info_list.rb +46 -0
- data/lib/gphoto2/port_result.rb +7 -0
- data/lib/gphoto2/version.rb +3 -0
- data/spec/gphoto2/camera_abilities_list_spec.rb +45 -0
- data/spec/gphoto2/camera_abilities_spec.rb +38 -0
- data/spec/gphoto2/camera_file_path_spec.rb +27 -0
- data/spec/gphoto2/camera_file_spec.rb +71 -0
- data/spec/gphoto2/camera_folder_spec.rb +110 -0
- data/spec/gphoto2/camera_list_spec.rb +35 -0
- data/spec/gphoto2/camera_spec.rb +292 -0
- data/spec/gphoto2/camera_widgets/date_camera_widget_spec.rb +15 -0
- data/spec/gphoto2/camera_widgets/radio_camera_widget_spec.rb +31 -0
- data/spec/gphoto2/camera_widgets/range_camera_widget_spec.rb +27 -0
- data/spec/gphoto2/camera_widgets/text_camera_widget_spec.rb +15 -0
- data/spec/gphoto2/camera_widgets/toggle_camera_widget_spec.rb +21 -0
- data/spec/gphoto2/context_spec.rb +17 -0
- data/spec/gphoto2/entry_spec.rb +27 -0
- data/spec/gphoto2/port_info_list_spec.rb +33 -0
- data/spec/gphoto2/port_info_spec.rb +53 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/shared_examples/camera_widget_examples.rb +89 -0
- metadata +194 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
module GPhoto2
|
2
|
+
class CameraAbilities
|
3
|
+
include FFI::GPhoto2
|
4
|
+
|
5
|
+
attr_reader :ptr
|
6
|
+
|
7
|
+
def self.find(model)
|
8
|
+
context = Context.new
|
9
|
+
|
10
|
+
camera_abilities_list = CameraAbilitiesList.new(context)
|
11
|
+
index = camera_abilities_list.lookup_model(model)
|
12
|
+
abilities = camera_abilities_list[index]
|
13
|
+
|
14
|
+
context.finalize
|
15
|
+
|
16
|
+
abilities
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(camera_abilities_list, index)
|
20
|
+
@camera_abilities_list = camera_abilities_list
|
21
|
+
@index = index
|
22
|
+
get_abilities
|
23
|
+
end
|
24
|
+
|
25
|
+
def [](field)
|
26
|
+
ptr[field]
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_ptr
|
30
|
+
@ptr
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def get_abilities
|
36
|
+
ptr = FFI::GPhoto2::CameraAbilities.new
|
37
|
+
rc = gp_abilities_list_get_abilities(@camera_abilities_list.ptr,
|
38
|
+
@index,
|
39
|
+
ptr)
|
40
|
+
GPhoto2.check!(rc)
|
41
|
+
@ptr = ptr
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module GPhoto2
|
2
|
+
class CameraAbilitiesList
|
3
|
+
include FFI::GPhoto2
|
4
|
+
|
5
|
+
attr_reader :ptr
|
6
|
+
|
7
|
+
def initialize(context)
|
8
|
+
@context = context
|
9
|
+
new
|
10
|
+
load
|
11
|
+
end
|
12
|
+
|
13
|
+
def detect
|
14
|
+
_detect
|
15
|
+
end
|
16
|
+
|
17
|
+
def lookup_model(model)
|
18
|
+
_lookup_model(model)
|
19
|
+
end
|
20
|
+
alias_method :index, :lookup_model
|
21
|
+
|
22
|
+
def at(index)
|
23
|
+
CameraAbilities.new(self, index)
|
24
|
+
end
|
25
|
+
alias_method :[], :at
|
26
|
+
|
27
|
+
def to_ptr
|
28
|
+
@ptr
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def new
|
34
|
+
ptr = FFI::MemoryPointer.new(FFI::GPhoto2::CameraAbilitiesList)
|
35
|
+
rc = gp_abilities_list_new(ptr)
|
36
|
+
GPhoto2.check!(rc)
|
37
|
+
@ptr = FFI::GPhoto2::CameraAbilitiesList.new(ptr.read_pointer)
|
38
|
+
end
|
39
|
+
|
40
|
+
def load
|
41
|
+
rc = gp_abilities_list_load(ptr, @context.ptr)
|
42
|
+
GPhoto2.check!(rc)
|
43
|
+
end
|
44
|
+
|
45
|
+
def _detect
|
46
|
+
port_info_list = PortInfoList.new
|
47
|
+
camera_list = CameraList.new
|
48
|
+
|
49
|
+
rc = gp_abilities_list_detect(ptr,
|
50
|
+
port_info_list.ptr,
|
51
|
+
camera_list.ptr,
|
52
|
+
@context.ptr)
|
53
|
+
GPhoto2.check!(rc)
|
54
|
+
|
55
|
+
camera_list
|
56
|
+
end
|
57
|
+
|
58
|
+
def _lookup_model(model)
|
59
|
+
index = rc = gp_abilities_list_lookup_model(ptr, model)
|
60
|
+
GPhoto2.check!(rc)
|
61
|
+
index
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module GPhoto2
|
2
|
+
class CameraFile
|
3
|
+
include FFI::GPhoto2
|
4
|
+
|
5
|
+
attr_reader :folder, :name, :ptr
|
6
|
+
|
7
|
+
def initialize(camera, folder = nil, name = nil)
|
8
|
+
@camera = camera
|
9
|
+
@folder, @name = folder, name
|
10
|
+
new
|
11
|
+
end
|
12
|
+
|
13
|
+
def preview?
|
14
|
+
@folder.nil? && @name.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
def save(pathname = default_filename)
|
18
|
+
File.binwrite(pathname, data)
|
19
|
+
end
|
20
|
+
|
21
|
+
def data
|
22
|
+
data_and_size.first
|
23
|
+
end
|
24
|
+
|
25
|
+
def size
|
26
|
+
data_and_size.last
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_ptr
|
30
|
+
@ptr
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def data_and_size
|
36
|
+
@data_and_size ||= begin
|
37
|
+
@camera.file(self) unless preview?
|
38
|
+
get_data_and_size
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def default_filename
|
43
|
+
# previews are always jpg
|
44
|
+
preview? ? 'capture_preview.jpg' : @name
|
45
|
+
end
|
46
|
+
|
47
|
+
def new
|
48
|
+
ptr = FFI::MemoryPointer.new(FFI::GPhoto2::CameraFile)
|
49
|
+
rc = gp_file_new(ptr)
|
50
|
+
GPhoto2.check!(rc)
|
51
|
+
@ptr = FFI::GPhoto2::CameraFile.new(ptr.read_pointer)
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_data_and_size
|
55
|
+
data = FFI::MemoryPointer.new(:uchar)
|
56
|
+
data_ptr = FFI::MemoryPointer.new(:pointer)
|
57
|
+
data_ptr.write_pointer(data)
|
58
|
+
size = FFI::MemoryPointer.new(:ulong)
|
59
|
+
|
60
|
+
rc = gp_file_get_data_and_size(ptr, data_ptr, size)
|
61
|
+
GPhoto2.check!(rc)
|
62
|
+
|
63
|
+
size = size.read_ulong
|
64
|
+
data = data_ptr.read_pointer.read_bytes(size)
|
65
|
+
|
66
|
+
[data, size]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module GPhoto2
|
2
|
+
class CameraFilePath
|
3
|
+
attr_reader :ptr
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@ptr = FFI::GPhoto2::CameraFilePath.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
ptr[:name].to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def folder
|
14
|
+
ptr[:folder].to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_ptr
|
18
|
+
@ptr
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module GPhoto2
|
2
|
+
class CameraFolder
|
3
|
+
include FFI::GPhoto2
|
4
|
+
|
5
|
+
attr_reader :path
|
6
|
+
|
7
|
+
def initialize(camera, path = '/')
|
8
|
+
@camera = camera
|
9
|
+
@path = path
|
10
|
+
end
|
11
|
+
|
12
|
+
def root?
|
13
|
+
@path == '/'
|
14
|
+
end
|
15
|
+
|
16
|
+
def name
|
17
|
+
if root?
|
18
|
+
'/'
|
19
|
+
else
|
20
|
+
@path.rpartition('/').last
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def folders
|
25
|
+
folder_list_folders
|
26
|
+
end
|
27
|
+
|
28
|
+
def files
|
29
|
+
folder_list_files
|
30
|
+
end
|
31
|
+
|
32
|
+
def cd(name)
|
33
|
+
case name
|
34
|
+
when '.'
|
35
|
+
self
|
36
|
+
when '..'
|
37
|
+
up
|
38
|
+
else
|
39
|
+
CameraFolder.new(@camera, File.join(@path, name))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
alias_method :/, :cd
|
43
|
+
|
44
|
+
def open(name)
|
45
|
+
CameraFile.new(@camera, @path, name)
|
46
|
+
end
|
47
|
+
|
48
|
+
def up
|
49
|
+
if root?
|
50
|
+
self
|
51
|
+
else
|
52
|
+
parent = @path.rpartition('/').first
|
53
|
+
parent = '/' if parent.empty?
|
54
|
+
CameraFolder.new(@camera, parent)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_s
|
59
|
+
name
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def folder_list_files
|
65
|
+
list = CameraList.new
|
66
|
+
|
67
|
+
rc = gp_camera_folder_list_files(@camera.ptr, @path, list.ptr, @camera.context.ptr)
|
68
|
+
GPhoto2.check!(rc)
|
69
|
+
|
70
|
+
list.to_a.map { |f| open(f.name) }
|
71
|
+
end
|
72
|
+
|
73
|
+
def folder_list_folders
|
74
|
+
list = CameraList.new
|
75
|
+
|
76
|
+
rc = gp_camera_folder_list_folders(@camera.ptr, @path, list.ptr, @camera.context.ptr)
|
77
|
+
GPhoto2.check!(rc)
|
78
|
+
|
79
|
+
list.to_a.map { |f| cd(f.name) }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module GPhoto2
|
2
|
+
class CameraList
|
3
|
+
include FFI::GPhoto2
|
4
|
+
|
5
|
+
attr_reader :ptr
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
new
|
9
|
+
end
|
10
|
+
|
11
|
+
def finalize
|
12
|
+
free
|
13
|
+
end
|
14
|
+
|
15
|
+
def size
|
16
|
+
count
|
17
|
+
end
|
18
|
+
alias_method :length, :size
|
19
|
+
|
20
|
+
def to_a
|
21
|
+
size.times.map { |i| Entry.new(self, i) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_ptr
|
25
|
+
@ptr
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def new
|
31
|
+
ptr = FFI::MemoryPointer.new(FFI::GPhoto2::CameraList)
|
32
|
+
rc = gp_list_new(ptr)
|
33
|
+
GPhoto2.check!(rc)
|
34
|
+
@ptr = FFI::GPhoto2::CameraList.new(ptr.read_pointer)
|
35
|
+
end
|
36
|
+
|
37
|
+
def count
|
38
|
+
rc = gp_list_count(ptr)
|
39
|
+
GPhoto2.check!(rc)
|
40
|
+
rc
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module GPhoto2
|
2
|
+
class CameraWidget
|
3
|
+
include FFI::GPhoto2
|
4
|
+
|
5
|
+
attr_reader :ptr
|
6
|
+
|
7
|
+
def self.factory(ptr, parent = nil)
|
8
|
+
# ptr fields are supposed to be private, but we ignore that here
|
9
|
+
type = ptr[:type].to_s.split('_').last.capitalize
|
10
|
+
klass = GPhoto2.const_get("#{type}CameraWidget")
|
11
|
+
klass.new(ptr, parent)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(ptr, parent = nil)
|
15
|
+
@ptr = ptr
|
16
|
+
@parent = parent
|
17
|
+
end
|
18
|
+
|
19
|
+
def finalize
|
20
|
+
free
|
21
|
+
end
|
22
|
+
alias_method :close, :finalize
|
23
|
+
|
24
|
+
def name
|
25
|
+
get_name
|
26
|
+
end
|
27
|
+
|
28
|
+
def value
|
29
|
+
get_value
|
30
|
+
end
|
31
|
+
|
32
|
+
def value=(value)
|
33
|
+
set_value(value)
|
34
|
+
value
|
35
|
+
end
|
36
|
+
|
37
|
+
def type
|
38
|
+
get_type
|
39
|
+
end
|
40
|
+
|
41
|
+
def children
|
42
|
+
count_children.times.map { |i| get_child(i) }
|
43
|
+
end
|
44
|
+
|
45
|
+
def flatten(map = {})
|
46
|
+
case type
|
47
|
+
when :window, :section
|
48
|
+
children.each { |child| child.flatten(map) }
|
49
|
+
when :menu
|
50
|
+
# noop
|
51
|
+
else
|
52
|
+
map[name] = self
|
53
|
+
end
|
54
|
+
|
55
|
+
map
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_s
|
59
|
+
value.to_s
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_ptr
|
63
|
+
@ptr
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def free
|
69
|
+
rc = gp_widget_free(ptr)
|
70
|
+
GPhoto2.check!(rc)
|
71
|
+
end
|
72
|
+
|
73
|
+
def get_name
|
74
|
+
str = FFI::MemoryPointer.new(:string)
|
75
|
+
str_ptr = FFI::MemoryPointer.new(:pointer)
|
76
|
+
str_ptr.write_pointer(str)
|
77
|
+
rc = gp_widget_get_name(ptr, str_ptr)
|
78
|
+
GPhoto2.check!(rc)
|
79
|
+
str_ptr.read_pointer.read_string
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_value
|
83
|
+
raise NotImplementedError
|
84
|
+
end
|
85
|
+
|
86
|
+
def set_value(value)
|
87
|
+
raise NotImplementedError
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_type
|
91
|
+
# assume CameraWidgetType is an int
|
92
|
+
type = FFI::MemoryPointer.new(:int)
|
93
|
+
rc = gp_widget_get_type(ptr, type)
|
94
|
+
GPhoto2.check!(rc)
|
95
|
+
CameraWidgetType[type.read_int]
|
96
|
+
end
|
97
|
+
|
98
|
+
def count_children
|
99
|
+
rc = gp_widget_count_children(ptr)
|
100
|
+
GPhoto2.check!(rc)
|
101
|
+
rc
|
102
|
+
end
|
103
|
+
|
104
|
+
def get_child(index)
|
105
|
+
widget_ptr = FFI::MemoryPointer.new(FFI::GPhoto2::CameraWidget)
|
106
|
+
rc = gp_widget_get_child(ptr, index, widget_ptr)
|
107
|
+
GPhoto2.check!(rc)
|
108
|
+
widget = FFI::GPhoto2::CameraWidget.new(widget_ptr.read_pointer)
|
109
|
+
CameraWidget.factory(widget, self)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module GPhoto2
|
2
|
+
class DateCameraWidget < CameraWidget
|
3
|
+
protected
|
4
|
+
|
5
|
+
def get_value
|
6
|
+
val = FFI::MemoryPointer.new(:int)
|
7
|
+
rc = gp_widget_get_value(ptr, val)
|
8
|
+
GPhoto2.check!(rc)
|
9
|
+
Time.at(val.read_int).utc
|
10
|
+
end
|
11
|
+
|
12
|
+
def set_value(date)
|
13
|
+
val = FFI::MemoryPointer.new(:int)
|
14
|
+
val.write_int(date.to_i)
|
15
|
+
rc = gp_widget_set_value(ptr, val)
|
16
|
+
GPhoto2.check!(rc)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|