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
@@ -5,8 +5,8 @@ module GPhoto2
5
5
  let(:context) { double('context') }
6
6
 
7
7
  before do
8
- CameraAbilitiesList.any_instance.stub(:new)
9
- CameraAbilitiesList.any_instance.stub(:load)
8
+ allow_any_instance_of(CameraAbilitiesList).to receive(:new)
9
+ allow_any_instance_of(CameraAbilitiesList).to receive(:load)
10
10
  end
11
11
 
12
12
  describe '#detect' do
@@ -14,7 +14,7 @@ module GPhoto2
14
14
  camera_list = double('camera_list')
15
15
 
16
16
  abilities_list = CameraAbilitiesList.new(context)
17
- abilities_list.stub(:_detect).and_return(camera_list)
17
+ allow(abilities_list).to receive(:_detect).and_return(camera_list)
18
18
 
19
19
  expect(abilities_list.detect).to eq(camera_list)
20
20
  end
@@ -25,7 +25,7 @@ module GPhoto2
25
25
  index = 0
26
26
 
27
27
  list = CameraAbilitiesList.new(context)
28
- list.stub(:_lookup_model).and_return(index)
28
+ allow(list).to receive(:_lookup_model).and_return(index)
29
29
 
30
30
  expect(list.lookup_model('model')).to eq(index)
31
31
  end
@@ -35,7 +35,7 @@ module GPhoto2
35
35
  it 'returns a new CameraAbilities instance at the specified index' do
36
36
  abilities = double('camera_abilities')
37
37
 
38
- CameraAbilities.stub(:new).and_return(abilities)
38
+ allow(CameraAbilities).to receive(:new).and_return(abilities)
39
39
  list = CameraAbilitiesList.new(context)
40
40
 
41
41
  expect(list.at(0)).to eq(abilities)
@@ -6,7 +6,7 @@ module GPhoto2
6
6
  let(:index) { 0 }
7
7
 
8
8
  before do
9
- CameraAbilities.any_instance.stub(:get_abilities)
9
+ allow_any_instance_of(CameraAbilities).to receive(:get_abilities)
10
10
  end
11
11
 
12
12
  describe '.find' do
@@ -14,13 +14,13 @@ module GPhoto2
14
14
  abilities = double('camera_abilities')
15
15
 
16
16
  context = double('context')
17
- context.stub(:finalize)
18
- Context.stub(:new).and_return(context)
17
+ allow(context).to receive(:finalize)
18
+ allow(Context).to receive(:new).and_return(context)
19
19
 
20
20
  camera_abilities_list = double('camera_abilities_list')
21
- CameraAbilitiesList.stub(:new).and_return(camera_abilities_list)
22
- camera_abilities_list.stub(:lookup_model).and_return(0)
23
- camera_abilities_list.stub(:[]).and_return(abilities)
21
+ allow(CameraAbilitiesList).to receive(:new).and_return(camera_abilities_list)
22
+ allow(camera_abilities_list).to receive(:lookup_model).and_return(0)
23
+ allow(camera_abilities_list).to receive(:[]).and_return(abilities)
24
24
 
25
25
  expect(CameraAbilities.find('model')).to eq(abilities)
26
26
  end
@@ -30,7 +30,7 @@ module GPhoto2
30
30
  it 'returns the value at the given field' do
31
31
  key, value = :model, 'name'
32
32
  abilities = CameraAbilities.new(camera_abilities_list, index)
33
- abilities.stub(:ptr).and_return({ key => value })
33
+ allow(abilities).to receive(:ptr).and_return({ key => value })
34
34
  expect(abilities[key]).to eq(value)
35
35
  end
36
36
  end
@@ -6,8 +6,8 @@ module GPhoto2
6
6
  let(:folder) { '/' }
7
7
 
8
8
  before do
9
- CameraFilePath.any_instance.stub(:name).and_return(name)
10
- CameraFilePath.any_instance.stub(:folder).and_return(folder)
9
+ allow_any_instance_of(CameraFilePath).to receive(:name).and_return(name)
10
+ allow_any_instance_of(CameraFilePath).to receive(:folder).and_return(folder)
11
11
  end
12
12
 
13
13
  describe '#name' do
@@ -8,22 +8,22 @@ module GPhoto2
8
8
  let(:data_and_size) { ['data', 384] }
9
9
 
10
10
  before do
11
- CameraFile.any_instance.stub(:new)
12
- CameraFile.any_instance.stub(:data_and_size).and_return(data_and_size)
11
+ allow_any_instance_of(CameraFile).to receive(:new)
12
+ allow_any_instance_of(CameraFile).to receive(:data_and_size).and_return(data_and_size)
13
13
  end
14
14
 
15
15
  describe '#preview' do
16
16
  context 'when a folder and file are set' do
17
17
  it 'returns false' do
18
18
  file = CameraFile.new(camera, folder, name)
19
- expect(file.preview?).to be_false
19
+ expect(file.preview?).to be(false)
20
20
  end
21
21
  end
22
22
 
23
23
  context 'when no folder or file is set' do
24
24
  it 'returns true' do
25
25
  file = CameraFile.new(camera)
26
- expect(file.preview?).to be_true
26
+ expect(file.preview?).to be(true)
27
27
  end
28
28
  end
29
29
  end
@@ -33,7 +33,7 @@ module GPhoto2
33
33
  let(:data) { data_and_size.first }
34
34
 
35
35
  before do
36
- File.stub(:binwrite)
36
+ allow(File).to receive(:binwrite)
37
37
  end
38
38
 
39
39
  context 'when a pathname is passed' do
@@ -63,7 +63,7 @@ module GPhoto2
63
63
  describe '#data' do
64
64
  it 'returns the data of the camera file' do
65
65
  file = CameraFile.new(camera, folder, name)
66
- file.stub(:data_and_size).and_return(data_and_size)
66
+ allow(file).to receive(:data_and_size).and_return(data_and_size)
67
67
  expect(file.data).to eq(data_and_size.first)
68
68
  end
69
69
  end
@@ -71,7 +71,7 @@ module GPhoto2
71
71
  describe '#size' do
72
72
  it 'returns the size of the camera file' do
73
73
  file = CameraFile.new(camera, folder, name)
74
- file.stub(:data_and_size).and_return(data_and_size)
74
+ allow(file).to receive(:data_and_size).and_return(data_and_size)
75
75
  expect(file.size).to eq(data_and_size.last)
76
76
  end
77
77
  end
@@ -32,7 +32,7 @@ module GPhoto2
32
32
  folder = CameraFolder.new(camera)
33
33
 
34
34
  folders = 2.times.map { folder }
35
- folder.stub(:folder_list_folders).and_return(folders)
35
+ allow(folder).to receive(:folder_list_folders).and_return(folders)
36
36
 
37
37
  expect(folder.folders).to eq(folders)
38
38
  end
@@ -44,7 +44,7 @@ module GPhoto2
44
44
 
45
45
  file = double('camera_file')
46
46
  files = 2.times.map { file }
47
- folder.stub(:folder_list_files).and_return(files)
47
+ allow(folder).to receive(:folder_list_files).and_return(files)
48
48
 
49
49
  expect(folder.files).to eq(files)
50
50
  end
@@ -77,7 +77,7 @@ module GPhoto2
77
77
  describe '#open' do
78
78
  it 'returns a new CameraFile of a file in the folder' do
79
79
  file = double('camera_file')
80
- CameraFile.stub(:new).and_return(file)
80
+ allow(CameraFile).to receive(:new).and_return(file)
81
81
 
82
82
  folder = CameraFolder.new(camera)
83
83
  expect(folder.open('capt0001.jpg')).to eq(file)
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  module GPhoto2
4
4
  describe CameraList do
5
5
  before do
6
- CameraList.any_instance.stub(:new)
6
+ allow_any_instance_of(CameraList).to receive(:new)
7
7
  end
8
8
 
9
9
  describe '#size' do
@@ -11,7 +11,7 @@ module GPhoto2
11
11
  size = 2
12
12
 
13
13
  list = CameraList.new
14
- list.stub(:count).and_return(size)
14
+ allow(list).to receive(:count).and_return(size)
15
15
 
16
16
  expect(list.size).to eq(size)
17
17
  end
@@ -22,7 +22,7 @@ module GPhoto2
22
22
  size = 2
23
23
 
24
24
  list = CameraList.new
25
- list.stub(:size).and_return(size)
25
+ allow(list).to receive(:size).and_return(size)
26
26
 
27
27
  ary = list.to_a
28
28
 
@@ -5,16 +5,20 @@ module GPhoto2
5
5
  let(:model) { 'Nikon DSC D5100 (PTP mode)' }
6
6
  let(:port) { 'usb:250,006' }
7
7
 
8
+ it_behaves_like Camera::Capture
9
+ it_behaves_like Camera::Configuration
10
+ it_behaves_like Camera::Event
11
+ it_behaves_like Camera::Filesystem
12
+
8
13
  describe '.all' do
9
14
  let(:abilities_list) { double('camera_abilities_list') }
10
15
  let(:camera_list) { double('camera_list') }
11
16
  let(:camera) { Camera.new(model, port) }
12
17
 
13
18
  before do
14
- Context.stub(:stub)
15
- CameraAbilitiesList.stub(:new).and_return(abilities_list)
16
- abilities_list.stub(:detect).and_return(camera_list)
17
- camera_list.stub_chain(:to_a, :map).and_return([camera])
19
+ allow(CameraAbilitiesList).to receive(:new).and_return(abilities_list)
20
+ allow(abilities_list).to receive(:detect).and_return(camera_list)
21
+ allow(camera_list).to receive_message_chain(:to_a, :map).and_return([camera])
18
22
  end
19
23
 
20
24
  it 'returns a list of device entries' do
@@ -26,16 +30,34 @@ module GPhoto2
26
30
 
27
31
  describe '.first' do
28
32
  context 'when devices are automatically detected' do
29
- it 'returns a new Camera using the first entry' do
30
- camera = Camera.new(model, port)
31
- Camera.stub(:all).and_return([camera])
32
- expect(Camera.first).to be_kind_of(Camera)
33
+ let(:camera) { Camera.new(model, port) }
34
+
35
+ before do
36
+ allow(Camera).to receive(:all).and_return([camera])
37
+ end
38
+
39
+ context 'when a block is given' do
40
+ it 'yeilds the first detected camera' do
41
+ expect(Camera).to receive(:first).and_yield(camera)
42
+ Camera.first { |c| }
43
+ end
44
+
45
+ it 'finalizes the camera when the block terminates' do
46
+ expect(camera).to receive(:finalize)
47
+ Camera.first { |c| }
48
+ end
49
+ end
50
+
51
+ context 'when no block is given' do
52
+ it 'returns a new Camera using the first entry' do
53
+ expect(Camera.first).to be_kind_of(Camera)
54
+ end
33
55
  end
34
56
  end
35
57
 
36
58
  context 'when no devices are detected' do
37
59
  it 'raises a RuntimeError' do
38
- Camera.stub(:all).and_return([])
60
+ allow(Camera).to receive(:all).and_return([])
39
61
  expect { Camera.first }.to raise_error(RuntimeError)
40
62
  end
41
63
  end
@@ -43,7 +65,7 @@ module GPhoto2
43
65
 
44
66
  describe '.open' do
45
67
  let(:camera) { double('camera') }
46
- before { Camera.stub(:new).and_return(camera) }
68
+ before { allow(Camera).to receive(:new).and_return(camera) }
47
69
 
48
70
  context 'when a block is given' do
49
71
  it 'yeilds a new camera instance' do
@@ -74,7 +96,7 @@ module GPhoto2
74
96
  end
75
97
 
76
98
  before do
77
- Camera.stub(:all).and_return(cameras)
99
+ allow(Camera).to receive(:all).and_return(cameras)
78
100
  end
79
101
 
80
102
  it 'filters all detected cameras by model' do
@@ -93,286 +115,29 @@ module GPhoto2
93
115
  describe '#exit' do
94
116
  it 'closes the camera connection' do
95
117
  camera = Camera.new(model, port)
96
- camera.stub(:_exit)
118
+ allow(camera).to receive(:_exit)
97
119
  expect(camera).to receive(:_exit)
98
120
  camera.exit
99
121
  end
100
122
  end
101
123
 
102
- describe '#capture' do
103
- let(:camera) { Camera.new(model, port) }
104
- let(:path) { double('camera_file_path', folder: 'folder', name: 'name') }
105
-
106
- before do
107
- camera.stub(:_capture).and_return(path)
108
- end
109
-
110
- it 'saves the camera configuration' do
111
- expect(camera).to receive(:save)
112
- camera.capture
113
- end
114
-
115
- it 'returns a new CameraFile' do
116
- expect(camera).to receive(:_capture)
117
- expect(camera.capture).to be_kind_of(CameraFile)
118
- end
119
- end
120
-
121
- describe '#preview' do
122
- let(:camera) { Camera.new(model, port) }
123
- let(:file) { double('camera_file') }
124
-
125
- before do
126
- camera.stub(:save)
127
- camera.stub(:capture_preview).and_return(file)
128
- end
129
-
130
- it 'saves the camera configuration' do
131
- expect(camera).to receive(:save)
132
- camera.preview
133
- end
134
-
135
- it 'returns a new CameraFile' do
136
- expect(camera.preview).to eq(file)
137
- end
138
- end
139
-
140
- describe '#wait' do
141
- let(:camera) { Camera.new(model, port) }
142
- let(:event) { double('camera_event') }
143
-
144
- before do
145
- camera.stub(:wait_for_event).and_return(event)
146
- end
147
-
148
- it 'waits for a camera event' do
149
- expect(camera).to receive(:wait_for_event)
150
- camera.wait
151
- end
152
-
153
- it 'returns an event symbol' do
154
- expect(camera.wait).to eq(event)
155
- end
156
- end
157
-
158
- describe '#wait_for' do
159
- let(:camera) { Camera.new(model, port) }
160
- let(:event) { double('camera_event', type: :capture_complete) }
161
-
162
- before do
163
- camera.stub(:wait).and_return(event)
164
- end
165
-
166
- it 'blocks until a given event is returned from #wait' do
167
- expect(camera).to receive(:wait)
168
- camera.wait_for(:capture_complete)
169
- end
170
-
171
- it 'returns the first event of the given type' do
172
- expect(camera.wait_for(:capture_complete)).to eq(event)
173
- end
174
- end
175
-
176
- describe '#window' do
177
- let(:camera) { Camera.new(model, port) }
178
- let(:window) { double('camera_widget') }
179
-
180
- it 'always returns the same CameraWidget instance' do
181
- camera.stub(:get_config).and_return(window)
182
- expect(camera.window).to eq(window)
183
- expect(camera.window).to eq(window)
184
- end
185
- end
186
-
187
- describe '#config' do
188
- it 'returns a map of configuration widgets' do
189
- camera = Camera.new(model, port)
190
- window = double('camera_widget')
191
- camera.stub(:window).and_return(window)
192
- window.stub(:flatten).and_return({ 'iso' => window })
193
-
194
- expect(camera.config).to eq({ 'iso' => window })
195
- end
196
- end
197
-
198
- describe '#filesystem' do
199
- let(:camera) { Camera.new(model, port) }
200
-
201
- context 'when a path is passed' do
202
- let(:path) { '/store_00010001' }
203
-
204
- it 'assumes the path is absolute' do
205
- fs = camera.filesystem(path[1..-1])
206
- expect(fs.path).to eq(path)
207
- end
208
-
209
- it 'returns a folder at the path that was passed' do
210
- fs = camera.filesystem(path)
211
- expect(fs.path).to eq(path)
212
- end
213
- end
214
-
215
- context 'when no path is passed' do
216
- it 'returns a folder at the root of the filesystem' do
217
- fs = camera.filesystem
218
- expect(fs.path).to eq('/')
219
- end
220
- end
221
- end
222
-
223
- describe '#file' do
224
- it 'retrieves a file from the camera' do
225
- camera = Camera.new(model, port)
226
- camera.stub(:file_get)
227
- expect(camera).to receive(:file_get)
228
- camera.file(double('camera_file'))
229
- end
230
- end
231
-
232
- describe '#delete' do
233
- it 'deletes a file from the camera' do
234
- camera = Camera.new(model, port)
235
- camera.stub(:file_delete)
236
- expect(camera).to receive(:file_delete)
237
- camera.delete(double('camera_file'))
238
- end
239
- end
240
-
241
- describe '#[]' do
242
- let(:window) { double('camera_widget') }
243
-
244
- let(:camera) do
245
- camera = Camera.new(model, port)
246
- camera.stub(:config).and_return({ 'iso' => window })
247
- camera
248
- end
249
-
250
- context 'when the specified key exists' do
251
- it 'returns a CameraWidget' do
252
- expect(camera['iso']).to eq(window)
253
- end
254
- end
255
-
256
- context 'when the specified key does not exist' do
257
- it 'returns nil' do
258
- expect(camera['shutterspeed2']).to be_nil
259
- end
260
- end
261
- end
262
-
263
- describe '#[]=' do
264
- let(:window) do
265
- window = double('camera_widget')
266
- expect(window).to receive(:value=).with(400)
267
- window
268
- end
269
-
270
- let(:camera) do
271
- camera = Camera.new(model, port)
272
- camera.stub(:[]).and_return(window)
273
- camera
274
- end
275
-
276
- it "sets a widget's value" do
277
- camera['iso'] = 400
278
- end
279
-
280
- it 'marks the camera as dirty' do
281
- camera['iso'] = 400
282
- expect(camera).to be_dirty
283
- end
284
-
285
- it 'returns the passed value' do
286
- expect(camera['iso'] = 400).to eq(400)
287
- end
288
- end
289
-
290
- describe '#update' do
291
- let(:camera) do
292
- camera = Camera.new(model, port)
293
- camera.stub(:[]=)
294
- camera.stub(:save)
295
- camera
296
- end
297
-
298
- it 'sets one or more camera setting' do
299
- expect(camera).to receive(:[]=).exactly(2).times
300
- camera.update('iso' => 400, 'shutterspeed2' => '1/30')
301
- end
302
-
303
- it 'immediately saves the settings to the camera' do
304
- expect(camera).to receive(:save)
305
- camera.update
306
- end
307
- end
308
-
309
- describe '#dirty?' do
310
- context 'when the configuration changed' do
311
- it 'returns true' do
312
- camera = Camera.new(model, port)
313
- camera.stub_chain(:[], :value=)
314
-
315
- camera['iso'] = 400
316
-
317
- expect(camera).to be_dirty
318
- end
319
- end
320
-
321
- context 'when the configuration has not changed' do
322
- it 'returns false' do
323
- camera = Camera.new(model, port)
324
- expect(camera).not_to be_dirty
325
- end
326
- end
327
- end
328
-
329
124
  describe '#can?' do
330
125
  let(:camera) { Camera.new(model, port) }
331
126
  let(:operations) { FFI::GPhoto2::CameraOperation[:capture_image] }
332
127
 
333
128
  before do
334
- camera.stub_chain(:abilities, :[])
335
- .with(:operations)
336
- .and_return(operations)
129
+ allow(camera).to receive_message_chain(:abilities, :[]).and_return(operations)
337
130
  end
338
131
 
339
132
  context 'when the camera does not have the ability perform an operation' do
340
133
  it 'return false' do
341
- expect(camera.can?(:capture_audio)).to be_false
134
+ expect(camera.can?(:capture_audio)).to be(false)
342
135
  end
343
136
  end
344
137
 
345
138
  context 'when the camera does have the ability to perform an operation' do
346
139
  it 'returns true' do
347
- expect(camera.can?(:capture_image)).to be_true
348
- end
349
- end
350
- end
351
-
352
- describe '#save' do
353
- let(:camera) do
354
- camera = Camera.new(model, port)
355
- camera.stub_chain(:[], :value=)
356
- camera.stub(:set_config)
357
- camera
358
- end
359
-
360
- context 'when the camera is marked as dirty' do
361
- it 'returns true' do
362
- camera['iso'] = 400
363
- expect(camera.save).to be_true
364
- end
365
-
366
- it 'marks the camera as not dirty' do
367
- camera['iso'] = 400
368
- camera.save
369
- expect(camera).not_to be_dirty
370
- end
371
- end
372
-
373
- context 'when the camera is not marked as dirty' do
374
- it 'returns false' do
375
- expect(camera.save).to be_false
140
+ expect(camera.can?(:capture_image)).to be(true)
376
141
  end
377
142
  end
378
143
  end