rbcdio 0.01

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/AUTHORS +1 -0
  2. data/COPYING +340 -0
  3. data/ChangeLog +315 -0
  4. data/INSTALL +236 -0
  5. data/Makefile.am +163 -0
  6. data/Makefile.in +557 -0
  7. data/NEWS +5 -0
  8. data/README +75 -0
  9. data/Rakefile +234 -0
  10. data/THANKS +3 -0
  11. data/VERSION +1 -0
  12. data/VERSION.in +1 -0
  13. data/config.guess +1473 -0
  14. data/config.sub +1576 -0
  15. data/configure +4802 -0
  16. data/configure.ac +158 -0
  17. data/data/copying.iso +0 -0
  18. data/data/isofs-m1.bin +0 -0
  19. data/data/isofs-m1.cue +3 -0
  20. data/doc/created.rid +1 -0
  21. data/doc/fr_class_index.html +42 -0
  22. data/doc/fr_file_index.html +40 -0
  23. data/doc/fr_method_index.html +133 -0
  24. data/doc/index.html +24 -0
  25. data/doc/rdoc-style.css +208 -0
  26. data/example/COPYING +340 -0
  27. data/example/README +47 -0
  28. data/example/audio.rb +186 -0
  29. data/example/cd-read.rb +167 -0
  30. data/example/copying +340 -0
  31. data/example/device.rb +91 -0
  32. data/example/drivers.rb +63 -0
  33. data/example/drives.rb +63 -0
  34. data/example/eject.rb +69 -0
  35. data/example/iso1.rb +89 -0
  36. data/example/iso2.rb +106 -0
  37. data/example/iso3.rb +111 -0
  38. data/example/tracks.rb +83 -0
  39. data/ext/cdio/Makefile +139 -0
  40. data/ext/cdio/extconf.rb +9 -0
  41. data/ext/cdio/rubycdio_wrap.c +3410 -0
  42. data/ext/iso9660/Makefile +139 -0
  43. data/ext/iso9660/extconf.rb +10 -0
  44. data/ext/iso9660/rubyiso9660_wrap.c +3005 -0
  45. data/install-sh +323 -0
  46. data/lib/Makefile +7 -0
  47. data/lib/cdio.rb +1000 -0
  48. data/lib/iso9660.rb +566 -0
  49. data/missing +360 -0
  50. data/rubycdio.m4 +14 -0
  51. data/swig/Makefile +7 -0
  52. data/swig/audio.swg +63 -0
  53. data/swig/compat.swg +104 -0
  54. data/swig/device.swg +513 -0
  55. data/swig/device_const.swg +144 -0
  56. data/swig/disc.swg +96 -0
  57. data/swig/read.swg +164 -0
  58. data/swig/rubycdio.swg +86 -0
  59. data/swig/rubyiso9660.swg +827 -0
  60. data/swig/track.swg +206 -0
  61. data/swig/types.swg +65 -0
  62. data/test/Makefile +7 -0
  63. data/test/Rakefile +8 -0
  64. data/test/cdda.bin +0 -0
  65. data/test/cdda.cue +7 -0
  66. data/test/cdda.toc +14 -0
  67. data/test/cdiotest.rb +228 -0
  68. data/test/isocopy.rb +394 -0
  69. data/test/isotest.rb +187 -0
  70. metadata +116 -0
data/lib/cdio.rb ADDED
@@ -0,0 +1,1000 @@
1
+ #!/usr/bin/env ruby
2
+ # $Id: cdio.rb,v 1.18 2006/12/16 13:24:48 rocky Exp $
3
+ #
4
+ # Copyright (C) 2006 Rocky Bernstein <rocky@gnu.org>
5
+ #
6
+ # This program is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation; either version 2 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
+ # 02110-1301 USA.
20
+ #
21
+ # Author:: Rocky Bernstein (mailto:rocky@gnu.org)
22
+ #
23
+ # = cdio
24
+ # Module for CD Input and Control library.
25
+ # == Version
26
+ # :include:VERSION
27
+ #
28
+ # == SYNOPSIS
29
+ #
30
+ # The CD Input and Control library (pycdio) encapsulates CD-ROM
31
+ # reading and control. Applications wishing to be oblivious of the OS-
32
+ # and device-dependent properties of a CD-ROM can use this library.
33
+ #
34
+ # require "cdio'
35
+ #
36
+ # cd_drives = Cdio::devices(Rubycdio::DRIVER_DEVICE)
37
+ # for drive in cd_drives
38
+ # puts "Drive %s" % drive
39
+ # end
40
+ # drivers.each_pair { |driver_name, driver_id|
41
+ # if Cdio::driver?(driver_id):
42
+ # puts "Driver %s is installed." % driver_name
43
+ # end
44
+ #
45
+ #
46
+ # == DESCRIPTION
47
+ #
48
+ #
49
+ # This is an Ruby interface to the GNU CD Input and Control library,
50
+ # <tt>libcdio</tt>, written in C. The library encapsulates CD-ROM reading
51
+ # and control. Ruby programs wishing to be oblivious of the OS- and
52
+ # device-dependent properties of a CD-ROM can use this library.
53
+ #
54
+ #
55
+ # The encapsulation is done in two parts. The lower-level Ruby
56
+ # module is called rubycdio and is generated by SWIG.
57
+ #
58
+ # This module uses rubycdio. Actually, there are no objects in
59
+ # module, but there are in classes Device and Track.
60
+ #
61
+ # Although <tt>rubycdio</tt> is perfectly usable on its own, it is expected
62
+ # that cdio is what most people will use. As rubycdio more closely
63
+ # models the C interface <tt>libcdio</tt>, it is conceivable (if unlikely)
64
+ # that die-hard libcdio C users who are very familiar with that
65
+ # interface could prefer that.
66
+ #
67
+
68
+ require "rubycdio"
69
+
70
+ module Cdio
71
+
72
+ # Raise a Driver Error exception on error as determined by drc
73
+ def possibly_raise_exception__(drc, msg=nil)
74
+ if drc==Rubycdio::DRIVER_OP_SUCCESS
75
+ return
76
+ end
77
+ if drc==Rubycdio::DRIVER_OP_ERROR
78
+ raise DriverError
79
+ end
80
+ if drc==Rubycdio::DRIVER_OP_UNINIT
81
+ raise DriverUninitError
82
+ end
83
+ if drc==Rubycdio::DRIVER_OP_UNSUPPORTED
84
+ raise DriverUnsupportedError
85
+ end
86
+ if drc==Rubycdio::DRIVER_OP_NOT_PERMITTED
87
+ raise DriverUnsupportedError
88
+ end
89
+ if drc==Rubycdio::DRIVER_OP_BAD_PARAMETER
90
+ raise DriverBadParameterError
91
+ end
92
+ if drc==Rubycdio::DRIVER_OP_BAD_POINTER
93
+ raise DriverBadPointerError
94
+ end
95
+ if drc==Rubycdio::DRIVER_OP_NO_DRIVER
96
+ raise NoDriverError
97
+ end
98
+ raise DeviceException('unknown exception %d' % drc)
99
+ end
100
+
101
+ # = class DeviceException
102
+ # General device or driver exceptions
103
+
104
+ class DeviceException < Exception
105
+ end
106
+
107
+ class DriverError < DeviceException; end
108
+ class DriverUnsupportedError < DeviceException; end
109
+ class DriverUninitError < DeviceException; end
110
+ class DriverNotPermittedError < DeviceException; end
111
+ class DriverBadParameterError < DeviceException; end
112
+ class DriverBadPointerError < DeviceException; end
113
+ class NoDriverError < DeviceException; end
114
+
115
+ class TrackError < DeviceException; end
116
+
117
+
118
+ # Note: the keys below match those the names returned by
119
+ # cdio_get_driver_name().
120
+ def drivers()
121
+ return {
122
+ :"Unknown" => Rubycdio::DRIVER_UNKNOWN,
123
+ :"AIX" => Rubycdio::DRIVER_AIX,
124
+ :"BSDI" => Rubycdio::DRIVER_BSDI,
125
+ :"FreeBSD" => Rubycdio::DRIVER_FREEBSD,
126
+ :"GNU/Linux" => Rubycdio::DRIVER_LINUX,
127
+ :"Solaris" => Rubycdio::DRIVER_SOLARIS,
128
+ :"OS X" => Rubycdio::DRIVER_OSX,
129
+ :"WIN32" => Rubycdio::DRIVER_WIN32,
130
+ :"CDRDAO" => Rubycdio::DRIVER_CDRDAO,
131
+ :"BIN/CUE" => Rubycdio::DRIVER_BINCUE,
132
+ :"NRG" => Rubycdio::DRIVER_NRG,
133
+ :"device" => Rubycdio::DRIVER_DEVICE
134
+ }
135
+ end
136
+
137
+ def read_mode2blocksize()
138
+ return {
139
+ Rubycdio::READ_MODE_AUDIO => Rubycdio::CD_FRAMESIZE_RAW,
140
+ Rubycdio::READ_MODE_M1F1 => Rubycdio::M2RAW_SECTOR_SIZE,
141
+ Rubycdio::READ_MODE_M1F2 => Rubycdio::CD_FRAMESIZE,
142
+ Rubycdio::READ_MODE_M2F1 => Rubycdio::M2RAW_SECTOR_SIZE,
143
+ Rubycdio::READ_MODE_M2F2 => Rubycdio::CD_FRAMESIZE
144
+ }
145
+ end
146
+
147
+
148
+ # close media tray in CD drive if there is a routine to do so.
149
+ # The driver id is returned. A DeviceException is thrown on error.
150
+ def close_tray(drive=nil, driver_id=Rubycdio::DRIVER_UNKNOWN)
151
+ drc, found_driver_id = Rubycdio::close_tray(drive, driver_id)
152
+ possibly_raise_exception__(drc)
153
+ return found_driver_id
154
+ end
155
+
156
+ # Returns: [device, driver]
157
+ #
158
+ # Return a string containing the default CD device if none is
159
+ # specified. if driver_id is DRIVER_UNKNOWN or DRIVER_DEVICE
160
+ # then one set the default device for that.
161
+ #
162
+ # nil is returned as the device if we couldn't get a default
163
+ # device.
164
+ def default_device_driver(driver_id=Rubycdio::DRIVER_DEVICE)
165
+ return Rubycdio::get_default_device_driver(driver_id)
166
+ end
167
+
168
+ # Returns: [device1, device2, ...]
169
+ #
170
+ # Get an list of device names.
171
+ def devices(driver_id=Rubycdio::DRIVER_UNKNOWN)
172
+ return Rubycdio::get_devices(driver_id)
173
+ end
174
+
175
+ # Returns: [device1, device2, ... driver_id]
176
+ #
177
+ # Like get_devices, but return the p_driver_id which may be different
178
+ # from the passed-in driver_id if it was Rubycdio::DRIVER_DEVICE or
179
+ # Rubycdio::DRIVER_UNKNOWN. The return driver_id may be useful because
180
+ # often one wants to get a drive name and then *open* it
181
+ # afterwards. Giving the driver back facilitates this, and speeds things
182
+ # up for libcdio as well.
183
+ def devices_ret(driver_id=Rubycdio::DRIVER_UNKNOWN)
184
+ devices = Rubycdio::get_devices_ret(driver_id)
185
+ end
186
+
187
+ # Get an array of device names in search_devices that have at least
188
+ # the capabilities listed by the capabities parameter.
189
+ #
190
+ # If any is false then every capability listed in the
191
+ # extended portion of capabilities (i.e. not the basic filesystem)
192
+ # must be satisified. If any is true, then if any of the
193
+ # capabilities matches, we call that a success.
194
+ #
195
+ # To find a CD-drive of any type, use the mask Rubycdio::CDIO_FS_MATCH_ALL.
196
+ #
197
+ # The array of device names is returned or NULL if we couldn't get a
198
+ # default device. It is also possible to return a non NULL but after
199
+ # dereferencing the the value is NULL. This also means nothing was
200
+ # found.
201
+ def devices_with_cap(capabilities, any=false)
202
+ return Rubycdio::get_devices_with_cap(capabilities, any)
203
+ end
204
+
205
+ # Returns: [device1, device2..., driver_id]
206
+ #
207
+ # Like cdio_get_devices_with_cap but we return the driver we found
208
+ # as well. This is because often one wants to search for kind of drive
209
+ # and then *open* it afterwards. Giving the driver back facilitates this,
210
+ # and speeds things up for libcdio as well.
211
+ def devices_with_cap_ret(capabilities, any=false)
212
+ return Rubycdio::get_devices_with_cap_ret(capabilities, any)
213
+ end
214
+
215
+ # return bool
216
+ #
217
+ # Return true if we have driver driver_id.
218
+ def driver?(driver_id)
219
+ if driver_id.class == Fixnum
220
+ return Rubycdio::have_driver(driver_id) == 1
221
+ elsif driver_id.class == Symbol and drivers.member?(driver_id)
222
+ ret = Rubycdio::have_driver(drivers[driver_id])
223
+ if ret == 0 then return false end
224
+ if ret == 1 then return true end
225
+ raise ArgumentError
226
+ else
227
+ raise ArgumentError
228
+ end
229
+ end
230
+
231
+ #--
232
+ # FIXME ? is not quite right
233
+ # binfile?(binfile_name)->cue_name
234
+ #++
235
+ #
236
+ # Determine if binfile_name is the BIN file part of a CDRWIN CD
237
+ # disk image.
238
+ #
239
+ # Return the corresponding CUE file if bin_name is a BIN file or
240
+ # nil if not a BIN file.
241
+ def binfile?(binfile_name)
242
+ return Rubycdio::is_binfile(binfile_name)
243
+ end
244
+
245
+ #--
246
+ # FIXME ? is not quite right
247
+ #++
248
+ # return bin_name
249
+ #
250
+ # Determine if cuefile_name is the CUE file part of a CDRWIN CD
251
+ # disk image.
252
+ #
253
+ # Return the corresponding BIN file if bin_name is a CUE file or
254
+ # nil if not a CUE file.
255
+ def cuefile?(cuefile_name)
256
+ return Rubycdio::is_cuefile(cuefile_name)
257
+ end
258
+
259
+ # Returns: bool
260
+ #
261
+ # Return true if source refers to a real hardware CD-ROM.
262
+ def device?(source, driver_id=Rubycdio::DRIVER_UNKNOWN)
263
+ if not driver_id then driver_id=Rubycdio::DRIVER_UNKNOWN end
264
+ return Rubycdio::device?(source, driver_id)
265
+ end
266
+
267
+ # Returns: bool
268
+ #
269
+ # Determine if nrgfile_name is a Nero CD disc image
270
+ def nrg?(nrgfile_name)
271
+ return Rubycdio::nrg?(nrgfile_name)
272
+ end
273
+
274
+ # tocfile?(tocfile_name)->bool
275
+ #
276
+ # Determine if tocfile_name is a cdrdao CD disc image
277
+ def tocfile?(tocfile_name)
278
+ return Rubycdio::tocfile?(tocfile_name)
279
+ end
280
+
281
+ # Convert bit mask for miscellaneous drive properties
282
+ # into a dictionary of drive capabilities
283
+ def convert_drive_cap_misc(bitmask)
284
+ result={}
285
+ if bitmask & Rubycdio::DRIVE_CAP_ERROR
286
+ result[:DRIVE_CAP_ERROR] = true
287
+ end
288
+ if bitmask & Rubycdio::DRIVE_CAP_UNKNOWN
289
+ result[:DRIVE_CAP_UNKNOWN] = true
290
+ end
291
+ if bitmask & Rubycdio::DRIVE_CAP_MISC_CLOSE_TRAY
292
+ result[:DRIVE_CAP_MISC_CLOSE_TRAY] = true
293
+ end
294
+ if bitmask & Rubycdio::DRIVE_CAP_MISC_EJECT
295
+ result[:DRIVE_CAP_MISC_EJECT] = true
296
+ end
297
+ if bitmask & Rubycdio::DRIVE_CAP_MISC_LOCK
298
+ result['DRIVE_CAP_MISC_LOCK'] = true
299
+ end
300
+ if bitmask & Rubycdio::DRIVE_CAP_MISC_SELECT_SPEED
301
+ result[:DRIVE_CAP_MISC_SELECT_SPEED] = true
302
+ end
303
+ if bitmask & Rubycdio::DRIVE_CAP_MISC_SELECT_DISC
304
+ result[:DRIVE_CAP_MISC_SELECT_DISC] = true
305
+ end
306
+ if bitmask & Rubycdio::DRIVE_CAP_MISC_MULTI_SESSION
307
+ result[:DRIVE_CAP_MISC_MULTI_SESSION] = true
308
+ end
309
+ if bitmask & Rubycdio::DRIVE_CAP_MISC_MEDIA_CHANGED
310
+ result[:DRIVE_CAP_MISC_MEDIA_CHANGED] = true
311
+ end
312
+ if bitmask & Rubycdio::DRIVE_CAP_MISC_RESET
313
+ result[:DRIVE_CAP_MISC_RESET] = true
314
+ end
315
+ if bitmask & Rubycdio::DRIVE_CAP_MISC_FILE
316
+ result[:DRIVE_CAP_MISC_FILE] = true
317
+ end
318
+ return result
319
+ end
320
+
321
+ # Convert bit mask for drive read properties
322
+ # into a dictionary of drive capabilities
323
+ def convert_drive_cap_read(bitmask)
324
+ result={}
325
+ if bitmask & Rubycdio::DRIVE_CAP_READ_AUDIO
326
+ result[:DRIVE_CAP_READ_AUDIO] = true
327
+ end
328
+ if bitmask & Rubycdio::DRIVE_CAP_READ_CD_DA
329
+ result[:DRIVE_CAP_READ_CD_DA] = true
330
+ end
331
+ if bitmask & Rubycdio::DRIVE_CAP_READ_CD_G
332
+ result[:DRIVE_CAP_READ_CD_G] = true
333
+ end
334
+ if bitmask & Rubycdio::DRIVE_CAP_READ_CD_R
335
+ result[:DRIVE_CAP_READ_CD_R] = true
336
+ end
337
+ if bitmask & Rubycdio::DRIVE_CAP_READ_CD_RW
338
+ result[:DRIVE_CAP_READ_CD_RW] = true
339
+ end
340
+ if bitmask & Rubycdio::DRIVE_CAP_READ_DVD_R
341
+ result[:DRIVE_CAP_READ_DVD_R] = true
342
+ end
343
+ if bitmask & Rubycdio::DRIVE_CAP_READ_DVD_PR
344
+ result[:DRIVE_CAP_READ_DVD_PR] = true
345
+ end
346
+ if bitmask & Rubycdio::DRIVE_CAP_READ_DVD_RAM
347
+ result[:DRIVE_CAP_READ_DVD_RAM] = true
348
+ end
349
+ if bitmask & Rubycdio::DRIVE_CAP_READ_DVD_ROM
350
+ result[:DRIVE_CAP_READ_DVD_ROM] = true
351
+ end
352
+ if bitmask & Rubycdio::DRIVE_CAP_READ_DVD_RW
353
+ result[:DRIVE_CAP_READ_DVD_RW] = true
354
+ end
355
+ if bitmask & Rubycdio::DRIVE_CAP_READ_DVD_RPW
356
+ result[:DRIVE_CAP_READ_DVD_RPW] = true
357
+ end
358
+ if bitmask & Rubycdio::DRIVE_CAP_READ_C2_ERRS
359
+ result[:DRIVE_CAP_READ_C2_ERRS] = true
360
+ end
361
+ if bitmask & Rubycdio::DRIVE_CAP_READ_MODE2_FORM1
362
+ result[:DRIVE_CAP_READ_MODE2_FORM1] = true
363
+ end
364
+ if bitmask & Rubycdio::DRIVE_CAP_READ_MODE2_FORM2
365
+ result[:DRIVE_CAP_READ_MODE2_FORM2] = true
366
+ end
367
+ if bitmask & Rubycdio::DRIVE_CAP_READ_MCN
368
+ result[:DRIVE_CAP_READ_MCN] = true
369
+ end
370
+ if bitmask & Rubycdio::DRIVE_CAP_READ_ISRC
371
+ result[:DRIVE_CAP_READ_ISRC] = true
372
+ end
373
+ return result
374
+ end
375
+
376
+ # Convert bit mask for drive write properties
377
+ # into a dictionary of drive capabilities
378
+ def convert_drive_cap_write(bitmask)
379
+ result={}
380
+ if bitmask & Rubycdio::DRIVE_CAP_WRITE_CD_R
381
+ result[:DRIVE_CAP_WRITE_CD_R] = true
382
+ end
383
+ if bitmask & Rubycdio::DRIVE_CAP_WRITE_CD_RW
384
+ result[:DRIVE_CAP_WRITE_CD_RW] = true
385
+ end
386
+ if bitmask & Rubycdio::DRIVE_CAP_WRITE_DVD_R
387
+ result[:DRIVE_CAP_WRITE_DVD_R] = true
388
+ end
389
+ if bitmask & Rubycdio::DRIVE_CAP_WRITE_DVD_PR
390
+ result[:DRIVE_CAP_WRITE_DVD_PR] = true
391
+ end
392
+ if bitmask & Rubycdio::DRIVE_CAP_WRITE_DVD_RAM
393
+ result[:DRIVE_CAP_WRITE_DVD_RAM] = true
394
+ end
395
+ if bitmask & Rubycdio::DRIVE_CAP_WRITE_DVD_RW
396
+ result[:DRIVE_CAP_WRITE_DVD_RW] = true
397
+ end
398
+ if bitmask & Rubycdio::DRIVE_CAP_WRITE_DVD_RPW
399
+ result[:DRIVE_CAP_WRITE_DVD_RPW] = true
400
+ end
401
+ if bitmask & Rubycdio::DRIVE_CAP_WRITE_MT_RAINIER
402
+ result[:DRIVE_CAP_WRITE_MT_RAINIER] = true
403
+ end
404
+ if bitmask & Rubycdio::DRIVE_CAP_WRITE_BURN_PROOF
405
+ result[:DRIVE_CAP_WRITE_BURN_PROOF] = true
406
+ end
407
+ return result
408
+ end
409
+
410
+ # = class Device
411
+ #
412
+ # CD Input and control class for discs/devices
413
+ #
414
+ # == SYNOPSIS
415
+ #
416
+ # require "cdio"
417
+ # d = Cdio::Device.new("", Rubycdio::DRIVER_UNKNOWN)
418
+ # drive_name = d.device()
419
+ # hw = d.hwinfo()
420
+ # if hw then
421
+ # puts "drive: %s, vendor: %s, model: %s, revision: %s" %
422
+ # [drive_name, hw["vendor"], hw["model"], hw["revision"]]
423
+ # end
424
+ #
425
+ # drivers.each_pair { |driver_name, driver_id|
426
+ # begin
427
+ # if driver?(driver_id):
428
+ # puts "Driver %s is installed." % driver_name
429
+ # end
430
+ # rescue ValueError
431
+ # end
432
+
433
+ class Device
434
+
435
+ def initialize(source=nil, driver_id=nil,
436
+ access_mode=nil)
437
+ @cd = nil
438
+ if source or driver_id
439
+ open(source, driver_id, access_mode)
440
+ end
441
+ end
442
+
443
+ # Returns: bool
444
+ #
445
+ # return true if CD-ROM understand ATAPI commands.
446
+ def ATAPI?()
447
+ return Rubycdio::ATAPI?(@cd)
448
+ end
449
+
450
+ # Returns: status
451
+ #
452
+ # Pause playing CD through analog output.
453
+ # A DeviceError exception may be raised.
454
+ def audio_pause()
455
+ drc=Rubycdio::audio_pause(@cd)
456
+ possibly_raise_exception__(drc)
457
+ end
458
+
459
+ # Returns: status
460
+ #
461
+ # Playing CD through analog output at the given lsn to the ending lsn
462
+ # A DeviceError exception may be raised.
463
+ def audio_play_lsn(start_lsn, end_lsn)
464
+ drc=Rubycdio::audio_play_lsn(@cd, start_lsn, end_lsn)
465
+ possibly_raise_exception__(drc)
466
+ end
467
+
468
+ # Returns: status
469
+ #
470
+ # Resume playing an audio CD through the analog interface.
471
+ # A DeviceError exception may be raised.
472
+ def audio_resume()
473
+ drc=Rubycdio::audio_resume(@cd)
474
+ possibly_raise_exception__(drc)
475
+ end
476
+
477
+ # Returns: status
478
+ #
479
+ # Stop playing an audio CD through the analog interface.
480
+ # A DeviceError exception may be raised.
481
+ def audio_stop()
482
+ drc=Rubycdio::audio_stop(@cd)
483
+ possibly_raise_exception__(drc)
484
+ end
485
+
486
+ # Free resources associated with p_cdio. Call this when done using
487
+ # using CD reading/control operations for the current device.
488
+ def close()
489
+ if @cd
490
+ Rubycdio::close(@cd)
491
+ else
492
+ puts "***No object to close"
493
+ end
494
+ @cd=nil
495
+ end
496
+
497
+ # Eject media in CD drive if there is a routine to do so.
498
+ # A DeviceError exception may be raised.
499
+ def eject_media()
500
+ drc=Rubycdio::eject_media(@cd)
501
+ @cd = nil
502
+ possibly_raise_exception__(drc)
503
+ end
504
+
505
+ # Eject media in CD drive if there is a routine to do so.
506
+ # An exception is thrown on error.
507
+ def eject_media_drive(drive=nil)
508
+ ### FIXME: combine into above by testing if drive is the string
509
+ ### nil versus drive = Rubycdio::DRIVER_UNKNOWN
510
+ Rubycdio::eject_media_drive(drive)
511
+ end
512
+
513
+ # Returns: String
514
+
515
+ # Get the value associatied with key.
516
+ def arg(key)
517
+ return Rubycdio::get_arg(@cd, key)
518
+ end
519
+
520
+ # Returns: String
521
+ #
522
+ # Get the default CD device.
523
+ # If we haven't initialized a specific device driver),
524
+ # then find a suitable one and return the default device for that.
525
+ # In some situations of drivers or OS's we can't find a CD device if
526
+ # there is no media in it and it is possible for this routine to return
527
+ # nil even though there may be a hardware CD-ROM.
528
+ def device()
529
+ if @cd
530
+ return Rubycdio::get_arg(@cd, "source")
531
+ end
532
+ return Rubycdio::get_device(@cd)
533
+ end
534
+
535
+ # Returns: Fixnum
536
+ #
537
+ # Get the LSN of the end of the CD
538
+ #
539
+ # DriverError and IOError may raised on error.
540
+ def disc_last_lsn()
541
+ lsn = Rubycdio::get_disc_last_lsn(@cd)
542
+ if lsn == Rubycdio::INVALID_LSN:
543
+ raise DriverError
544
+ end
545
+ return lsn
546
+ end
547
+
548
+ # Returns: String
549
+ #
550
+ # Get disc mode - the kind of CD (CD-DA, CD-ROM mode 1, CD-MIXED, ...)
551
+ # that we've got. The notion of 'CD' is extended a little to include
552
+ # DVD's.
553
+ def disc_mode()
554
+ if not @cd then return "Uninitialized Device" end
555
+ return Rubycdio::get_disc_mode(@cd)
556
+ end
557
+
558
+ # Get drive capabilities of device.
559
+ #
560
+ # In some situations of drivers or OS's we can't find a CD
561
+ # device if there is no media in it. In this situation
562
+ # capabilities will show up as empty even though there is a
563
+ # hardware CD-ROM. get_drive_cap_dev()->(read_cap, write_cap,
564
+ # misc_cap)
565
+ #
566
+ # Get drive capabilities of device.
567
+ #
568
+ # In some situations of drivers or OS's we can't find a CD
569
+ # device if there is no media in it. In this situation
570
+ # capabilities will show up as empty even though there is a
571
+ # hardware CD-ROM.
572
+ def drive_cap()
573
+ b_read_cap, b_write_cap, b_misc_cap = Rubycdio::get_drive_cap(@cd)
574
+ return [convert_drive_cap_read(b_read_cap),
575
+ convert_drive_cap_write(b_write_cap),
576
+ convert_drive_cap_misc(b_misc_cap)]
577
+ end
578
+
579
+ def drive_cap_dev(device=nil)
580
+ #---
581
+ ### FIXME: combine into above by testing on the type of device.
582
+ #+++
583
+ b_read_cap, b_write_cap, b_misc_cap =
584
+ Rubycdio::get_drive_cap_dev(device);
585
+ return [convert_drive_cap_read(b_read_cap),
586
+ convert_drive_cap_write(b_write_cap),
587
+ convert_drive_cap_misc(b_misc_cap)]
588
+ end
589
+
590
+ # Returns: String
591
+ #
592
+ # return a string containing the name of the driver in use.
593
+ #
594
+ # An IOError exception is raised on error.
595
+ def driver_name()
596
+ if not @cd then raise DriverUninitError end
597
+ return Rubycdio::get_driver_name(@cd)
598
+ end
599
+
600
+ # Returns: Fixnum
601
+ #
602
+ # Return the driver id of the driver in use.
603
+ # if object has not been initialized or is nil,
604
+ # return Rubycdio::DRIVER_UNKNOWN.
605
+ def driver_id()
606
+ return Rubycdio::get_driver_id(@cd)
607
+ end
608
+
609
+ # Returns: Track
610
+ #
611
+ # return a Track object of the first track. nil is returned
612
+ # if there was a problem.
613
+ def first_track()
614
+ track = Rubycdio::get_first_track_num(@cd)
615
+ if track == Rubycdio::INVALID_TRACK
616
+ return nil
617
+ end
618
+ return Track.new(@cd, track)
619
+ end
620
+
621
+ # Returns: {"vendor"=>??, "model"=>??, "release"=>??}
622
+ #
623
+ # Get the CD-ROM hardware info via a SCSI MMC INQUIRY command.
624
+ def hwinfo()
625
+ return Rubycdio::get_hwinfo(@cd)
626
+ end
627
+
628
+ # Returns: FixNum
629
+
630
+ # Return the Joliet level recognized for cdio. This only makes
631
+ # sense for something that has an ISO-9660 filesystem.
632
+
633
+ def joliet_level()
634
+ return Rubycdio::get_joliet_level(@cd)
635
+ end
636
+
637
+ # Returns: Fixnum
638
+
639
+ # Get the LSN of the first track of the last session of on the CD.
640
+ # An exception is thrown on error.
641
+
642
+ def last_session()
643
+ drc, session = Rubycdio::get_last_session(@cd)
644
+ possibly_raise_exception__(drc)
645
+ return session
646
+ end
647
+
648
+ # Returns: Track
649
+ #
650
+ # return a Track object of the first track. nil is returned
651
+ # if there was a problem.
652
+ def last_track()
653
+ track = Rubycdio::get_last_track_num(@cd)
654
+ if track == Rubycdio::INVALID_TRACK
655
+ return nil
656
+ end
657
+ return Track.new(@cd, track)
658
+ end
659
+
660
+ # Returns: String
661
+ #
662
+ # Get the media catalog number (MCN) from the CD.
663
+ def mcn()
664
+ return Rubycdio::get_mcn(@cd)
665
+ end
666
+
667
+ # Find out if media has changed since the last call.
668
+ # Return true if media has changed since last call. An exception
669
+ # Error is given on error.
670
+ def media_changed?()
671
+ drc = Rubycdio::get_media_changed(@cd)
672
+ if drc == 0 then return false end
673
+ if drc == 1 then return true end
674
+ possibly_raise_exception__(drc)
675
+ raise DeviceException
676
+ end
677
+
678
+ # Returns: Fixnum
679
+ #
680
+ # Return the number of tracks on the CD.
681
+ # A TrackError or IOError exception may be raised on error.
682
+ def num_tracks()
683
+ track = Rubycdio::get_num_tracks(@cd)
684
+ if track == Rubycdio::INVALID_TRACK
685
+ raise TrackError
686
+ end
687
+ return track
688
+ end
689
+
690
+ # Returns: track
691
+ #
692
+ # Return a track object for the given track number.
693
+ def track(track_num)
694
+ return Track.new(@cd, track_num)
695
+ end
696
+
697
+ # Returns: track
698
+ #
699
+ # Find the track which contains lsn.
700
+ # nil is returned if the lsn outside of the CD or
701
+ # if there was some error.
702
+ #
703
+ # If the lsn is before the pregap of the first track,
704
+ # A track object with a 0 track is returned.
705
+ # Otherwise we return the track that spans the lsn.
706
+ def track_for_lsn(lsn)
707
+ track = Rubycdio::get_last_track_num(@cd)
708
+ if track == Rubycdio::INVALID_TRACK:
709
+ return nil
710
+ end
711
+ return Track.new(@cd, track)
712
+ end
713
+
714
+ # Returns: Fixnum
715
+ # Reposition read offset
716
+ # Similar to (if not the same as) libc's fseek()
717
+ #
718
+ # cdio is object to get adjested, offset is amount to seek and
719
+ # whence is like corresponding parameter in libc's lseek, e.g.
720
+ # it should be SEEK_SET or SEEK_END.
721
+ #
722
+ # the offset is returned or -1 on error.
723
+ def lseek(offset, whence)
724
+ return Rubycdio::lseek(@cd, offset, whence)
725
+ end
726
+
727
+ # Sets up to read from place specified by source, driver_id and
728
+ # access mode. This should be called before using any other routine
729
+ # except those that act on a CD-ROM drive by name.
730
+ #
731
+ # If nil is given as the source, we'll use the default driver device.
732
+ # If nil is given as the driver_id, we'll find a suitable device driver.
733
+ #
734
+ # If device object was, previously opened it is closed first.
735
+ #
736
+ # Device is opened so that subsequent operations can be performed.
737
+ def open(source=nil, driver_id=Rubycdio::DRIVER_UNKNOWN,
738
+ access_mode=nil)
739
+ if not driver_id
740
+ driver_id=Rubycdio::DRIVER_UNKNOWN
741
+ end
742
+ if not source
743
+ source = ''
744
+ end
745
+ if not access_mode
746
+ access_mode = ''
747
+ end
748
+ if @cd
749
+ close()
750
+ end
751
+ @cd = Rubycdio::open_cd(source, driver_id, access_mode)
752
+ end
753
+
754
+ # Returns: [size, data]
755
+ #
756
+ # Reads the next size bytes.
757
+ # Similar to (if not the same as) libc's read()
758
+ #
759
+ # The number of bytes read and the data is returned.
760
+ # A DeviceError exception may be raised.
761
+ def read(size)
762
+ size, data = Rubycdio::read_cd(@cd, size)
763
+ possibly_raise_exception__(size)
764
+ return [size, data]
765
+ end
766
+
767
+ # return [size, data]
768
+ #
769
+ # Reads a number of data sectors (AKA blocks).
770
+ #
771
+ # lsn is sector to read, bytes is the number of bytes.
772
+ # A DeviceError exception may be raised.
773
+ def read_data_blocks(lsn, blocks=1)
774
+ size = Rubycdio::ISO_BLOCKSIZE*blocks
775
+ triple = Rubycdio::read_data_bytes(@cd, lsn,
776
+ Rubycdio::ISO_BLOCKSIZE, size)
777
+ if not triple
778
+ return [-1, nil]
779
+ end
780
+ data, size, drc = triple
781
+ possibly_raise_exception__(drc)
782
+ return [size, data]
783
+ end
784
+
785
+ # return [blocks, data]
786
+ #
787
+ # Reads a number of sectors (AKA blocks).
788
+ #
789
+ # lsn is sector to read, bytes is the number of bytes.
790
+ #
791
+ # If read_mode is Rubycdio::MODE_AUDIO, the return buffer size will be
792
+ # truncated to multiple of Rubycdio::CDIO_FRAMESIZE_RAW i_blocks bytes.
793
+ #
794
+ # If read_mode is Rubycdio::MODE_DATA, buffer will be truncated to a
795
+ # multiple of Rubycdio::ISO_BLOCKSIZE, Rubycdio::M1RAW_SECTOR_SIZE or
796
+ # Rubycdio::M2F2_SECTOR_SIZE bytes depending on what mode the data is in.
797
+ #
798
+ # If read_mode is Rubycdio::MODE_M2F1, buffer will be truncated to a
799
+ # multiple of Rubycdio::M2RAW_SECTOR_SIZE bytes.
800
+ #
801
+ # If read_mode is Rubycdio::MODE_M2F2, the return buffer size will be
802
+ # truncated to a multiple of Rubycdio::CD_FRAMESIZE bytes.
803
+ #
804
+ # The number of bytes read and the data is returned.
805
+ # A DeviceError exception may be raised.
806
+ def read_sectors(lsn, read_mode, blocks=1)
807
+ begin
808
+ blocksize = read_mode2blocksize()[read_mode]
809
+ size = blocks * blocksize
810
+ rescue
811
+ return [-1, nil]
812
+ end
813
+ triple = Rubycdio::read_sectors(@cd, lsn, read_mode, size)
814
+ if not triple
815
+ return [-1, nil]
816
+ end
817
+ data, size, drc = triple
818
+ possibly_raise_exception__(drc)
819
+ blocks = size / blocksize
820
+ return [blocks, data]
821
+ end
822
+
823
+ # Set the blocksize for subsequent reads.
824
+ # An exception is thrown on error.
825
+ def blocksize=(blocksize)
826
+ drc = Rubycdio::set_blocksize(@cd, blocksize)
827
+ possibly_raise_exception__(drc)
828
+ end
829
+
830
+ # Set the drive speed. An exception is thrown on error.
831
+ def speed=(speed)
832
+ drc = Rubycdio::set_speed(@cd, speed)
833
+ possibly_raise_exception__(drc)
834
+ end
835
+ end # Device
836
+
837
+ # = CD Input and control track class
838
+ #
839
+ # == SYNOPSIS
840
+ #
841
+ # require "cdio"
842
+ # d = Device.new("/dev/cdrom")
843
+ # t = d.first_track()
844
+ # first_track = t.track
845
+ # num_tracks = d.num_tracks()
846
+ # last_track = first_track+num_tracks-1
847
+ # for i in first_track .. last_track
848
+ # t = d.track(i)
849
+ # puts "%3d: %06u %-6s %s" % [t.track, t.lsn(), t.msf(), t.format()]
850
+ # end
851
+ # puts "%3X: %06u leadout" % [Rubycdio::CDROM_LEADOUT_TRACK, d.disc_last_lsn()]
852
+ #
853
+ class Track
854
+
855
+ attr_accessor :track
856
+
857
+ def initialize(device, track_num)
858
+
859
+ if track_num.class != Fixnum
860
+ raise TrackError('track number parameter is not an integer')
861
+ end
862
+ @track = track_num
863
+
864
+ # See if the device parameter is a string or
865
+ # a device object.
866
+ if device.class == String
867
+ @device = Device.new(device)
868
+ else
869
+ @device = device
870
+ end
871
+ end
872
+
873
+ # Returns: Fixnum
874
+ #
875
+ # Return number of channels in track: 2 or 4.
876
+ # Not meaningful if track is not an audio track.
877
+ # An exception can be raised on error.
878
+ def audio_channels()
879
+ channels = Rubycdio::get_track_channels(@device, @track)
880
+ if -2 == channels
881
+ raise DriverUnsupportedError
882
+ elsif -1 == channels
883
+ raise TrackError
884
+ else
885
+ return channels
886
+ end
887
+ end
888
+
889
+ # Returns: bool
890
+ #
891
+ # Return copy protection status on a track. Is this meaningful
892
+ # not an audio track?
893
+ def copy_permit?()
894
+ return Rubycdio::track_copy_permit?(@device, @track)
895
+ end
896
+
897
+ # Returns: format (String)
898
+ #
899
+ # Get the format (e.g. 'audio', 'mode2', 'mode1') of track.
900
+ def format()
901
+ return Rubycdio::get_track_format(@device, @track)
902
+ end
903
+
904
+ # Returns: Fixnum (lsn)
905
+ #
906
+ # Return the ending LSN for a track.
907
+ # A TrackError or IOError exception may be raised on error.
908
+ def last_lsn()
909
+ lsn = Rubycdio::get_track_last_lsn(@device, @track)
910
+ if lsn == Rubycdio::INVALID_LSN
911
+ raise TrackError('Invalid LSN returned')
912
+ end
913
+ return lsn
914
+ end
915
+
916
+ # Returns: Fixnum (lba)
917
+ #
918
+ # Return the starting LBA for a track
919
+ # A TrackError exception is raised on error.
920
+ def lba()
921
+ lba = Rubycdio::get_track_lba(@device, @track)
922
+ if lba == Rubycdio::INVALID_LBA
923
+ raise TrackError('Invalid LBA returned')
924
+ end
925
+ return lba
926
+ end
927
+
928
+ # Returns: Fixnum (lsn)
929
+ #
930
+ # Return the starting LSN for a track
931
+ # A TrackError exception is raised on error.
932
+ def lsn()
933
+ lsn = Rubycdio::get_track_lsn(@device, @track)
934
+ if lsn == Rubycdio::INVALID_LSN:
935
+ raise TrackError('Invalid LSN returned')
936
+ end
937
+ return lsn
938
+ end
939
+
940
+ # Returns: String
941
+ #
942
+ # Return the starting MSF (minutes/secs/frames) for track number track.
943
+ # Track numbers usually start at something greater than 0, usually 1.
944
+ #
945
+ # Returns string of the form <i>mm:ss:ff</i> if all good, or string nil on
946
+ # error.
947
+ def msf()
948
+ return Rubycdio::get_track_msf(@device, @track)
949
+ end
950
+
951
+ # Returns: String
952
+ #
953
+ # Get linear preemphasis status on an audio track.
954
+ # This is not meaningful if not an audio track?
955
+ # A TrackError exception is raised on error.
956
+ def preemphasis()
957
+ rc = Rubycdio::get_track_preemphasis(@device, @track)
958
+ if rc == Rubycdio::TRACK_FLAG_FALSE:
959
+ return 'none'
960
+ elsif rc == Rubycdio::TRACK_FLAG_TRUE:
961
+ return 'preemphasis'
962
+ elsif rc == Rubycdio::TRACK_FLAG_UNKNOWN:
963
+ return 'unknown'
964
+ else
965
+ raise TrackError('Invalid return value %d' % d)
966
+ end
967
+ end
968
+
969
+ # Returns: Fixnum
970
+ #
971
+ # Get the number of sectors between this track an the next. This
972
+ # includes any pregap sectors before the start of the next track.
973
+ # Track numbers usually start at something
974
+ # greater than 0, usually 1.
975
+ #
976
+ # A TrackError exception is raised on error.
977
+ def sec_count()
978
+ sec_count = Rubycdio::get_track_sec_count(@device, @track)
979
+ if sec_count == 0
980
+ raise TrackError
981
+ end
982
+ return sec_count
983
+ end
984
+
985
+ # Return true if we have XA data (green, mode2 form1) or
986
+ # XA data (green, mode2 form2). That is track begins:
987
+ # sync - header - subheader
988
+ # 12 4 - 8
989
+ def green?()
990
+ return Rubycdio::track_green?(@device, @track)
991
+ end
992
+
993
+ end # class Track
994
+
995
+ end # Cdio
996
+ include Cdio
997
+ #
998
+ # Local variables:
999
+ # mode: Ruby
1000
+ # End: