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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -1
  3. data/Rakefile +2 -0
  4. data/examples/intervalometer.rb +9 -7
  5. data/examples/list_config.rb +3 -5
  6. data/examples/live_view.rb +6 -12
  7. data/examples/record_movie.rb +10 -13
  8. data/ffi-gphoto2.gemspec +2 -1
  9. data/lib/ffi/gphoto2_port.rb +2 -2
  10. data/lib/gphoto2/camera/capture.rb +59 -0
  11. data/lib/gphoto2/camera/configuration.rb +136 -0
  12. data/lib/gphoto2/camera/event.rb +56 -0
  13. data/lib/gphoto2/camera/filesystem.rb +44 -0
  14. data/lib/gphoto2/camera.rb +95 -166
  15. data/lib/gphoto2/camera_abilities.rb +6 -6
  16. data/lib/gphoto2/camera_abilities_list.rb +7 -6
  17. data/lib/gphoto2/camera_event.rb +1 -8
  18. data/lib/gphoto2/camera_file.rb +15 -5
  19. data/lib/gphoto2/camera_file_path.rb +3 -5
  20. data/lib/gphoto2/camera_folder.rb +11 -0
  21. data/lib/gphoto2/camera_list.rb +3 -10
  22. data/lib/gphoto2/camera_widgets/camera_widget.rb +27 -14
  23. data/lib/gphoto2/camera_widgets/radio_camera_widget.rb +1 -0
  24. data/lib/gphoto2/camera_widgets/range_camera_widget.rb +1 -0
  25. data/lib/gphoto2/context.rb +2 -6
  26. data/lib/gphoto2/entry.rb +2 -0
  27. data/lib/gphoto2/port_info.rb +8 -6
  28. data/lib/gphoto2/port_info_list.rb +5 -6
  29. data/lib/gphoto2/port_result.rb +2 -0
  30. data/lib/gphoto2/struct.rb +11 -0
  31. data/lib/gphoto2/version.rb +1 -1
  32. data/lib/gphoto2.rb +13 -0
  33. data/spec/gphoto2/camera_abilities_list_spec.rb +5 -5
  34. data/spec/gphoto2/camera_abilities_spec.rb +7 -7
  35. data/spec/gphoto2/camera_file_path_spec.rb +2 -2
  36. data/spec/gphoto2/camera_file_spec.rb +7 -7
  37. data/spec/gphoto2/camera_folder_spec.rb +3 -3
  38. data/spec/gphoto2/camera_list_spec.rb +3 -3
  39. data/spec/gphoto2/camera_spec.rb +37 -272
  40. data/spec/gphoto2/camera_widgets/date_camera_widget_spec.rb +1 -1
  41. data/spec/gphoto2/camera_widgets/radio_camera_widget_spec.rb +4 -4
  42. data/spec/gphoto2/camera_widgets/range_camera_widget_spec.rb +2 -2
  43. data/spec/gphoto2/camera_widgets/text_camera_widget_spec.rb +1 -1
  44. data/spec/gphoto2/camera_widgets/toggle_camera_widget_spec.rb +2 -2
  45. data/spec/gphoto2/context_spec.rb +1 -1
  46. data/spec/gphoto2/entry_spec.rb +2 -2
  47. data/spec/gphoto2/port_info_list_spec.rb +4 -4
  48. data/spec/gphoto2/port_info_spec.rb +9 -10
  49. data/spec/spec_helper.rb +0 -7
  50. data/spec/support/shared_examples/camera/capture_examples.rb +41 -0
  51. data/spec/support/shared_examples/camera/configuration_examples.rb +161 -0
  52. data/spec/support/shared_examples/camera/event_examples.rb +39 -0
  53. data/spec/support/shared_examples/camera/filesystem_examples.rb +46 -0
  54. data/spec/support/shared_examples/camera_widget_examples.rb +13 -13
  55. 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.stub(:value).and_return(Time.now)
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.stub(:value).and_return('text')
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.stub(:count_choices).and_return(size)
21
- widget.stub(:get_choice).and_return("choice")
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.stub(:value).and_return(0.0)
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.stub(:get_range).and_return([min, max, inc])
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.stub(:value).and_return('text')
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.stub(:value).and_return(true)
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.stub(:value).and_return(false)
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
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  module GPhoto2
4
4
  describe Context do
5
5
  before do
6
- Context.any_instance.stub(:new)
6
+ allow_any_instance_of(Context).to receive(:new)
7
7
  end
8
8
 
9
9
  describe '#finalize' do
@@ -8,8 +8,8 @@ module GPhoto2
8
8
  let(:value) { 'usb:250,006' }
9
9
 
10
10
  before do
11
- entry.stub(:get_name).and_return(name)
12
- entry.stub(:get_value).and_return(value)
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.any_instance.stub(:new)
7
- PortInfoList.any_instance.stub(:load)
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.stub(:_lookup_path).and_return(index)
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.any_instance.stub(:new)
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.any_instance.stub(:new)
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.any_instance.stub(:new)
15
- PortInfoList.any_instance.stub(:load)
16
- PortInfoList.any_instance.stub(:lookup_path)
17
- PortInfoList.any_instance.stub(:[]).and_return do
18
- PortInfo.new(port_info_list, index)
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.stub(:get_name).and_return(name)
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.stub(:get_path).and_return(path)
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.stub(:get_type).and_return(type)
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