ffi-gphoto2 0.4.1 → 0.5.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 +4 -4
- data/.rspec +2 -1
- data/Rakefile +2 -0
- data/examples/intervalometer.rb +9 -7
- data/examples/list_config.rb +3 -5
- data/examples/live_view.rb +6 -12
- data/examples/record_movie.rb +10 -13
- data/ffi-gphoto2.gemspec +2 -1
- data/lib/ffi/gphoto2_port.rb +2 -2
- data/lib/gphoto2/camera/capture.rb +59 -0
- data/lib/gphoto2/camera/configuration.rb +136 -0
- data/lib/gphoto2/camera/event.rb +56 -0
- data/lib/gphoto2/camera/filesystem.rb +44 -0
- data/lib/gphoto2/camera.rb +95 -166
- data/lib/gphoto2/camera_abilities.rb +6 -6
- data/lib/gphoto2/camera_abilities_list.rb +7 -6
- data/lib/gphoto2/camera_event.rb +1 -8
- data/lib/gphoto2/camera_file.rb +15 -5
- data/lib/gphoto2/camera_file_path.rb +3 -5
- data/lib/gphoto2/camera_folder.rb +11 -0
- data/lib/gphoto2/camera_list.rb +3 -10
- data/lib/gphoto2/camera_widgets/camera_widget.rb +27 -14
- data/lib/gphoto2/camera_widgets/radio_camera_widget.rb +1 -0
- data/lib/gphoto2/camera_widgets/range_camera_widget.rb +1 -0
- data/lib/gphoto2/context.rb +2 -6
- data/lib/gphoto2/entry.rb +2 -0
- data/lib/gphoto2/port_info.rb +8 -6
- data/lib/gphoto2/port_info_list.rb +5 -6
- data/lib/gphoto2/port_result.rb +2 -0
- data/lib/gphoto2/struct.rb +11 -0
- data/lib/gphoto2/version.rb +1 -1
- data/lib/gphoto2.rb +13 -0
- data/spec/gphoto2/camera_abilities_list_spec.rb +5 -5
- data/spec/gphoto2/camera_abilities_spec.rb +7 -7
- data/spec/gphoto2/camera_file_path_spec.rb +2 -2
- data/spec/gphoto2/camera_file_spec.rb +7 -7
- data/spec/gphoto2/camera_folder_spec.rb +3 -3
- data/spec/gphoto2/camera_list_spec.rb +3 -3
- data/spec/gphoto2/camera_spec.rb +37 -272
- data/spec/gphoto2/camera_widgets/date_camera_widget_spec.rb +1 -1
- data/spec/gphoto2/camera_widgets/radio_camera_widget_spec.rb +4 -4
- data/spec/gphoto2/camera_widgets/range_camera_widget_spec.rb +2 -2
- data/spec/gphoto2/camera_widgets/text_camera_widget_spec.rb +1 -1
- data/spec/gphoto2/camera_widgets/toggle_camera_widget_spec.rb +2 -2
- data/spec/gphoto2/context_spec.rb +1 -1
- data/spec/gphoto2/entry_spec.rb +2 -2
- data/spec/gphoto2/port_info_list_spec.rb +4 -4
- data/spec/gphoto2/port_info_spec.rb +9 -10
- data/spec/spec_helper.rb +0 -7
- data/spec/support/shared_examples/camera/capture_examples.rb +41 -0
- data/spec/support/shared_examples/camera/configuration_examples.rb +161 -0
- data/spec/support/shared_examples/camera/event_examples.rb +39 -0
- data/spec/support/shared_examples/camera/filesystem_examples.rb +46 -0
- data/spec/support/shared_examples/camera_widget_examples.rb +13 -13
- metadata +32 -4
@@ -7,7 +7,7 @@ module GPhoto2
|
|
7
7
|
describe '#value' do
|
8
8
|
it 'has a Time return value' do
|
9
9
|
widget = DateCameraWidget.new(nil)
|
10
|
-
widget.
|
10
|
+
allow(widget).to receive(:value).and_return(Time.now)
|
11
11
|
expect(widget.value).to be_kind_of(Time)
|
12
12
|
end
|
13
13
|
end
|
@@ -7,7 +7,7 @@ module GPhoto2
|
|
7
7
|
describe '#value' do
|
8
8
|
it 'has a String return value' do
|
9
9
|
widget = RadioCameraWidget.new(nil)
|
10
|
-
widget.
|
10
|
+
allow(widget).to receive(:value).and_return('text')
|
11
11
|
expect(widget.value).to be_kind_of(String)
|
12
12
|
end
|
13
13
|
end
|
@@ -17,11 +17,11 @@ module GPhoto2
|
|
17
17
|
size = 2
|
18
18
|
|
19
19
|
widget = RadioCameraWidget.new(nil)
|
20
|
-
widget.
|
21
|
-
widget.
|
20
|
+
allow(widget).to receive(:count_choices).and_return(size)
|
21
|
+
allow(widget).to receive(:get_choice).and_return("choice")
|
22
22
|
|
23
23
|
expect(widget).to receive(:get_choice).exactly(size).times
|
24
|
-
|
24
|
+
|
25
25
|
choices = widget.choices
|
26
26
|
|
27
27
|
expect(choices.size).to eq(size)
|
@@ -7,7 +7,7 @@ module GPhoto2
|
|
7
7
|
describe '#value' do
|
8
8
|
it 'has a Float return value' do
|
9
9
|
widget = RangeCameraWidget.new(nil)
|
10
|
-
widget.
|
10
|
+
allow(widget).to receive(:value).and_return(0.0)
|
11
11
|
expect(widget.value).to be_kind_of(Float)
|
12
12
|
end
|
13
13
|
end
|
@@ -18,7 +18,7 @@ module GPhoto2
|
|
18
18
|
range = (min..max).step(inc).to_a
|
19
19
|
|
20
20
|
widget = RangeCameraWidget.new(nil)
|
21
|
-
widget.
|
21
|
+
allow(widget).to receive(:get_range).and_return([min, max, inc])
|
22
22
|
|
23
23
|
expect(widget.range).to eq(range)
|
24
24
|
end
|
@@ -7,7 +7,7 @@ module GPhoto2
|
|
7
7
|
describe '#value' do
|
8
8
|
it 'has a String return value' do
|
9
9
|
widget = TextCameraWidget.new(nil)
|
10
|
-
widget.
|
10
|
+
allow(widget).to receive(:value).and_return('text')
|
11
11
|
expect(widget.value).to be_kind_of(String)
|
12
12
|
end
|
13
13
|
end
|
@@ -7,13 +7,13 @@ module GPhoto2
|
|
7
7
|
describe '#value' do
|
8
8
|
it 'can have a TrueClass return value' do
|
9
9
|
widget = ToggleCameraWidget.new(nil)
|
10
|
-
widget.
|
10
|
+
allow(widget).to receive(:value).and_return(true)
|
11
11
|
expect(widget.value).to be_kind_of(TrueClass)
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'can have a FalseClass return value' do
|
15
15
|
widget = ToggleCameraWidget.new(nil)
|
16
|
-
widget.
|
16
|
+
allow(widget).to receive(:value).and_return(false)
|
17
17
|
expect(widget.value).to be_kind_of(FalseClass)
|
18
18
|
end
|
19
19
|
end
|
data/spec/gphoto2/entry_spec.rb
CHANGED
@@ -8,8 +8,8 @@ module GPhoto2
|
|
8
8
|
let(:value) { 'usb:250,006' }
|
9
9
|
|
10
10
|
before do
|
11
|
-
entry.
|
12
|
-
entry.
|
11
|
+
allow(entry).to receive(:get_name).and_return(name)
|
12
|
+
allow(entry).to receive(:get_value).and_return(value)
|
13
13
|
end
|
14
14
|
|
15
15
|
describe '#name' do
|
@@ -3,8 +3,8 @@ require 'spec_helper'
|
|
3
3
|
module GPhoto2
|
4
4
|
describe PortInfoList do
|
5
5
|
before do
|
6
|
-
PortInfoList.
|
7
|
-
PortInfoList.
|
6
|
+
allow_any_instance_of(PortInfoList).to receive(:new)
|
7
|
+
allow_any_instance_of(PortInfoList).to receive(:load)
|
8
8
|
end
|
9
9
|
|
10
10
|
describe '#lookup_path' do
|
@@ -13,7 +13,7 @@ module GPhoto2
|
|
13
13
|
index = 0
|
14
14
|
|
15
15
|
list = PortInfoList.new
|
16
|
-
list.
|
16
|
+
allow(list).to receive(:_lookup_path).and_return(index)
|
17
17
|
|
18
18
|
expect(list.lookup_path(port)).to eq(index)
|
19
19
|
end
|
@@ -21,7 +21,7 @@ module GPhoto2
|
|
21
21
|
|
22
22
|
describe '#at' do
|
23
23
|
it 'returns a new PortInfo instance at the specified index' do
|
24
|
-
PortInfo.
|
24
|
+
allow_any_instance_of(PortInfo).to receive(:new)
|
25
25
|
|
26
26
|
list = PortInfoList.new
|
27
27
|
port_info = list.at(0)
|
@@ -6,17 +6,16 @@ module GPhoto2
|
|
6
6
|
let(:index) { 0 }
|
7
7
|
|
8
8
|
before do
|
9
|
-
PortInfo.
|
9
|
+
allow_any_instance_of(PortInfo).to receive(:new)
|
10
10
|
end
|
11
11
|
|
12
12
|
describe '.find' do
|
13
13
|
it 'returns a new PortInfo instance from a port path' do
|
14
|
-
PortInfoList.
|
15
|
-
PortInfoList.
|
16
|
-
PortInfoList.
|
17
|
-
|
18
|
-
|
19
|
-
end
|
14
|
+
allow_any_instance_of(PortInfoList).to receive(:new)
|
15
|
+
allow_any_instance_of(PortInfoList).to receive(:load)
|
16
|
+
allow_any_instance_of(PortInfoList).to receive(:lookup_path)
|
17
|
+
info = PortInfo.new(port_info_list, index)
|
18
|
+
allow_any_instance_of(PortInfoList).to receive(:[]).and_return(info)
|
20
19
|
|
21
20
|
port_info = PortInfo.find('usb:250,006')
|
22
21
|
expect(port_info).to be_kind_of(PortInfo)
|
@@ -27,7 +26,7 @@ module GPhoto2
|
|
27
26
|
it 'returns the name of the port' do
|
28
27
|
name = 'name'
|
29
28
|
port_info = PortInfo.new(port_info_list, index)
|
30
|
-
port_info.
|
29
|
+
allow(port_info).to receive(:get_name).and_return(name)
|
31
30
|
expect(port_info.name).to eq(name)
|
32
31
|
end
|
33
32
|
end
|
@@ -36,7 +35,7 @@ module GPhoto2
|
|
36
35
|
it 'returns the path of the port' do
|
37
36
|
path = 'path'
|
38
37
|
port_info = PortInfo.new(port_info_list, index)
|
39
|
-
port_info.
|
38
|
+
allow(port_info).to receive(:get_path).and_return(path)
|
40
39
|
expect(port_info.path).to eq(path)
|
41
40
|
end
|
42
41
|
end
|
@@ -45,7 +44,7 @@ module GPhoto2
|
|
45
44
|
it 'returns the type of the port' do
|
46
45
|
type = :usb
|
47
46
|
port_info = PortInfo.new(port_info_list, index)
|
48
|
-
port_info.
|
47
|
+
allow(port_info).to receive(:get_type).and_return(type)
|
49
48
|
expect(port_info.type).to eq(type)
|
50
49
|
end
|
51
50
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,10 +3,3 @@ require 'gphoto2'
|
|
3
3
|
|
4
4
|
__dir__ ||= File.dirname(__FILE__)
|
5
5
|
Dir[File.join(__dir__, 'support/**/*.rb')].each { |f| require f }
|
6
|
-
|
7
|
-
RSpec.configure do |config|
|
8
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
-
config.run_all_when_everything_filtered = true
|
10
|
-
config.filter_run :focus
|
11
|
-
config.order = 'random'
|
12
|
-
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module GPhoto2
|
2
|
+
shared_examples_for Camera::Capture do
|
3
|
+
describe '#capture' do
|
4
|
+
let(:camera) { Camera.new(model, port) }
|
5
|
+
let(:path) { double('camera_file_path', folder: 'folder', name: 'name') }
|
6
|
+
|
7
|
+
before do
|
8
|
+
allow(camera).to receive(:_capture).and_return(path)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'saves the camera configuration' do
|
12
|
+
expect(camera).to receive(:save)
|
13
|
+
camera.capture
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns a new CameraFile' do
|
17
|
+
expect(camera).to receive(:_capture)
|
18
|
+
expect(camera.capture).to be_kind_of(CameraFile)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#preview' do
|
23
|
+
let(:camera) { Camera.new(model, port) }
|
24
|
+
let(:file) { double('camera_file') }
|
25
|
+
|
26
|
+
before do
|
27
|
+
allow(camera).to receive(:save)
|
28
|
+
allow(camera).to receive(:capture_preview).and_return(file)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'saves the camera configuration' do
|
32
|
+
expect(camera).to receive(:save)
|
33
|
+
camera.preview
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns a new CameraFile' do
|
37
|
+
expect(camera.preview).to eq(file)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
module GPhoto2
|
2
|
+
shared_examples_for Camera::Configuration do
|
3
|
+
describe '#window' do
|
4
|
+
let(:camera) { Camera.new(model, port) }
|
5
|
+
let(:window) { double('camera_widget') }
|
6
|
+
|
7
|
+
it 'always returns the same CameraWidget instance' do
|
8
|
+
allow(camera).to receive(:get_config).and_return(window)
|
9
|
+
expect(camera.window).to eq(window)
|
10
|
+
expect(camera.window).to eq(window)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#config' do
|
15
|
+
it 'returns a map of configuration widgets' do
|
16
|
+
camera = Camera.new(model, port)
|
17
|
+
window = double('camera_widget')
|
18
|
+
allow(camera).to receive(:window).and_return(window)
|
19
|
+
allow(window).to receive(:flatten).and_return({ 'iso' => window })
|
20
|
+
|
21
|
+
expect(camera.config).to eq({ 'iso' => window })
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#reload' do
|
26
|
+
let(:camera) do
|
27
|
+
camera = Camera.new(model, port)
|
28
|
+
window = double('camera_widget')
|
29
|
+
allow(window).to receive(:flatten)
|
30
|
+
allow(camera).to receive(:get_config).and_return(window)
|
31
|
+
camera
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'reloads the configuration from the camera' do
|
35
|
+
expect(camera).to receive(:get_config).once
|
36
|
+
camera.reload
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'marks the camera as not dirty' do
|
40
|
+
camera.reload
|
41
|
+
expect(camera.dirty?).to be(false)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#[]' do
|
46
|
+
let(:window) { double('camera_widget') }
|
47
|
+
|
48
|
+
let(:camera) do
|
49
|
+
camera = Camera.new(model, port)
|
50
|
+
allow(camera).to receive(:config).and_return({ 'iso' => window })
|
51
|
+
camera
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'when the specified key exists' do
|
55
|
+
it 'returns a CameraWidget' do
|
56
|
+
expect(camera['iso']).to eq(window)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when the specified key does not exist' do
|
61
|
+
it 'returns nil' do
|
62
|
+
expect(camera['shutterspeed2']).to be_nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#[]=' do
|
68
|
+
let(:window) do
|
69
|
+
window = double('camera_widget')
|
70
|
+
expect(window).to receive(:value=).with(400)
|
71
|
+
window
|
72
|
+
end
|
73
|
+
|
74
|
+
let(:camera) do
|
75
|
+
camera = Camera.new(model, port)
|
76
|
+
allow(camera).to receive(:[]).and_return(window)
|
77
|
+
camera
|
78
|
+
end
|
79
|
+
|
80
|
+
it "sets a widget's value" do
|
81
|
+
camera['iso'] = 400
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'marks the camera as dirty' do
|
85
|
+
camera['iso'] = 400
|
86
|
+
expect(camera).to be_dirty
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'returns the passed value' do
|
90
|
+
expect(camera['iso'] = 400).to eq(400)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '#update' do
|
95
|
+
let(:camera) do
|
96
|
+
camera = Camera.new(model, port)
|
97
|
+
allow(camera).to receive(:[]=)
|
98
|
+
allow(camera).to receive(:save)
|
99
|
+
camera
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'sets one or more camera setting' do
|
103
|
+
expect(camera).to receive(:[]=).exactly(2).times
|
104
|
+
camera.update('iso' => 400, 'shutterspeed2' => '1/30')
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'immediately saves the settings to the camera' do
|
108
|
+
expect(camera).to receive(:save)
|
109
|
+
camera.update
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe '#save' do
|
114
|
+
let(:camera) do
|
115
|
+
camera = Camera.new(model, port)
|
116
|
+
allow(camera).to receive_message_chain(:[], :value=)
|
117
|
+
allow(camera).to receive(:set_config)
|
118
|
+
camera
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'when the camera is marked as dirty' do
|
122
|
+
it 'returns true' do
|
123
|
+
camera['iso'] = 400
|
124
|
+
expect(camera.save).to be(true)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'marks the camera as not dirty' do
|
128
|
+
camera['iso'] = 400
|
129
|
+
camera.save
|
130
|
+
expect(camera).not_to be_dirty
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'when the camera is not marked as dirty' do
|
135
|
+
it 'returns false' do
|
136
|
+
expect(camera.save).to be(false)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe '#dirty?' do
|
142
|
+
context 'when the configuration changed' do
|
143
|
+
it 'returns true' do
|
144
|
+
camera = Camera.new(model, port)
|
145
|
+
allow(camera).to receive_message_chain(:[], :value=)
|
146
|
+
|
147
|
+
camera['iso'] = 400
|
148
|
+
|
149
|
+
expect(camera).to be_dirty
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'when the configuration has not changed' do
|
154
|
+
it 'returns false' do
|
155
|
+
camera = Camera.new(model, port)
|
156
|
+
expect(camera).not_to be_dirty
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module GPhoto2
|
2
|
+
shared_examples_for Camera::Event do
|
3
|
+
describe '#wait' do
|
4
|
+
let(:camera) { Camera.new(model, port) }
|
5
|
+
let(:event) { double('camera_event') }
|
6
|
+
|
7
|
+
before do
|
8
|
+
allow(camera).to receive(:wait_for_event).and_return(event)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'waits for a camera event' do
|
12
|
+
expect(camera).to receive(:wait_for_event)
|
13
|
+
camera.wait
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns an event symbol' do
|
17
|
+
expect(camera.wait).to eq(event)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#wait_for' do
|
22
|
+
let(:camera) { Camera.new(model, port) }
|
23
|
+
let(:event) { double('camera_event', type: :capture_complete) }
|
24
|
+
|
25
|
+
before do
|
26
|
+
allow(camera).to receive(:wait).and_return(event)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'blocks until a given event is returned from #wait' do
|
30
|
+
expect(camera).to receive(:wait)
|
31
|
+
camera.wait_for(:capture_complete)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns the first event of the given type' do
|
35
|
+
expect(camera.wait_for(:capture_complete)).to eq(event)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module GPhoto2
|
2
|
+
shared_examples_for Camera::Filesystem do
|
3
|
+
describe '#filesystem' do
|
4
|
+
let(:camera) { Camera.new(model, port) }
|
5
|
+
|
6
|
+
context 'when a path is passed' do
|
7
|
+
let(:path) { '/store_00010001' }
|
8
|
+
|
9
|
+
it 'assumes the path is absolute' do
|
10
|
+
fs = camera.filesystem(path[1..-1])
|
11
|
+
expect(fs.path).to eq(path)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'returns a folder at the path that was passed' do
|
15
|
+
fs = camera.filesystem(path)
|
16
|
+
expect(fs.path).to eq(path)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when no path is passed' do
|
21
|
+
it 'returns a folder at the root of the filesystem' do
|
22
|
+
fs = camera.filesystem
|
23
|
+
expect(fs.path).to eq('/')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#file' do
|
29
|
+
it 'retrieves a file from the camera' do
|
30
|
+
camera = Camera.new(model, port)
|
31
|
+
allow(camera).to receive(:file_get)
|
32
|
+
expect(camera).to receive(:file_get)
|
33
|
+
camera.file(double('camera_file'))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#delete' do
|
38
|
+
it 'deletes a file from the camera' do
|
39
|
+
camera = Camera.new(model, port)
|
40
|
+
allow(camera).to receive(:file_delete)
|
41
|
+
expect(camera).to receive(:file_delete)
|
42
|
+
camera.delete(double('camera_file'))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|